Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make templates fallback methods template-agnostic #46372

Draft
wants to merge 7 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions plugins/woocommerce/changelog/fix-agnostic-fallback-methods
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: tweak
Comment: Refactor block templates fallback methods so they are template-agnostic


30 changes: 17 additions & 13 deletions plugins/woocommerce/src/Blocks/BlockTemplatesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,14 @@ public function get_block_template_fallback( $template, $id, $template_type ) {
$template_name_parts = explode( '//', $id );
$theme = $template_name_parts[0] ?? '';
$slug = $template_name_parts[1] ?? '';
$registered_template = BlockTemplateUtils::get_template( $slug );

if ( empty( $theme ) || empty( $slug ) || ! BlockTemplateUtils::template_is_eligible_for_product_archive_fallback( $slug ) ) {
if ( empty( $theme ) || empty( $slug ) || ! $registered_template || ! isset( $registered_template->fallback_template ) ) {
return null;
}

$wp_query_args = array(
'post_name__in' => array( ProductCatalogTemplate::SLUG, $slug ),
'post_name__in' => array( $registered_template->fallback_template, $slug ),
'post_type' => $template_type,
'post_status' => array( 'auto-draft', 'draft', 'publish', 'trash' ),
'no_found_rows' => true,
Expand All @@ -171,7 +172,7 @@ public function get_block_template_fallback( $template, $id, $template_type ) {
return null;
}

if ( count( $posts ) > 0 && ProductCatalogTemplate::SLUG === $posts[0]->post_name ) {
if ( count( $posts ) > 0 && $registered_template->fallback_template === $posts[0]->post_name ) {
$template = _build_block_template_result_from_post( $posts[0] );

if ( ! is_wp_error( $template ) ) {
Expand Down Expand Up @@ -203,7 +204,7 @@ public function add_archive_product_to_eligible_for_fallback_templates( $templat
$templates_eligible_for_fallback = array_filter(
$template_slugs,
function ( $template_slug ) {
return BlockTemplateUtils::template_is_eligible_for_product_archive_fallback( $template_slug );
return BlockTemplateUtils::template_is_eligible_for_fallback( $template_slug );
}
);

Expand Down Expand Up @@ -255,9 +256,10 @@ public function get_block_file_template( $template, $id, $template_type ) {
list( $template_id, $template_slug ) = $template_name_parts;

// If the theme has an archive-product.html template, but not a taxonomy-product_cat/tag/attribute.html template let's use the themes archive-product.html template.
if ( BlockTemplateUtils::template_is_eligible_for_product_archive_fallback_from_theme( $template_slug ) ) {
$template_path = BlockTemplateUtils::get_theme_template_path( ProductCatalogTemplate::SLUG );
$template_object = BlockTemplateUtils::create_new_block_template_object( $template_path, $template_type, $template_slug, true );
if ( BlockTemplateUtils::template_is_eligible_for_fallback_from_theme( $template_slug ) ) {
$registered_template = BlockTemplateUtils::get_template( $template_slug );
$template_path = BlockTemplateUtils::get_theme_template_path( $registered_template->fallback_template );
$template_object = BlockTemplateUtils::create_new_block_template_object( $template_path, $template_type, $template_slug, true );
return BlockTemplateUtils::build_template_result_from_file( $template_object, $template_type );
}

Expand Down Expand Up @@ -452,7 +454,7 @@ function ( $template ) use ( $template_slug ) {
continue;
}

if ( BlockTemplateUtils::template_is_eligible_for_product_archive_fallback_from_db( $template_slug, $already_found_templates ) ) {
if ( BlockTemplateUtils::template_is_eligible_for_fallback_from_db( $template_slug, $already_found_templates ) ) {
$template = clone BlockTemplateUtils::get_fallback_template_from_db( $template_slug, $already_found_templates );
$template_id = explode( '//', $template->id );
$template->id = $template_id[0] . '//' . $template_slug;
Expand All @@ -464,16 +466,18 @@ function ( $template ) use ( $template_slug ) {
}

// If the theme has an archive-product.html template, but not a taxonomy-product_cat/tag/attribute.html template let's use the themes archive-product.html template.
if ( BlockTemplateUtils::template_is_eligible_for_product_archive_fallback_from_theme( $template_slug ) ) {
$template_file = BlockTemplateUtils::get_theme_template_path( ProductCatalogTemplate::SLUG );
$templates[] = BlockTemplateUtils::create_new_block_template_object( $template_file, $template_type, $template_slug, true );
if ( BlockTemplateUtils::template_is_eligible_for_fallback_from_theme( $template_slug ) ) {
$registered_template = BlockTemplateUtils::get_template( $template_slug );
$template_file = BlockTemplateUtils::get_theme_template_path( $registered_template->fallback_template );
$templates[] = BlockTemplateUtils::create_new_block_template_object( $template_file, $template_type, $template_slug, true );
continue;
}

// At this point the template only exists in the Blocks filesystem, if is a taxonomy-product_cat/tag/attribute.html template
// let's use the archive-product.html template from Blocks.
if ( BlockTemplateUtils::template_is_eligible_for_product_archive_fallback( $template_slug ) ) {
$template_file = $this->get_template_path_from_woocommerce( ProductCatalogTemplate::SLUG );
$registered_template = BlockTemplateUtils::get_template( $template_slug );
if ( $registered_template && isset( $registered_template->fallback_template ) ) {
$template_file = $this->get_template_path_from_woocommerce( $registered_template->fallback_template );
$templates[] = BlockTemplateUtils::create_new_block_template_object( $template_file, $template_type, $template_slug, false );
continue;
}
Expand Down
52 changes: 27 additions & 25 deletions plugins/woocommerce/src/Blocks/Utils/BlockTemplateUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -505,15 +505,15 @@ public static function supports_block_templates( $template_type = 'wp_template'
}

/**
* Checks if we can fall back to the `archive-product` template for a given slug.
* Checks if we can fall back to a different template for a given slug.
*
* `taxonomy-product_cat`, `taxonomy-product_tag`, `taxonomy-product_attribute` templates can
* generally use the `archive-product` as a fallback if there are no specific overrides.
*
* @param string $template_slug Slug to check for fallbacks.
* @return boolean
*/
public static function template_is_eligible_for_product_archive_fallback( $template_slug ) {
public static function template_is_eligible_for_fallback( $template_slug ) {
$registered_template = self::get_template( $template_slug );
if ( $registered_template && isset( $registered_template->fallback_template ) ) {
return ProductCatalogTemplate::SLUG === $registered_template->fallback_template;
Expand All @@ -528,20 +528,21 @@ public static function template_is_eligible_for_product_archive_fallback( $templ
* @param array $db_templates Templates that have already been found on the db.
* @return boolean
*/
public static function template_is_eligible_for_product_archive_fallback_from_db( $template_slug, $db_templates ) {
$eligible_for_fallback = self::template_is_eligible_for_product_archive_fallback( $template_slug );
if ( ! $eligible_for_fallback ) {
return false;
}
public static function template_is_eligible_for_fallback_from_db( $template_slug, $db_templates ) {
$registered_template = self::get_template( $template_slug );

$array_filter = array_filter(
$db_templates,
function ( $template ) use ( $template_slug ) {
return ProductCatalogTemplate::SLUG === $template->slug;
}
);
if ( $registered_template && isset( $registered_template->fallback_template ) ) {
$array_filter = array_filter(
$db_templates,
function ( $template ) use ( $registered_template ) {
return isset( $registered_template->fallback_template ) && $registered_template->fallback_template === $template->slug;
}
);

return count( $array_filter ) > 0;
}

return count( $array_filter ) > 0;
return false;
}

/**
Expand All @@ -552,14 +553,13 @@ function ( $template ) use ( $template_slug ) {
* @return boolean|object
*/
public static function get_fallback_template_from_db( $template_slug, $db_templates ) {
$eligible_for_fallback = self::template_is_eligible_for_product_archive_fallback( $template_slug );
if ( ! $eligible_for_fallback ) {
return false;
}
$registered_template = self::get_template( $template_slug );

foreach ( $db_templates as $template ) {
if ( ProductCatalogTemplate::SLUG === $template->slug ) {
return $template;
if ( $registered_template && isset( $registered_template->fallback_template ) ) {
foreach ( $db_templates as $template ) {
if ( $registered_template->fallback_template === $template->slug ) {
return $template;
}
}
}

Expand All @@ -575,10 +575,12 @@ public static function get_fallback_template_from_db( $template_slug, $db_templa
* @param string $template_slug Slug to check for fallbacks.
* @return boolean
*/
public static function template_is_eligible_for_product_archive_fallback_from_theme( $template_slug ) {
return self::template_is_eligible_for_product_archive_fallback( $template_slug )
public static function template_is_eligible_for_fallback_from_theme( $template_slug ) {
$registered_template = self::get_template( $template_slug );

return $registered_template && isset( $registered_template->fallback_template )
&& ! self::theme_has_template( $template_slug )
&& self::theme_has_template( ProductCatalogTemplate::SLUG );
&& self::theme_has_template( $registered_template->fallback_template );
}

/**
Expand All @@ -604,7 +606,7 @@ public static function set_has_theme_file_if_fallback_is_available( $query_resul
$query_result_template->slug === $template->slug
&& $query_result_template->theme === $template->theme
) {
if ( self::template_is_eligible_for_product_archive_fallback_from_theme( $template->slug ) ) {
if ( self::template_is_eligible_for_fallback_from_theme( $template->slug ) ) {
$query_result_template->has_theme_file = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected function setUp(): void {
}

/**
* Provides data for testing template_is_eligible_for_product_archive_fallback.
* Provides data for testing template_is_eligible_for_fallback functions.
*/
public function provideFallbackData() {
return array(
Expand All @@ -50,39 +50,39 @@ public function provideFallbackData() {
}

/**
* Test template_is_eligible_for_product_archive_fallback.
* Test template_is_eligible_for_fallback.
*
* @param string $input The template slug.
* @param bool $expected The expected result.
*
* @dataProvider provideFallbackData
*/
public function test_template_is_eligible_for_product_archive_fallback( $input, $expected ) {
$this->assertEquals( $expected, BlockTemplateUtils::template_is_eligible_for_product_archive_fallback( $input ) );
public function test_template_is_eligible_for_fallback( $input, $expected ) {
$this->assertEquals( $expected, BlockTemplateUtils::template_is_eligible_for_fallback( $input ) );
}

/**
* Test template_is_eligible_for_product_archive_fallback_from_db when the template is not eligible.
* Test template_is_eligible_for_fallback_from_db when the template is not eligible.
*/
public function test_template_is_eligible_for_product_archive_fallback_from_db_no_eligible_template() {
$this->assertEquals( false, BlockTemplateUtils::template_is_eligible_for_product_archive_fallback_from_db( 'single-product', array() ) );
public function test_template_is_eligible_for_fallback_from_db_no_eligible_template() {
$this->assertEquals( false, BlockTemplateUtils::template_is_eligible_for_fallback_from_db( 'single-product', array() ) );
}

/**
* Test template_is_eligible_for_product_archive_fallback_from_db when the template is eligible but not in the db.
* Test template_is_eligible_for_fallback_from_db when the template is eligible but not in the db.
*/
public function test_template_is_eligible_for_product_archive_fallback_from_db_eligible_template_empty_db() {
$this->assertEquals( false, BlockTemplateUtils::template_is_eligible_for_product_archive_fallback_from_db( 'taxonomy-product_cat', array() ) );
public function test_template_is_eligible_for_fallback_from_db_eligible_template_empty_db() {
$this->assertEquals( false, BlockTemplateUtils::template_is_eligible_for_fallback_from_db( 'taxonomy-product_cat', array() ) );
}

/**
* Test template_is_eligible_for_product_archive_fallback_from_db when the template is eligible and in the db.
* Test template_is_eligible_for_fallback_from_db when the template is eligible and in the db.
*/
public function test_template_is_eligible_for_product_archive_fallback_from_db_eligible_template_custom_in_the_db() {
public function test_template_is_eligible_for_fallback_from_db_eligible_template_custom_in_the_db() {
$db_templates = array(
(object) array( 'slug' => 'archive-product' ),
);
$this->assertEquals( true, BlockTemplateUtils::template_is_eligible_for_product_archive_fallback_from_db( 'taxonomy-product_cat', $db_templates ) );
$this->assertEquals( true, BlockTemplateUtils::template_is_eligible_for_fallback_from_db( 'taxonomy-product_cat', $db_templates ) );
}

/**
Expand Down