将产品首次发布日期保存为 "First publish date" 并设置自定义产品徽章

Save product first publishing date as "First publish date" and set custom product badges

目前,当在商店中创建和发布产品时,我总是总是显示“新”产品徽章。为此,我们使用标准的 WooCommerce 函数 $product->get_date_modified().

但是,我们还希望在产品有货时显示“有货”产品徽章。为此,我们使用该答案中的代码:

所以在这种情况下,我们不想同时显示“新品”和“有货”徽章。这就是为什么我们尝试编写一个检查代码来帮助决定必须显示哪个徽章。

为此,我尝试存储产品的首次发布日期,以便显示或不显示自定义徽章。

目标是:

当前代码

// Save date in custom field when product is first published
// If a product has no "first published date" store the current date (when product is saved) as first publishing date

function woo_first_product_published_date( $product_id ) {

if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        
    if ( ! empty ( $first_publish_date) ) {

    // Store current date

    } 
 }


// Check if stock is 0 or not
function woo_updated_product_stock( $product_id ) {

   $product  = wc_get_product( $product_id );

   $stock_qty  = $product->get_stock_quantity();

// If stock is >=1 AND publishing date is older than 10 days set custom value to true
   if ($stock_qty >=1 && get_post_meta( $product->get_id(), '_first_publish_date', true) > 10 )
}

// IF a product published date is today or in the last 10 days => do nothing
   else{
      update_post_meta( $product_id, '_earlier_update',  false);
   }
}

add_action( 'woocommerce_updated_product_stock', 'woo_updated_product_stock', 10, 3);
add_action( 'woocommerce_update_product', 'woo_updated_product_stock',10, 3 );
add_action('save_post_product', 'woo_updated_product_stock', 10, 3);


// Add "back in stock" badge
add_action( 'woocommerce_before_shop_loop_item_title', function() {      
    global $product;
    $newness_days  = 10;
    $product_id    = $product->get_id();
    $date_modified = $product->get_date_modified()->date('Y-m-d');
    
    // Add 10 day on product modify date  becase fresh back in stock will show 10 days from current modify dates
    $back_in_stock = strtotime($date_modified. " + $newness_days day");
    $today         = strtotime(date('Y-m-d'));

    $earlier_update = get_post_meta( $product_id, '_earlier_update', true );
        
    if (($earlier_update && $today < $back_in_stock) && !$product->is_on_sale() && $product->is_in_stock() ) {
    echo '<div class="badge_loop_wrapper"><img src="https://staging01.ch/wp-content/uploads/2021/09/back_in_stock_badge.png"/></div>';
    
    }
});


// Add "new" badge for new products in store
add_action( 'woocommerce_before_shop_loop_item_title', function() {      
   global $product;
   $newness_days = 10;
   $created = strtotime( $product->get_date_modified() );
    
    // Check if product is new
    if ( ( time() - ( 60 * 60 * 24 * $newness_days ) ) < $created && !$product->is_on_sale() && $product->is_in_stock() && get_post_meta( $product->get_id(), '_earlier_update', true) !== '1' ) {
      echo '<div class="badge_loop_wrapper"><img src="https://staging01.ch/wp-content/uploads/2021/01/new_badge.png"/></div>';
   }

});

根据我从你的问题中收集到的信息,你正在寻找解决方案太过分了,使用 $product->get_date_created()$product->get_date_modified() 就足够了,而无需在(重新)保存时自己添加额外的数据产品。

  • 如果产品已创建且不早于 10 天,将显示 'new' 徽章
  • 如果产品在创建后的前 10 天内修改。 'new' 徽章仍会显示
  • 如果之后编辑产品(更新库存),那么 'back in stock' 徽章将显示,前提是此调整不早于 10 天
  • 当然你可以扩展 'modified' 检查额外的检查,是否真的有股票等等,但是代码的基本原理是一样的

所以以下内容应该足够了:

function action_woocommerce_before_shop_loop_item_title() {
    global $product;
    
    // Is a WC product
    if ( is_a( $product, 'WC_Product' ) ) {
        // 10 days in seconds
        $ten_days = 10 * 24 * 60 * 60;
        
        // Get now datetime (from Woocommerce datetime object) + Get now timestamp
        $datetime_now = new WC_DateTime();
        $timestamp_now = $datetime_now->getTimestamp();
        
        // Get product created datetime + product created timestamp
        $datetime_created  = $product->get_date_created();
        $timestamp_created = $datetime_created->getTimestamp();
        
        // Difference in seconds between now and date created
        $time_delta_created = $timestamp_now - $timestamp_created;
        
        // If the difference is less than 10, apply "New" label
        if ( $time_delta_created < $ten_days ) {
            echo '<span>' . __( 'New', 'woocommerce' ) . '</span>';
        } else {
            // Get product modified datetime + product modified timestamp
            $datetime_modified  = $product->get_date_modified();
            $timestamp_modified = $datetime_modified->getTimestamp();
            
            // Difference in seconds between now and date created
            $time_delta_modified = $timestamp_now - $timestamp_modified;
            
            // If the difference is less than 10, apply "Back in stock" label
            if ( $time_delta_modified < $ten_days ) {
                echo '<span>' . __( 'Back in stock', 'woocommerce' ) . '</span>';
            }
        }
    }
}
add_action( 'woocommerce_before_shop_loop_item_title', 'action_woocommerce_before_shop_loop_item_title', 10 );

如果产品不是立即发布,而是在 +10 天后才发布,则 $product->get_date_created() 无法使用。

要解决此问题,您可以添加以下内容,这会将创建日期调整为产品发布日期,而不是产品创建日期。还提供了一个额外的检查,用于确定产品的发布状态之后何时应该更改。

/**
 * Fire a callback only when my-custom-post-type posts are transitioned to 'publish'.
 *
 * @param string  $new_status New post status.
 * @param string  $old_status Old post status.
 * @param WP_Post $post       Post object.
 */
function action_transition_post_status( $new_status, $old_status, $post ) {
    if ( $old_status != 'publish' && $new_status == 'publish' && ! empty( $post->ID ) && in_array( $post->post_type, array( 'product' ) ) ) {
        // Get product
        $product = wc_get_product( $post->ID );
        
        // Is a WC product
        if ( is_a( $product, 'WC_Product' ) ) {         
            // Get meta value
            $published_first_time = $product->get_meta( '_published_first_time' );
            
            // When empty OR false
            if ( empty ( $published_first_time ) || $published_first_time == false ) {
                // Update meta data
                $product->update_meta_data( '_published_first_time', true );
                
                // Get an instance of the current WC_DateTime object
                $date_time = new WC_DateTime();
                
                // Set product created date
                $product->set_date_created( $date_time );
                
                // Save the data (in database)
                $product->save();
            }
        }
    }
}
add_action( 'transition_post_status', 'action_transition_post_status', 10, 3 );