<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[59951] trunk: Editor: Fix unexpected behavior due to conflicting custom block template.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/59951">59951</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/59951","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>flixos90</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2025-03-07 17:53:37 +0000 (Fri, 07 Mar 2025)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Editor: Fix unexpected behavior due to conflicting custom block template.
This changeset fixes both a visual and functional bug related to template selection in the editor that occurred when having a custom block template registered that was using the same slug as another block template already registered by the theme, including the default block templates.
Props aljullu, antonvlasenko, apermo, audrasjb, azaozz, ntsekouras.
Fixes <a href="https://core.trac.wordpress.org/ticket/62319">#62319</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesblocktemplateutilsphp">trunk/src/wp-includes/block-template-utils.php</a></li>
<li><a href="#trunktestsphpunittestsblocksgetBlockTemplatesphp">trunk/tests/phpunit/tests/blocks/getBlockTemplates.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesblocktemplateutilsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/block-template-utils.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/block-template-utils.php 2025-03-07 16:20:04 UTC (rev 59950)
+++ trunk/src/wp-includes/block-template-utils.php 2025-03-07 17:53:37 UTC (rev 59951)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1185,9 +1185,35 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * over the theme-provided ones, so we skip querying and building them.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> $query['slug__not_in'] = wp_list_pluck( $query_result, 'slug' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $template_files = _get_block_templates_files( $template_type, $query );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*
+ * We need to unset the post_type query param because some templates
+ * would be excluded otherwise, like `page.html` when looking for
+ * `page` templates. We need all templates so we can exclude duplicates
+ * from plugin-registered templates.
+ * See: https://github.com/WordPress/gutenberg/issues/65584
+ */
+ $template_files_query = $query;
+ unset( $template_files_query['post_type'] );
+ $template_files = _get_block_templates_files( $template_type, $template_files_query );
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $template_files as $template_file ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $query_result[] = _build_block_template_result_from_file( $template_file, $template_type );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the query doesn't specify a post type, or it does and the template matches the post type, add it.
+ if (
+ ! isset( $query['post_type'] ) ||
+ (
+ isset( $template_file['postTypes'] ) &&
+ in_array( $query['post_type'], $template_file['postTypes'], true )
+ )
+ ) {
+ $query_result[] = _build_block_template_result_from_file( $template_file, $template_type );
+ } elseif ( ! isset( $template_file['postTypes'] ) ) {
+ // The custom templates with no associated post types are available for all post types as long
+ // as they are not default templates.
+ $candidate = _build_block_template_result_from_file( $template_file, $template_type );
+ $default_template_types = get_default_block_template_types();
+ if ( ! isset( $default_template_types[ $candidate->slug ] ) ) {
+ $query_result[] = $candidate;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( 'wp_template' === $template_type ) {
</span></span></pre></div>
<a id="trunktestsphpunittestsblocksgetBlockTemplatesphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/blocks/getBlockTemplates.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/blocks/getBlockTemplates.php 2025-03-07 16:20:04 UTC (rev 59950)
+++ trunk/tests/phpunit/tests/blocks/getBlockTemplates.php 2025-03-07 17:53:37 UTC (rev 59951)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -228,4 +228,64 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * @dataProvider data_get_block_templates_should_not_leak_plugin_registered_templates_with_default_post_type_slugs
+ * @ticket 62319
+ *
+ * @covers ::get_block_templates
+ *
+ * @param string $template_slug Default slug for the post type.
+ * @param string $post_type Post type for query.
+ * @param array $expected Expected template IDs.
+ */
+ public function test_get_block_templates_should_not_leak_plugin_registered_templates_with_default_post_type_slugs( $template_slug, $post_type, $expected ) {
+ $template_name = 'test-plugin//' . $template_slug;
+ $template_args = array(
+ 'content' => 'Template content',
+ 'title' => 'Test Template for ' . $post_type,
+ 'description' => 'Description of test template',
+ 'post_types' => array( $post_type ),
+ );
+ register_block_template( $template_name, $template_args );
+
+ $templates = get_block_templates( array( 'post_type' => $post_type ) );
+
+ $this->assertSameSets(
+ $expected,
+ $this->get_template_ids( $templates )
+ );
+
+ unregister_block_template( $template_name );
+ }
+
+ /**
+ * Data provider.
+ *
+ * Make sure that plugin-registered templates with default post type slugs (ie: `single` or `page`)
+ * don't leak into `get_block_templates()`.
+ * See: https://core.trac.wordpress.org/ticket/62319.
+ *
+ * @return array
+ */
+ public function data_get_block_templates_should_not_leak_plugin_registered_templates_with_default_post_type_slugs() {
+ return array(
+ 'post' => array(
+ 'template_slug' => 'single',
+ 'post_type' => 'post',
+ 'expected' => array(
+ 'block-theme//custom-hero-template',
+ 'block-theme//custom-single-post-template',
+ ),
+ ),
+ 'page' => array(
+ 'template_slug' => 'page',
+ 'post_type' => 'page',
+ 'expected' => array(
+ 'block-theme//custom-hero-template',
+ 'block-theme//page-home',
+ ),
+ ),
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>
</body>
</html>