Commit 2c90c67c authored by webchick's avatar webchick

Issue #1067408 by alexpott, Jalandhar, jessebeach, Désiré, neetu morwani,...

Issue #1067408 by alexpott, Jalandhar, jessebeach, Désiré, neetu morwani, dawehner, sun: Themes do not have an installation status.
parent 45e59c9b
module: {} module: {}
theme: theme: {}
stark: 0
disabled: disabled:
theme: {} theme: {}
...@@ -203,7 +203,7 @@ services: ...@@ -203,7 +203,7 @@ services:
arguments: ['%container.modules%', '@cache.bootstrap'] arguments: ['%container.modules%', '@cache.bootstrap']
theme_handler: theme_handler:
class: Drupal\Core\Extension\ThemeHandler class: Drupal\Core\Extension\ThemeHandler
arguments: ['@config.factory', '@module_handler', '@cache.default', '@info_parser', '@config.installer', '@router.builder'] arguments: ['@config.factory', '@module_handler', '@state', '@info_parser', '@config.installer', '@router.builder']
entity.manager: entity.manager:
class: Drupal\Core\Entity\EntityManager class: Drupal\Core\Entity\EntityManager
arguments: ['@container.namespaces', '@module_handler', '@cache.discovery', '@language_manager', '@string_translation'] arguments: ['@container.namespaces', '@module_handler', '@cache.discovery', '@language_manager', '@string_translation']
......
...@@ -686,6 +686,8 @@ function install_tasks($install_state) { ...@@ -686,6 +686,8 @@ function install_tasks($install_state) {
'display_name' => t('Install site'), 'display_name' => t('Install site'),
'type' => 'batch', 'type' => 'batch',
), ),
'install_profile_themes' => array(
),
'install_import_translations' => array( 'install_import_translations' => array(
'display_name' => t('Set up translations'), 'display_name' => t('Set up translations'),
'display' => $needs_translations, 'display' => $needs_translations,
...@@ -1827,6 +1829,34 @@ function install_profile_modules(&$install_state) { ...@@ -1827,6 +1829,34 @@ function install_profile_modules(&$install_state) {
return $batch; return $batch;
} }
/**
* Installs themes.
*
* This does not use a batch, since installing themes is faster than modules and
* because an installation profile typically enables 1-3 themes only (default
* theme, base theme, admin theme).
*
* @param $install_state
* An array of information about the current installation state.
*/
function install_profile_themes(&$install_state) {
$theme_handler = \Drupal::service('theme_handler');
// ThemeHandler::enable() resets the current list of themes. The theme used in
// the installer is not necessarily in the list of themes to install, so
// retain the current list.
// @see _drupal_maintenance_theme()
$current_themes = $theme_handler->listInfo();
// Install the themes specified by the installation profile.
$themes = $install_state['profile_info']['themes'];
$theme_handler->enable($themes);
foreach ($current_themes as $theme) {
$theme_handler->addTheme($theme);
}
}
/** /**
* Imports languages via a batch process during installation. * Imports languages via a batch process during installation.
* *
......
...@@ -1077,6 +1077,7 @@ function install_profile_info($profile, $langcode = 'en') { ...@@ -1077,6 +1077,7 @@ function install_profile_info($profile, $langcode = 'en') {
// Set defaults for module info. // Set defaults for module info.
$defaults = array( $defaults = array(
'dependencies' => array(), 'dependencies' => array(),
'themes' => array('stark'),
'description' => '', 'description' => '',
'version' => NULL, 'version' => NULL,
'hidden' => FALSE, 'hidden' => FALSE,
......
...@@ -9,26 +9,18 @@ ...@@ -9,26 +9,18 @@
use Drupal\Core\Extension\ExtensionDiscovery; use Drupal\Core\Extension\ExtensionDiscovery;
/** /**
* Builds a list of bootstrap modules and enabled modules and themes. * Builds a list of enabled themes.
* *
* @param $type * @param $type
* The type of list to return: * The type of list to return:
* - module_enabled: All enabled modules. * - theme: All enabled themes.
* - bootstrap: All enabled modules required for bootstrap.
* - theme: All themes.
* *
* @return * @return
* An associative array of modules or themes, keyed by name. For $type * An associative array of themes, keyed by name.
* 'bootstrap' and 'module_enabled', the array values equal the keys.
* For $type 'theme', the array values are objects representing the * For $type 'theme', the array values are objects representing the
* respective database row, with the 'info' property already unserialized. * respective database row, with the 'info' property already unserialized.
* *
* @see list_themes() * @see list_themes()
*
* @todo There are too many layers/levels of caching involved for system_list()
* data. Consider to add a \Drupal::config($name, $cache = TRUE) argument to allow
* callers like system_list() to force-disable a possible configuration
* storage cache or some other way to circumvent it/take it over.
*/ */
function system_list($type) { function system_list($type) {
$lists = &drupal_static(__FUNCTION__); $lists = &drupal_static(__FUNCTION__);
...@@ -40,32 +32,15 @@ function system_list($type) { ...@@ -40,32 +32,15 @@ function system_list($type) {
'theme' => array(), 'theme' => array(),
'filepaths' => array(), 'filepaths' => array(),
); );
// Build a list of themes. // ThemeHandler maintains the 'system.theme.data' state record.
$enabled_themes = \Drupal::config('core.extension')->get('theme') ?: array(); $theme_data = \Drupal::state()->get('system.theme.data', array());
// @todo Themes include all themes, including disabled/uninstalled. This
// system.theme.data state will go away entirely as soon as themes have
// a proper installation status.
// @see http://drupal.org/node/1067408
$theme_data = \Drupal::state()->get('system.theme.data');
if (empty($theme_data)) {
// @todo: system_list() may be called from _drupal_bootstrap_code(), in
// which case system.module is not loaded yet.
// Prevent a filesystem scan in drupal_load() and include it directly.
// @see http://drupal.org/node/1067408
require_once DRUPAL_ROOT . '/core/modules/system/system.module';
$theme_data = system_rebuild_theme_data();
}
foreach ($theme_data as $name => $theme) { foreach ($theme_data as $name => $theme) {
$theme->status = (int) isset($enabled_themes[$name]);
$lists['theme'][$name] = $theme; $lists['theme'][$name] = $theme;
// Build a list of filenames so drupal_get_filename can use it. $lists['filepaths'][] = array(
if (isset($enabled_themes[$name])) { 'type' => 'theme',
$lists['filepaths'][] = array( 'name' => $name,
'type' => 'theme', 'filepath' => $theme->getPathname(),
'name' => $name, );
'filepath' => $theme->getPathname(),
);
}
} }
\Drupal::cache('bootstrap')->set('system_list', $lists); \Drupal::cache('bootstrap')->set('system_list', $lists);
} }
...@@ -84,25 +59,17 @@ function system_list($type) { ...@@ -84,25 +59,17 @@ function system_list($type) {
function system_list_reset() { function system_list_reset() {
drupal_static_reset('system_list'); drupal_static_reset('system_list');
drupal_static_reset('system_rebuild_module_data'); drupal_static_reset('system_rebuild_module_data');
drupal_static_reset('list_themes');
\Drupal::cache('bootstrap')->delete('system_list'); \Drupal::cache('bootstrap')->delete('system_list');
\Drupal::cache()->delete('system_info');
// Clear the library info cache. // Clear the library info cache.
// Libraries may be provided by all extension types, and may be altered by any // Libraries may be provided by all extension types, and may be altered by any
// other extensions (types) due to the nature of // other extensions (types) due to the nature of
// \Drupal\Core\Extension\ModuleHandler::alter() and the fact that profiles // \Drupal\Core\Extension\ModuleHandler::alter() and the fact that profiles
// are recorded and handled as modules. // are recorded and handled as modules.
// @todo Trigger an event upon module install/uninstall and theme
// enable/disable, and move this into an event subscriber.
// @see https://drupal.org/node/2206347
Cache::invalidateTags(array('extension' => TRUE)); Cache::invalidateTags(array('extension' => TRUE));
// Remove last known theme data state.
// This causes system_list() to call system_rebuild_theme_data() on its next
// invocation. When enabling a module that implements hook_system_info_alter()
// to inject a new (testing) theme or manipulate an existing theme, then that
// will cause system_list_reset() to be called, but theme data is not
// necessarily rebuilt afterwards.
// @todo Obsolete with proper installation status for themes.
\Drupal::state()->delete('system.theme.data');
} }
/** /**
......
...@@ -103,7 +103,21 @@ function drupal_theme_initialize() { ...@@ -103,7 +103,21 @@ function drupal_theme_initialize() {
// Determine the active theme for the theme negotiator service. This includes // Determine the active theme for the theme negotiator service. This includes
// the default theme as well as really specific ones like the ajax base theme. // the default theme as well as really specific ones like the ajax base theme.
$request = \Drupal::request(); $request = \Drupal::request();
$theme = \Drupal::service('theme.negotiator')->determineActiveTheme($request) ?: 'stark'; $theme = \Drupal::service('theme.negotiator')->determineActiveTheme($request);
// If no theme could be negotiated, or if the negotiated theme is not within
// the list of enabled themes, fall back to the default theme output of core
// and modules (similar to Stark, but without a theme extension at all). This
// is possible, because _drupal_theme_initialize() always loads the Twig theme
// engine.
if (!$theme || !isset($themes[$theme])) {
$theme = 'core';
$theme_key = $theme;
// /core/core.info.yml does not actually exist, but is required because
// Extension expects a pathname.
_drupal_theme_initialize(new Extension('theme', 'core/core.info.yml'));
return;
}
// Store the identifier for retrieving theme settings with. // Store the identifier for retrieving theme settings with.
$theme_key = $theme; $theme_key = $theme;
...@@ -401,6 +415,8 @@ function _theme($hook, $variables = array()) { ...@@ -401,6 +415,8 @@ function _theme($hook, $variables = array()) {
if (!$module_handler->isLoaded() && !defined('MAINTENANCE_MODE')) { if (!$module_handler->isLoaded() && !defined('MAINTENANCE_MODE')) {
throw new Exception(t('_theme() may not be called until all modules are loaded.')); throw new Exception(t('_theme() may not be called until all modules are loaded.'));
} }
// Ensure the theme is initialized.
drupal_theme_initialize();
/** @var \Drupal\Core\Utility\ThemeRegistry $theme_registry */ /** @var \Drupal\Core\Utility\ThemeRegistry $theme_registry */
$theme_registry = \Drupal::service('theme.registry')->getRuntime(); $theme_registry = \Drupal::service('theme.registry')->getRuntime();
...@@ -851,8 +867,8 @@ function theme_get_setting($setting_name, $theme = NULL) { ...@@ -851,8 +867,8 @@ function theme_get_setting($setting_name, $theme = NULL) {
// Get the values for the theme-specific settings from the .info.yml files // Get the values for the theme-specific settings from the .info.yml files
// of the theme and all its base themes. // of the theme and all its base themes.
if ($theme) { $themes = list_themes();
$themes = list_themes(); if ($theme && isset($themes[$theme])) {
$theme_object = $themes[$theme]; $theme_object = $themes[$theme];
// Create a list which includes the current theme and all its base themes. // Create a list which includes the current theme and all its base themes.
...@@ -874,7 +890,7 @@ function theme_get_setting($setting_name, $theme = NULL) { ...@@ -874,7 +890,7 @@ function theme_get_setting($setting_name, $theme = NULL) {
// Get the global settings from configuration. // Get the global settings from configuration.
$cache[$theme]->merge(\Drupal::config('system.theme.global')->get()); $cache[$theme]->merge(\Drupal::config('system.theme.global')->get());
if ($theme) { if ($theme && isset($themes[$theme])) {
// Retrieve configured theme-specific settings, if any. // Retrieve configured theme-specific settings, if any.
try { try {
if ($theme_settings = \Drupal::config($theme . '.settings')->get()) { if ($theme_settings = \Drupal::config($theme . '.settings')->get()) {
...@@ -975,13 +991,16 @@ function theme_settings_convert_to_config(array $theme_settings, Config $config) ...@@ -975,13 +991,16 @@ function theme_settings_convert_to_config(array $theme_settings, Config $config)
* @param $theme_list * @param $theme_list
* An array of theme names. * An array of theme names.
* *
* @return bool
* Whether any of the given themes have been enabled.
*
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal::service('theme_handler')->enable(). * Use \Drupal::service('theme_handler')->enable().
* *
* @see \Drupal\Core\Extension\ThemeHandler::enable(). * @see \Drupal\Core\Extension\ThemeHandler::enable().
*/ */
function theme_enable($theme_list) { function theme_enable($theme_list) {
\Drupal::service('theme_handler')->enable($theme_list); return \Drupal::service('theme_handler')->enable($theme_list);
} }
/** /**
...@@ -990,13 +1009,16 @@ function theme_enable($theme_list) { ...@@ -990,13 +1009,16 @@ function theme_enable($theme_list) {
* @param $theme_list * @param $theme_list
* An array of theme names. * An array of theme names.
* *
* @return bool
* Whether any of the given themes have been disabled.
*
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal::service('theme_handler')->disable(). * Use \Drupal::service('theme_handler')->disable().
* *
* @see \Drupal\Core\Extension\ThemeHandler::disable(). * @see \Drupal\Core\Extension\ThemeHandler::disable().
*/ */
function theme_disable($theme_list) { function theme_disable($theme_list) {
\Drupal::service('theme_handler')->disable($theme_list); return \Drupal::service('theme_handler')->disable($theme_list);
} }
/** /**
......
...@@ -66,7 +66,7 @@ function _drupal_maintenance_theme() { ...@@ -66,7 +66,7 @@ function _drupal_maintenance_theme() {
} }
// Ensure that system.module is loaded. // Ensure that system.module is loaded.
if (!function_exists('_system_rebuild_theme_data')) { if (!function_exists('system_rebuild_theme_data')) {
$module_handler = \Drupal::moduleHandler(); $module_handler = \Drupal::moduleHandler();
$module_handler->addModule('system', 'core/modules/system'); $module_handler->addModule('system', 'core/modules/system');
$module_handler->load('system'); $module_handler->load('system');
...@@ -74,6 +74,14 @@ function _drupal_maintenance_theme() { ...@@ -74,6 +74,14 @@ function _drupal_maintenance_theme() {
$themes = list_themes(); $themes = list_themes();
// If no themes are installed yet, or if the requested custom theme is not
// installed, retrieve all available themes.
if (empty($themes) || !isset($themes[$custom_theme])) {
$theme_handler = \Drupal::service('theme_handler');
$themes = $theme_handler->rebuildThemeData();
$theme_handler->addTheme($themes[$custom_theme]);
}
// list_themes() triggers a \Drupal\Core\Extension\ModuleHandler::alter() in // list_themes() triggers a \Drupal\Core\Extension\ModuleHandler::alter() in
// maintenance mode, but we can't let themes alter the .info.yml data until // maintenance mode, but we can't let themes alter the .info.yml data until
// we know a theme's base themes. So don't set global $theme until after // we know a theme's base themes. So don't set global $theme until after
......
...@@ -41,7 +41,7 @@ public function register(ContainerBuilder $container) { ...@@ -41,7 +41,7 @@ public function register(ContainerBuilder $container) {
$container->register('theme_handler', 'Drupal\Core\Extension\ThemeHandler') $container->register('theme_handler', 'Drupal\Core\Extension\ThemeHandler')
->addArgument(new Reference('config.factory')) ->addArgument(new Reference('config.factory'))
->addArgument(new Reference('module_handler')) ->addArgument(new Reference('module_handler'))
->addArgument(new Reference('cache.default')) ->addArgument(new Reference('state'))
->addArgument(new Reference('info_parser')); ->addArgument(new Reference('info_parser'));
} }
} }
......
...@@ -758,8 +758,6 @@ public function install(array $module_list, $enable_dependencies = TRUE) { ...@@ -758,8 +758,6 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
// Refresh the schema to include it. // Refresh the schema to include it.
drupal_get_schema(NULL, TRUE); drupal_get_schema(NULL, TRUE);
// Update the theme registry to include it.
drupal_theme_rebuild();
// Allow modules to react prior to the installation of a module. // Allow modules to react prior to the installation of a module.
$this->invokeAll('module_preinstall', array($module)); $this->invokeAll('module_preinstall', array($module));
...@@ -804,8 +802,18 @@ public function install(array $module_list, $enable_dependencies = TRUE) { ...@@ -804,8 +802,18 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
// Record the fact that it was installed. // Record the fact that it was installed.
$modules_installed[] = $module; $modules_installed[] = $module;
// Update the theme registry to include it.
drupal_theme_rebuild();
// Modules can alter theme info, so refresh theme data.
// @todo ThemeHandler cannot be injected into ModuleHandler, since that
// causes a circular service dependency.
// @see https://drupal.org/node/2208429
\Drupal::service('theme_handler')->refreshInfo();
// Allow the module to perform install tasks. // Allow the module to perform install tasks.
$this->invoke($module, 'install'); $this->invoke($module, 'install');
// Record the fact that it was installed. // Record the fact that it was installed.
watchdog('system', '%module module installed.', array('%module' => $module), WATCHDOG_INFO); watchdog('system', '%module module installed.', array('%module' => $module), WATCHDOG_INFO);
} }
...@@ -912,6 +920,12 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) { ...@@ -912,6 +920,12 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
// Update the theme registry to remove the newly uninstalled module. // Update the theme registry to remove the newly uninstalled module.
drupal_theme_rebuild(); drupal_theme_rebuild();
// Modules can alter theme info, so refresh theme data.
// @todo ThemeHandler cannot be injected into ModuleHandler, since that
// causes a circular service dependency.
// @see https://drupal.org/node/2208429
\Drupal::service('theme_handler')->refreshInfo();
watchdog('system', '%module module uninstalled.', array('%module' => $module), WATCHDOG_INFO); watchdog('system', '%module module uninstalled.', array('%module' => $module), WATCHDOG_INFO);
$schema_store->delete($module); $schema_store->delete($module);
......
...@@ -17,28 +17,35 @@ interface ThemeHandlerInterface { ...@@ -17,28 +17,35 @@ interface ThemeHandlerInterface {
* *
* @param array $theme_list * @param array $theme_list
* An array of theme names. * An array of theme names.
* @param bool $enable_dependencies
* (optional) If TRUE, dependencies will automatically be installed in the
* correct order. This incurs a significant performance cost, so use FALSE
* if you know $theme_list is already complete and in the correct order.
*
* @return bool
* Whether any of the given themes have been enabled.
* *
* @throws \Drupal\Core\Extension\ExtensionNameLengthException * @throws \Drupal\Core\Extension\ExtensionNameLengthException
* Thrown when the theme name is to long * Thrown when the theme name is to long
*/ */
public function enable(array $theme_list); public function enable(array $theme_list, $enable_dependencies = TRUE);
/** /**
* Disables a given list of themes. * Disables a given list of themes.
* *
* @param array $theme_list * @param array $theme_list
* An array of theme names. * An array of theme names.
*
* @return bool
* Whether any of the given themes have been disabled.
*/ */
public function disable(array $theme_list); public function disable(array $theme_list);
/** /**
* Returns a list of all currently available themes. * Returns a list of currently enabled themes.
*
* Retrieved from the database, if available and the site is not in
* maintenance mode; otherwise compiled freshly from the filesystem.
* *
* @return \Drupal\Core\Extension\Extension[] * @return \Drupal\Core\Extension\Extension[]
* An associative array of the currently available themes. The keys are the * An associative array of the currently enabled themes. The keys are the
* themes' machine names and the values are objects having the following * themes' machine names and the values are objects having the following
* properties: * properties:
* - filename: The filepath and name of the .info.yml file. * - filename: The filepath and name of the .info.yml file.
...@@ -75,6 +82,14 @@ public function disable(array $theme_list); ...@@ -75,6 +82,14 @@ public function disable(array $theme_list);
*/ */
public function listInfo(); public function listInfo();
/**
* Refreshes the theme info data of currently enabled themes.
*
* Modules can alter theme info, so this is typically called after a module
* has been installed or uninstalled.
*/
public function refreshInfo();
/** /**
* Resets the internal state of the theme handler. * Resets the internal state of the theme handler.
*/ */
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\DestructableInterface; use Drupal\Core\DestructableInterface;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\Lock\LockBackendInterface;
use Drupal\Core\Utility\ThemeRegistry; use Drupal\Core\Utility\ThemeRegistry;
...@@ -145,23 +146,17 @@ public function __construct(CacheBackendInterface $cache, LockBackendInterface $ ...@@ -145,23 +146,17 @@ public function __construct(CacheBackendInterface $cache, LockBackendInterface $
protected function init($theme_name = NULL) { protected function init($theme_name = NULL) {
// Unless instantiated for a specific theme, use globals. // Unless instantiated for a specific theme, use globals.
if (!isset($theme_name)) { if (!isset($theme_name)) {
// #1: The theme registry might get instantiated before the theme was if (isset($GLOBALS['theme']) && isset($GLOBALS['theme_info'])) {
// initialized. Cope with that. $this->theme = $GLOBALS['theme_info'];
if (!isset($GLOBALS['theme_info']) || !isset($GLOBALS['theme'])) { $this->baseThemes = $GLOBALS['base_theme_info'];
unset($this->runtimeRegistry); $this->engine = $GLOBALS['theme_engine'];
unset($this->registry);
drupal_theme_initialize();
} }
// #2: The testing framework only cares for the global $theme variable at else {
// this point. Cope with that. // @see drupal_theme_initialize()
if ($GLOBALS['theme'] != $GLOBALS['theme_info']->getName()) { $this->theme = new Extension('theme', 'core/core.info.yml');
unset($this->runtimeRegistry); $this->baseThemes = array();
unset($this->registry); $this->engine = 'twig';
$this->initializeTheme();
} }
$this->theme = $GLOBALS['theme_info'];
$this->baseThemes = $GLOBALS['base_theme_info'];
$this->engine = $GLOBALS['theme_engine'];
} }
// Instead of the global theme, a specific theme was requested. // Instead of the global theme, a specific theme was requested.
else { else {
......
...@@ -211,7 +211,7 @@ function testImport() { ...@@ -211,7 +211,7 @@ function testImport() {
$this->assertTrue(empty($installed), 'No modules installed during import'); $this->assertTrue(empty($installed), 'No modules installed during import');
$theme_info = \Drupal::service('theme_handler')->listInfo(); $theme_info = \Drupal::service('theme_handler')->listInfo();
$this->assertTrue(isset($theme_info['bartik']) && !$theme_info['bartik']->status, 'Bartik theme disabled during import.'); $this->assertFalse(isset($theme_info['bartik']), 'Bartik theme disabled during import.');
// Verify that the action.settings configuration object was only deleted // Verify that the action.settings configuration object was only deleted
// once during the import process. // once during the import process.
......
...@@ -55,6 +55,28 @@ function config_translation_theme() { ...@@ -55,6 +55,28 @@ function config_translation_theme() {
); );
} }
/**
* Implements hook_themes_enabled().
*/
function config_translation_themes_enabled() {
// Themes can provide *.config_translation.yml declarations.
// @todo Make ThemeHandler trigger an event instead and make
// ConfigMapperManager plugin manager subscribe to it.
// @see https://drupal.org/node/2206347
\Drupal::service('plugin.manager.config_translation.mapper')->clearCachedDefinitions();
}
/**
* Implements hook_themes_disabled().
*/
function config_translation_themes_disabled() {
// Themes can provide *.config_translation.yml declarations.
// @todo Make ThemeHandler trigger an event instead and make
// ConfigMapperManager plugin manager subscribe to it.
// @see https://drupal.org/node/2206347
\Drupal::service('plugin.manager.config_translation.mapper')->clearCachedDefinitions();
}
/** /**
* Implements hook_entity_type_alter(). * Implements hook_entity_type_alter().
*/ */
......
...@@ -67,6 +67,14 @@ public function __construct(CacheBackendInterface $cache_backend, LanguageManage ...@@ -67,6 +67,14 @@ public function __construct(CacheBackendInterface $cache_backend, LanguageManage
$this->typedConfigManager = $typed_config_manager; $this->typedConfigManager = $typed_config_manager;
// Look at all themes and modules. // Look at all themes and modules.
// @todo If the list of enabled modules and themes is changed, new
// definitions are not picked up immediately and obsolete definitions are
// not removed, because the list of search directories is only compiled
// once in this constructor. The current code only works due to
// coincidence: The request that enables e.g. a new theme does not
// instantiate this plugin manager at the beginning of the request; when
// routes are being rebuilt at the end of the request, this service only
// happens to get instantiated with the updated list of enabled themes.
$directories = array(); $directories = array();
foreach ($module_handler->getModuleList() as $name => $module) { foreach ($module_handler->getModuleList() as $name => $module) {
$directories[$name] = $module->getPath(); $directories[$name] = $module->getPath();
......
...@@ -654,25 +654,6 @@ public function testAlterInfo() { ...@@ -654,25 +654,6 @@ public function testAlterInfo() {
$this->assertNoText(t('Password recovery')); $this->assertNoText(t('Password recovery'));
} }
/**
* Tests that theme provided *.config_translation.yml files are found.
*/
public function testThemeDiscovery() {
// Enable the test theme and rebuild routes.
$theme = 'config_translation_test_theme';
theme_enable(array($theme));
// Enabling a theme will cause the kernel terminate event to rebuild the
// router. Simulate that here.
\Drupal::service('router.builder')->rebuildIfNeeded();
$this->drupalLogin($this->admin_user);
$translation_base_url = 'admin/config/development/performance/translate';
$this->drupalGet($translation_base_url);
$this->assertResponse(200);
$this->assertLinkByHref("$translation_base_url/fr/add");
}
/** /**
* Gets translation from locale storage. * Gets translation from locale storage.
* *
......
<?php
/**
* @file
* Contains \Drupal\config_translation\Tests\ConfigTranslationUiThemeTest.
*/
namespace Drupal\config_translation\Tests;
use Drupal\Core\Language\Language;
use Drupal\simpletest\WebTestBase;
/**
* Functional tests for the Language list configuration forms.
*/
class ConfigTranslationUiThemeTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('config_translation', 'config_translation_test');
/**
* Languages to enable.
*
* @var array
*/
protected $langcodes = array('fr', 'ta');
/**
* Administrator user for tests.
*