mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-07-01 15:50:09 +00:00
Editor: Ensure main query loop is entered for singular content in block themes.
Block themes currently lack the means to trigger the main query loop for singular content, since they cannot reasonably use the `core/query` and `core/post-template` blocks which are intended only for displaying a list of posts. So far, the missing main query loop on singular block templates has been worked around by enforcing the loop in certain `core/post-*` blocks, which however causes other bugs. This changeset ensures that the main query loop is still started for singular block theme templates, by wrapping the entire template into the loop, which will by definition only have a single cycle as it only encompasses a single post. This is currently the most reliable solution, since even if there were blocks to properly trigger the main query loop on singular content, it would be unrealistic to expect all existing block themes to update their templates accordingly. It may be revisited in the future. Props gziolo, youknowriad, joemcgill, costdev, mukesh27, flixos90. Fixes #58154. See #59225, #58027. git-svn-id: https://develop.svn.wordpress.org/trunk@56507 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -210,12 +210,12 @@ function _block_template_render_title_tag() {
|
||||
*
|
||||
* @global string $_wp_current_template_content
|
||||
* @global WP_Embed $wp_embed
|
||||
* @global WP_Query $wp_query
|
||||
*
|
||||
* @return string Block template markup.
|
||||
*/
|
||||
function get_the_block_template_html() {
|
||||
global $_wp_current_template_content;
|
||||
global $wp_embed;
|
||||
global $_wp_current_template_content, $wp_embed, $wp_query;
|
||||
|
||||
if ( ! $_wp_current_template_content ) {
|
||||
if ( is_user_logged_in() ) {
|
||||
@@ -228,7 +228,30 @@ function get_the_block_template_html() {
|
||||
$content = $wp_embed->autoembed( $content );
|
||||
$content = shortcode_unautop( $content );
|
||||
$content = do_shortcode( $content );
|
||||
$content = do_blocks( $content );
|
||||
|
||||
/*
|
||||
* Most block themes omit the `core/query` and `core/post-template` blocks in their singular content templates.
|
||||
* While this technically still works since singular content templates are always for only one post, it results in
|
||||
* the main query loop never being entered which causes bugs in core and the plugin ecosystem.
|
||||
*
|
||||
* The workaround below ensures that the loop is started even for those singular templates. The while loop will by
|
||||
* definition only go through a single iteration, i.e. `do_blocks()` is only called once. Additional safeguard
|
||||
* checks are included to ensure the main query loop has not been tampered with and really only encompasses a
|
||||
* single post.
|
||||
*
|
||||
* Even if the block template contained a `core/query` and `core/post-template` block referencing the main query
|
||||
* loop, it would not cause errors since it would use a cloned instance and go through the same loop of a single
|
||||
* post, within the actual main query loop.
|
||||
*/
|
||||
if ( is_singular() && 1 === $wp_query->post_count && have_posts() ) {
|
||||
while ( have_posts() ) {
|
||||
the_post();
|
||||
$content = do_blocks( $content );
|
||||
}
|
||||
} else {
|
||||
$content = do_blocks( $content );
|
||||
}
|
||||
|
||||
$content = wptexturize( $content );
|
||||
$content = convert_smilies( $content );
|
||||
$content = wp_filter_content_tags( $content, 'template' );
|
||||
|
||||
@@ -184,4 +184,118 @@ class Tests_Block_Template extends WP_UnitTestCase {
|
||||
$resolved_template_path = locate_block_template( '', 'search', array() );
|
||||
$this->assertSame( '', $resolved_template_path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that `get_the_block_template_html()` wraps block parsing into the query loop when on a singular template.
|
||||
*
|
||||
* This is necessary since block themes do not include the necessary blocks to trigger the main query loop, and
|
||||
* since there is only a single post in the main query loop in such cases anyway.
|
||||
*
|
||||
* @ticket 58154
|
||||
* @covers ::get_the_block_template_html
|
||||
*/
|
||||
public function test_get_the_block_template_html_enforces_singular_query_loop() {
|
||||
global $_wp_current_template_content, $wp_query, $wp_the_query;
|
||||
|
||||
// Register test block to log `in_the_loop()` results.
|
||||
$in_the_loop_logs = array();
|
||||
$this->register_in_the_loop_logger_block( $in_the_loop_logs );
|
||||
|
||||
// Set main query to single post.
|
||||
$post_id = self::factory()->post->create( array( 'post_title' => 'A single post' ) );
|
||||
$wp_query = new WP_Query( array( 'p' => $post_id ) );
|
||||
$wp_the_query = $wp_query;
|
||||
|
||||
// Use block template that just renders post title and the above test block.
|
||||
$_wp_current_template_content = '<!-- wp:post-title /--><!-- wp:test/in-the-loop-logger /-->';
|
||||
|
||||
$expected = '<div class="wp-site-blocks">';
|
||||
$expected .= '<h2 class="wp-block-post-title">A single post</h2>';
|
||||
$expected .= '</div>';
|
||||
|
||||
$output = get_the_block_template_html();
|
||||
$this->unregister_in_the_loop_logger_block();
|
||||
$this->assertSame( $expected, $output, 'Unexpected block template output' );
|
||||
$this->assertSame( array( true ), $in_the_loop_logs, 'Main query loop was not triggered' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that `get_the_block_template_html()` does not start the main query loop generally.
|
||||
*
|
||||
* @ticket 58154
|
||||
* @covers ::get_the_block_template_html
|
||||
*/
|
||||
public function test_get_the_block_template_html_does_not_generally_enforce_loop() {
|
||||
global $_wp_current_template_content, $wp_query, $wp_the_query;
|
||||
|
||||
// Register test block to log `in_the_loop()` results.
|
||||
$in_the_loop_logs = array();
|
||||
$this->register_in_the_loop_logger_block( $in_the_loop_logs );
|
||||
|
||||
// Set main query to a general post query (i.e. not for a specific post).
|
||||
$post_id = self::factory()->post->create(
|
||||
array(
|
||||
'post_title' => 'A single post',
|
||||
'post_content' => 'The content.',
|
||||
)
|
||||
);
|
||||
$wp_query = new WP_Query(
|
||||
array(
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
)
|
||||
);
|
||||
$wp_the_query = $wp_query;
|
||||
|
||||
/*
|
||||
* Use block template that renders the above test block, followed by a main query loop.
|
||||
* `get_the_block_template_html()` should not start the loop, but the `core/query` and `core/post-template`
|
||||
* blocks should.
|
||||
*/
|
||||
$_wp_current_template_content = '<!-- wp:test/in-the-loop-logger /-->';
|
||||
$_wp_current_template_content .= '<!-- wp:query {"query":{"inherit":true}} -->';
|
||||
$_wp_current_template_content .= '<!-- wp:post-template -->';
|
||||
$_wp_current_template_content .= '<!-- wp:post-title /-->';
|
||||
$_wp_current_template_content .= '<!-- wp:post-content /--><!-- wp:test/in-the-loop-logger /-->';
|
||||
$_wp_current_template_content .= '<!-- /wp:post-template -->';
|
||||
$_wp_current_template_content .= '<!-- /wp:query -->';
|
||||
|
||||
$expected = '<div class="wp-site-blocks">';
|
||||
$expected .= '<ul class="wp-block-post-template is-layout-flow wp-block-post-template-is-layout-flow wp-block-query-is-layout-flow">';
|
||||
$expected .= '<li class="wp-block-post post-' . $post_id . ' post type-post status-publish format-standard hentry category-uncategorized">';
|
||||
$expected .= '<h2 class="wp-block-post-title">A single post</h2>';
|
||||
$expected .= '<div class="entry-content wp-block-post-content is-layout-flow wp-block-post-content-is-layout-flow">' . wpautop( 'The content.' ) . '</div>';
|
||||
$expected .= '</li>';
|
||||
$expected .= '</ul>';
|
||||
$expected .= '</div>';
|
||||
|
||||
$output = get_the_block_template_html();
|
||||
$this->unregister_in_the_loop_logger_block();
|
||||
$this->assertSame( $expected, $output, 'Unexpected block template output' );
|
||||
$this->assertSame( array( false, true ), $in_the_loop_logs, 'Main query loop was triggered incorrectly' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a test block to log `in_the_loop()` results.
|
||||
*
|
||||
* @param array $in_the_loop_logs Array to log function results in. Passed by reference.
|
||||
*/
|
||||
private function register_in_the_loop_logger_block( array &$in_the_loop_logs ) {
|
||||
register_block_type(
|
||||
'test/in-the-loop-logger',
|
||||
array(
|
||||
'render_callback' => function() use ( &$in_the_loop_logs ) {
|
||||
$in_the_loop_logs[] = in_the_loop();
|
||||
return '';
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the test block registered by the `register_in_the_loop_logger_block()` method.
|
||||
*/
|
||||
private function unregister_in_the_loop_logger_block() {
|
||||
unregister_block_type( 'test/in-the-loop-logger' );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user