--- 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,
- );
-}