diff --git a/src/wp-includes/block-template-utils.php b/src/wp-includes/block-template-utils.php index a7d5d4aa1141d..893dc868196fd 100644 --- a/src/wp-includes/block-template-utils.php +++ b/src/wp-includes/block-template-utils.php @@ -1255,7 +1255,7 @@ function ( $template ) { $matching_registered_templates ); - $query_result = array_merge( $query_result, $matching_registered_templates ); + $query_result = array_merge( $query_result, array_values( $matching_registered_templates ) ); } } diff --git a/tests/phpunit/tests/blocks/editor.php b/tests/phpunit/tests/blocks/editor.php index 1de4dbf1719a6..28f3d911ab68f 100644 --- a/tests/phpunit/tests/blocks/editor.php +++ b/tests/phpunit/tests/blocks/editor.php @@ -484,6 +484,39 @@ public function test_wp_get_post_content_block_attributes_no_layout() { $this->assertSame( array(), wp_get_post_content_block_attributes() ); } + /** + * Reproduces WordPress/gutenberg#80291: PHP warnings when a + * plugin-registered template (registered via register_block_template()) + * is assigned to an individual post that hasn't had that template saved + * as a 'wp_template' post yet. + * + * @ticket + */ + public function test_wp_get_post_content_block_attributes_with_registry_only_assigned_template() { + switch_theme( 'block-theme' ); + + $template_name = 'test-plugin//solo-post-template'; + register_block_template( + $template_name, + array( + 'content' => '', + 'post_types' => array( 'post' ), + ) + ); + + $post_id = self::factory()->post->create(); + update_post_meta( $post_id, '_wp_page_template', 'solo-post-template' ); + + global $post_ID; + $post_ID = $post_id; + + $attributes = wp_get_post_content_block_attributes(); + + unregister_block_template( $template_name ); + + $this->assertSame( array( 'layout' => array( 'type' => 'constrained' ) ), $attributes ); + } + /** * @ticket 53458 */ diff --git a/tests/phpunit/tests/blocks/getBlockTemplates.php b/tests/phpunit/tests/blocks/getBlockTemplates.php index 791f449a163c5..7ccf92f745cc8 100644 --- a/tests/phpunit/tests/blocks/getBlockTemplates.php +++ b/tests/phpunit/tests/blocks/getBlockTemplates.php @@ -259,6 +259,44 @@ public function test_get_block_templates_should_not_leak_plugin_registered_templ unregister_block_template( $template_name ); } + /** + * When the only template matching the query comes from the plugin + * template registry — i.e. there is no corresponding 'wp_template' post + * and no matching theme template file — get_block_templates() must + * still return a sequentially indexed array so that callers can safely + * rely on $templates[0]. + * + * @ticket + * + * @covers ::get_block_templates + */ + public function test_get_block_templates_returns_sequentially_indexed_array_for_registry_only_match() { + $template_name = 'test-plugin//registry-only-template'; + register_block_template( + $template_name, + array( + 'content' => 'Template content', + 'post_types' => array( 'post' ), + ) + ); + + $templates = get_block_templates( array( 'slug__in' => array( 'registry-only-template' ) ) ); + + unregister_block_template( $template_name ); + + $this->assertSame( + array_values( $templates ), + $templates, + 'get_block_templates() must return a sequentially indexed array, even when the only match comes from the plugin template registry.' + ); + $this->assertArrayHasKey( + 0, + $templates, + 'Index 0 must exist so callers like wp_get_post_content_block_attributes() can safely access $templates[0].' + ); + $this->assertSame( 'registry-only-template', $templates[0]->slug ); + } + /** * Data provider. *