wc_schedule_product_sale_events()
Schedule start/end sale actions for a product based on its sale dates.
Uses Action Scheduler to fire events at the exact sale start/end times, rather than relying on the daily cron.
An action is not scheduled if an identical one (same hook, args, group and timestamp) is already pending, so concurrent processes saving the same product don't pile up duplicate actions.
No Hooks.
Returns
null. Nothing (null).
Usage
wc_schedule_product_sale_events( $product ): void;
- $product(WC_Product) (required)
- Product object.
Changelog
| Since 10.5.0 | Introduced. |
wc_schedule_product_sale_events() wc schedule product sale events code WC 11.0.0
function wc_schedule_product_sale_events( WC_Product $product ): void {
$product_id = $product->get_id();
$schedule = function ( ?WC_DateTime $date, string $hook ) use ( $product_id ): void {
if ( is_null( $date ) ) {
return;
}
$timestamp = $date->getTimestamp();
if ( $timestamp <= time() ) {
return;
}
$args = array( 'product_id' => $product_id );
// An identical pending action means a concurrent process (parallel save, importer,
// daily cron) already scheduled it after the unschedule-all step ran. The query
// filters by the exact timestamp: a pending action for a different time (e.g. left
// behind by a process that saw older sale dates) must not block scheduling.
$identical_pending = as_get_scheduled_actions(
array(
'hook' => $hook,
'args' => $args,
'group' => 'woocommerce-sales',
'status' => ActionScheduler_Store::STATUS_PENDING,
'date' => gmdate( 'Y-m-d H:i:s', $timestamp ),
'date_compare' => '=',
'per_page' => 1,
),
'ids'
);
if ( empty( $identical_pending ) ) {
as_schedule_single_action( $timestamp, $hook, $args, 'woocommerce-sales' );
}
};
$schedule( $product->get_date_on_sale_from( 'edit' ), 'wc_product_start_scheduled_sale' );
$schedule( $product->get_date_on_sale_to( 'edit' ), 'wc_product_end_scheduled_sale' );
}