locate_block_template

The timeline below displays how wordpress function locate_block_template has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.3

/**
 * 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 Site Editor template canvas file, or the fallback PHP template.
 */
function locate_block_template($template, $type, array $templates)
{
    global $_wp_current_template_content, $_wp_current_template_id;
    if (!current_theme_supports('block-templates')) {
        return $template;
    }
    if ($template) {
        /*
         * locate_template() has found a PHP template at the path specified by $template.
         * That means that we have a fallback candidate if we cannot find a block template
         * with higher specificity.
         *
         * Thus, before looking for matching block themes, we shorten our list of candidate
         * templates accordingly.
         */
        // Locate the index of $template (without the theme directory path) in $templates.
        $relative_template_path = str_replace(array(get_stylesheet_directory() . '/', get_template_directory() . '/'), '', $template);
        $index = array_search($relative_template_path, $templates, true);
        // If the template hierarchy algorithm has successfully located a PHP template file,
        // we will only consider block templates with higher or equal specificity.
        $templates = array_slice($templates, 0, $index + 1);
    }
    $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(
                /* translators: %s: Template title */
                __('Empty template: %s'),
                $block_template->title
            );
        } elseif (!empty($block_template->content)) {
            $_wp_current_template_content = $block_template->content;
        }
        if (isset($_GET['_wp-find-template'])) {
            wp_send_json_success($block_template);
        }
    } else {
        if ($template) {
            return $template;
        }
        if ('index' === $type) {
            if (isset($_GET['_wp-find-template'])) {
                wp_send_json_error(array('message' => __('No matching template found.')));
            }
        } else {
            return '';
            // So that the template loader keeps looking for templates.
        }
    }
    // Add hooks for template canvas.
    // Add viewport meta tag.
    add_action('wp_head', '_block_template_viewport_meta_tag', 0);
    // Render title tag with content, regardless of whether theme has title-tag support.
    remove_action('wp_head', '_wp_render_title_tag', 1);
    // Remove conditional title tag rendering...
    add_action('wp_head', '_block_template_render_title_tag', 1);
    // ...and make it unconditional.
    // This file will be included instead of the theme's template file.
    return ABSPATH . WPINC . '/template-canvas.php';
}

WordPress Version: 1.1

/**
 * 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
 *
 * @global string $_wp_current_template_content
 *
 * @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 Site Editor template canvas file, or the fallback PHP template.
 */
function locate_block_template($template, $type, array $templates)
{
    global $_wp_current_template_content;
    if (!current_theme_supports('block-templates')) {
        return $template;
    }
    if ($template) {
        /*
         * locate_template() has found a PHP template at the path specified by $template.
         * That means that we have a fallback candidate if we cannot find a block template
         * with higher specificity.
         *
         * Thus, before looking for matching block themes, we shorten our list of candidate
         * templates accordingly.
         */
        // Locate the index of $template (without the theme directory path) in $templates.
        $relative_template_path = str_replace(array(get_stylesheet_directory() . '/', get_template_directory() . '/'), '', $template);
        $index = array_search($relative_template_path, $templates, true);
        // If the template hierarchy algorithm has successfully located a PHP template file,
        // we will only consider block templates with higher or equal specificity.
        $templates = array_slice($templates, 0, $index + 1);
    }
    $block_template = resolve_block_template($type, $templates, $template);
    if ($block_template) {
        if (empty($block_template->content) && is_user_logged_in()) {
            $_wp_current_template_content = sprintf(
                /* translators: %s: Template title */
                __('Empty template: %s'),
                $block_template->title
            );
        } elseif (!empty($block_template->content)) {
            $_wp_current_template_content = $block_template->content;
        }
        if (isset($_GET['_wp-find-template'])) {
            wp_send_json_success($block_template);
        }
    } else {
        if ($template) {
            return $template;
        }
        if ('index' === $type) {
            if (isset($_GET['_wp-find-template'])) {
                wp_send_json_error(array('message' => __('No matching template found.')));
            }
        } else {
            return '';
            // So that the template loader keeps looking for templates.
        }
    }
    // Add hooks for template canvas.
    // Add viewport meta tag.
    add_action('wp_head', '_block_template_viewport_meta_tag', 0);
    // Render title tag with content, regardless of whether theme has title-tag support.
    remove_action('wp_head', '_wp_render_title_tag', 1);
    // Remove conditional title tag rendering...
    add_action('wp_head', '_block_template_render_title_tag', 1);
    // ...and make it unconditional.
    // This file will be included instead of the theme's template file.
    return ABSPATH . WPINC . '/template-canvas.php';
}

WordPress Version: 6.1

