protected Registry::processExtension(array &$cache, $name, $type, $theme, $path)
Process a single implementation of hook_theme().
array $cache: The theme registry that will eventually be cached; It is an associative array keyed by theme hooks, whose values are associative arrays describing the hook:
string $name: The name of the module, theme engine, base theme engine, theme or base theme implementing hook_theme().
string $type: One of 'module', 'theme_engine', 'base_theme_engine', 'theme', or 'base_theme'. Unlike regular hooks that can only be implemented by modules, each of these can implement hook_theme(). This function is called in aforementioned order and new entries override older ones. For example, if a theme hook is both defined by a module and a theme, then the definition in the theme will be used.
string $theme: The actual name of theme, module, etc. that is being processed.
string $path: The directory where $name is. For example, modules/system or themes/bartik.
\BadFunctionCallException
\Drupal\Core\Theme\ThemeManagerInterface::render()
\Drupal\Core\Extension\ThemeHandler::listInfo()
protected function processExtension(array &$cache, $name, $type, $theme, $path) { $result = array(); $hook_defaults = array( 'variables' => TRUE, 'render element' => TRUE, 'pattern' => TRUE, 'base hook' => TRUE, ); $module_list = array_keys($this->moduleHandler->getModuleList()); // Invoke the hook_theme() implementation, preprocess what is returned, and // merge it into $cache. $function = $name . '_theme'; if (function_exists($function)) { $result = $function($cache, $type, $theme, $path); foreach ($result as $hook => $info) { // When a theme or engine overrides a module's theme function // $result[$hook] will only contain key/value pairs for information being // overridden. Pull the rest of the information from what was defined by // an earlier hook. // Fill in the type and path of the module, theme, or engine that // implements this theme function. $result[$hook]['type'] = $type; $result[$hook]['theme path'] = $path; // If a theme hook has a base hook, mark its preprocess functions always // incomplete in order to inherit the base hook's preprocess functions. if (!empty($result[$hook]['base hook'])) { $result[$hook]['incomplete preprocess functions'] = TRUE; } if (isset($cache[$hook]['includes'])) { $result[$hook]['includes'] = $cache[$hook]['includes']; } // Load the includes, as they may contain preprocess functions. if (isset($info['includes'])) { foreach ($info['includes'] as $include_file) { include_once $this->root . '/' . $include_file; } } // If the theme implementation defines a file, then also use the path // that it defined. Otherwise use the default path. This allows // system.module to declare theme functions on behalf of core .include // files. if (isset($info['file'])) { $include_file = isset($info['path']) ? $info['path'] : $path; $include_file .= '/' . $info['file']; include_once $this->root . '/' . $include_file; $result[$hook]['includes'][] = $include_file; } // A template file is the default implementation for a theme hook, but // if the theme hook specifies a function callback instead, check to // ensure the function actually exists. if (isset($info['function'])) { if (!function_exists($info['function'])) { throw new \BadFunctionCallException(sprintf( 'Theme hook "%s" refers to a theme function callback that does not exist: "%s"', $hook, $info['function'] )); } } // Provide a default naming convention for 'template' based on the // hook used. If the template does not exist, the theme engine used // should throw an exception at runtime when attempting to include // the template file. elseif (!isset($info['template'])) { $info['template'] = strtr($hook, '_', '-'); $result[$hook]['template'] = $info['template']; } // Prepend the current theming path when none is set. This is required // for the default theme engine to know where the template lives. if (isset($result[$hook]['template']) && !isset($info['path'])) { $result[$hook]['path'] = $path . '/templates'; } // If the default keys are not set, use the default values registered // by the module. if (isset($cache[$hook])) { $result[$hook] += array_intersect_key($cache[$hook], $hook_defaults); } // Preprocess variables for all theming hooks, whether the hook is // implemented as a template or as a function. Ensure they are arrays. if (!isset($info['preprocess functions']) || !is_array($info['preprocess functions'])) { $info['preprocess functions'] = array(); $prefixes = array(); if ($type == 'module') { // Default variable preprocessor prefix. $prefixes[] = 'template'; // Add all modules so they can intervene with their own variable // preprocessors. This allows them to provide variable preprocessors // even if they are not the owner of the current hook. $prefixes = array_merge($prefixes, $module_list); } elseif ($type == 'theme_engine' || $type == 'base_theme_engine') { // Theme engines get an extra set that come before the normally // named variable preprocessors. $prefixes[] = $name . '_engine'; // The theme engine registers on behalf of the theme using the // theme's name. $prefixes[] = $theme; } else { // This applies when the theme manually registers their own variable // preprocessors. $prefixes[] = $name; } foreach ($prefixes as $prefix) { // Only use non-hook-specific variable preprocessors for theming // hooks implemented as templates. See the @defgroup themeable // topic. if (isset($info['template']) && function_exists($prefix . '_preprocess')) { $info['preprocess functions'][] = $prefix . '_preprocess'; } if (function_exists($prefix . '_preprocess_' . $hook)) { $info['preprocess functions'][] = $prefix . '_preprocess_' . $hook; } } } // Check for the override flag and prevent the cached variable // preprocessors from being used. This allows themes or theme engines // to remove variable preprocessors set earlier in the registry build. if (!empty($info['override preprocess functions'])) { // Flag not needed inside the registry. unset($result[$hook]['override preprocess functions']); } elseif (isset($cache[$hook]['preprocess functions']) && is_array($cache[$hook]['preprocess functions'])) { $info['preprocess functions'] = array_merge($cache[$hook]['preprocess functions'], $info['preprocess functions']); } $result[$hook]['preprocess functions'] = $info['preprocess functions']; } // Merge the newly created theme hooks into the existing cache. $cache = $result + $cache; } // Let themes have variable preprocessors even if they didn't register a // template. if ($type == 'theme' || $type == 'base_theme') { foreach ($cache as $hook => $info) { // Check only if not registered by the theme or engine. if (empty($result[$hook])) { if (!isset($info['preprocess functions'])) { $cache[$hook]['preprocess functions'] = array(); } // Only use non-hook-specific variable preprocessors for theme hooks // implemented as templates. See the @defgroup themeable topic. if (isset($info['template']) && function_exists($name . '_preprocess')) { $cache[$hook]['preprocess functions'][] = $name . '_preprocess'; } if (function_exists($name . '_preprocess_' . $hook)) { $cache[$hook]['preprocess functions'][] = $name . '_preprocess_' . $hook; $cache[$hook]['theme path'] = $path; } } } } }
© 2001–2016 by the original authors
Licensed under the GNU General Public License, version 2 and later.
Drupal is a registered trademark of Dries Buytaert.
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Theme!Registry.php/function/Registry::processExtension/8.1.x