WooCommerce Code Reference

StoredStateSetupForProducts.php

Source code

<?php
/**
 * Handles stored state setup for products.
 */

namespace Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors;

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine;

/**
 * Handles stored state setup for products.
 */
class StoredStateSetupForProducts {
	const ASYNC_RUN_REMOTE_NOTIFICATIONS_ACTION_NAME =
		'woocommerce_admin/stored_state_setup_for_products/async/run_remote_notifications';

	/**
	 * Initialize the class via the admin_init hook.
	 */
	public static function admin_init() {
		add_action( 'product_page_product_importer', array( __CLASS__, 'run_on_product_importer' ) );
		add_action( 'transition_post_status', array( __CLASS__, 'run_on_transition_post_status' ), 10, 3 );
	}

	/**
	 * Initialize the class via the init hook.
	 *
	 * @internal
	 */
	final public static function init() {
		add_action( self::ASYNC_RUN_REMOTE_NOTIFICATIONS_ACTION_NAME, array( __CLASS__, 'run_remote_notifications' ) );
	}

	/**
	 * Run the remote notifications engine. This is triggered by
	 * action-scheduler after a product is added. It also cleans up from
	 * setting the product count increment.
	 */
	public static function run_remote_notifications() {
		RemoteInboxNotificationsEngine::run();
	}

	/**
	 * Set initial stored state values.
	 *
	 * @param object $stored_state The stored state.
	 *
	 * @return object The stored state.
	 */
	public static function init_stored_state( $stored_state ) {
		$stored_state->there_were_no_products = ! self::are_there_products();
		$stored_state->there_are_now_products = ! $stored_state->there_were_no_products;

		return $stored_state;
	}

	/**
	 * Are there products query.
	 *
	 * @return bool
	 */
	private static function are_there_products() {
		$query    = new \WC_Product_Query(
			array(
				'limit'    => 1,
				'paginate' => true,
				'return'   => 'ids',
				'status'   => array( 'publish' ),
			)
		);
		$products = $query->get_products();
		$count    = $products->total;

		return $count > 0;
	}

	/**
	 * Runs on product importer steps.
	 */
	public static function run_on_product_importer() {
		// We're only interested in when the importer completes.
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		if ( ! isset( $_REQUEST['step'] ) ) {
			return;
		}
		if ( 'done' !== $_REQUEST['step'] ) {
			return;
		}
		// phpcs:enable

		self::update_stored_state_and_possibly_run_remote_notifications();
	}

	/**
	 * Runs when a post status transitions, but we're only interested if it is
	 * a product being published.
	 *
	 * @param string $new_status The new status.
	 * @param string $old_status The old status.
	 * @param Post   $post       The post.
	 */
	public static function run_on_transition_post_status( $new_status, $old_status, $post ) {
		if (
			'product' !== $post->post_type ||
			'publish' !== $new_status
		) {
			return;
		}

		self::update_stored_state_and_possibly_run_remote_notifications();
	}

	/**
	 * Enqueues an async action (using action-scheduler) to run remote
	 * notifications.
	 */
	private static function update_stored_state_and_possibly_run_remote_notifications() {
		$stored_state = RemoteInboxNotificationsEngine::get_stored_state();
		// If the stored_state is the same, we don't need to run remote notifications to avoid unnecessary action scheduling.
		if ( true === $stored_state->there_are_now_products ) {
			return;
		}

		$stored_state->there_are_now_products = true;
		RemoteInboxNotificationsEngine::update_stored_state( $stored_state );

		// Run self::run_remote_notifications asynchronously.
		as_enqueue_async_action( self::ASYNC_RUN_REMOTE_NOTIFICATIONS_ACTION_NAME );
	}
}