diff --git a/plugins/woocommerce/changelog/fix-50055-compatibility-layer-patterns b/plugins/woocommerce/changelog/fix-50055-compatibility-layer-patterns
new file mode 100644
index 00000000000..e6811df2b13
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-50055-compatibility-layer-patterns
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Update the logic that conditionally activates the compatibility layer in WooCommerce block templates so it detects blocks inside patterns
diff --git a/plugins/woocommerce/src/Blocks/Templates/AbstractTemplateCompatibility.php b/plugins/woocommerce/src/Blocks/Templates/AbstractTemplateCompatibility.php
index 3d622a345c2..b06892291c3 100644
--- a/plugins/woocommerce/src/Blocks/Templates/AbstractTemplateCompatibility.php
+++ b/plugins/woocommerce/src/Blocks/Templates/AbstractTemplateCompatibility.php
@@ -61,9 +61,9 @@ abstract class AbstractTemplateCompatibility {
* @since 7.6.0
* @param boolean.
*/
- $is_disabled_compatility_layer = apply_filters( 'woocommerce_disable_compatibility_layer', false );
+ $is_disabled_compatibility_layer = apply_filters( 'woocommerce_disable_compatibility_layer', false );
- if ( $is_disabled_compatility_layer ) {
+ if ( $is_disabled_compatibility_layer ) {
return $block_content;
}
diff --git a/plugins/woocommerce/src/Blocks/Templates/SingleProductTemplate.php b/plugins/woocommerce/src/Blocks/Templates/SingleProductTemplate.php
index 942f807422f..69ef307fc3a 100644
--- a/plugins/woocommerce/src/Blocks/Templates/SingleProductTemplate.php
+++ b/plugins/woocommerce/src/Blocks/Templates/SingleProductTemplate.php
@@ -23,7 +23,7 @@ class SingleProductTemplate extends AbstractTemplate {
*/
public function init() {
add_action( 'template_redirect', array( $this, 'render_block_template' ) );
- add_filter( 'get_block_templates', array( $this, 'update_single_product_content' ), 11, 3 );
+ add_filter( 'get_block_templates', array( $this, 'update_single_product_content' ), 11, 1 );
}
/**
@@ -51,13 +51,31 @@ class SingleProductTemplate extends AbstractTemplate {
if ( ! is_embed() && is_singular( 'product' ) ) {
global $post;
- $valid_slugs = array( self::SLUG );
- if ( 'product' === $post->post_type && $post->post_name ) {
+ $valid_slugs = array( self::SLUG );
+ $single_product_slug = 'product' === $post->post_type && $post->post_name ? 'single-product-' . $post->post_name : '';
+ if ( $single_product_slug ) {
$valid_slugs[] = 'single-product-' . $post->post_name;
}
$templates = get_block_templates( array( 'slug__in' => $valid_slugs ) );
- if ( isset( $templates[0] ) && BlockTemplateUtils::template_has_legacy_template_block( $templates[0] ) ) {
+ if ( count( $templates ) === 0 ) {
+ return;
+ }
+
+ // Use the first template by default.
+ $template = $templates[0];
+
+ // Check if there is a template matching the slug `single-product-{post_name}`.
+ if ( count( $valid_slugs ) > 1 && count( $templates ) > 1 ) {
+ foreach ( $templates as $t ) {
+ if ( $single_product_slug === $t->slug ) {
+ $template = $t;
+ break;
+ }
+ }
+ }
+
+ if ( isset( $template ) && BlockTemplateUtils::template_has_legacy_template_block( $template ) ) {
add_filter( 'woocommerce_disable_compatibility_layer', '__return_true' );
}
@@ -68,12 +86,10 @@ class SingleProductTemplate extends AbstractTemplate {
/**
* Add the block template objects to be used.
*
- * @param array $query_result Array of template objects.
- * @param array $query Optional. Arguments to retrieve templates.
- * @param string $template_type wp_template or wp_template_part.
+ * @param array $query_result Array of template objects.
* @return array
*/
- public function update_single_product_content( $query_result, $query, $template_type ) {
+ public function update_single_product_content( $query_result ) {
$query_result = array_map(
function ( $template ) {
if ( str_contains( $template->slug, self::SLUG ) ) {
diff --git a/plugins/woocommerce/src/Blocks/Templates/SingleProductTemplateCompatibility.php b/plugins/woocommerce/src/Blocks/Templates/SingleProductTemplateCompatibility.php
index 05191bcbdbb..f48d7697798 100644
--- a/plugins/woocommerce/src/Blocks/Templates/SingleProductTemplateCompatibility.php
+++ b/plugins/woocommerce/src/Blocks/Templates/SingleProductTemplateCompatibility.php
@@ -1,6 +1,8 @@
get_registered( $block['attrs']['slug'] );
+ $pattern_blocks = parse_blocks( $pattern['content'] );
+
+ if ( self::has_block_including_patterns( $block_names, $pattern_blocks ) ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
/**
* Returns whether the passed `$template` has the legacy template block.
*
@@ -703,7 +736,13 @@ class BlockTemplateUtils {
* @return boolean
*/
public static function template_has_legacy_template_block( $template ) {
- return has_block( 'woocommerce/legacy-template', $template->content );
+ if ( has_block( 'woocommerce/legacy-template', $template->content ) ) {
+ return true;
+ }
+
+ $blocks = parse_blocks( $template->content );
+
+ return self::has_block_including_patterns( array( 'woocommerce/legacy-template' ), $blocks );
}
/**
diff --git a/plugins/woocommerce/tests/php/src/Blocks/Templates/SingleProductTemplateCompatibilityTests.php b/plugins/woocommerce/tests/php/src/Blocks/Templates/SingleProductTemplateCompatibilityTests.php
index 4ab7388ed9c..e67d08b5563 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/Templates/SingleProductTemplateCompatibilityTests.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/Templates/SingleProductTemplateCompatibilityTests.php
@@ -37,10 +37,10 @@ class SingleProductTemplateCompatibilityTests extends WP_UnitTestCase {
$result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
$expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
- $this->assertEquals( $result_without_withespace, $expected_single_product_template_without_whitespace, '' );
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
}
/**
@@ -72,10 +72,10 @@ class SingleProductTemplateCompatibilityTests extends WP_UnitTestCase {
$result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
$expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
- $this->assertEquals( $result_without_withespace, $expected_single_product_template_without_whitespace, '' );
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
}
/**
@@ -155,10 +155,80 @@ class SingleProductTemplateCompatibilityTests extends WP_UnitTestCase {
$result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
$expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
- $this->assertEquals( $result_without_withespace, $expected_single_product_template_without_whitespace, '' );
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
+ }
+
+ /**
+ * Test that the Single Product Template is wrapped in a div with the correct class if it contains a pattern that contains a block related to the Single Product Template.
+ */
+ public function test_add_compatibility_layer_if_contains_pattern_with_single_product_blocks() {
+ register_block_pattern(
+ 'test-pattern',
+ array(
+ 'title' => 'Test Pattern',
+ 'description' => 'Test Pattern Description',
+ 'content' => '',
+ )
+ );
+
+ $default_single_product_template = '
+
+
+ ';
+
+ $expected_single_product_template = '
+
+
+
+
+
+
+ ';
+
+ $result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
+
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
+ $expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
+
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
+ }
+
+ /**
+ * Test that the Single Product Template is wrapped in a div with the correct class if it contains a pattern that contains an inner block related to the Single Product Template.
+ */
+ public function test_add_compatibility_layer_if_contains_pattern_with_inner_single_product_blocks() {
+ register_block_pattern(
+ 'test-pattern',
+ array(
+ 'title' => 'Test Pattern',
+ 'description' => 'Test Pattern Description',
+ 'content' => '',
+ )
+ );
+
+ $default_single_product_template = '
+
+
+ ';
+
+ $expected_single_product_template = '
+
+
+
+
+
+
+ ';
+
+ $result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
+
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
+ $expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
+
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
}
/**
@@ -222,10 +292,10 @@ class SingleProductTemplateCompatibilityTests extends WP_UnitTestCase {
$result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
$expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
- $this->assertEquals( $result_without_withespace, $expected_single_product_template_without_whitespace, '' );
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
}
/**
@@ -251,10 +321,10 @@ class SingleProductTemplateCompatibilityTests extends WP_UnitTestCase {
$result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
$expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
- $this->assertEquals( $result_without_withespace, $expected_single_product_template_without_whitespace, '' );
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
}
@@ -281,10 +351,10 @@ class SingleProductTemplateCompatibilityTests extends WP_UnitTestCase {
$result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
$expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
- $this->assertEquals( $result_without_withespace, $expected_single_product_template_without_whitespace, '' );
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
}
/**
@@ -322,10 +392,10 @@ class SingleProductTemplateCompatibilityTests extends WP_UnitTestCase {
$result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
$expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
- $this->assertEquals( $result_without_withespace, $expected_single_product_template_without_whitespace, '' );
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
}
/**
@@ -359,10 +429,10 @@ class SingleProductTemplateCompatibilityTests extends WP_UnitTestCase {
$result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
$expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
- $this->assertEquals( $result_without_withespace, $expected_single_product_template_without_whitespace, '' );
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
}
/**
@@ -398,9 +468,9 @@ class SingleProductTemplateCompatibilityTests extends WP_UnitTestCase {
$result = SingleProductTemplateCompatibility::add_compatibility_layer( $default_single_product_template );
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
$expected_single_product_template_without_whitespace = preg_replace( '/\s+/', '', $expected_single_product_template );
- $this->assertEquals( $result_without_withespace, $expected_single_product_template_without_whitespace, '' );
+ $this->assertEquals( $result_without_whitespace, $expected_single_product_template_without_whitespace, '' );
}
}
diff --git a/plugins/woocommerce/tests/php/src/Blocks/Templates/SingleProductTemplateTests.php b/plugins/woocommerce/tests/php/src/Blocks/Templates/SingleProductTemplateTests.php
index 7649173e24a..634df6d181c 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/Templates/SingleProductTemplateTests.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/Templates/SingleProductTemplateTests.php
@@ -11,6 +11,203 @@ use \WP_UnitTestCase;
*/
class SingleProductTemplateTests extends WP_UnitTestCase {
+ /**
+ * Test that the Product Catalog template content isn't updated mistakenly.
+ * In other words, make sure the Single Product template logic doesn't leak
+ * into other templates.
+ *
+ */
+ public function test_dont_update_single_product_content_for_other_templates() {
+ $single_product_template = new SingleProductTemplate();
+ $default_product_catalog_template_content = '
+
+
+ ';
+
+ $template = new \WP_Block_Template();
+ $template->slug = 'archive-product';
+ $template->title = 'Product Catalog';
+ $template->content = $default_product_catalog_template_content;
+ $template->type = 'wp_template';
+
+ $result = $single_product_template->update_single_product_content(
+ array(
+ $template,
+ ),
+ );
+
+ $this->assertEquals(
+ $default_product_catalog_template_content,
+ $result[0]->content
+ );
+ }
+
+ /**
+ * Test that the Single Product template content isn't updated if it
+ * contains the Legacy Template block.
+ *
+ */
+ public function test_dont_update_single_product_content_with_legacy_template() {
+ $single_product_template = new SingleProductTemplate();
+ $default_single_product_template_content = '
+
+
+ ';
+
+ $template = new \WP_Block_Template();
+ $template->slug = 'single-product';
+ $template->title = 'Single Product';
+ $template->content = $default_single_product_template_content;
+ $template->type = 'wp_template';
+
+ $result = $single_product_template->update_single_product_content(
+ array(
+ $template,
+ ),
+ );
+
+ $this->assertEquals(
+ $default_single_product_template_content,
+ $result[0]->content
+ );
+ }
+
+ /**
+ * Test that the Single Product template content is updated if it doesn't
+ * contain the Legacy Template block.
+ *
+ */
+ public function test_update_single_product_content_with_legacy_template() {
+ $single_product_template = new SingleProductTemplate();
+ $default_single_product_template_content = '
+
+
+ ';
+ $expected_single_product_template_content = '
+
+
+
+
+
+
+ ';
+
+ $template = new \WP_Block_Template();
+ $template->slug = 'single-product';
+ $template->title = 'Single Product';
+ $template->content = $default_single_product_template_content;
+ $template->type = 'wp_template';
+
+ $result = $single_product_template->update_single_product_content(
+ array(
+ $template,
+ ),
+ );
+
+ $expected_single_product_template_without_whitespace = preg_replace(
+ '/\s+/',
+ '',
+ $expected_single_product_template_content
+ );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result[0]->content );
+
+ $this->assertEquals(
+ $expected_single_product_template_without_whitespace,
+ $result_without_whitespace
+ );
+ }
+
+ /**
+ * Test that the Single Product template content isn't updated if it
+ * contains a pattern with the Legacy Template block.
+ *
+ */
+ public function test_dont_update_single_product_content_with_legacy_template_inside_a_pattern() {
+ register_block_pattern(
+ 'test-pattern',
+ array(
+ 'title' => 'Test Pattern',
+ 'description' => 'Test Pattern Description',
+ 'content' => '',
+ )
+ );
+ $single_product_template = new SingleProductTemplate();
+ $default_single_product_template_content = '
+
+
+ ';
+
+ $template = new \WP_Block_Template();
+ $template->slug = 'single-product';
+ $template->title = 'Single Product';
+ $template->content = $default_single_product_template_content;
+ $template->type = 'wp_template';
+
+ $result = $single_product_template->update_single_product_content(
+ array(
+ $template,
+ ),
+ );
+
+ $this->assertEquals(
+ $default_single_product_template_content,
+ $result[0]->content
+ );
+ }
+
+ /**
+ * Test that the Single Product template content is updated if it doesn't
+ * contain the Legacy Template block.
+ *
+ */
+ public function test_update_single_product_content_with_legacy_template_inside_a_pattern() {
+ register_block_pattern(
+ 'test-pattern',
+ array(
+ 'title' => 'Test Pattern',
+ 'description' => 'Test Pattern Description',
+ 'content' => '',
+ )
+ );
+ $single_product_template = new SingleProductTemplate();
+ $default_single_product_template_content = '
+
+
+ ';
+ $expected_single_product_template_content = '
+
+
+
+
+
+
+ ';
+
+ $template = new \WP_Block_Template();
+ $template->slug = 'single-product';
+ $template->title = 'Single Product';
+ $template->content = $default_single_product_template_content;
+ $template->type = 'wp_template';
+
+ $result = $single_product_template->update_single_product_content(
+ array(
+ $template,
+ ),
+ );
+
+ $expected_single_product_template_without_whitespace = preg_replace(
+ '/\s+/',
+ '',
+ $expected_single_product_template_content
+ );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result[0]->content );
+
+ $this->assertEquals(
+ $expected_single_product_template_without_whitespace,
+ $result_without_whitespace
+ );
+ }
+
/**
* Test that the password form isn't added to the Single Product Template.
*
@@ -38,7 +235,7 @@ class SingleProductTemplateTests extends WP_UnitTestCase {
$default_single_product_template
);
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
$expected_single_product_template_without_whitespace = preg_replace(
'/\s+/',
'',
@@ -46,9 +243,8 @@ class SingleProductTemplateTests extends WP_UnitTestCase {
);
$this->assertEquals(
- $result_without_withespace,
- $expected_single_product_template_without_whitespace,
- ''
+ $result_without_whitespace,
+ $expected_single_product_template_without_whitespace
);
}
@@ -81,11 +277,11 @@ class SingleProductTemplateTests extends WP_UnitTestCase {
$default_single_product_template
);
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
- $result_without_withespace_without_custom_pwbox_ids = preg_replace(
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace_without_custom_pwbox_ids = preg_replace(
'/pwbox-\d+/',
'',
- $result_without_withespace
+ $result_without_whitespace
);
$expected_single_product_template_without_whitespace = preg_replace(
@@ -101,9 +297,8 @@ class SingleProductTemplateTests extends WP_UnitTestCase {
);
$this->assertEquals(
- $result_without_withespace_without_custom_pwbox_ids,
- $expected_single_product_template_without_whitespace_without_custom_pwbox_ids,
- ''
+ $result_without_whitespace_without_custom_pwbox_ids,
+ $expected_single_product_template_without_whitespace_without_custom_pwbox_ids
);
}
@@ -219,11 +414,11 @@ class SingleProductTemplateTests extends WP_UnitTestCase {
$default_single_product_template
);
- $result_without_withespace = preg_replace( '/\s+/', '', $result );
- $result_without_withespace_without_custom_pwbox_ids = preg_replace(
+ $result_without_whitespace = preg_replace( '/\s+/', '', $result );
+ $result_without_whitespace_without_custom_pwbox_ids = preg_replace(
'/pwbox-\d+/',
'',
- $result_without_withespace
+ $result_without_whitespace
);
$expected_single_product_template_without_whitespace = preg_replace(
@@ -239,9 +434,8 @@ class SingleProductTemplateTests extends WP_UnitTestCase {
);
$this->assertEquals(
- $result_without_withespace_without_custom_pwbox_ids,
- $expected_single_product_template_without_whitespace_without_custom_pwbox_ids,
- ''
+ $result_without_whitespace_without_custom_pwbox_ids,
+ $expected_single_product_template_without_whitespace_without_custom_pwbox_ids
);
}
}