/**
 * 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
 *
 * @global string $_wp_current_template_content
 *
 * @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.
 */
function locate_block_template($template, $type, array $templates)
{
    global $_wp_current_template_content;
    if (!current_theme_supports('block-templates')) {
        return $template;
    }
    if ($template) {
        /*
         * locate_template() has found a PHP template at the path specified by $template.
         * That means that we have a fallback candidate if we cannot find a block template
         * with higher specificity.
         *
         * Thus, before looking for matching block themes, we shorten our list of candidate
         * templates accordingly.
         */
        // Locate the index of $template (without the theme directory path) in $templates.
        $relative_template_path = str_replace(array(get_stylesheet_directory() . '/', get_template_directory() . '/'), '', $template);
        $index = array_search($relative_template_path, $templates, true);
        // If the template hierarchy algorithm has successfully located a PHP template file,
        // we will only consider block templates with higher or equal specificity.
        $templates = array_slice($templates, 0, $index + 1);
    }
    $block_template = resolve_block_template($type, $templates, $template);
    if ($block_template) {
        if (empty($block_template->content) && is_user_logged_in()) {
            $_wp_current_template_content = sprintf(
                /* translators: %s: Template title */
                __('Empty template: %s'),
                $block_template->title
            );
        } elseif (!empty($block_template->content)) {
            $_wp_current_template_content = $block_template->content;
        }
        if (isset($_GET['_wp-find-template'])) {
            wp_send_json_success($block_template);
        }
    } else {
        if ($template) {
            return $template;
        }
        if ('index' === $type) {
            if (isset($_GET['_wp-find-template'])) {
                wp_send_json_error(array('message' => __('No matching template found.')));
            }
        } else {
            return '';
            // So that the template loader keeps looking for templates.
        }
    }
    // Add hooks for template canvas.
    // Add viewport meta tag.
    add_action('wp_head', '_block_template_viewport_meta_tag', 0);
    // Render title tag with content, regardless of whether theme has title-tag support.
    remove_action('wp_head', '_wp_render_title_tag', 1);
    // Remove conditional title tag rendering...
    add_action('wp_head', '_block_template_render_title_tag', 1);
    // ...and make it unconditional.
    // This file will be included instead of the theme's template file.
    return ABSPATH . WPINC . '/template-canvas.php';
}

WordPress Version: 9.1

/**
 * Find 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
 *
 * @global string $_wp_current_template_content
 *
 * @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.
 */
function locate_block_template($template, $type, array $templates)
{
    global $_wp_current_template_content;
    if (!current_theme_supports('block-templates')) {
        return $template;
    }
    if ($template) {
        /*
         * locate_template() has found a PHP template at the path specified by $template.
         * That means that we have a fallback candidate if we cannot find a block template
         * with higher specificity.
         *
         * Thus, before looking for matching block themes, we shorten our list of candidate
         * templates accordingly.
         */
        // Locate the index of $template (without the theme directory path) in $templates.
        $relative_template_path = str_replace(array(get_stylesheet_directory() . '/', get_template_directory() . '/'), '', $template);
        $index = array_search($relative_template_path, $templates, true);
        // If the template hiearchy algorithm has successfully located a PHP template file,
        // we will only consider block templates with higher or equal specificity.
        $templates = array_slice($templates, 0, $index + 1);
    }
    $block_template = resolve_block_template($type, $templates, $template);
    if ($block_template) {
        if (empty($block_template->content) && is_user_logged_in()) {
            $_wp_current_template_content = sprintf(
                /* translators: %s: Template title */
                __('Empty template: %s'),
                $block_template->title
            );
        } elseif (!empty($block_template->content)) {
            $_wp_current_template_content = $block_template->content;
        }
        if (isset($_GET['_wp-find-template'])) {
            wp_send_json_success($block_template);
        }
    } else {
        if ($template) {
            return $template;
        }
        if ('index' === $type) {
            if (isset($_GET['_wp-find-template'])) {
                wp_send_json_error(array('message' => __('No matching template found.')));
            }
        } else {
            return '';
            // So that the template loader keeps looking for templates.
        }
    }
    // Add hooks for template canvas.
    // Add viewport meta tag.
    add_action('wp_head', '_block_template_viewport_meta_tag', 0);
    // Render title tag with content, regardless of whether theme has title-tag support.
    remove_action('wp_head', '_wp_render_title_tag', 1);
    // Remove conditional title tag rendering...
    add_action('wp_head', '_block_template_render_title_tag', 1);
    // ...and make it unconditional.
    // This file will be included instead of the theme's template file.
    return ABSPATH . WPINC . '/template-canvas.php';
}

WordPress Version: 5.9

