Automattic\WooCommerce\Internal\PushNotifications\Services

PendingNotificationStore{}WC 10.7.0

Store that collects notifications during a request and dispatches them all on shutdown via the InternalNotificationDispatcher. Should be accessed from the container (wc_get_container) to ensure store is shared by all usage.

Notifications are keyed by {type}_{resource_id} (with blog ID from get_current_blog_id()) to prevent duplicates within a single request.

No Hooks.

Usage

$PendingNotificationStore = new PendingNotificationStore();
// use class methods

Methods

  1. public add( Notification $notification )
  2. public count()
  3. public dispatch_all()
  4. public get_all()
  5. public init( InternalNotificationDispatcher $dispatcher )
  6. public register()

Changelog

Since 10.7.0 Introduced.

PendingNotificationStore{} code WC 10.7.0

class PendingNotificationStore {
	/**
	 * Whether the store is enabled and accepting notifications.
	 *
	 * @var bool
	 */
	private bool $enabled = false;

	/**
	 * The dispatcher that will be used to send notifications on shutdown.
	 *
	 * @var InternalNotificationDispatcher
	 *
	 * @phpstan-ignore property.onlyWritten (this will be read when the loopback
	 * controller is added)
	 */
	private InternalNotificationDispatcher $dispatcher;

	/**
	 * Pending notifications keyed by identifier.
	 *
	 * @var array<string, Notification>
	 */
	private array $pending = array();

	/**
	 * Whether the shutdown hook has been registered.
	 *
	 * @var bool
	 */
	private bool $shutdown_registered = false;

	/**
	 * Initialize dependencies.
	 *
	 * @internal
	 *
	 * @param InternalNotificationDispatcher $dispatcher The dispatcher to use on shutdown.
	 *
	 * @since 10.7.0
	 */
	final public function init( InternalNotificationDispatcher $dispatcher ): void {
		$this->dispatcher = $dispatcher;
	}

	/**
	 * Enables the store so it accepts notifications.
	 *
	 * Called from PushNotifications::on_init() after enablement checks pass.
	 *
	 * @return void
	 *
	 * @since 10.7.0
	 */
	public function register(): void {
		$this->enabled = true;
	}

	/**
	 * Adds a notification to the pending store.
	 *
	 * Duplicate notifications (same type and resource ID) within a single
	 * request are silently ignored. The shutdown hook is registered on the
	 * first call.
	 *
	 * @param Notification $notification The notification to add.
	 * @return void
	 *
	 * @since 10.7.0
	 */
	public function add( Notification $notification ): void {
		if ( ! $this->enabled ) {
			return;
		}

		$key = $notification->get_identifier();

		if ( isset( $this->pending[ $key ] ) ) {
			return;
		}

		$this->pending[ $key ] = $notification;

		if ( ! $this->shutdown_registered ) {
			add_action( 'shutdown', array( $this, 'dispatch_all' ) );
			$this->shutdown_registered = true;
		}
	}

	/**
	 * Dispatches all pending notifications via the loopback endpoint.
	 *
	 * Called on shutdown. Sends all pending notifications through the
	 * InternalNotificationDispatcher, then clears the store.
	 *
	 * @return void
	 *
	 * @since 10.7.0
	 */
	public function dispatch_all(): void {
		if ( empty( $this->pending ) ) {
			return;
		}

		/**
		 * Fires when pending push notifications are ready to be dispatched.
		 *
		 * @param Notification[] $notifications The notifications to dispatch.
		 *
		 * @since 10.7.0
		 *
		 * The call to dispatch the notifications will go here when the
		 * receiving controller has been added.
		 */

		/**
		 * Store is single-use per request lifecycle, so disable it and clear
		 * pending notifications.
		 */
		$this->enabled = false;
		$this->pending = array();
	}

	/**
	 * Returns the number of pending notifications.
	 *
	 * @return int
	 *
	 * @since 10.7.0
	 */
	public function count(): int {
		return count( $this->pending );
	}

	/**
	 * Returns all pending notifications.
	 *
	 * @return Notification[]
	 *
	 * @since 10.7.0
	 */
	public function get_all(): array {
		return array_values( $this->pending );
	}
}