Created
June 6, 2014 22:28
-
-
Save neclimdul/7e837fccd17d89815c19 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc | |
index ed2fc97..e244104 100644 | |
--- a/core/includes/install.core.inc | |
+++ b/core/includes/install.core.inc | |
@@ -9,6 +9,7 @@ | |
use Drupal\Core\Installer\Exception\AlreadyInstalledException; | |
use Drupal\Core\Installer\Exception\InstallerException; | |
use Drupal\Core\Installer\Exception\NoProfilesException; | |
+use Drupal\Core\Installer\InstallerKernel; | |
use Drupal\Core\Language\Language; | |
use Drupal\Core\Language\LanguageManager; | |
use Drupal\Core\Page\DefaultHtmlPageRenderer; | |
@@ -351,7 +352,7 @@ function install_begin_request(&$install_state) { | |
$environment = 'prod'; | |
} | |
- $kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), $environment, FALSE); | |
+ $kernel = InstallerKernel::createFromRequest($request, drupal_classloader(), $environment); | |
$kernel->setSitePath($site_path); | |
$kernel->boot(); | |
$container = $kernel->getContainer(); | |
@@ -367,8 +368,6 @@ function install_begin_request(&$install_state) { | |
$container->get('string_translation') | |
->addTranslator($container->get('string_translator.file_translation')); | |
- $kernel->prepareLegacyRequest($request); | |
- | |
// Set the default language to the selected language, if any. | |
if (isset($install_state['parameters']['langcode'])) { | |
$default_language = new Language(array('id' => $install_state['parameters']['langcode'])); | |
@@ -408,6 +407,8 @@ function install_begin_request(&$install_state) { | |
// checked by other subsystems (e.g., the theme system). | |
$module_handler->loadAll(); | |
+ $kernel->prepareLegacyRequest($request); | |
+ | |
// Prepare for themed output. We need to run this at the beginning of the | |
// page request to avoid a different theme accidentally getting set. (We also | |
// need to run it even in the case of command-line installations, to prevent | |
diff --git a/core/includes/install.inc b/core/includes/install.inc | |
index ce7db87..6b54f9b 100644 | |
--- a/core/includes/install.inc | |
+++ b/core/includes/install.inc | |
@@ -636,8 +636,11 @@ function drupal_install_system($install_state) { | |
unset($GLOBALS['conf']['container_service_providers']['InstallerServiceProvider']); | |
// Reboot into a full production environment to continue the installation. | |
+ /** @var \Drupal\Core\Installer\InstallerKernel $kernel */ | |
$kernel = \Drupal::service('kernel'); | |
$kernel->shutdown(); | |
+ // Have installer rebuild from the disk, rather then building from scratch. | |
+ $kernel->rebuildContainer(FALSE); | |
$kernel->prepareLegacyRequest(\Drupal::request()); | |
// Install base system configuration. | |
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php | |
index 135ab43..8713290 100644 | |
--- a/core/lib/Drupal/Core/DrupalKernel.php | |
+++ b/core/lib/Drupal/Core/DrupalKernel.php | |
@@ -21,10 +21,12 @@ | |
use Drupal\Core\Language\Language; | |
use Drupal\Core\PhpStorage\PhpStorageFactory; | |
use Drupal\Core\Site\Settings; | |
+use Symfony\Component\DependencyInjection\ContainerInterface; | |
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; | |
use Symfony\Component\DependencyInjection\Dumper\PhpDumper; | |
use Symfony\Component\HttpFoundation\RedirectResponse; | |
use Symfony\Component\HttpFoundation\Request; | |
+use Symfony\Component\HttpFoundation\RequestStack; | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Component\HttpKernel\TerminableInterface; | |
use Composer\Autoload\ClassLoader; | |
@@ -77,15 +79,6 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { | |
protected $moduleList; | |
/** | |
- * Holds an updated list of enabled modules. | |
- * | |
- * @var array | |
- * An associative array whose keys are module names and whose values are | |
- * ignored. | |
- */ | |
- protected $newModuleList; | |
- | |
- /** | |
* List of available modules and installation profiles. | |
* | |
* @var \Drupal\Core\Extension\Extension[] | |
@@ -121,13 +114,6 @@ 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 | |
@@ -246,15 +232,11 @@ public static function createFromRequest(Request $request, ClassLoader $class_lo | |
* @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 the kernel attempting to read the dependency | |
- * injection container from disk. Defaults to $allow_dumping. | |
*/ | |
- public function __construct($environment, ClassLoader $class_loader, $allow_dumping = TRUE, $allow_loading = NULL) { | |
+ public function __construct($environment, ClassLoader $class_loader, $allow_dumping = TRUE) { | |
$this->environment = $environment; | |
$this->classLoader = $class_loader; | |
$this->allowDumping = $allow_dumping; | |
- $this->allowLoading = isset($allow_loading) ? $allow_loading : $allow_dumping; | |
} | |
/** | |
@@ -652,22 +634,17 @@ protected function moduleData($module) { | |
* needed. | |
*/ | |
public function updateModules(array $module_list, array $module_filenames = array()) { | |
- $this->newModuleList = $module_list; | |
+ $this->moduleList = $module_list; | |
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 container 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. | |
+ // then rebuild the container in order to refresh the serviceProvider list | |
+ // and container. | |
if ($this->booted) { | |
- $this->booted = FALSE; | |
- $this->boot(); | |
+ $this->initializeContainer(TRUE); | |
} | |
} | |
@@ -696,13 +673,17 @@ protected function getKernelParameters() { | |
/** | |
* Initializes the service container. | |
+ * | |
+ * @param bool $rebuild | |
+ * Force a container rebuild. | |
+ * @return \Symfony\Component\DependencyInjection\ContainerInterface | |
*/ | |
- protected function initializeContainer() { | |
+ protected function initializeContainer($rebuild = FALSE) { | |
$this->containerNeedsDumping = FALSE; | |
- $persist = $this->getServicesToPersist(); | |
// The request service requires custom persisting logic, since it is also | |
// potentially scoped. | |
$request_scope = FALSE; | |
+ $request_stack = $request = NULL; | |
if (isset($this->container)) { | |
if ($this->container->isScopeActive('request')) { | |
$request_scope = TRUE; | |
@@ -710,12 +691,16 @@ protected function initializeContainer() { | |
if ($this->container->initialized('request')) { | |
$request = $this->container->get('request'); | |
} | |
+ if ($this->container->initialized('request_stack')) { | |
+ $request_stack = $this->container->get('request_stack'); | |
+ } | |
} | |
$this->container = NULL; | |
- $class = $this->getClassName(); | |
- $cache_file = $class . '.php'; | |
- if ($this->allowLoading) { | |
+ if (!$rebuild) { | |
+ $class = $this->getClassName(); | |
+ $cache_file = $class . '.php'; | |
+ | |
// First, try to load. | |
if (!class_exists($class, FALSE)) { | |
$this->storage()->load($cache_file); | |
@@ -724,50 +709,17 @@ protected function initializeContainer() { | |
if (class_exists($class, FALSE)) { | |
$fully_qualified_class_name = '\\' . $class; | |
$this->container = new $fully_qualified_class_name; | |
- $this->persistServices($persist); | |
} | |
} | |
- // First check whether the list of modules changed in this request. | |
- if (isset($this->newModuleList)) { | |
- if (isset($this->container) && isset($this->moduleList) && array_keys($this->moduleList) !== array_keys($this->newModuleList)) { | |
- unset($this->container); | |
- } | |
- $this->moduleList = $this->newModuleList; | |
- unset($this->newModuleList); | |
- } | |
- if (isset($this->container)) { | |
- // All namespaces must be registered before we attempt to use any service | |
- // from the container. | |
- $this->classLoaderAddMultiplePsr4($this->container->getParameter('container.namespaces')); | |
- } | |
- else { | |
- $this->container = $this->buildContainer(); | |
- $this->persistServices($persist); | |
- // The namespaces are marked as persistent, so objects like the annotated | |
- // class discovery still has the right object. We may have updated the | |
- // list of modules, so set it. | |
- if ($this->container->initialized('container.namespaces')) { | |
- $this->container->get('container.namespaces')->exchangeArray($this->container->getParameter('container.namespaces')); | |
- } | |
- | |
- if ($this->allowDumping) { | |
- $this->containerNeedsDumping = TRUE; | |
- } | |
+ if (!isset($this->container)) { | |
+ $this->container = $this->buildContainer(); | |
} | |
- $this->container->set('kernel', $this); | |
+ $this->attachShit($this->container, $request, $request_stack, $request_scope); | |
- // Set the class loader which was registered as a synthetic service. | |
- $this->container->set('class_loader', $this->classLoader); | |
- // If we have a request set it back to the new container. | |
- if ($request_scope) { | |
- $this->container->enterScope('request'); | |
- } | |
- if (isset($request)) { | |
- $this->container->set('request', $request); | |
- } | |
\Drupal::setContainer($this->container); | |
+ return $this->container; | |
} | |
/** | |
@@ -982,14 +934,12 @@ protected function initializeCookieGlobals(Request $request) { | |
/** | |
* Returns service instances to persist from an old container to a new one. | |
*/ | |
- protected function getServicesToPersist() { | |
+ protected function getServicesToPersist(ContainerInterface $container) { | |
$persist = array(); | |
- if (isset($this->container)) { | |
- foreach ($this->container->getParameter('persistIds') as $id) { | |
- // It's pointless to persist services not yet initialized. | |
- if ($this->container->initialized($id)) { | |
- $persist[$id] = $this->container->get($id); | |
- } | |
+ foreach ($container->getParameter('persistIds') as $id) { | |
+ // It's pointless to persist services not yet initialized. | |
+ if ($container->initialized($id)) { | |
+ $persist[$id] = $container->get($id); | |
} | |
} | |
return $persist; | |
@@ -998,22 +948,83 @@ protected function getServicesToPersist() { | |
/** | |
* Moves persistent service instances into a new container. | |
*/ | |
- protected function persistServices(array $persist) { | |
+ protected function persistServices(ContainerInterface $container, array $persist) { | |
foreach ($persist as $id => $object) { | |
// Do not override services already set() on the new container, for | |
// example 'service_container'. | |
- if (!$this->container->initialized($id)) { | |
- $this->container->set($id, $object); | |
+ if (!$container->initialized($id)) { | |
+ $container->set($id, $object); | |
} | |
} | |
} | |
/** | |
- * Builds the service container. | |
+ * Force a container rebuild. | |
+ * | |
+ * @return \Symfony\Component\DependencyInjection\ContainerInterface | |
+ */ | |
+ public function rebuildContainer() { | |
+ return $this->initializeContainer(TRUE); | |
+ } | |
+ | |
+ /** | |
+ * Build a new container. | |
+ */ | |
+ protected function buildContainer(Request $request = NULL, $request_scope = NULL) { | |
+ // We are forcing a container build so it is reasonable to assume that the | |
+ // calling method knows something about the system has changed requiring the | |
+ // container to be dumped to the filesystem. | |
+ if ($this->allowDumping) { | |
+ $this->containerNeedsDumping = TRUE; | |
+ } | |
+ | |
+ $container = $this->compileContainer(); | |
+ $container = $this->attachShit($container, $request, $request_scope); | |
+ | |
+ return $container; | |
+ } | |
+ | |
+ protected function attachShit(ContainerInterface $container, Request $request = NULL, RequestStack $request_stack = NULL, $request_scope = NULL) { | |
+ | |
+ $persist = array(); | |
+ if (isset($this->container)) { | |
+ $persist = $this->getServicesToPersist($this->container); | |
+ } | |
+ $this->persistServices($container, $persist); | |
+ | |
+ // All namespaces must be registered before we attempt to use any service | |
+ // from the container. | |
+ $this->classLoaderAddMultiplePsr4($container->getParameter('container.namespaces')); | |
+ | |
+ // The namespaces are marked as persistent, so objects like the annotated | |
+ // class discovery still has the right object. We may have updated the | |
+ // list of modules, so set it. | |
+ if ($container->initialized('container.namespaces')) { | |
+ $container->get('container.namespaces')->exchangeArray($container->getParameter('container.namespaces')); | |
+ } | |
+ $container->set('kernel', $this); | |
+ | |
+ // Set the class loader which was registered as a synthetic service. | |
+ $container->set('class_loader', $this->classLoader); | |
+ // If we have a request set it back to the new container. | |
+ if ($request_scope) { | |
+ $container->enterScope('request'); | |
+ } | |
+ if (isset($request)) { | |
+ $container->set('request', $request); | |
+ } | |
+ if (isset($request_stack)) { | |
+ $container->set('request_stack', $request_stack); | |
+ } | |
+ return $container; | |
+ } | |
+ | |
+ /** | |
+ * Compiles a new service container. | |
* | |
* @return ContainerBuilder The compiled service container | |
*/ | |
- protected function buildContainer() { | |
+ protected function compileContainer() { | |
$this->initializeServiceProviders(); | |
$container = $this->getContainerBuilder(); | |
$container->set('kernel', $this); | |
diff --git a/core/lib/Drupal/Core/Installer/InstallerKernel.php b/core/lib/Drupal/Core/Installer/InstallerKernel.php | |
new file mode 100644 | |
index 0000000..dcac1b5 | |
--- /dev/null | |
+++ b/core/lib/Drupal/Core/Installer/InstallerKernel.php | |
@@ -0,0 +1,36 @@ | |
+<?php | |
+ | |
+/** | |
+ * @file | |
+ * Contains \Drupal\Core\Installer\InstallerKernel. | |
+ */ | |
+ | |
+namespace Drupal\Core\Installer; | |
+ | |
+use Drupal\Core\DependencyInjection\ContainerBuilder; | |
+use Drupal\Core\DrupalKernel; | |
+use Drupal\Core\Site\Settings; | |
+use Symfony\Component\DependencyInjection\Exception\RuntimeException; | |
+ | |
+/** | |
+ * Extend DrupalKernel to handle force some kernel behaviors. | |
+ */ | |
+class InstallerKernel extends DrupalKernel { | |
+ | |
+ /** | |
+ * {@inheritdoc} | |
+ */ | |
+ protected function initializeContainer($rebuild = TRUE) { | |
+ $container = parent::initializeContainer($rebuild); | |
+ return $container; | |
+ } | |
+ | |
+ /** | |
+ * {@inheritdoc} | |
+ */ | |
+ protected function dumpDrupalContainer(ContainerBuilder $container, $baseClass) { | |
+ if (Settings::get('hash_salt')) { | |
+ return parent::dumpDrupalContainer($container, $baseClass); | |
+ } | |
+ } | |
+} | |
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php | |
index e75411d..0b5c19b 100644 | |
--- a/core/modules/simpletest/src/WebTestBase.php | |
+++ b/core/modules/simpletest/src/WebTestBase.php | |
@@ -866,8 +866,10 @@ protected function setUp() { | |
$request = \Drupal::request(); | |
$this->kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod', TRUE); | |
+ // Force the container to be built from scratch instead of loaded from the | |
+ // disk. This forces us to not accidently load the parent site. | |
+ $container = $this->kernel->rebuildContainer(); | |
$this->kernel->prepareLegacyRequest($request); | |
- $container = $this->kernel->getContainer(); | |
$config = $container->get('config.factory'); | |
// Manually create and configure private and temporary files directories. | |
@@ -1087,15 +1089,8 @@ protected function writeCustomTranslations() { | |
protected function rebuildContainer() { | |
// Maintain the current global request object. | |
$request = \Drupal::request(); | |
- | |
// Rebuild the kernel and bring it back to a fully bootstrapped state. | |
- $this->kernel->shutdown(); | |
- $this->kernel->prepareLegacyRequest($request); | |
- | |
- // DrupalKernel replaces the container in \Drupal::getContainer() with a | |
- // different object, so we need to replace the instance on this test class. | |
- $this->container = $this->kernel->getContainer(); | |
- | |
+ $this->container = $this->kernel->rebuildContainer(); | |
$this->container->get('current_user')->setAccount(\Drupal::currentUser()); | |
// The request context is normally set by the router_listener from within |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment