diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 4bf703f..1e67d46 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1461,7 +1461,7 @@ function install_bootstrap_full(&$install_state) { // e.g. 'prod', 'dev', and a boolean indicating whether it is in debug mode. // Drupal does not currently make use of either of these, though that may // change with http://drupal.org/node/1537198. - $kernel = new DrupalKernel('prod', FALSE, system_list()); + $kernel = new DrupalKernel('prod', FALSE); $kernel->boot(); drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); } diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index f866a48..497aa8d 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -32,9 +32,14 @@ class DrupalKernel extends Kernel { */ protected $systemList; - public function __construct($environment, $debug, $system_list) { + public function __construct($environment, $debug, $system_list = NULL) { parent::__construct($environment, $debug); - $this->systemList = $system_list; + if (isset($system_list)) { + $this->systemList = $system_list; + } + else { + $this->systemList = system_list(); + } } /** @@ -96,13 +101,17 @@ class DrupalKernel extends Kernel { } else { $this->container = $this->buildContainer(); - if ($storage->writeable()) { - $this->dumpDrupalContainer($cache_file, $this->container, $class, $this->getContainerBaseClass(), $storage); + if (!$this->dumpDrupalContainer($cache_file, $this->container, $class, $this->getContainerBaseClass(), $storage)) { + $exception = 'Container cannot be written to disk'; } } $this->container->set('kernel', $this); drupal_container($this->container); + + if (isset($exception)) { + watchdog('DrupalKernel', $exception); + } } /** @@ -149,8 +158,14 @@ class DrupalKernel extends Kernel { * The name of the container's base class * @param PhpStorageInterface $storage * The PHP storage class. + * + * @return bool + * TRUE if the container was successfully dumped to disk. */ protected function dumpDrupalContainer($cache_file, ContainerBuilder $container, $class, $baseClass, PhpStorageInterface $storage) { + if (!$storage->writeable()) { + return FALSE; + } // Cache the container. $dumper = new PhpDumper($container); $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass)); @@ -159,7 +174,7 @@ class DrupalKernel extends Kernel { $content = self::stripComments($content); } - $storage->save($cache_file, $content); + return $storage->save($cache_file, $content); } /** diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 0783633..385d6f4 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -673,7 +673,7 @@ abstract class WebTestBase extends TestBase { // container in drupal_container(). Drupal\simpletest\TestBase::tearDown() // restores the original container. // @see Drupal\Core\DrupalKernel::initializeContainer() - $this->kernel = new DrupalKernel('testing', FALSE, system_list()); + $this->kernel = new DrupalKernel('testing', FALSE); // Booting the kernel is necessary to initialize the new DIC. While // normally the kernel gets booted on demand in // Symfony\Component\HttpKernel\handle(), this kernel needs manual booting diff --git a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php new file mode 100644 index 0000000..b13616c --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php @@ -0,0 +1,97 @@ + 'DrupalKernel tests', + 'description' => 'Tests DIC compilation to disk.', + 'group' => 'DrupalKernel', + ); + } + + /** + * Test DIC compilation. + */ + function testCompileDIC() { + global $conf; + $conf['php_storage']['service_container'] = array( + 'class' => 'Drupal\Component\PhpStorage\MTimeProtectedFileStorage', + 'secret' => $GLOBALS['drupal_hash_salt'], + ); + $module_enabled = array( + 'system' => 'system', + 'user' => 'user', + ); + $module_enabled_hash = hash('sha256', implode(',', array_keys($module_enabled))); + $system_list = array( + 'module_enabled' => $module_enabled, + 'module_enabled_hash' => $module_enabled_hash, + ); + $kernel = new DrupalKernel('testing', FALSE, $system_list); + $kernel->boot(); + // Instantiate it a second time and we should get the compiled Container + // class. + $kernel = new DrupalKernel('testing', FALSE, $system_list); + $kernel->boot(); + $container = drupal_container(); + $refClass = new ReflectionClass($container); + $is_compiled_container = + $refClass->getParentClass()->getName() == 'Symfony\Component\DependencyInjection\Container' && + !$refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder'); + $this->assertTrue($is_compiled_container); + // We make this assertion here purely to show that the new container below + // is functioning correctly, i.e. we get a brand new ContainerBuilder + // which has the required new services. + $this->assertFalse($container->has('bundle_test_class')); + + // Reset the container. + drupal_container(NULL, TRUE); + + // Now use the read-only storage implementation + drupal_static_reset('drupal_php_storage'); + $conf['php_storage']['service_container'] = array( + 'class' => 'Drupal\Component\PhpStorage\FileReadOnlyStorage', + ); + + // Add another module so that a different hash is used for the class name + // and we can test that the new module's bundle is registered to the new + // container. + $module_enabled = array( + 'system' => 'system', + 'user' => 'user', + 'bundle_test' => 'bundle_test', + ); + $module_enabled_hash = hash('sha256', implode(',', array_keys($module_enabled))); + $system_list = array( + 'module_enabled' => $module_enabled, + 'module_enabled_hash' => $module_enabled_hash, + ); + $kernel = new DrupalKernel('testing', FALSE, $system_list); + $kernel->boot(); + // Instantiate it a second time and we should still get a ContainerBuilder + // class. + $kernel = new DrupalKernel('testing', FALSE, $system_list); + $kernel->boot(); + $container = drupal_container(); + $refClass = new ReflectionClass($container); + $is_container_builder = $refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder'); + $this->assertTrue($is_container_builder); + // Assert that the new module's bundle was registered to the new container. + $this->assertTrue($container->has('bundle_test_class')); + } +} diff --git a/core/modules/system/tests/http.php b/core/modules/system/tests/http.php index 313c4c0..297e3c7 100644 --- a/core/modules/system/tests/http.php +++ b/core/modules/system/tests/http.php @@ -36,6 +36,6 @@ $request = Request::createFromGlobals(); drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); -$kernel = new DrupalKernel('prod', FALSE, system_list()); +$kernel = new DrupalKernel('prod', FALSE); $response = $kernel->handle($request)->prepare($request)->send(); $kernel->terminate($request, $response); diff --git a/core/modules/system/tests/https.php b/core/modules/system/tests/https.php index d55d596..8e09a5d 100644 --- a/core/modules/system/tests/https.php +++ b/core/modules/system/tests/https.php @@ -35,6 +35,6 @@ $request = Request::createFromGlobals(); drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); -$kernel = new DrupalKernel('prod', FALSE, system_list()); +$kernel = new DrupalKernel('prod', FALSE); $response = $kernel->handle($request)->prepare($request)->send(); $kernel->terminate($request, $response); diff --git a/index.php b/index.php index e24a769..38177ab 100644 --- a/index.php +++ b/index.php @@ -28,7 +28,7 @@ require_once DRUPAL_ROOT . '/core/includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); // @todo Figure out how best to handle the Kernel constructor parameters. -$kernel = new DrupalKernel('prod', FALSE, system_list()); +$kernel = new DrupalKernel('prod', FALSE); // Create a request object from the HTTPFoundation. $request = Request::createFromGlobals();