wc_schedule_product_sale_events() │ WC 10.5.0

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.

Хуков нет.

Возвращает

void. Ничего (null).

Использование

wc_schedule_product_sale_events( $product ): void;
$product(WC_Product) (обязательный)
Product object.

Список изменений

С версии 10.5.0 Введена.

Код wc_schedule_product_sale_events() WC 11.2.2

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' );
}