diff --git a/src/wp-includes/block-template-utils.php b/src/wp-includes/block-template-utils.php index 66c48db7f1305..57c534a04ff11 100644 --- a/src/wp-includes/block-template-utils.php +++ b/src/wp-includes/block-template-utils.php @@ -1326,19 +1326,60 @@ function get_template_hierarchy( $slug, $is_custom = false, $template_prefix = ' } $template_hierarchy = array( $slug ); - // Most default templates don't have `$template_prefix` assigned. - if ( $template_prefix ) { - list( $type ) = explode( '-', $template_prefix ); - // These checks are needed because the `$slug` above is always added. + if ( ! empty( $template_prefix ) ) { + list($type) = explode( '-', $template_prefix ); + // We need these checks because we always add the `$slug` above. if ( ! in_array( $template_prefix, array( $slug, $type ), true ) ) { $template_hierarchy[] = $template_prefix; } if ( $slug !== $type ) { $template_hierarchy[] = $type; } + } else { + $matches = array(); + if ( preg_match( '/^(author|category|archive|tag|page)-(.+)$/', $slug, $matches ) ) { + $template_hierarchy[] = $matches[1]; + } elseif ( preg_match( '/^(single|taxonomy)-(.+)$/', $slug, $matches ) ) { + $type = $matches[1]; + $slug_remaining = $matches[2]; + if ( 'single' === $type ) { + $post_types = get_post_types(); + foreach ( $post_types as $post_type ) { + if ( str_starts_with( $slug_remaining, $post_type ) ) { + // If $slug_remaining is equal to $post_type we have the single-$post_type template. + if ( $slug_remaining === $post_type ) { + $template_hierarchy[] = 'single'; + break; + } + // If $slug_remaining is single-$post_type-$slug template. + if ( str_starts_with( $slug_remaining, $post_type . '-' ) && strlen( $slug_remaining ) > strlen( $post_type ) + 1 ) { + $template_hierarchy[] = "single-$post_type"; + $template_hierarchy[] = 'single'; + break; + } + } + } + } elseif ( 'taxonomy' === $type ) { + $taxonomies = get_taxonomies(); + foreach ( $taxonomies as $taxonomy ) { + if ( str_starts_with( $slug_remaining, $taxonomy ) ) { + // If $slug_remaining is equal to $taxonomy we have the taxonomy-$taxonomy template. + if ( $slug_remaining === $taxonomy ) { + $template_hierarchy[] = 'taxonomy'; + break; + } + // If $slug_remaining is taxonomy-$taxonomy-$term template. + if ( str_starts_with( $slug_remaining, $taxonomy . '-' ) && strlen( $slug_remaining ) > strlen( $taxonomy ) + 1 ) { + $template_hierarchy[] = "taxonomy-$taxonomy"; + $template_hierarchy[] = 'taxonomy'; + break; + } + } + } + } + } } - // Handle `archive` template. if ( str_starts_with( $slug, 'author' ) || @@ -1353,7 +1394,6 @@ function get_template_hierarchy( $slug, $is_custom = false, $template_prefix = ' if ( 'attachment' === $slug ) { $template_hierarchy[] = 'single'; } - // Handle `singular` template. if ( str_starts_with( $slug, 'single' ) || @@ -1362,8 +1402,6 @@ function get_template_hierarchy( $slug, $is_custom = false, $template_prefix = ' ) { $template_hierarchy[] = 'singular'; } - $template_hierarchy[] = 'index'; - return $template_hierarchy; } diff --git a/tests/phpunit/tests/block-templates/getTemplateHierarchy.php b/tests/phpunit/tests/block-templates/getTemplateHierarchy.php index e550b22778417..533885102ade5 100644 --- a/tests/phpunit/tests/block-templates/getTemplateHierarchy.php +++ b/tests/phpunit/tests/block-templates/getTemplateHierarchy.php @@ -8,6 +8,22 @@ */ class Tests_Block_Templates_GetTemplate_Hierarchy extends WP_Block_Templates_UnitTestCase { + public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { + register_post_type( + 'custom_book', + array( + 'public' => true, + 'show_in_rest' => true, + ) + ); + register_taxonomy( 'book_type', 'custom_book' ); + } + + public static function wpTearDownAfterClass() { + unregister_post_type( 'custom_book' ); + unregister_taxonomy( 'book_type' ); + } + /** * @dataProvider data_get_template_hierarchy * @@ -83,14 +99,26 @@ public function data_get_template_hierarchy() { 'args' => array( 'category-fruits', false, 'category' ), 'expected' => array( 'category-fruits', 'category', 'archive', 'index' ), ), + 'single word categories no prefix' => array( + 'args' => array( 'category-fruits', false ), + 'expected' => array( 'category-fruits', 'category', 'archive', 'index' ), + ), 'multi word categories' => array( 'args' => array( 'category-fruits-yellow', false, 'category' ), 'expected' => array( 'category-fruits-yellow', 'category', 'archive', 'index' ), ), + 'multi word categories no prefix' => array( + 'args' => array( 'category-fruits-yellow', false ), + 'expected' => array( 'category-fruits-yellow', 'category', 'archive', 'index' ), + ), 'single word taxonomy and term' => array( 'args' => array( 'taxonomy-books-action', false, 'taxonomy-books' ), 'expected' => array( 'taxonomy-books-action', 'taxonomy-books', 'taxonomy', 'archive', 'index' ), ), + 'single word taxonomy and term no prefix' => array( + 'args' => array( 'taxonomy-books-action', false ), + 'expected' => array( 'taxonomy-books-action', 'taxonomy-books', 'taxonomy', 'archive', 'index' ), + ), 'single word taxonomy and multi word term' => array( 'args' => array( 'taxonomy-books-action-adventure', false, 'taxonomy-books' ), 'expected' => array( 'taxonomy-books-action-adventure', 'taxonomy-books', 'taxonomy', 'archive', 'index' ), @@ -119,6 +147,46 @@ public function data_get_template_hierarchy() { 'args' => array( 'author-rigas', false, 'author' ), 'expected' => array( 'author-rigas', 'author', 'archive', 'index' ), ), + 'multiple word taxonomy no prefix' => array( + 'args' => array( 'taxonomy-book_type-adventure', false ), + 'expected' => array( 'taxonomy-book_type-adventure', 'taxonomy-book_type', 'taxonomy', 'archive', 'index' ), + ), + 'single post type no prefix' => array( + 'args' => array( 'single-custom_book', false ), + 'expected' => array( + 'single-custom_book', + 'single', + 'singular', + 'index', + ), + ), + 'single post and post type no prefix' => array( + 'args' => array( 'single-custom_book-book-1', false ), + 'expected' => array( + 'single-custom_book-book-1', + 'single-custom_book', + 'single', + 'singular', + 'index', + ), + ), + 'page no prefix' => array( + 'args' => array( 'page-hi', false ), + 'expected' => array( + 'page-hi', + 'page', + 'singular', + 'index', + ), + ), + 'post type archive no prefix' => array( + 'args' => array( 'archive-book', false ), + 'expected' => array( + 'archive-book', + 'archive', + 'index', + ), + ), ); } }