Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Fix custom templates with fallback being incorrectly attributed #5447

Merged
merged 5 commits into from
Dec 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 5 additions & 18 deletions src/BlockTemplatesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,16 +175,10 @@ public function add_block_templates( $query_result, $query, $template_type ) {
// @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;
}

Expand Down Expand Up @@ -348,14 +342,7 @@ function ( $template ) use ( $template_slug ) {
}

// 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;
Expand Down
51 changes: 51 additions & 0 deletions src/Utils/BlockTemplateUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -281,4 +281,55 @@ public static function supports_block_templates() {

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;
}
}