Create a class to store the variables as private, internal members. Set up the variables when the post object is set up, that’s the action the_post
.
Then assign class methods as callbacks instead of separate functions.
Here is your code slightly reformatted:
The class
class WPSE_WC_Badge
{
private $title="";
private $class="";
private $duration = '';
private $postdate="";
private $postdatestamp = '';
private $difference = 0;
public function __construct( \WP_Post $post )
{
$this->title = get_post_meta( $post->ID, '_wc_simple_product_badge_title', TRUE ); // badge title
$this->class = get_post_meta( $post->ID, '_wc_simple_product_badge_class', TRUE ); // badge class
$this->duration = get_post_meta( $post->ID, '_wc_simple_product_badge_duration', TRUE ); // badge duration
$this->postdate = get_the_time( 'Y-m-d', $post ); // post date
$this->postdatestamp = strtotime( $this->postdate ); // post date in unix timestamp
// difference in days between now and product's post date
$this->difference = round( ( time() - $this->postdatestamp ) / DAY_IN_SECONDS );
}
function loop()
{
if ( ! empty( $this->title ) && empty( $this->duration )
|| ! empty( $this->title ) && $this->difference <= $this->duration
)
{ // Check to see if there is a title and the product is still within the duration timeframe if specified
echo '<span class="wc_simple_product_badge ' . $this->class . '">' . $this->title . '</span>';
}
}
function single( $img_html )
{
$single_opt = get_post_meta( get_the_ID(), '_wc_simple_product_badge_single_page_option', TRUE ); // badge on single page
if ( ! empty ( $this->title ) && empty( $this->duration ) && $single_opt === 'yes'
|| ! empty( $this->title ) && $this->difference <= $this->duration && $single_opt === 'yes'
)
{
echo '<span class="wc_simple_product_badge ' . $this->class . '">' . $this->title . '</span>';
return $img_html;
}
return $img_html;
}
}
And the registration
add_action( 'the_post', function( \WP_Post $post ) {
$badge = new WPSE_WC_Badge( $post );
// Display the product badge on the shop page
add_action( 'woocommerce_after_shop_loop_item_title', [ $badge, 'loop' ], 30 );
// Display the product badge on the single page
add_filter( 'woocommerce_single_product_image_html', [ $badge, 'single' ] );
});
I haven’t tested this, please take it just as starting point.