Automattic\WooCommerce\Blocks\BlockTypes

SavedForLater::renderprotectedWC 1.0

Render the block.

Метод класса: SavedForLater{}

Хуков нет.

Возвращает

Строку. Rendered block type output.

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

// protected - в коде основоного (родительского) или дочернего класса
$result = $this->render( $attributes, $content, $block );
$attributes(массив) (обязательный)
Block attributes.
$content(строка) (обязательный)
Block content.
$block(WP_Block) (обязательный)
Block instance.

Код SavedForLater::render() WC 11.0.1

protected function render( $attributes, $content, $block ) {
	// Guests have no personal list — bail before enqueuing assets or seeding state.
	if ( ! is_user_logged_in() ) {
		return '';
	}

	// Set from render() (not Cart::enqueue_data via has_block()) so it works when this
	// block is auto-injected via the Block Hooks API and isn't in stored post_content.
	if ( wc_get_container()->get( LegacyProxy::class )->call_function( 'is_cart' ) ) {
		$this->asset_data_registry->add( 'cartPageHasSavedForLater', true );
	}

	// Clamp to the 2-6 range the SCSS `@for $i from 2 through 6` loop and
	// the editor `RangeControl` both support. `absint()` first defends
	// against a code-editor override (the attribute can be set to any
	// JSON value there); the `min`/`max` then keep the value within the
	// range where a `&.columns-#{$i}` rule actually exists.
	$column_count = min( 6, max( 2, absint( $attributes['columnCount'] ?? 5 ) ) );

	wp_enqueue_script_module( $this->get_full_block_name() );

	$consent = 'I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WooCommerce';
	BlocksSharedState::load_store_config( $consent );
	BlocksSharedState::load_placeholder_image( $consent );
	// `Move to cart` calls into the shared cart store, which expects
	// `state.cart.items` and friends. Without this load the cart store
	// would have no hydrated cart and the action would throw on the
	// first click.
	BlocksSharedState::load_cart_state( $consent );

	$items = $this->prefetch_items();

	// Seed the shared shopper-lists store with the rest URL, the
	// pre-fetched items, and a starter nonce. The starter nonce is
	// what the cart store also seeds via `state.nonce` — the JS layer
	// keeps it fresh by reading the `Nonce` response header on every
	// subsequent request, so this is just the bootstrap value (and
	// avoids deadlocking mutations that await `isNonceReady` before
	// any GET has fired).
	wp_interactivity_state(
		'woocommerce/shopper-lists',
		array(
			'restUrl' => get_rest_url(),
			'nonce'   => wp_create_nonce( 'wc_store_api' ),
			'lists'   => array(
				self::LIST_SLUG => array(
					'items'     => $items,
					'isLoading' => false,
				),
			),
		)
	);

	// Templates flow through `wp_interactivity_config` so the JS-side
	// getters can interpolate them (`%d`, `%s`). Visible strings (empty
	// state, error, action label) are rendered server-side and toggled
	// with directives, so they don't need to ride here too.
	wp_interactivity_config(
		'woocommerce/saved-for-later',
		array(
			'quantityLabelTemplate' => $this->get_quantity_label_template(),
			'removeLabelTemplate'   => $this->get_remove_label_template(),
		)
	);

	// `hasShownItems` seeds the per-block context so the empty message
	// stays hidden for new shoppers who land on a page with nothing
	// saved. The JS-side watcher flips it to `true` the first time the
	// list has any items (whether that's the SSR seed or a runtime add
	// via "Save for later"), and `state.isEmpty` only flips on when the
	// flag is set *and* the list is currently empty. The flag lives in
	// the per-block context, so it naturally resets on every full page
	// load — no extra Store API field or persisted flag needed.
	// `data-wp-context---notices` seeds the store-notices namespace
	// alongside the block's own context on the same wrapper.
	$wrapper_attributes = array(
		'class'                     => 'wc-block-saved-for-later',
		'data-wp-interactive'       => 'woocommerce/saved-for-later',
		'data-wp-context'           => (string) wp_json_encode(
			array(
				'hasShownItems' => ! empty( $items ),
				// `stdClass` so it serialises as `{}`, not `[]` —
				// iAPI's reactive proxy only fires updates on object
				// writes, not array expandos.
				'pendingKeys'   => new \stdClass(),
			)
		),
		'data-wp-context---notices' => 'woocommerce/store-notices::' . (string) wp_json_encode( array( 'notices' => array() ) ),
		'data-wp-watch'             => 'callbacks.trackShownItems',
	);

	$list_class = sprintf( 'wc-block-saved-for-later__list columns-%d', $column_count );

	$ul_inner    = $this->render_template_markup() . $this->render_items_markup( $items ) . $this->render_empty_markup();
	$before_list = $this->render_header_markup( $content, empty( $items ) ) . ShopperListRenderer::render_interactivity_notices_region( 'wc-block-saved-for-later__notices' );

	return ShopperListRenderer::render_grid_wrapper( $wrapper_attributes, $list_class, $ul_inner, $before_list );
}