processor.
* @param array $block The block details.
*/
private function handle_block_dimensions( $p, $block ) {
if ( isset( $block['attrs']['dimensions'] ) && isset( $block['attrs']['dimensions']['widthType'] ) ) {
if ( 'fixed' === $block['attrs']['dimensions']['widthType'] ) {
$this->set_fixed_width_style( $p, $block['attrs']['dimensions']['fixedWidth'] );
}
}
}
/**
* Add interactive links to all anchors inside the Query Pagination block.
* This enabled client-side navigation for the product collection block.
*
* @param string $block_content The block content.
* @param array $block The full block, including name and attributes.
* @param \WP_Block $instance The block instance.
*/
public function add_navigation_link_directives( $block_content, $block, $instance ) {
$query_context = $instance->context['query'] ?? array();
$is_product_collection_block = $query_context['isProductCollectionBlock'] ?? false;
$query_id = $instance->context['queryId'] ?? null;
$parsed_query_id = $this->parsed_block['attrs']['queryId'] ?? null;
$is_enhanced_pagination_enabled = ! ( $this->parsed_block['attrs']['forcePageReload'] ?? false );
// Only proceed if the block is a product collection block,
// enhanced pagination is enabled and query IDs match.
if ( $is_product_collection_block && $is_enhanced_pagination_enabled && $query_id === $parsed_query_id ) {
$p = new \WP_HTML_Tag_Processor( $block_content );
$p->next_tag( array( 'class_name' => 'wp-block-query-pagination' ) );
while ( $p->next_tag( 'A' ) ) {
if ( $p->has_class( 'wp-block-query-pagination-next' ) || $p->has_class( 'wp-block-query-pagination-previous' ) ) {
$p->set_attribute( 'data-wp-on--click', 'woocommerce/product-collection::actions.navigate' );
$p->set_attribute(
'data-wp-key',
$p->has_class( 'wp-block-query-pagination-next' )
? 'product-collection-pagination--next'
: 'product-collection-pagination--previous'
);
$p->set_attribute( 'data-wp-watch', 'woocommerce/product-collection::callbacks.prefetch' );
$p->set_attribute( 'data-wp-on--mouseenter', 'woocommerce/product-collection::actions.prefetchOnHover' );
} elseif ( $p->has_class( 'page-numbers' ) ) {
$p->set_attribute( 'data-wp-on--click', 'woocommerce/product-collection::actions.navigate' );
$p->set_attribute( 'data-wp-key', 'product-collection-pagination-numbers--' . $p->get_attribute( 'aria-label' ) );
}
}
return $p->get_updated_html();
}
return $block_content;
}
/**
* Provides the location context to each inner block of the product collection block.
* Hint: Only blocks using the 'query' context will be affected.
*
* The sourceData structure depends on the context type as follows:
* - site: [ ]
* - order: [ 'orderId' => int ]
* - cart: [ 'productIds' => int[] ]
* - archive: [ 'taxonomy' => string, 'termId' => int ]
* - product: [ 'productId' => int ]
*
* @example array(
* 'type' => 'product',
* 'sourceData' => array( 'productId' => 123 ),
* )
*
* @param array $context The block context.
* @return array $context {
* The block context including the product collection location context.
*
* @type array $productCollectionLocation {
* @type string $type The context type. Possible values are 'site', 'order', 'cart', 'archive', 'product'.
* @type array $sourceData The context source data. Can be the product ID of the viewed product, the order ID of the current order viewed, etc. See structure above for more details.
* }
* }
*/
public function extend_context_for_inner_blocks( $context ) {
// Run only on frontend.
// This is needed to avoid SSR renders while in editor. @see https://github.com/woocommerce/woocommerce/issues/45181.
if ( is_admin() || \WC()->is_rest_api_request() ) {
return $context;
}
// Add iapi/provider to inner blocks so they can run this store's Interactivity API actions.
$context['iapi/provider'] = 'woocommerce/product-collection';
// Target only product collection's inner blocks that use the 'query' context.
if ( ! isset( $context['query'] ) || ! isset( $context['query']['isProductCollectionBlock'] ) || ! $context['query']['isProductCollectionBlock'] ) {
return $context;
}
$is_in_single_product = isset( $context['singleProduct'] ) && ! empty( $context['postId'] );
$context['productCollectionLocation'] = $is_in_single_product ? array(
'type' => 'product',
'sourceData' => array(
'productId' => absint( $context['postId'] ),
),
) : $this->get_location_context();
return $context;
}
/**
* Get the global location context.
* Serve as a runtime cache for the location context.
*
* @see ProductCollectionUtils::parse_frontend_location_context()
*
* @return array The location context.
*/
private function get_location_context() {
static $location_context = null;
if ( null === $location_context ) {
$location_context = ProductCollectionUtils::parse_frontend_location_context();
}
return $location_context;
}
}
Fatal error: Uncaught Error: Class 'Automattic\WooCommerce\Blocks\BlockTypes\ProductCollection\Renderer' not found in /var/www/html/declev.store/web/wp-content/plugins/woocommerce/src/Blocks/BlockTypes/ProductCollection/Controller.php:55
Stack trace:
#0 /var/www/html/declev.store/web/wp-content/plugins/woocommerce/src/Blocks/BlockTypes/AbstractBlock.php(71): Automattic\WooCommerce\Blocks\BlockTypes\ProductCollection\Controller->initialize()
#1 /var/www/html/declev.store/web/wp-content/plugins/woocommerce/src/Blocks/BlockTypesController.php(117): Automattic\WooCommerce\Blocks\BlockTypes\AbstractBlock->__construct(Object(Automattic\WooCommerce\Blocks\Assets\Api), Object(Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry), Object(Automattic\WooCommerce\Blocks\Integrations\IntegrationRegistry))
#2 /var/www/html/declev.store/web/wp-includes/class-wp-hook.php(324): Automattic\WooCommerce\Blocks\BlockTypesController->register_blocks('')
#3 /var/www/html/declev.store/web/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filt in /var/www/html/declev.store/web/wp-content/plugins/woocommerce/src/Blocks/BlockTypes/ProductCollection/Controller.php on line 55