Fix custom templates with fallback being incorrectly attributed (https://github.com/woocommerce/woocommerce-blocks/pull/5447)

* Fix custom templates with fallback being incorrectly attributed

Category and tags templates can fallback to the generic archive if, e.g., the theme
provides one for the latter but not for the former. However, since Gutenberg is not
aware of this fallback mechanism, it would incorrectly attribute the custom template
to the user instead of the theme.

Here we are explicitly setting the `has_theme_file` to make sure Gutenberg knows
we do, in fact, have a theme fail (if not what it expects).

Also skip the loop if template is duplicate but has no fallback

Fixes woocommerce/woocommerce-blocks#5441
This commit is contained in:
Lucio Giannotta 2021-12-24 16:15:19 +01:00 committed by GitHub
parent 5036c69638
commit 4d616d7a76
2 changed files with 56 additions and 18 deletions

View File

@ -175,16 +175,10 @@ class BlockTemplatesController {
// @todo: Add apply_filters to _gutenberg_get_template_files() in Gutenberg to prevent duplication of logic.
foreach ( $template_files as $template_file ) {
// Avoid adding the same template if it's already in the array of $query_result.
if (
array_filter(
$query_result,
function( $query_result_template ) use ( $template_file ) {
return $query_result_template->slug === $template_file->slug &&
$query_result_template->theme === $template_file->theme;
}
)
) {
// If we have a template which is eligible for a fallback, we need to explicitly tell Gutenberg that
// it has a theme file (because it is using the fallback template file). And then `continue` to avoid
// adding duplicates.
if ( BlockTemplateUtils::set_has_theme_file_if_fallback_is_available( $query_result, $template_file ) ) {
continue;
}
@ -348,14 +342,7 @@ class BlockTemplatesController {
}
// If the theme has an archive-product.html template, but not a taxonomy-product_cat.html template let's use the themes archive-product.html template.
if ( 'taxonomy-product_cat' === $template_slug && ! BlockTemplateUtils::theme_has_template( 'taxonomy-product_cat' ) && BlockTemplateUtils::theme_has_template( 'archive-product' ) ) {
$template_file = get_stylesheet_directory() . '/' . self::TEMPLATES_DIR_NAME . '/archive-product.html';
$templates[] = BlockTemplateUtils::create_new_block_template_object( $template_file, $template_type, $template_slug, true );
continue;
}
// If the theme has an archive-product.html template, but not a taxonomy-product_tag.html template let's use the themes archive-product.html template.
if ( 'taxonomy-product_tag' === $template_slug && ! BlockTemplateUtils::theme_has_template( 'taxonomy-product_tag' ) && BlockTemplateUtils::theme_has_template( 'archive-product' ) ) {
if ( BlockTemplateUtils::template_is_eligible_for_product_archive_fallback( $template_slug ) ) {
$template_file = get_stylesheet_directory() . '/' . self::TEMPLATES_DIR_NAME . '/archive-product.html';
$templates[] = BlockTemplateUtils::create_new_block_template_object( $template_file, $template_type, $template_slug, true );
continue;

View File

@ -281,4 +281,55 @@ class BlockTemplateUtils {
return true;
}
/**
* Checks if we can fallback to the `archive-product` template for a given slug
*
* `taxonomy-product_cat` and `taxonomy-product_tag` 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 ) {
$eligible_for_fallbacks = array( 'taxonomy-product_cat', 'taxonomy-product_tag' );
return in_array( $template_slug, $eligible_for_fallbacks, true )
&& ! self::theme_has_template( $template_slug )
&& self::theme_has_template( 'archive-product' );
}
/**
* Sets the `has_theme_file` to `true` for templates with fallbacks
*
* There are cases (such as tags and categories) in which fallback templates
* can be used; so, while *technically* the theme doesn't have a specific file
* for them, it is important that we tell Gutenberg that we do, in fact,
* have a theme file (i.e. the fallback one).
*
* **Note:** this function changes the array that has been passed.
*
* It returns `true` if anything was changed, `false` otherwise.
*
* @param array $query_result Array of template objects.
* @param array $template A specific template object which could have a fallback.
*
* @return boolean
*/
public static function set_has_theme_file_if_fallback_is_available( $query_result, $template ) {
foreach ( $query_result as &$query_result_template ) {
if (
$query_result_template->slug === $template->slug
&& $query_result_template->theme === $template->theme
) {
if ( self::template_is_eligible_for_product_archive_fallback( $template->slug ) ) {
$query_result_template->has_theme_file = true;
}
return true;
}
}
return false;
}
}