Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save neclimdul/7e837fccd17d89815c19 to your computer and use it in GitHub Desktop.
Save neclimdul/7e837fccd17d89815c19 to your computer and use it in GitHub Desktop.
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