1.20.x theme.inc | backdrop_find_theme_templates($cache, $extension, $path) |
Allows themes and/or theme engines to discover overridden templates.
Parameters
$cache: The existing cache of theme hooks to test against.
$extension: The extension that these templates will have.
$path: The path to search.
Return value
array: An array of all template locations. Keyed by the theme callback, each entry contains the following keys:
- template: The template file name/
- path: The path to the template file relative to the Backdrop root.
- base hook: If this template is dynamically named (usually with two hyphens in the template name), a string indicating the base theme callback.
File
- includes/
theme.inc, line 1313 - The theme system, which controls the output of Backdrop.
Code
function backdrop_find_theme_templates($cache, $extension, $path) {
$implementations = array();
// Collect paths to all sub-themes grouped by base themes. These will be
// used for filtering. This allows base themes to have sub-themes in its
// folder hierarchy without affecting the base themes template discovery.
$theme_paths = array();
foreach (list_themes() as $theme_info) {
if (!empty($theme_info->base_theme)) {
$theme_paths[$theme_info->base_theme][$theme_info->name] = dirname($theme_info->filename);
}
}
foreach ($theme_paths as $basetheme => $subthemes) {
foreach ($subthemes as $subtheme => $subtheme_path) {
if (isset($theme_paths[$subtheme])) {
$theme_paths[$basetheme] = array_merge($theme_paths[$basetheme], $theme_paths[$subtheme]);
}
}
}
global $theme;
$subtheme_paths = isset($theme_paths[$theme]) ? $theme_paths[$theme] : array();
// Escape the periods in the extension.
$regex = '/' . str_replace('.', '\.', $extension) . '$/';
// Save effort by skipping directories that should not contain templates.
$ignore_directories = array(
'assets',
'css',
'scss',
'less',
'js',
'images',
'node_modules',
'bower_components',
);
$no_mask = '/^((\..*)|' . implode('|', $ignore_directories) . ')$/';
// Get a listing of all template files in the path to search.
$files = file_scan_directory($path, $regex, array('key' => 'name', 'nomask' => $no_mask));
// Find templates that implement registered theme hooks and include that in
// what is returned so that the registry knows that the theme has this
// implementation.
foreach ($files as $template => $file) {
// Ignore sub-theme templates for the current theme.
if (strpos($file->uri, str_replace($subtheme_paths, '', $file->uri)) !== 0) {
continue;
}
// Chop off the remaining '.tpl' extension. $template already has the
// rightmost extension removed, but there might still be more, such as with
// .tpl.php, which still has .tpl in $template at this point.
if (($pos = strpos($template, '.tpl')) !== FALSE) {
$template = substr($template, 0, $pos);
}
// Transform - in filenames to _ to match function naming scheme
// for the purposes of searching.
$hook = strtr($template, '-', '_');
if (isset($cache[$hook])) {
$implementations[$hook] = array(
'template' => $template,
'path' => dirname($file->uri),
);
}
// Match templates based on the 'template' filename.
foreach ($cache as $hook => $info) {
if (isset($info['template'])) {
$template_candidates = array($info['template'], str_replace($info['theme path'] . '/', '', $info['template']));
if (in_array($template, $template_candidates)) {
$implementations[$hook] = array(
'template' => $template,
'path' => dirname($file->uri),
);
}
}
}
}
// Find templates that implement possible "suggestion" variants of registered
// theme hooks and add those as new registered theme hooks. See
// backdrop_find_theme_functions() for more information about suggestions and
// the use of 'pattern' and 'base hook'.
$patterns = array_keys($files);
foreach ($cache as $hook => $info) {
$pattern = isset($info['pattern']) ? $info['pattern'] : ($hook . '__');
if (!isset($info['base hook']) && !empty($pattern)) {
// Transform _ in pattern to - to match file naming scheme
// for the purposes of searching.
$pattern = strtr($pattern, '_', '-');
$matches = preg_grep('/^' . $pattern . '/', $patterns);
if ($matches) {
foreach ($matches as $match) {
$file = substr($match, 0, strpos($match, '.'));
// Put the underscores back in for the hook name and register this
// pattern.
$arg_name = isset($info['variables']) ? 'variables' : 'render element';
$implementations[strtr($file, '-', '_')] = array(
'template' => $file,
'path' => dirname($files[$match]->uri),
$arg_name => $info[$arg_name],
'base hook' => $hook,
);
}
}
}
}
return $implementations;
}