namespace Automattic\WooCommerce\Blocks\Utils;
use InvalidArgumentException;
use Automattic\WooCommerce\Blocks\Package;
use Automattic\WooCommerce\Blocks\Domain\Services\Hydration;
* Manages the registration of interactivity config and state that is commonly shared by WooCommerce blocks.
* Initialization only happens on the first call to load_store_config.
* This is a private API and may change in future versions.
class BlocksSharedState {
* The consent statement for using private APIs of this class.
private static string $consent_statement = 'I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WooCommerce';
* The namespace for the config.
private static string $settings_namespace = 'woocommerce';
* Whether the core config has been registered.
private static bool $core_config_registered = false;
private static ?array $blocks_shared_cart_state = null;
* Prevent caching on certain pages.
private static function prevent_cache(): void {
\WC_Cache_Helper::set_nocache_constants();
* Check that the consent statement was passed.
* @param string $consent_statement The consent statement string.
* @throws InvalidArgumentException If the statement does not match.
private static function check_consent( string $consent_statement ): bool {
if ( $consent_statement !== self::$consent_statement ) {
throw new InvalidArgumentException( 'This method cannot be called without consenting the API may change.' );
* Load store config (currency, locale, core data) into interactivity config.
* @param string $consent_statement The consent statement string.
* @throws InvalidArgumentException If consent statement doesn't match.
public static function load_store_config( string $consent_statement ): void {
self::check_consent( $consent_statement );
if ( self::$core_config_registered ) {
self::$core_config_registered = true;
wp_interactivity_config( self::$settings_namespace, self::get_currency_data() );
wp_interactivity_config( self::$settings_namespace, self::get_locale_data() );
* Load cart state into interactivity state.
* @param string $consent_statement The consent statement string.
* @throws InvalidArgumentException If consent statement doesn't match.
public static function load_cart_state( string $consent_statement ): void {
self::check_consent( $consent_statement );
if ( null === self::$blocks_shared_cart_state ) {
$cart_exists = isset( WC()->cart );
$cart_has_contents = $cart_exists && ! WC()->cart->is_empty();
$cart_response = Package::container()->get( Hydration::class )->get_rest_api_response_data( '/wc/store/v1/cart' );
self::$blocks_shared_cart_state = $cart_response['body'] ?? array();
self::$blocks_shared_cart_state = array();
if ( $cart_has_contents ) {
'cart' => self::$blocks_shared_cart_state,
'nonce' => wp_create_nonce( 'wc_store_api' ),
'restUrl' => get_rest_url(),
* Get currency data to include in settings.
private static function get_currency_data(): array {
$currency = get_woocommerce_currency();
'precision' => wc_get_price_decimals(),
'symbol' => html_entity_decode( get_woocommerce_currency_symbol( $currency ) ),
'symbolPosition' => get_option( 'woocommerce_currency_pos' ),
'decimalSeparator' => wc_get_price_decimal_separator(),
'thousandSeparator' => wc_get_price_thousand_separator(),
'priceFormat' => html_entity_decode( get_woocommerce_price_format() ),
* Get locale data to include in settings.
private static function get_locale_data(): array {
'siteLocale' => get_locale(),
'userLocale' => get_user_locale(),
'weekdaysShort' => array_values( $wp_locale->weekday_abbrev ),
* Load placeholder image into interactivity config.
* @param string $consent_statement The consent statement string.
* @throws InvalidArgumentException If consent statement doesn't match.
public static function load_placeholder_image( string $consent_statement ): void {
self::check_consent( $consent_statement );
self::$settings_namespace,
array( 'placeholderImgSrc' => wc_placeholder_img_src() )
* Get cart errors formatted as notices for the store-notices interactivity store.
* Returns errors from the hydrated cart state in the format expected by
* the store-notices store context.
* @param string $consent_statement The consent statement string.
* @return array Array of notices with id, notice, type, and dismissible keys.
* @throws InvalidArgumentException If consent statement doesn't match.
public static function get_cart_error_notices( string $consent_statement ): array {
self::check_consent( $consent_statement );
// Ensure cart state is loaded so this method works independently.
if ( null === self::$blocks_shared_cart_state ) {
self::load_cart_state( $consent_statement );
$errors = self::$blocks_shared_cart_state['errors'] ?? array();
foreach ( $errors as $error ) {
'id' => wp_unique_id( 'store-notice-' ),
'notice' => $error['message'] ?? '',