diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-includes/block-template.php --- a/wp/wp-includes/block-template.php Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-includes/block-template.php Fri Sep 05 18:40:08 2025 +0200 @@ -6,47 +6,35 @@ */ /** - * Adds necessary filters to use 'wp_template' posts instead of theme template files. + * Adds necessary hooks to resolve '_wp-find-template' requests. * * @access private * @since 5.9.0 */ function _add_template_loader_filters() { - if ( ! current_theme_supports( 'block-templates' ) ) { - return; - } - - $template_types = array_keys( get_default_block_template_types() ); - foreach ( $template_types as $template_type ) { - // Skip 'embed' for now because it is not a regular template type. - if ( 'embed' === $template_type ) { - continue; - } - add_filter( str_replace( '-', '', $template_type ) . '_template', 'locate_block_template', 20, 3 ); - } - - // Request to resolve a template. - if ( isset( $_GET['_wp-find-template'] ) ) { - add_filter( 'pre_get_posts', '_resolve_template_for_new_post' ); + if ( isset( $_GET['_wp-find-template'] ) && current_theme_supports( 'block-templates' ) ) { + add_action( 'pre_get_posts', '_resolve_template_for_new_post' ); } } /** - * Find a block template with equal or higher specificity than a given PHP template file. + * Finds a block template with equal or higher specificity than a given PHP template file. * * Internally, this communicates the block content that needs to be used by the template canvas through a global variable. * * @since 5.8.0 + * @since 6.3.0 Added `$_wp_current_template_id` global for editing of current template directly from the admin bar. * * @global string $_wp_current_template_content + * @global string $_wp_current_template_id * * @param string $template Path to the template. See locate_template(). * @param string $type Sanitized filename without extension. * @param string[] $templates A list of template candidates, in descending order of priority. - * @return string The path to the Full Site Editing template canvas file, or the fallback PHP template. + * @return string The path to the Site Editor template canvas file, or the fallback PHP template. */ function locate_block_template( $template, $type, array $templates ) { - global $_wp_current_template_content; + global $_wp_current_template_content, $_wp_current_template_id; if ( ! current_theme_supports( 'block-templates' ) ) { return $template; @@ -78,6 +66,8 @@ $block_template = resolve_block_template( $type, $templates, $template ); if ( $block_template ) { + $_wp_current_template_id = $block_template->id; + if ( empty( $block_template->content ) && is_user_logged_in() ) { $_wp_current_template_content = sprintf( @@ -118,7 +108,7 @@ } /** - * Return the correct 'wp_template' to render for the request template type. + * Returns the correct 'wp_template' to render for the request template type. * * @access private * @since 5.8.0 @@ -145,7 +135,6 @@ // Find all potential templates 'wp_template' post matching the hierarchy. $query = array( - 'theme' => wp_get_theme()->get_stylesheet(), 'slug__in' => $slugs, ); $templates = get_block_templates( $query ); @@ -166,8 +155,8 @@ // Is the active theme a child theme, and is the PHP fallback template part of it? if ( - strpos( $fallback_template, $theme_base_path ) === 0 && - strpos( $fallback_template, $parent_theme_base_path ) === false + str_starts_with( $fallback_template, $theme_base_path ) && + ! str_contains( $fallback_template, $parent_theme_base_path ) ) { $fallback_template_slug = substr( $fallback_template, @@ -219,14 +208,15 @@ * @access private * @since 5.8.0 * + * @global string $_wp_current_template_id * @global string $_wp_current_template_content - * @global WP_Embed $wp_embed + * @global WP_Embed $wp_embed WordPress Embed object. + * @global WP_Query $wp_query WordPress Query object. * * @return string Block template markup. */ function get_the_block_template_html() { - global $_wp_current_template_content; - global $wp_embed; + global $_wp_current_template_id, $_wp_current_template_content, $wp_embed, $wp_query; if ( ! $_wp_current_template_content ) { if ( is_user_logged_in() ) { @@ -237,12 +227,45 @@ $content = $wp_embed->run_shortcode( $_wp_current_template_content ); $content = $wp_embed->autoembed( $content ); - $content = do_blocks( $content ); + $content = shortcode_unautop( $content ); + $content = do_shortcode( $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. + * + * This special logic should be skipped if the current template does not come from the current theme, in which case + * it has been injected by a plugin by hijacking the block template loader mechanism. In that case, entirely custom + * logic may be applied which is unpredictable and therefore safer to omit this special handling on. + */ + if ( + $_wp_current_template_id && + str_starts_with( $_wp_current_template_id, get_stylesheet() . '//' ) && + 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 = shortcode_unautop( $content ); - $content = wp_filter_content_tags( $content ); - $content = do_shortcode( $content ); + $content = wp_filter_content_tags( $content, 'template' ); $content = str_replace( ']]>', ']]>', $content ); // Wrap block template in .wp-site-blocks to allow for specific descendant styles @@ -335,35 +358,3 @@ $wp_query->set( 'post_status', 'auto-draft' ); } } - -/** - * Returns the correct template for the site's home page. - * - * @access private - * @since 6.0.0 - * - * @return array|null A template object, or null if none could be found. - */ -function _resolve_home_block_template() { - $show_on_front = get_option( 'show_on_front' ); - $front_page_id = get_option( 'page_on_front' ); - - if ( 'page' === $show_on_front && $front_page_id ) { - return array( - 'postType' => 'page', - 'postId' => $front_page_id, - ); - } - - $hierarchy = array( 'front-page', 'home', 'index' ); - $template = resolve_block_template( 'home', $hierarchy, '' ); - - if ( ! $template ) { - return null; - } - - return array( - 'postType' => 'wp_template', - 'postId' => $template->id, - ); -}