[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> block-template.php (source)

   1  <?php
   2  /**
   3   * Block template loader functions.
   4   *
   5   * @package WordPress
   6   */
   7  
   8  /**
   9   * Adds necessary filters to use 'wp_template' posts instead of theme template files.
  10   *
  11   * @access private
  12   * @since 5.9.0
  13   */
  14  function _add_template_loader_filters() {
  15      if ( ! current_theme_supports( 'block-templates' ) ) {
  16          return;
  17      }
  18  
  19      $template_types = array_keys( get_default_block_template_types() );
  20      foreach ( $template_types as $template_type ) {
  21          // Skip 'embed' for now because it is not a regular template type.
  22          if ( 'embed' === $template_type ) {
  23              continue;
  24          }
  25          add_filter( str_replace( '-', '', $template_type ) . '_template', 'locate_block_template', 20, 3 );
  26      }
  27  
  28      // Request to resolve a template.
  29      if ( isset( $_GET['_wp-find-template'] ) ) {
  30          add_filter( 'pre_get_posts', '_resolve_template_for_new_post' );
  31      }
  32  }
  33  
  34  /**
  35   * Find a block template with equal or higher specificity than a given PHP template file.
  36   *
  37   * Internally, this communicates the block content that needs to be used by the template canvas through a global variable.
  38   *
  39   * @since 5.8.0
  40   *
  41   * @global string $_wp_current_template_content
  42   *
  43   * @param string   $template  Path to the template. See locate_template().
  44   * @param string   $type      Sanitized filename without extension.
  45   * @param string[] $templates A list of template candidates, in descending order of priority.
  46   * @return string The path to the Full Site Editing template canvas file, or the fallback PHP template.
  47   */
  48  function locate_block_template( $template, $type, array $templates ) {
  49      global $_wp_current_template_content;
  50  
  51      if ( ! current_theme_supports( 'block-templates' ) ) {
  52          return $template;
  53      }
  54  
  55      if ( $template ) {
  56          /*
  57           * locate_template() has found a PHP template at the path specified by $template.
  58           * That means that we have a fallback candidate if we cannot find a block template
  59           * with higher specificity.
  60           *
  61           * Thus, before looking for matching block themes, we shorten our list of candidate
  62           * templates accordingly.
  63           */
  64  
  65          // Locate the index of $template (without the theme directory path) in $templates.
  66          $relative_template_path = str_replace(
  67              array( get_stylesheet_directory() . '/', get_template_directory() . '/' ),
  68              '',
  69              $template
  70          );
  71          $index                  = array_search( $relative_template_path, $templates, true );
  72  
  73          // If the template hierarchy algorithm has successfully located a PHP template file,
  74          // we will only consider block templates with higher or equal specificity.
  75          $templates = array_slice( $templates, 0, $index + 1 );
  76      }
  77  
  78      $block_template = resolve_block_template( $type, $templates, $template );
  79  
  80      if ( $block_template ) {
  81          if ( empty( $block_template->content ) && is_user_logged_in() ) {
  82              $_wp_current_template_content =
  83              sprintf(
  84                  /* translators: %s: Template title */
  85                  __( 'Empty template: %s' ),
  86                  $block_template->title
  87              );
  88          } elseif ( ! empty( $block_template->content ) ) {
  89              $_wp_current_template_content = $block_template->content;
  90          }
  91          if ( isset( $_GET['_wp-find-template'] ) ) {
  92              wp_send_json_success( $block_template );
  93          }
  94      } else {
  95          if ( $template ) {
  96              return $template;
  97          }
  98  
  99          if ( 'index' === $type ) {
 100              if ( isset( $_GET['_wp-find-template'] ) ) {
 101                  wp_send_json_error( array( 'message' => __( 'No matching template found.' ) ) );
 102              }
 103          } else {
 104              return ''; // So that the template loader keeps looking for templates.
 105          }
 106      }
 107  
 108      // Add hooks for template canvas.
 109      // Add viewport meta tag.
 110      add_action( 'wp_head', '_block_template_viewport_meta_tag', 0 );
 111  
 112      // Render title tag with content, regardless of whether theme has title-tag support.
 113      remove_action( 'wp_head', '_wp_render_title_tag', 1 );    // Remove conditional title tag rendering...
 114      add_action( 'wp_head', '_block_template_render_title_tag', 1 ); // ...and make it unconditional.
 115  
 116      // This file will be included instead of the theme's template file.
 117      return ABSPATH . WPINC . '/template-canvas.php';
 118  }
 119  
 120  /**
 121   * Return the correct 'wp_template' to render for the request template type.
 122   *
 123   * @access private
 124   * @since 5.8.0
 125   * @since 5.9.0 Added the `$fallback_template` parameter.
 126   *
 127   * @param string   $template_type      The current template type.
 128   * @param string[] $template_hierarchy The current template hierarchy, ordered by priority.
 129   * @param string   $fallback_template  A PHP fallback template to use if no matching block template is found.
 130   * @return WP_Block_Template|null template A template object, or null if none could be found.
 131   */
 132  function resolve_block_template( $template_type, $template_hierarchy, $fallback_template ) {
 133      if ( ! $template_type ) {
 134          return null;
 135      }
 136  
 137      if ( empty( $template_hierarchy ) ) {
 138          $template_hierarchy = array( $template_type );
 139      }
 140  
 141      $slugs = array_map(
 142          '_strip_template_file_suffix',
 143          $template_hierarchy
 144      );
 145  
 146      // Find all potential templates 'wp_template' post matching the hierarchy.
 147      $query     = array(
 148          'theme'    => wp_get_theme()->get_stylesheet(),
 149          'slug__in' => $slugs,
 150      );
 151      $templates = get_block_templates( $query );
 152  
 153      // Order these templates per slug priority.
 154      // Build map of template slugs to their priority in the current hierarchy.
 155      $slug_priorities = array_flip( $slugs );
 156  
 157      usort(
 158          $templates,
 159          static function ( $template_a, $template_b ) use ( $slug_priorities ) {
 160              return $slug_priorities[ $template_a->slug ] - $slug_priorities[ $template_b->slug ];
 161          }
 162      );
 163  
 164      $theme_base_path        = get_stylesheet_directory() . DIRECTORY_SEPARATOR;
 165      $parent_theme_base_path = get_template_directory() . DIRECTORY_SEPARATOR;
 166  
 167      // Is the active theme a child theme, and is the PHP fallback template part of it?
 168      if (
 169          strpos( $fallback_template, $theme_base_path ) === 0 &&
 170          strpos( $fallback_template, $parent_theme_base_path ) === false
 171      ) {
 172          $fallback_template_slug = substr(
 173              $fallback_template,
 174              // Starting position of slug.
 175              strpos( $fallback_template, $theme_base_path ) + strlen( $theme_base_path ),
 176              // Remove '.php' suffix.
 177              -4
 178          );
 179  
 180          // Is our candidate block template's slug identical to our PHP fallback template's?
 181          if (
 182              count( $templates ) &&
 183              $fallback_template_slug === $templates[0]->slug &&
 184              'theme' === $templates[0]->source
 185          ) {
 186              // Unfortunately, we cannot trust $templates[0]->theme, since it will always
 187              // be set to the active theme's slug by _build_block_template_result_from_file(),
 188              // even if the block template is really coming from the active theme's parent.
 189              // (The reason for this is that we want it to be associated with the active theme
 190              // -- not its parent -- once we edit it and store it to the DB as a wp_template CPT.)
 191              // Instead, we use _get_block_template_file() to locate the block template file.
 192              $template_file = _get_block_template_file( 'wp_template', $fallback_template_slug );
 193              if ( $template_file && get_template() === $template_file['theme'] ) {
 194                  // The block template is part of the parent theme, so we
 195                  // have to give precedence to the child theme's PHP template.
 196                  array_shift( $templates );
 197              }
 198          }
 199      }
 200  
 201      return count( $templates ) ? $templates[0] : null;
 202  }
 203  
 204  /**
 205   * Displays title tag with content, regardless of whether theme has title-tag support.
 206   *
 207   * @access private
 208   * @since 5.8.0
 209   *
 210   * @see _wp_render_title_tag()
 211   */
 212  function _block_template_render_title_tag() {
 213      echo '<title>' . wp_get_document_title() . '</title>' . "\n";
 214  }
 215  
 216  /**
 217   * Returns the markup for the current template.
 218   *
 219   * @access private
 220   * @since 5.8.0
 221   *
 222   * @global string   $_wp_current_template_content
 223   * @global WP_Embed $wp_embed
 224   *
 225   * @return string Block template markup.
 226   */
 227  function get_the_block_template_html() {
 228      global $_wp_current_template_content;
 229      global $wp_embed;
 230  
 231      if ( ! $_wp_current_template_content ) {
 232          if ( is_user_logged_in() ) {
 233              return '<h1>' . esc_html__( 'No matching template found' ) . '</h1>';
 234          }
 235          return;
 236      }
 237  
 238      $content = $wp_embed->run_shortcode( $_wp_current_template_content );
 239      $content = $wp_embed->autoembed( $content );
 240      $content = do_blocks( $content );
 241      $content = wptexturize( $content );
 242      $content = convert_smilies( $content );
 243      $content = shortcode_unautop( $content );
 244      $content = wp_filter_content_tags( $content );
 245      $content = do_shortcode( $content );
 246      $content = str_replace( ']]>', ']]&gt;', $content );
 247  
 248      // Wrap block template in .wp-site-blocks to allow for specific descendant styles
 249      // (e.g. `.wp-site-blocks > *`).
 250      return '<div class="wp-site-blocks">' . $content . '</div>';
 251  }
 252  
 253  /**
 254   * Renders a 'viewport' meta tag.
 255   *
 256   * This is hooked into {@see 'wp_head'} to decouple its output from the default template canvas.
 257   *
 258   * @access private
 259   * @since 5.8.0
 260   */
 261  function _block_template_viewport_meta_tag() {
 262      echo '<meta name="viewport" content="width=device-width, initial-scale=1" />' . "\n";
 263  }
 264  
 265  /**
 266   * Strips .php or .html suffix from template file names.
 267   *
 268   * @access private
 269   * @since 5.8.0
 270   *
 271   * @param string $template_file Template file name.
 272   * @return string Template file name without extension.
 273   */
 274  function _strip_template_file_suffix( $template_file ) {
 275      return preg_replace( '/\.(php|html)$/', '', $template_file );
 276  }
 277  
 278  /**
 279   * Removes post details from block context when rendering a block template.
 280   *
 281   * @access private
 282   * @since 5.8.0
 283   *
 284   * @param array $context Default context.
 285   *
 286   * @return array Filtered context.
 287   */
 288  function _block_template_render_without_post_block_context( $context ) {
 289      /*
 290       * When loading a template directly and not through a page that resolves it,
 291       * the top-level post ID and type context get set to that of the template.
 292       * Templates are just the structure of a site, and they should not be available
 293       * as post context because blocks like Post Content would recurse infinitely.
 294       */
 295      if ( isset( $context['postType'] ) && 'wp_template' === $context['postType'] ) {
 296          unset( $context['postId'] );
 297          unset( $context['postType'] );
 298      }
 299  
 300      return $context;
 301  }
 302  
 303  /**
 304   * Sets the current WP_Query to return auto-draft posts.
 305   *
 306   * The auto-draft status indicates a new post, so allow the the WP_Query instance to
 307   * return an auto-draft post for template resolution when editing a new post.
 308   *
 309   * @access private
 310   * @since 5.9.0
 311   *
 312   * @param WP_Query $wp_query Current WP_Query instance, passed by reference.
 313   */
 314  function _resolve_template_for_new_post( $wp_query ) {
 315      remove_filter( 'pre_get_posts', '_resolve_template_for_new_post' );
 316  
 317      // Pages.
 318      $page_id = isset( $wp_query->query['page_id'] ) ? $wp_query->query['page_id'] : null;
 319  
 320      // Posts, including custom post types.
 321      $p = isset( $wp_query->query['p'] ) ? $wp_query->query['p'] : null;
 322  
 323      $post_id = $page_id ? $page_id : $p;
 324      $post    = get_post( $post_id );
 325  
 326      if (
 327          $post &&
 328          'auto-draft' === $post->post_status &&
 329          current_user_can( 'edit_post', $post->ID )
 330      ) {
 331          $wp_query->set( 'post_status', 'auto-draft' );
 332      }
 333  }
 334  
 335  /**
 336   * Returns the correct template for the site's home page.
 337   *
 338   * @access private
 339   * @since 6.0.0
 340   *
 341   * @return array|null A template object, or null if none could be found.
 342   */
 343  function _resolve_home_block_template() {
 344      $show_on_front = get_option( 'show_on_front' );
 345      $front_page_id = get_option( 'page_on_front' );
 346  
 347      if ( 'page' === $show_on_front && $front_page_id ) {
 348          return array(
 349              'postType' => 'page',
 350              'postId'   => $front_page_id,
 351          );
 352      }
 353  
 354      $hierarchy = array( 'front-page', 'home', 'index' );
 355      $template  = resolve_block_template( 'home', $hierarchy, '' );
 356  
 357      if ( ! $template ) {
 358          return null;
 359      }
 360  
 361      return array(
 362          'postType' => 'wp_template',
 363          'postId'   => $template->id,
 364      );
 365  }


Generated: Tue Dec 24 01:00:02 2024 Cross-referenced by PHPXref 0.7.1