/** * Builds the theme registry cache. * * Theme hook definitions are collected in the following order: * - Modules * - Base theme engines * - Base themes * - Theme engine * - Theme * * All theme hook definitions are essentially just collated and merged in the * above order. However, various extension-specific default values and * customizations are required; e.g., to record the effective file path for * theme template. Therefore, this method first collects all extensions per * type, and then dispatches the processing for each extension to * processExtension(). * * After completing the collection, modules are allowed to alter it. Lastly, * any derived and incomplete theme hook definitions that are hook suggestions * for base hooks (e.g., 'block__node' for the base hook 'block') need to be * determined based on the full registry and classified as 'base hook'. * * See the @link themeable Default theme implementations topic @endlink for * details. * * @return \Drupal\Core\Utility\ThemeRegistry * The build theme registry. * * @see hook_theme_registry_alter() */ protected function build() { $cache = array(); // First, preprocess the theme hooks advertised by modules. This will // serve as the basic registry. Since the list of enabled modules is the // same regardless of the theme used, this is cached in its own entry to // save building it for every theme. if ($cached = $this->cache->get('theme_registry:build:modules')) { $cache = $cached->data; } else { foreach ($this->moduleHandler->getImplementations('theme') as $module) { $this->processExtension($cache, $module, 'module', $module, $this->getPath($module)); } // Only cache this registry if all modules are loaded. if ($this->moduleHandler->isLoaded()) { $this->cache->set("theme_registry:build:modules", $cache, Cache::PERMANENT, array('theme_registry')); } } // Process each base theme. // Ensure that we start with the root of the parents, so that both CSS files // and preprocess functions comes first. foreach (array_reverse($this->theme->getBaseThemes()) as $base) { // If the base theme uses a theme engine, process its hooks. $base_path = $base->getPath(); if ($this->theme->getEngine()) { $this->processExtension($cache, $this->theme->getEngine(), 'base_theme_engine', $base->getName(), $base_path); } $this->processExtension($cache, $base->getName(), 'base_theme', $base->getName(), $base_path); } // And then the same thing, but for the theme. if ($this->theme->getEngine()) { $this->processExtension($cache, $this->theme->getEngine(), 'theme_engine', $this->theme->getName(), $this->theme->getPath()); } // Hooks provided by the theme itself. $this->processExtension($cache, $this->theme->getName(), 'theme', $this->theme->getName(), $this->theme->getPath()); // Discover and add all preprocess functions for theme hook suggestions. $this->postProcessExtension($cache, $this->theme); // Let modules and themes alter the registry. $this->moduleHandler->alter('theme_registry', $cache); $this->themeManager->alterForTheme($this->theme, 'theme_registry', $cache); // @todo Implement more reduction of the theme registry entry. // Optimize the registry to not have empty arrays for functions. foreach ($cache as $hook => $info) { if (empty($info['preprocess functions'])) { unset($cache[$hook]['preprocess functions']); } } $this->registry[$this->theme->getName()] = $cache; return $this->registry[$this->theme->getName()]; }