Commit 67e93b23 authored by catch's avatar catch

Issue #2109287 by dawehner, Cottser, tim.plunkett, kim.pepper: Replace...

Issue #2109287 by dawehner, Cottser, tim.plunkett, kim.pepper: Replace list_themes() with a service.
parent 1ceeda43
......@@ -173,6 +173,9 @@ services:
default_plugin_manager:
abstract: true
arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
theme_handler:
class: Drupal\Core\Extension\ThemeHandler
arguments: ['@config.factory', '@module_handler', '@cache.cache', '@info_parser', '@router.builder']
entity.manager:
class: Drupal\Core\Entity\EntityManager
arguments: ['@container.namespaces', '@service_container', '@module_handler', '@cache.cache', '@language_manager', '@string_translation']
......
......@@ -484,7 +484,14 @@ function install_begin_request(&$install_state) {
// Register the info parser.
$container->register('info_parser', 'Drupal\Core\Extension\InfoParser');
$container->register('theme_handler', 'Drupal\Core\Extension\ThemeHandler')
->addArgument(new Reference('config.factory'))
->addArgument(new Reference('module_handler'))
->addArgument(new Reference('cache.cache'))
->addArgument(new Reference('info_parser'));
}
// Set the request in the kernel to the new created Request above
// so it is available to the rest of the installation process.
$container->set('request', $request);
......
......@@ -355,52 +355,19 @@ function drupal_theme_rebuild() {
* the themes' machine names, and the values are the themes' human-readable
* names. This element is not set if there are no themes on the system that
* declare this theme as their base theme.
*
* @deprecated as of Drupal 8.0. Use \Drupal::service('theme_handler')->listInfo().
*/
function list_themes($refresh = FALSE) {
$list = &drupal_static(__FUNCTION__, array());
/** @var \Drupal\Core\Extension\ThemeHandler $theme_handler */
$theme_handler = \Drupal::service('theme_handler');
if ($refresh) {
$list = array();
$theme_handler->reset();
system_list_reset();
}
if (empty($list)) {
$list = array();
// Extract from the database only when it is available.
// Also check that the site is not in the middle of an install or update.
try {
$themes = system_list('theme');
}
catch (Exception $e) {
// If the database is not available, rebuild the theme data.
$themes = _system_rebuild_theme_data();
}
foreach ($themes as $theme) {
foreach ($theme->info['stylesheets'] as $media => $stylesheets) {
foreach ($stylesheets as $stylesheet => $path) {
$theme->stylesheets[$media][$stylesheet] = $path;
}
}
foreach ($theme->info['scripts'] as $script => $path) {
$theme->scripts[$script] = $path;
}
if (isset($theme->info['engine'])) {
$theme->engine = $theme->info['engine'];
}
if (isset($theme->info['base theme'])) {
$theme->base_theme = $theme->info['base theme'];
}
// Status is normally retrieved from the database. Add zero values when
// read from the installation directory to prevent notices.
if (!isset($theme->status)) {
$theme->status = 0;
}
$list[$theme->name] = $theme;
}
}
return $list;
return $theme_handler->listInfo();
}
/**
......@@ -413,38 +380,15 @@ function list_themes($refresh = FALSE) {
* An array of available themes.
* @param $key
* The name of the theme whose base we are looking for.
* @param $used_keys
* (optional) A recursion parameter preventing endless loops. Defaults to
* NULL.
*
* @return
* Returns an array of all of the theme's ancestors; the first element's value
* will be NULL if an error occurred.
*
* @deprecated as of Drupal 8.0. Use \Drupal::service('theme_handler')->getBaseThemes().
*/
function drupal_find_base_themes($themes, $key, $used_keys = array()) {
$base_key = $themes[$key]->info['base theme'];
// Does the base theme exist?
if (!isset($themes[$base_key])) {
return array($base_key => NULL);
}
$current_base_theme = array($base_key => $themes[$base_key]->info['name']);
// Is the base theme itself a child of another theme?
if (isset($themes[$base_key]->info['base theme'])) {
// Do we already know the base themes of this theme?
if (isset($themes[$base_key]->base_themes)) {
return $themes[$base_key]->base_themes + $current_base_theme;
}
// Prevent loops.
if (!empty($used_keys[$base_key])) {
return array($base_key => NULL);
}
$used_keys[$base_key] = TRUE;
return drupal_find_base_themes($themes, $base_key, $used_keys) + $current_base_theme;
}
// If we get here, then this is our parent theme.
return $current_base_theme;
function drupal_find_base_themes($themes, $key) {
return \Drupal::service('theme_handler')->getBaseThemes($themes, $key);
}
/**
......@@ -1133,38 +1077,11 @@ function theme_settings_convert_to_config(array $theme_settings, Config $config)
*
* @param $theme_list
* An array of theme names.
*
* @deprecated as of Drupal 8.0. Use \Drupal::service('theme_handler')->enable().
*/
function theme_enable($theme_list) {
drupal_clear_css_cache();
$theme_config = \Drupal::config('system.theme');
$disabled_themes = \Drupal::config('system.theme.disabled');
foreach ($theme_list as $key) {
// Throw an exception if the theme name is too long.
if (strlen($key) > DRUPAL_EXTENSION_NAME_MAX_LENGTH) {
throw new ExtensionNameLengthException(format_string('Theme name %name is over the maximum allowed length of @max characters.', array(
'%name' => $key,
'@max' => DRUPAL_EXTENSION_NAME_MAX_LENGTH,
)));
}
// The value is not used; the weight is ignored for themes currently.
$theme_config->set("enabled.$key", 0)->save();
$disabled_themes->clear($key)->save();
// Refresh the theme list as config_install_default_config() needs an
// updated list to work.
list_themes(TRUE);
// Install default configuration of the theme.
config_install_default_config('theme', $key);
}
\Drupal::service('router.builder')->rebuild();
menu_router_rebuild();
\Drupal::cache('cache')->deleteTags(array('local_task' => 1));
drupal_theme_rebuild();
// Invoke hook_themes_enabled() after the themes have been enabled.
\Drupal::moduleHandler()->invokeAll('themes_enabled', array($theme_list));
\Drupal::service('theme_handler')->enable($theme_list);
}
/**
......@@ -1172,36 +1089,11 @@ function theme_enable($theme_list) {
*
* @param $theme_list
* An array of theme names.
*
* @deprecated as of Drupal 8.0. Use \Drupal::service('theme_handler')->disable().
*/
function theme_disable($theme_list) {
// Don't disable the default theme.
if ($pos = array_search(\Drupal::config('system.theme')->get('default'), $theme_list) !== FALSE) {
unset($theme_list[$pos]);
if (empty($theme_list)) {
return;
}
}
drupal_clear_css_cache();
$theme_config = \Drupal::config('system.theme');
$disabled_themes = \Drupal::config('system.theme.disabled');
foreach ($theme_list as $key) {
// The value is not used; the weight is ignored for themes currently.
$theme_config->clear("enabled.$key");
$disabled_themes->set($key, 0);
}
$theme_config->save();
$disabled_themes->save();
list_themes(TRUE);
\Drupal::service('router.builder')->rebuild();
menu_router_rebuild();
\Drupal::cache('cache')->deleteTags(array('local_task' => 1));
drupal_theme_rebuild();
// Invoke hook_themes_disabled after the themes have been disabled.
\Drupal::moduleHandler()->invokeAll('themes_disabled', array($theme_list));
\Drupal::service('theme_handler')->disable($theme_list);
}
/**
......
......@@ -9,6 +9,7 @@
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderInterface;
use Symfony\Component\DependencyInjection\Reference;
/**
* ServiceProvider class for update.php service overrides.
......@@ -38,6 +39,12 @@ public function register(ContainerBuilder $container) {
->register("cache_factory", 'Drupal\Core\Cache\MemoryBackendFactory');
$container
->register('router.builder', 'Drupal\Core\Routing\RouteBuilderStatic');
$container->register('theme_handler', 'Drupal\Core\Extension\ThemeHandler')
->addArgument(new Reference('config.factory'))
->addArgument(new Reference('module_handler'))
->addArgument(new Reference('cache.cache'))
->addArgument(new Reference('info_parser'));
}
}
This diff is collapsed.
<?php
/**
* @file
* Contains \Drupal\Core\Extension\ThemeHandlerInterface.
*/
namespace Drupal\Core\Extension;
/**
* Manages the list of available themes as well as enable/disable them.
*/
interface ThemeHandlerInterface {
/**
* Enables a given list of themes.
*
* @param array $theme_list
* An array of theme names.
*
* @throws \Drupal\Core\Extension\ExtensionNameLengthException
* Thrown when the theme name is to long
*/
public function enable(array $theme_list);
/**
* Disables a given list of themes.
*
* @param array $theme_list
* An array of theme names.
*/
public function disable(array $theme_list);
/**
* Returns a list of all currently available themes.
*
* Retrieved from the database, if available and the site is not in
* maintenance mode; otherwise compiled freshly from the filesystem.
*
* @return array
* An associative array of the currently available themes. The keys are the
* themes' machine names and the values are objects having the following
* properties:
* - filename: The filepath and name of the .info.yml file.
* - name: The machine name of the theme.
* - status: 1 for enabled, 0 for disabled themes.
* - info: The contents of the .info.yml file.
* - stylesheets: A two dimensional array, using the first key for the
* media attribute (e.g. 'all'), the second for the name of the file
* (e.g. style.css). The value is a complete filepath (e.g.
* themes/bartik/style.css). Not set if no stylesheets are defined in the
* .info.yml file.
* - scripts: An associative array of JavaScripts, using the filename as key
* and the complete filepath as value. Not set if no scripts are defined
* in the .info.yml file.
* - prefix: The base theme engine prefix.
* - engine: The machine name of the theme engine.
* - base_theme: If this is a sub-theme, the machine name of the base theme
* defined in the .info.yml file. Otherwise, the element is not set.
* - base_themes: If this is a sub-theme, an associative array of the
* base-theme ancestors of this theme, starting with this theme's base
* theme, then the base theme's own base theme, etc. Each entry has an
* array key equal to the theme's machine name, and a value equal to the
* human-readable theme name; if a theme with matching machine name does
* not exist in the system, the value will instead be NULL (and since the
* system would not know whether that theme itself has a base theme, that
* will end the array of base themes). This is not set if the theme is not
* a sub-theme.
* - sub_themes: An associative array of themes on the system that are
* either direct sub-themes (that is, they declare this theme to be
* their base theme), direct sub-themes of sub-themes, etc. The keys are
* the themes' machine names, and the values are the themes'
* human-readable names. This element is not set if there are no themes on
* the system that declare this theme as their base theme.
*/
public function listInfo();
/**
* Resets the internal state of the theme handler.
*/
public function reset();
/**
* Helper function to scan and collect theme .info.yml data and their engines.
*
* @return array
* An associative array of themes information.
*/
public function rebuildThemeData();
/**
* Finds all the base themes for the specified theme.
*
* Themes can inherit templates and function implementations from earlier
* themes.
*
* @param array $themes
* An array of available themes.
* @param string $theme
* The name of the theme whose base we are looking for.
*
* @return array
* Returns an array of all of the theme's ancestors; the first element's
* value will be NULL if an error occurred.
*/
public function getBaseThemes(array $themes, $theme);
}
......@@ -2461,117 +2461,11 @@ function system_rebuild_module_data() {
*
* @return
* An associative array of themes information.
*
* @deprecated as of Drupal 8.0. Use \Drupal::service('theme_handler')->rebuildThemeData().
*/
function _system_rebuild_theme_data() {
// Find themes
$themes = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info.yml$/', 'themes');
// Allow modules to add further themes.
if ($module_themes = \Drupal::moduleHandler()->invokeAll('system_theme_info')) {
foreach ($module_themes as $name => $uri) {
// @see file_scan_directory()
$themes[$name] = (object) array(
'uri' => $uri,
'filename' => pathinfo($uri, PATHINFO_FILENAME),
'name' => $name,
);
}
}
// Find theme engines
$engines = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.engine$/', 'themes/engines');
// Set defaults for theme info.
$defaults = array(
'engine' => 'twig',
'regions' => array(
'sidebar_first' => 'Left sidebar',
'sidebar_second' => 'Right sidebar',
'content' => 'Content',
'header' => 'Header',
'footer' => 'Footer',
'highlighted' => 'Highlighted',
'help' => 'Help',
'page_top' => 'Page top',
'page_bottom' => 'Page bottom',
),
'description' => '',
'features' => _system_default_theme_features(),
'screenshot' => 'screenshot.png',
'php' => DRUPAL_MINIMUM_PHP,
'stylesheets' => array(),
'scripts' => array(),
);
$sub_themes = array();
// Read info files for each theme
foreach ($themes as $key => $theme) {
$themes[$key]->filename = $theme->uri;
$themes[$key]->info = \Drupal::service('info_parser')->parse($theme->uri) + $defaults;
// Skip this extension if its type is not theme.
if (!isset($themes[$key]->info['type']) || $themes[$key]->info['type'] != 'theme') {
unset($themes[$key]);
continue;
}
// Add the info file modification time, so it becomes available for
// contributed modules to use for ordering theme lists.
$themes[$key]->info['mtime'] = filemtime($theme->uri);
// Invoke hook_system_info_alter() to give installed modules a chance to
// modify the data in the .info.yml files if necessary.
$type = 'theme';
drupal_alter('system_info', $themes[$key]->info, $themes[$key], $type);
if (!empty($themes[$key]->info['base theme'])) {
$sub_themes[] = $key;
}
$engine = $themes[$key]->info['engine'];
if (isset($engines[$engine])) {
$themes[$key]->owner = $engines[$engine]->uri;
$themes[$key]->prefix = $engines[$engine]->name;
$themes[$key]->template = TRUE;
}
// Prefix stylesheets and scripts with module path.
$path = dirname($theme->uri);
$theme->info['stylesheets'] = _system_info_add_path($theme->info['stylesheets'], $path);
$theme->info['scripts'] = _system_info_add_path($theme->info['scripts'], $path);
// Give the screenshot proper path information.
if (!empty($themes[$key]->info['screenshot'])) {
$themes[$key]->info['screenshot'] = $path . '/' . $themes[$key]->info['screenshot'];
}
}
// Now that we've established all our master themes, go back and fill in data
// for subthemes.
foreach ($sub_themes as $key) {
$themes[$key]->base_themes = drupal_find_base_themes($themes, $key);
// Don't proceed if there was a problem with the root base theme.
if (!current($themes[$key]->base_themes)) {
continue;
}
$base_key = key($themes[$key]->base_themes);
foreach (array_keys($themes[$key]->base_themes) as $base_theme) {
$themes[$base_theme]->sub_themes[$key] = $themes[$key]->info['name'];
}
// Copy the 'owner' and 'engine' over if the top level theme uses a theme
// engine.
if (isset($themes[$base_key]->owner)) {
if (isset($themes[$base_key]->info['engine'])) {
$themes[$key]->info['engine'] = $themes[$base_key]->info['engine'];
$themes[$key]->owner = $themes[$base_key]->owner;
$themes[$key]->prefix = $themes[$base_key]->prefix;
}
else {
$themes[$key]->prefix = $key;
}
}
}
return $themes;
return \Drupal::service('theme_handler')->rebuildThemeData();
}
/**
......@@ -2607,41 +2501,6 @@ function system_rebuild_theme_data() {
return $themes;
}
/**
* Prefixes all values in an .info.yml file array with a given path.
*
* This helper function is mainly used to prefix all array values of an
* .info.yml file property with a single given path (to the module or theme);
* e.g., to prefix all values of the 'stylesheets' or 'scripts' properties with
* the file path to the defining module/theme.
*
* @param $info
* A nested array of data of an .info.yml file to be processed.
* @param $path
* A file path to prepend to each value in $info.
*
* @return
* The $info array with prefixed values.
*
* @see _system_rebuild_module_data()
* @see _system_rebuild_theme_data()
*/
function _system_info_add_path($info, $path) {
foreach ($info as $key => $value) {
// Recurse into nested values until we reach the deepest level.
if (is_array($value)) {
$info[$key] = _system_info_add_path($info[$key], $path);
}
// Unset the original value's key and set the new value with prefix, using
// the original value as key, so original values can still be looked up.
else {
unset($info[$key]);
$info[$value] = $path . '/' . $value;
}
}
return $info;
}
/**
* Returns an array of default theme features.
*/
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment