Changeset 56507
- Timestamp:
- 09/01/2023 05:30:02 PM (12 months ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/block-template.php
r56209 r56507 211 211 * @global string $_wp_current_template_content 212 212 * @global WP_Embed $wp_embed 213 * @global WP_Query $wp_query 213 214 * 214 215 * @return string Block template markup. 215 216 */ 216 217 function get_the_block_template_html() { 217 global $_wp_current_template_content; 218 global $wp_embed; 218 global $_wp_current_template_content, $wp_embed, $wp_query; 219 219 220 220 if ( ! $_wp_current_template_content ) { … … 229 229 $content = shortcode_unautop( $content ); 230 230 $content = do_shortcode( $content ); 231 $content = do_blocks( $content ); 231 232 /* 233 * Most block themes omit the `core/query` and `core/post-template` blocks in their singular content templates. 234 * While this technically still works since singular content templates are always for only one post, it results in 235 * the main query loop never being entered which causes bugs in core and the plugin ecosystem. 236 * 237 * The workaround below ensures that the loop is started even for those singular templates. The while loop will by 238 * definition only go through a single iteration, i.e. `do_blocks()` is only called once. Additional safeguard 239 * checks are included to ensure the main query loop has not been tampered with and really only encompasses a 240 * single post. 241 * 242 * Even if the block template contained a `core/query` and `core/post-template` block referencing the main query 243 * loop, it would not cause errors since it would use a cloned instance and go through the same loop of a single 244 * post, within the actual main query loop. 245 */ 246 if ( is_singular() && 1 === $wp_query->post_count && have_posts() ) { 247 while ( have_posts() ) { 248 the_post(); 249 $content = do_blocks( $content ); 250 } 251 } else { 252 $content = do_blocks( $content ); 253 } 254 232 255 $content = wptexturize( $content ); 233 256 $content = convert_smilies( $content ); -
trunk/tests/phpunit/tests/block-template.php
r55457 r56507 185 185 $this->assertSame( '', $resolved_template_path ); 186 186 } 187 188 /** 189 * Tests that `get_the_block_template_html()` wraps block parsing into the query loop when on a singular template. 190 * 191 * This is necessary since block themes do not include the necessary blocks to trigger the main query loop, and 192 * since there is only a single post in the main query loop in such cases anyway. 193 * 194 * @ticket 58154 195 * @covers ::get_the_block_template_html 196 */ 197 public function test_get_the_block_template_html_enforces_singular_query_loop() { 198 global $_wp_current_template_content, $wp_query, $wp_the_query; 199 200 // Register test block to log `in_the_loop()` results. 201 $in_the_loop_logs = array(); 202 $this->register_in_the_loop_logger_block( $in_the_loop_logs ); 203 204 // Set main query to single post. 205 $post_id = self::factory()->post->create( array( 'post_title' => 'A single post' ) ); 206 $wp_query = new WP_Query( array( 'p' => $post_id ) ); 207 $wp_the_query = $wp_query; 208 209 // Use block template that just renders post title and the above test block. 210 $_wp_current_template_content = '<!-- wp:post-title /--><!-- wp:test/in-the-loop-logger /-->'; 211 212 $expected = '<div class="wp-site-blocks">'; 213 $expected .= '<h2 class="wp-block-post-title">A single post</h2>'; 214 $expected .= '</div>'; 215 216 $output = get_the_block_template_html(); 217 $this->unregister_in_the_loop_logger_block(); 218 $this->assertSame( $expected, $output, 'Unexpected block template output' ); 219 $this->assertSame( array( true ), $in_the_loop_logs, 'Main query loop was not triggered' ); 220 } 221 222 /** 223 * Tests that `get_the_block_template_html()` does not start the main query loop generally. 224 * 225 * @ticket 58154 226 * @covers ::get_the_block_template_html 227 */ 228 public function test_get_the_block_template_html_does_not_generally_enforce_loop() { 229 global $_wp_current_template_content, $wp_query, $wp_the_query; 230 231 // Register test block to log `in_the_loop()` results. 232 $in_the_loop_logs = array(); 233 $this->register_in_the_loop_logger_block( $in_the_loop_logs ); 234 235 // Set main query to a general post query (i.e. not for a specific post). 236 $post_id = self::factory()->post->create( 237 array( 238 'post_title' => 'A single post', 239 'post_content' => 'The content.', 240 ) 241 ); 242 $wp_query = new WP_Query( 243 array( 244 'post_type' => 'post', 245 'post_status' => 'publish', 246 ) 247 ); 248 $wp_the_query = $wp_query; 249 250 /* 251 * Use block template that renders the above test block, followed by a main query loop. 252 * `get_the_block_template_html()` should not start the loop, but the `core/query` and `core/post-template` 253 * blocks should. 254 */ 255 $_wp_current_template_content = '<!-- wp:test/in-the-loop-logger /-->'; 256 $_wp_current_template_content .= '<!-- wp:query {"query":{"inherit":true}} -->'; 257 $_wp_current_template_content .= '<!-- wp:post-template -->'; 258 $_wp_current_template_content .= '<!-- wp:post-title /-->'; 259 $_wp_current_template_content .= '<!-- wp:post-content /--><!-- wp:test/in-the-loop-logger /-->'; 260 $_wp_current_template_content .= '<!-- /wp:post-template -->'; 261 $_wp_current_template_content .= '<!-- /wp:query -->'; 262 263 $expected = '<div class="wp-site-blocks">'; 264 $expected .= '<ul class="wp-block-post-template is-layout-flow wp-block-post-template-is-layout-flow wp-block-query-is-layout-flow">'; 265 $expected .= '<li class="wp-block-post post-' . $post_id . ' post type-post status-publish format-standard hentry category-uncategorized">'; 266 $expected .= '<h2 class="wp-block-post-title">A single post</h2>'; 267 $expected .= '<div class="entry-content wp-block-post-content is-layout-flow wp-block-post-content-is-layout-flow">' . wpautop( 'The content.' ) . '</div>'; 268 $expected .= '</li>'; 269 $expected .= '</ul>'; 270 $expected .= '</div>'; 271 272 $output = get_the_block_template_html(); 273 $this->unregister_in_the_loop_logger_block(); 274 $this->assertSame( $expected, $output, 'Unexpected block template output' ); 275 $this->assertSame( array( false, true ), $in_the_loop_logs, 'Main query loop was triggered incorrectly' ); 276 } 277 278 /** 279 * Registers a test block to log `in_the_loop()` results. 280 * 281 * @param array $in_the_loop_logs Array to log function results in. Passed by reference. 282 */ 283 private function register_in_the_loop_logger_block( array &$in_the_loop_logs ) { 284 register_block_type( 285 'test/in-the-loop-logger', 286 array( 287 'render_callback' => function() use ( &$in_the_loop_logs ) { 288 $in_the_loop_logs[] = in_the_loop(); 289 return ''; 290 }, 291 ) 292 ); 293 } 294 295 /** 296 * Unregisters the test block registered by the `register_in_the_loop_logger_block()` method. 297 */ 298 private function unregister_in_the_loop_logger_block() { 299 unregister_block_type( 'test/in-the-loop-logger' ); 300 } 187 301 }
Note: See TracChangeset
for help on using the changeset viewer.