diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 9603d38..7018c18 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -117,6 +117,13 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { protected $allowDumping; /** + * Whether the container can be loaded. + * + * @var bool + */ + protected $allowLoading; + + /** * Whether the container needs to be dumped once booting is complete. * * @var bool @@ -171,12 +178,16 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { * @param bool $allow_dumping * (optional) FALSE to stop the container from being written to or read * from disk. Defaults to TRUE. + * @param bool $allow_loading + * (optional) FALSE to prevent that the kernel is attempted to be read from + * disk. Defaults to $allow_dumping. */ - public function __construct($environment, ClassLoader $class_loader, $allow_dumping = TRUE) { + public function __construct($environment, ClassLoader $class_loader, $allow_dumping = TRUE, $allow_loading = NULL) { $this->environment = $environment; $this->booted = FALSE; $this->classLoader = $class_loader; $this->allowDumping = $allow_dumping; + $this->allowLoading = isset($allow_loading) ? $allow_loading : $allow_dumping; } /** @@ -344,6 +355,12 @@ public function updateModules(array $module_list, array $module_filenames = arra foreach ($module_filenames as $name => $extension) { $this->moduleData[$name] = $extension; } + + // This method is called whenever the list of modules changed. Therefore + // disable loading of a dumped kernel from the disk, because it is + // guaranteed to be out of date and needs to be rebuilt anyway. + $this->allowLoading = FALSE; + // If we haven't yet booted, we don't need to do anything: the new module // list will take effect when boot() is called. If we have already booted, // then reboot in order to refresh the serviceProvider list and container. @@ -397,7 +414,7 @@ protected function initializeContainer() { $class = $this->getClassName(); $cache_file = $class . '.php'; - if ($this->allowDumping) { + if ($this->allowLoading) { // First, try to load. if (!class_exists($class, FALSE)) { $this->storage()->load($cache_file); @@ -417,33 +434,12 @@ protected function initializeContainer() { $this->moduleList = $this->newModuleList; unset($this->newModuleList); } - // Second, check if some other request -- for example on another web - // frontend or during the installer -- changed the list of enabled modules. if (isset($this->container)) { // All namespaces must be registered before we attempt to use any service // from the container. - $container_modules = $this->container->getParameter('container.modules'); - $namespaces_before = $this->classLoader->getPrefixesPsr4(); $this->registerNamespacesPsr4($this->container->getParameter('container.namespaces')); - - // If 'container.modules' is wrong, the container must be rebuilt. - if (!isset($this->moduleList)) { - $this->moduleList = $this->container->get('config.factory')->get('core.extension')->get('module') ?: array(); - } - if (array_keys($this->moduleList) !== array_keys($container_modules)) { - $persist = $this->getServicesToPersist(); - unset($this->container); - // Revert the class loader to its prior state. However, - // registerNamespaces() performs a merge rather than replace, so to - // effectively remove erroneous registrations, we must replace them with - // empty arrays. - $namespaces_after = $this->classLoader->getPrefixesPsr4(); - $namespaces_before += array_fill_keys(array_diff(array_keys($namespaces_after), array_keys($namespaces_before)), array()); - $this->registerNamespacesPsr4($namespaces_before); - } } - - if (!isset($this->container)) { + else { $this->container = $this->buildContainer(); $this->persistServices($persist); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 340b555..a120883 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -1094,7 +1094,7 @@ protected function rebuildContainer($environment = 'prod') { $request_stack = \Drupal::service('request_stack'); } - $this->kernel = new DrupalKernel($environment, drupal_classloader(), FALSE); + $this->kernel = new DrupalKernel($environment, drupal_classloader(), TRUE, FALSE); $this->kernel->boot(); // DrupalKernel replaces the container in \Drupal::getContainer() with a // different object, so we need to replace the instance on this test class. diff --git a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php index aaca572..5d8726a 100644 --- a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php @@ -56,7 +56,6 @@ function testCompileDIC() { // Instantiate it a second time and we should get the compiled Container // class. $kernel = new DrupalKernel('testing', $classloader); - $kernel->updateModules($module_enabled); $kernel->boot(); $container = $kernel->getContainer(); $refClass = new \ReflectionClass($container); @@ -64,6 +63,10 @@ function testCompileDIC() { $refClass->getParentClass()->getName() == 'Drupal\Core\DependencyInjection\Container' && !$refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder'); $this->assertTrue($is_compiled_container); + // Verify that the list of modules is the same for the initial and the + // compiled container. + $module_list = array_keys($container->get('module_handler')->getModuleList()); + $this->assertEqual(array_values($module_enabled), $module_list); // Now use the read-only storage implementation, simulating a "production" // environment. @@ -71,7 +74,6 @@ function testCompileDIC() { $php_storage['service_container']['class'] = 'Drupal\Component\PhpStorage\FileReadOnlyStorage'; $this->settingsSet('php_storage', $php_storage); $kernel = new DrupalKernel('testing', $classloader); - $kernel->updateModules($module_enabled); $kernel->boot(); $container = $kernel->getContainer(); $refClass = new \ReflectionClass($container); @@ -79,6 +81,10 @@ function testCompileDIC() { $refClass->getParentClass()->getName() == 'Drupal\Core\DependencyInjection\Container' && !$refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder'); $this->assertTrue($is_compiled_container); + // Verify that the list of modules is the same for the initial and the + // compiled container. + $module_list = array_keys($container->get('module_handler')->getModuleList()); + $this->assertEqual(array_values($module_enabled), $module_list); // Test that our synthetic services are there. $classloader = $container->get('class_loader'); $refClass = new \ReflectionClass($classloader);