Commit 10ab4722 authored by catch's avatar catch

Issue #1331486 by katbailey, chx, sun, beejeebus, amateescu: Move...

Issue #1331486 by katbailey, chx, sun, beejeebus, amateescu: Move module_invoke_*() and friends to an Extensions class.
parent 2cf9e49e
......@@ -78,11 +78,11 @@ function authorize_access_allowed() {
// We have to enable the user and system modules, even to check access and
// display errors via the maintenance theme.
$module_list['system']['filename'] = 'core/modules/system/system.module';
$module_list['user']['filename'] = 'core/modules/user/user.module';
module_list(NULL, $module_list);
drupal_load('module', 'system');
drupal_load('module', 'user');
$module_list['system'] = 'core/modules/system/system.module';
$module_list['user'] = 'core/modules/user/user.module';
drupal_container()->get('module_handler')->setModuleList($module_list);
drupal_container()->get('module_handler')->load('system');
drupal_container()->get('module_handler')->load('user');
// Initialize the language system.
drupal_language_initialize();
......
......@@ -888,6 +888,14 @@ function drupal_get_filename($type, $name, $filename = NULL) {
// nothing
}
else {
if ($type == 'module') {
if (empty($files[$type])) {
$files[$type] = drupal_container()->get('module_handler')->getModuleList();
}
if (isset($files[$type][$name])) {
return $files[$type][$name];
}
}
// Verify that we have an keyvalue service before using it. This is required
// because this function is called during installation.
// @todo Inject database connection into KeyValueStore\DatabaseStorage.
......@@ -1133,8 +1141,9 @@ function drupal_page_is_cacheable($allow_caching = NULL) {
* @see bootstrap_hooks()
*/
function bootstrap_invoke_all($hook) {
foreach (module_list('bootstrap') as $module) {
drupal_load('module', $module);
$module_handler = drupal_container()->get('module_handler');
foreach ($module_handler->getBootstrapModules() as $module) {
$module_handler->load($module);
module_invoke($module, $hook);
}
}
......@@ -1153,6 +1162,10 @@ function bootstrap_invoke_all($hook) {
* TRUE if the item is loaded or has already been loaded.
*/
function drupal_load($type, $name) {
if ($type == 'module' && drupal_container()->get('module_handler')->moduleExists($name)) {
return drupal_container()->get('module_handler')->load($name);
}
// Once a file is included this can't be reversed during a request so do not
// use drupal_static() here.
static $files = array();
......@@ -2276,10 +2289,6 @@ function _drupal_exception_handler($exception) {
* Sets up the script environment and loads settings.php.
*/
function _drupal_bootstrap_configuration() {
// Set the Drupal custom error handler.
set_error_handler('_drupal_error_handler');
set_exception_handler('_drupal_exception_handler');
drupal_environment_initialize();
// Start a page timer:
timer_start('page');
......@@ -2294,6 +2303,11 @@ function _drupal_bootstrap_configuration() {
// Load the procedural configuration system helper functions.
require_once DRUPAL_ROOT . '/core/includes/config.inc';
// Set the Drupal custom error handler. (requires config())
set_error_handler('_drupal_error_handler');
set_exception_handler('_drupal_exception_handler');
// Redirect the user to the installation script if Drupal has not been
// installed yet (i.e., if no $databases array has been defined in the
// settings.php file) and we are not already installing.
......@@ -2423,7 +2437,7 @@ function _drupal_bootstrap_variables() {
$conf = variable_initialize(isset($conf) ? $conf : array());
// Load bootstrap modules.
require_once DRUPAL_ROOT . '/core/includes/module.inc';
module_load_all(TRUE);
drupal_container()->get('module_handler')->loadBootstrapModules();
}
/**
......@@ -2476,6 +2490,82 @@ function drupal_container(ContainerInterface $new_container = NULL) {
return $container;
}
/**
* Returns the list of enabled modules.
*
* @deprecated as of Drupal 8.0. Use
* drupal_container()->get('module_handler')->getModuleList().
*
* @see \Drupal\Core\Extension\ModuleHandler::getModuleList()
*/
function module_list() {
$modules = array_keys(drupal_container()->get('module_handler')->getModuleList());
return array_combine($modules, $modules);
}
/**
* Determines which modules are implementing a hook.
*
* @deprecated as of Drupal 8.0. Use
* drupal_container()->get('module_handler')->getImplementations($hook).
*
* @see \Drupal\Core\Extension\ModuleHandler::getImplementations()
*/
function module_implements($hook) {
return drupal_container()->get('module_handler')->getImplementations($hook);
}
/**
* Invokes a hook in all enabled modules that implement it.
*
* @deprecated as of Drupal 8.0. Use
* drupal_container()->get('module_handler')->invokeAll($hook).
*
* @see \Drupal\Core\Extension\ModuleHandler::invokeAll()
*/
function module_invoke_all($hook) {
$args = func_get_args();
// Remove $hook from the arguments.
array_shift($args);
return drupal_container()->get('module_handler')->invokeAll($hook, $args);
}
/**
* Passes alterable variables to specific hook_TYPE_alter() implementations.
*
* @deprecated as of Drupal 8.0. Use
* drupal_container()->get('module_handler')->alter($hook).
*
* @see \Drupal\Core\Extension\ModuleHandler::alter()
*/
function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
return drupal_container()->get('module_handler')->alter($type, $data, $context1, $context2);
}
/**
* Determines whether a given module exists.
*
* @deprecated as of Drupal 8.0. Use
* drupal_container()->get('module_handler')->moduleExists($hook).
*
* @see \Drupal\Core\Extension\ModuleHandler::moduleExists()
*/
function module_exists($module) {
return drupal_container()->get('module_handler')->moduleExists($module);
}
/**
* Determines whether a module implements a hook.
*
* @deprecated as of Drupal 8.0. Use
* drupal_container()->get('module_handler')->implementsHook($module, $hook).
*
* @see \Drupal\Core\Extension\ModuleHandler::implementsHook()
*/
function module_hook($module, $hook) {
return drupal_container()->get('module_handler')->implementsHook($module, $hook);
}
/**
* Returns the state storage service.
*
......
......@@ -4839,7 +4839,7 @@ function _drupal_bootstrap_code() {
require_once DRUPAL_ROOT . '/core/includes/entity.inc';
// Load all enabled modules
module_load_all();
drupal_container()->get('module_handler')->loadAll();
// Make sure all stream wrappers are registered.
file_get_stream_wrappers();
......@@ -6438,7 +6438,7 @@ function drupal_flush_all_caches() {
// Ensure that all modules that are currently supposed to be enabled are
// actually loaded.
module_load_all();
drupal_container()->get('module_handler')->loadAll();
// Update the list of bootstrap modules.
// Allows developers to get new hook_boot() implementations registered without
......@@ -6511,69 +6511,11 @@ function debug($data, $label = NULL, $print_r = FALSE) {
trigger_error(trim($label ? "$label: $string" : $string));
}
/**
* Parses a dependency for comparison by drupal_check_incompatibility().
*
* @param $dependency
* A dependency string, for example 'foo (>=8.x-4.5-beta5, 3.x)'.
*
* @return
* An associative array with three keys:
* - 'name' includes the name of the thing to depend on (e.g. 'foo').
* - 'original_version' contains the original version string (which can be
* used in the UI for reporting incompatibilities).
* - 'versions' is a list of associative arrays, each containing the keys
* 'op' and 'version'. 'op' can be one of: '=', '==', '!=', '<>', '<',
* '<=', '>', or '>='. 'version' is one piece like '4.5-beta3'.
* Callers should pass this structure to drupal_check_incompatibility().
*
* @see drupal_check_incompatibility()
*/
function drupal_parse_dependency($dependency) {
// We use named subpatterns and support every op that version_compare
// supports. Also, op is optional and defaults to equals.
$p_op = '(?P<operation>!=|==|=|<|<=|>|>=|<>)?';
// Core version is always optional: 8.x-2.x and 2.x is treated the same.
$p_core = '(?:' . preg_quote(DRUPAL_CORE_COMPATIBILITY) . '-)?';
$p_major = '(?P<major>\d+)';
// By setting the minor version to x, branches can be matched.
$p_minor = '(?P<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)';
$value = array();
$parts = explode('(', $dependency, 2);
$value['name'] = trim($parts[0]);
if (isset($parts[1])) {
$value['original_version'] = ' (' . $parts[1];
foreach (explode(',', $parts[1]) as $version) {
if (preg_match("/^\s*$p_op\s*$p_core$p_major\.$p_minor/", $version, $matches)) {
$op = !empty($matches['operation']) ? $matches['operation'] : '=';
if ($matches['minor'] == 'x') {
// Drupal considers "2.x" to mean any version that begins with
// "2" (e.g. 2.0, 2.9 are all "2.x"). PHP's version_compare(),
// on the other hand, treats "x" as a string; so to
// version_compare(), "2.x" is considered less than 2.0. This
// means that >=2.x and <2.x are handled by version_compare()
// as we need, but > and <= are not.
if ($op == '>' || $op == '<=') {
$matches['major']++;
}
// Equivalence can be checked by adding two restrictions.
if ($op == '=' || $op == '==') {
$value['versions'][] = array('op' => '<', 'version' => ($matches['major'] + 1) . '.x');
$op = '>=';
}
}
$value['versions'][] = array('op' => $op, 'version' => $matches['major'] . '.' . $matches['minor']);
}
}
}
return $value;
}
/**
* Checks whether a version is compatible with a given dependency.
*
* @param $v
* The parsed dependency structure from drupal_parse_dependency().
* A parsed dependency structure e.g. from ModuleHandler::parseDependency().
* @param $current_version
* The version to check against (like 4.2).
*
......@@ -6581,7 +6523,7 @@ function drupal_parse_dependency($dependency) {
* NULL if compatible, otherwise the original dependency version string that
* caused the incompatibility.
*
* @see drupal_parse_dependency()
* @see \Drupal\Core\Extension\ModuleHandler::parseDependency()
*/
function drupal_check_incompatibility($v, $current_version) {
if (!empty($v['versions'])) {
......
......@@ -338,6 +338,7 @@ function install_begin_request(&$install_state) {
$container->register('config.factory', 'Drupal\Core\Config\ConfigFactory')
->addArgument(new Reference('config.storage'))
->addArgument(new Reference('event_dispatcher'));
// The install process cannot use the database lock backend since the database
// is not fully up, so we use a null backend implementation during the
// installation process. This will also speed up the installation process.
......@@ -346,6 +347,10 @@ function install_begin_request(&$install_state) {
// (as opposed to the cache backend) so we can afford having a null
// implementation here.
$container->register('lock', 'Drupal\Core\Lock\NullLockBackend');
// Register a module handler for managing enabled modules.
$container
->register('module_handler', 'Drupal\Core\Extension\ModuleHandler');
drupal_container($container);
}
......@@ -353,10 +358,13 @@ function install_begin_request(&$install_state) {
drupal_language_initialize();
require_once DRUPAL_ROOT . '/core/includes/ajax.inc';
// Override the module list with a minimal set of modules.
$module_list['system']['filename'] = 'core/modules/system/system.module';
module_list(NULL, $module_list);
drupal_load('module', 'system');
$module_handler = drupal_container()->get('module_handler');
if (!$module_handler->moduleExists('system')) {
// Override the module list with a minimal set of modules.
$module_handler->setModuleList(array('system' => 'core/modules/system/system.module'));
}
$module_handler->load('system');
require_once DRUPAL_ROOT . '/core/includes/cache.inc';
$conf['cache_classes'] = array('cache' => 'Drupal\Core\Cache\MemoryBackend');
......@@ -1570,9 +1578,7 @@ function install_bootstrap_full(&$install_state) {
// cache backend will be used again.
unset($GLOBALS['conf']['cache_classes']['cache']);
drupal_static_reset('cache');
// Clear the module list that was overriden earlier in the process.
// This will allow all freshly installed modules to be loaded.
module_list_reset();
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
}
......
......@@ -424,15 +424,10 @@ function drupal_install_system() {
->set('enabled.system', 0)
->save();
// Clear out module list and hook implementation statics.
system_list_reset();
module_list_reset();
module_implements_reset();
// To ensure that the system module can be found by the plugin system, warm
// the module list cache.
// @todo Remove this in http://drupal.org/node/1798732.
module_list();
// Update the module list to include it.
drupal_container()->get('module_handler')->setModuleList(array('system' => $system_path . '/system.module'));
drupal_container()->get('module_handler')->resetImplementations();
config_install_default_config('module', 'system');
module_invoke('system', 'install');
......
This diff is collapsed.
......@@ -77,16 +77,7 @@ function drupal_get_complete_schema($rebuild = FALSE) {
else {
$schema = array();
// Load the .install files to get hook_schema.
// On some databases this function may be called before bootstrap has
// been completed, so we force the functions we need to load just in case.
if (function_exists('module_load_all_includes')) {
// This function can be called very early in the bootstrap process, so
// we force the system_list() static cache to be refreshed to ensure
// that it contains the complete list of modules before we go on to call
// module_load_all_includes().
system_list_reset();
module_load_all_includes('install');
}
drupal_container()->get('module_handler')->loadAllIncludes('install');
require_once DRUPAL_ROOT . '/core/includes/common.inc';
// Invoke hook_schema for all modules.
......@@ -130,8 +121,7 @@ function drupal_get_schema_versions($module) {
$updates = &drupal_static(__FUNCTION__, NULL);
if (!isset($updates[$module])) {
$updates = array();
foreach (module_list() as $loaded_module) {
foreach (drupal_container()->get('module_handler')->getModuleList() as $loaded_module => $filename) {
$updates[$loaded_module] = array();
}
......@@ -341,7 +331,9 @@ function _drupal_schema_initialize(&$schema, $module, $remove_descriptions = TRU
* An array of fields.
*/
function drupal_schema_fields_sql($table, $prefix = NULL) {
$schema = drupal_get_schema($table);
if (!$schema = drupal_get_schema($table)) {
return array();
}
$fields = array_keys($schema['fields']);
if ($prefix) {
$columns = array();
......
......@@ -368,14 +368,14 @@ function _theme_load_registry($theme, $base_theme = NULL, $theme_engine = NULL,
$registry = _theme_build_registry($theme, $base_theme, $theme_engine);
// Only persist this registry if all modules are loaded. This assures a
// complete set of theme hooks.
if (module_load_all(NULL)) {
if (drupal_container()->get('module_handler')->isLoaded()) {
_theme_save_registry($theme, $registry);
}
}
return $registry;
}
else {
return new ThemeRegistry('theme_registry:runtime:' . $theme->name, 'cache', array('theme_registry' => TRUE));
return new ThemeRegistry('theme_registry:runtime:' . $theme->name, 'cache', array('theme_registry' => TRUE), drupal_container()->get('module_handler')->isLoaded());
}
}
......@@ -441,7 +441,6 @@ function drupal_theme_rebuild() {
* themes/bartik.
*
* @see theme()
* @see _theme_process_registry()
* @see hook_theme()
* @see list_themes()
*/
......@@ -548,7 +547,7 @@ function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
// Add all modules so they can intervene with their own variable
// processors. This allows them to provide variable processors even
// if they are not the owner of the current hook.
$prefixes += module_list();
$prefixes = array_merge($prefixes, array_keys(drupal_container()->get('module_handler')->getModuleList()));
}
elseif ($type == 'theme_engine' || $type == 'base_theme_engine') {
// Theme engines get an extra set that come before the normally
......@@ -644,7 +643,7 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) {
_theme_process_registry($cache, $module, 'module', $module, drupal_get_path('module', $module));
}
// Only cache this registry if all modules are loaded.
if (module_load_all(NULL)) {
if (drupal_container()->get('module_handler')->isLoaded()) {
cache()->set("theme_registry:build:modules", $cache, CacheBackendInterface::CACHE_PERMANENT, array('theme_registry' => TRUE));
}
}
......@@ -959,7 +958,7 @@ function theme($hook, $variables = array()) {
// If called before all modules are loaded, we do not necessarily have a full
// theme registry to work with, and therefore cannot process the theme
// request properly. See also _theme_load_registry().
if (!module_load_all(NULL) && !defined('MAINTENANCE_MODE')) {
if (!drupal_container()->get('module_handler')->isLoaded() && !defined('MAINTENANCE_MODE')) {
throw new Exception(t('theme() may not be called until all modules are loaded.'));
}
......
......@@ -55,9 +55,10 @@ function _drupal_maintenance_theme() {
// Ensure that system.module is loaded.
if (!function_exists('_system_rebuild_theme_data')) {
$module_list['system']['filename'] = 'core/modules/system/system.module';
module_list(NULL, $module_list);
drupal_load('module', 'system');
$module_list['system'] = 'core/modules/system/system.module';
$module_handler = drupal_container()->get('module_handler');
$module_handler->setModuleList($module_list);
$module_handler->load('system');
}
$themes = list_themes();
......
......@@ -11,6 +11,7 @@
use Drupal\Component\Graph\Graph;
use Drupal\Core\Config\FileStorage;
use Drupal\Core\Config\ConfigException;
use Drupal\Core\DrupalKernel;
use Drupal\Component\Uuid\Uuid;
use Drupal\Component\Utility\NestedArray;
......@@ -93,6 +94,19 @@ function update_prepare_d8_bootstrap() {
// Bootstrap to configuration.
drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
// During the bootstrap to DRUPAL_BOOTSTRAP_PAGE_CACHE, code will try to read
// the cache but the cache tables are not compatible yet. Use the Null backend
// by default to avoid exceptions.
$GLOBALS['conf']['cache_classes'] = array('cache' => 'Drupal\Core\Cache\NullBackend');
// Enable UpdateBundle service overrides.
$GLOBALS['conf']['container_bundles'][] = 'Drupal\Core\DependencyInjection\UpdateBundle';
// Bootstrap the kernel.
// Do not attempt to dump and write it.
$kernel = new DrupalKernel('update', FALSE, drupal_classloader(), FALSE);
$kernel->boot();
// Check whether settings.php needs to be rewritten.
$settings_exist = !empty($GLOBALS['config_directories']);
......@@ -125,9 +139,9 @@ function update_prepare_d8_bootstrap() {
include_once DRUPAL_ROOT . '/core/includes/module.inc';
include_once DRUPAL_ROOT . '/core/includes/cache.inc';
$module_list['system']['filename'] = 'core/modules/system/system.module';
module_list(NULL, $module_list);
require_once DRUPAL_ROOT . '/' . $module_list['system']['filename'];
$module_handler = drupal_container()->get('module_handler');
$module_handler->setModuleList(array('system' => 'core/modules/system/system.module'));
$module_handler->load('system');
// Ensure the configuration directories exist and are writable, or create
// them. If the directories have not been specified in settings.php and
// created manually already, and either directory cannot be created by the
......@@ -135,10 +149,7 @@ function update_prepare_d8_bootstrap() {
drupal_install_config_directories();
}
// Bootstrap the database. During this, the DRUPAL_BOOTSTRAP_PAGE_CACHE will
// try to read the cache but the cache tables might not be Drupal 8
// compatible yet. Use the null backend by default to avoid exceptions.
$GLOBALS['conf']['cache_classes'] = array('cache' => 'Drupal\Core\Cache\NullBackend');
// Bootstrap the database.
drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
// If the site has not updated to Drupal 8 yet, check to make sure that it is
......@@ -353,8 +364,8 @@ function update_prepare_d8_bootstrap() {
// Populate a fixed module list (again, why did it get lost?) to avoid
// errors due to the drupal_alter() in _system_rebuild_module_data().
$module_list['system']['filename'] = 'core/modules/system/system.module';
module_list(NULL, $module_list);
$module_list['system'] = 'core/modules/system/system.module';
drupal_container()->get('module_handler')->setModuleList($module_list);
$module_data = _system_rebuild_module_data();
// Migrate each extension into configuration, varying by the extension's
......@@ -378,7 +389,13 @@ function update_prepare_d8_bootstrap() {
}
$schema_store->set($record->name, $record->schema_version);
}
$module_config->set('enabled', module_config_sort($module_config->get('enabled')))->save();
$sorted_modules = module_config_sort($module_config->get('enabled'));
$module_config->set('enabled', $sorted_modules)->save();
$sorted_with_filenames = array();
foreach (array_keys($sorted_modules) as $m) {
$sorted_with_filenames[$m] = drupal_get_filename('module', $m);
}
drupal_container()->get('module_handler')->setModuleList($sorted_with_filenames);
$disabled_modules->save();
$theme_config->save();
$disabled_themes->save();
......@@ -388,8 +405,6 @@ function update_prepare_d8_bootstrap() {
update_prepare_stored_includes();
// Update the environment for the language bootstrap if needed.
update_prepare_d8_language();
// Prime the classloader.
system_list('module_enabled');
// Change language column to langcode in url_alias.
if (db_table_exists('url_alias') && db_field_exists('url_alias', 'language')) {
......
......@@ -77,6 +77,12 @@ public function build(ContainerBuilder $container) {
->setFactoryClass('Drupal\Component\Utility\Settings')
->setFactoryMethod('getSingleton');
// Register the State k/v store as a service.
$container->register('state', 'Drupal\Core\KeyValueStore\KeyValueStoreInterface')
->setFactoryService(new Reference('keyvalue'))
->setFactoryMethod('get')
->addArgument('state');
// Register the Queue factory.
$container
->register('queue', 'Drupal\Core\Queue\QueueFactory')
......@@ -114,6 +120,20 @@ public function build(ContainerBuilder $container) {
->addArgument(new Reference('service_container'));
$container->register('controller_resolver', 'Drupal\Core\ControllerResolver')
->addArgument(new Reference('service_container'));
$container
->register('cache.cache', 'Drupal\Core\Cache\CacheBackendInterface')
->setFactoryClass('Drupal\Core\Cache\CacheFactory')
->setFactoryMethod('get')
->addArgument('cache');
$container
->register('cache.bootstrap', 'Drupal\Core\Cache\CacheBackendInterface')
->setFactoryClass('Drupal\Core\Cache\CacheFactory')
->setFactoryMethod('get')
->addArgument('bootstrap');
$this->registerModuleHandler($container);
$container->register('http_kernel', 'Drupal\Core\HttpKernel')
->addArgument(new Reference('event_dispatcher'))
->addArgument(new Reference('service_container'))
......@@ -144,7 +164,8 @@ public function build(ContainerBuilder $container) {
$container->register('router.builder', 'Drupal\Core\Routing\RouteBuilder')
->addArgument(new Reference('router.dumper'))
->addArgument(new Reference('lock'))
->addArgument(new Reference('event_dispatcher'));
->addArgument(new Reference('event_dispatcher'))
->addArgument(new Reference('module_handler'));
$container
->register('cache.path', 'Drupal\Core\Cache\CacheBackendInterface')
......@@ -209,6 +230,7 @@ public function build(ContainerBuilder $container) {
->setScope('request')
->addTag('event_subscriber');
$container->register('request_close_subscriber', 'Drupal\Core\EventSubscriber\RequestCloseSubscriber')
->addArgument(new Reference('module_handler'))
->addTag('event_subscriber');
$container->register('config_global_override_subscriber', 'Drupal\Core\EventSubscriber\ConfigGlobalOverrideSubscriber')
->addTag('event_subscriber');
......@@ -247,6 +269,25 @@ public function build(ContainerBuilder $container) {
$container->addCompilerPass(new RegisterAccessChecksPass());
}
/**
* Registers the module handler.
*/
protected function registerModuleHandler(ContainerBuilder $container) {
// The ModuleHandler manages enabled modules and provides the ability to
// invoke hooks in all enabled modules.
if ($container->getParameter('kernel.environment') == 'install') {
// During installation we use the non-cached version.
$container->register('module_handler', 'Drupal\Core\Extension\ModuleHandler')
->addArgument('%container.modules%');
}
else {
$container->register('module_handler', 'Drupal\Core\Extension\CachedModuleHandler')
->addArgument('%container.modules%')
->addArgument(new Reference('state'))
->addArgument(new Reference('cache.bootstrap'));
}
}
/**
* Registers the various services for the routing system.
*
......
<?php
/**
* @file
* Contains \Drupal\Core\DependencyInjection\UpdateBundle.
*/
namespace Drupal\Core\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
/**
* Bundle class for update.php service overrides.
*
* This bundle is manually added by update.php via $conf['container_bundles']
* and required to prevent various services from trying to retrieve data from
* storages that do not exist yet.
*/
class UpdateBundle extends Bundle {
/**
* Implements \Symfony\Component\HttpKernel\Bundle\BundleInterface::build().
*/
public function build(ContainerBuilder $container) {
// Disable the Lock service.
$container
->register('lock', 'Drupal\Core\Lock\NullLockBackend');
// Prevent config from accessing {cache_config}.
// @see $conf['cache_classes'], update_prepare_d8_bootstrap()
$container
->register('config.storage', 'Drupal\Core\Config\FileStorage')
->addArgument(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY));
}
}
......@@ -223,6 +223,9 @@ protected function moduleData($module) {
/**
* Implements Drupal\Core\DrupalKernelInterface::updateModules().
*
* @todo Remove obsolete $module_list parameter. Only $module_filenames is
* needed.
*/
public function updateModules(array $module_list, array $module_filenames = array()) {
$this->newModuleList = $module_list;
......
......@@ -7,6 +7,8 @@
namespace Drupal\Core\EventSubscriber;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Extension\CachedModuleHandlerInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
......@@ -16,6 +18,18 @@
*/
class RequestCloseSubscriber implements EventSubscriberInterface {
/**
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructor.
*/
function __construct(ModuleHandlerInterface $module_handler) {
$this->moduleHandler = $module_handler;
}
/**
* Performs end of request tasks.
*
......@@ -28,8 +42,15 @@ class RequestCloseSubscriber implements EventSubscriberInterface {
* The Event to process.
*/
public function onTerminate(PostResponseEvent $event) {
module_invoke_all('exit');
module_implements_write_cache();
$this->moduleHandler->invokeAll('exit');
$request_method = $event->getRequest()->getMethod();
// Check whether we need to write the module implementations cache. We do
// not want to cache hooks which are only invoked on HTTP POST requests
// since these do not need to be optimized as tightly, and not doing so
// keeps the cache entry smaller.
if (($request_method == 'GET' || $request_method == 'HEAD') && $this->moduleHandler instanceof CachedModuleHandlerInterface) {
$this->moduleHandler->writeCache();
}
system_run_automated_cron();
}
......
<?php
/**
* @file
* Contains Drupal\Core\Extension\CachedModuleHandler.
*/
namespace Drupal\Core\Extension;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
/**
* Class that manages enabled modules in a Drupal installation.
*/
class CachedModuleHandler extends ModuleHandler implements CachedModuleHandlerInterface {