ound', ), ), 'woocommerce_archive_description' => array( 'block_name' => 'core/term-description', 'position' => 'before', 'hooked' => array( 'woocommerce_taxonomy_archive_description' => 10, 'woocommerce_product_archive_description' => 10, ), ), ); } /** * Check if current page is a product archive template. */ private function is_archive_template() { return is_shop() || is_product_taxonomy(); } /** * Loop through inner blocks recursively to find the Products blocks that * inherits query from template. * * @param array $block Parsed block data. */ private function inner_blocks_walker( &$block ) { if ( $this->is_products_block_with_inherit_query( $block ) ) { $this->inject_attribute( $block ); $this->remove_default_hooks(); } if ( ! empty( $block['innerBlocks'] ) ) { array_walk( $block['innerBlocks'], array( $this, 'inner_blocks_walker' ) ); } } /** * Restore default hooks except the ones that are not supposed to be re-added. */ private function restore_default_hooks() { foreach ( $this->hook_data as $hook => $data ) { if ( ! isset( $data['hooked'] ) ) { continue; } foreach ( $data['hooked'] as $callback => $priority ) { if ( ! in_array( $callback, $data['permanently_removed_actions'] ?? [], true ) ) { add_action( $hook, $callback, $priority ); } } } } /** * Check if the block is a Products block that inherits query from template. * * @param array $block Parsed block data. */ private function is_products_block_with_inherit_query( $block ) { return 'core/query' === $block['blockName'] && isset( $block['attrs']['namespace'] ) && 'woocommerce/product-query' === $block['attrs']['namespace'] && isset( $block['attrs']['query']['inherit'] ) && $block['attrs']['query']['inherit']; } /** * Recursively inject the custom attribute to all nested blocks. * * @param array $block Parsed block data. */ private function inject_attribute( &$block ) { $block['attrs']['isInherited'] = 1; if ( ! empty( $block['innerBlocks'] ) ) { array_walk( $block['innerBlocks'], array( $this, 'inject_attribute' ) ); } } }