/**
 * Find 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
 *
 * @global string $_wp_current_template_content
 *
 * @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.
 */
function locate_block_template($template, $type, array $templates)
{
    global $_wp_current_template_content;
    if ($template) {
        /*
         * locate_template() has found a PHP template at the path specified by $template.
         * That means that we have a fallback candidate if we cannot find a block template
         * with higher specificity.
         *
         * Thus, before looking for matching block themes, we shorten our list of candidate
         * templates accordingly.
         */
        // Locate the index of $template (without the theme directory path) in $templates.
        $relative_template_path = str_replace(array(get_stylesheet_directory() . '/', get_template_directory() . '/'), '', $template);
        $index = array_search($relative_template_path, $templates, true);
        // If the template hiearchy algorithm has successfully located a PHP template file,
        // we will only consider block templates with higher or equal specificity.
        $templates = array_slice($templates, 0, $index + 1);
    }
    $block_template = resolve_block_template($type, $templates, $template);
    if ($block_template) {
        if (empty($block_template->content) && is_user_logged_in()) {
            $_wp_current_template_content = sprintf(
                /* translators: %s: Template title */
                __('Empty template: %s'),
                $block_template->title
            );
        } elseif (!empty($block_template->content)) {
            $_wp_current_template_content = $block_template->content;
        }
        if (isset($_GET['_wp-find-template'])) {
            wp_send_json_success($block_template);
        }
    } else {
        if ($template) {
            return $template;
        }
        if ('index' === $type) {
            if (isset($_GET['_wp-find-template'])) {
                wp_send_json_error(array('message' => __('No matching template found.')));
            }
        } else {
            return '';
            // So that the template loader keeps looking for templates.
        }
    }
    // Add hooks for template canvas.
    // Add viewport meta tag.
    add_action('wp_head', '_block_template_viewport_meta_tag', 0);
    // Render title tag with content, regardless of whether theme has title-tag support.
    remove_action('wp_head', '_wp_render_title_tag', 1);
    // Remove conditional title tag rendering...
    add_action('wp_head', '_block_template_render_title_tag', 1);
    // ...and make it unconditional.
    // This file will be included instead of the theme's template file.
    return ABSPATH . WPINC . '/template-canvas.php';
}

WordPress Version: 5.8

/**
 * Block template loader functions.
 *
 * @package WordPress
 */
/**
 * Find 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
 *
 * @global string $_wp_current_template_content
 *
 * @param string $template  Path to the template. See locate_template().
 * @param string $type      Sanitized filename without extension.
 * @param array  $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.
 */
function locate_block_template($template, $type, array $templates)
{
    global $_wp_current_template_content;
    if ($template) {
        /*
         * locate_template() has found a PHP template at the path specified by $template.
         * That means that we have a fallback candidate if we cannot find a block template
         * with higher specificity.
         *
         * Thus, before looking for matching block themes, we shorten our list of candidate
         * templates accordingly.
         */
        // Locate the index of $template (without the theme directory path) in $templates.
        $relative_template_path = str_replace(array(get_stylesheet_directory() . '/', get_template_directory() . '/'), '', $template);
        $index = array_search($relative_template_path, $templates, true);
        // If the template hiearchy algorithm has successfully located a PHP template file,
        // we will only consider block templates with higher or equal specificity.
        $templates = array_slice($templates, 0, $index + 1);
    }
    $block_template = resolve_block_template($type, $templates);
    if ($block_template) {
        if (empty($block_template->content) && is_user_logged_in()) {
            $_wp_current_template_content = sprintf(
                /* translators: %s: Template title */
                __('Empty template: %s'),
                $block_template->title
            );
        } elseif (!empty($block_template->content)) {
            $_wp_current_template_content = $block_template->content;
        }
        if (isset($_GET['_wp-find-template'])) {
            wp_send_json_success($block_template);
        }
    } else {
        if ($template) {
            return $template;
        }
        if ('index' === $type) {
            if (isset($_GET['_wp-find-template'])) {
                wp_send_json_error(array('message' => __('No matching template found.')));
            }
        } else {
            return '';
            // So that the template loader keeps looking for templates.
        }
    }
    // Add hooks for template canvas.
    // Add viewport meta tag.
    add_action('wp_head', '_block_template_viewport_meta_tag', 0);
    // Render title tag with content, regardless of whether theme has title-tag support.
    remove_action('wp_head', '_wp_render_title_tag', 1);
    // Remove conditional title tag rendering...
    add_action('wp_head', '_block_template_render_title_tag', 1);
    // ...and make it unconditional.
    // This file will be included instead of the theme's template file.
    return ABSPATH . WPINC . '/template-canvas.php';
}