Created
July 14, 2021 13:42
-
-
Save podarok/1c68ac88cc988f223a09e47c3933e70d to your computer and use it in GitHub Desktop.
2160091-6e84b57.diff
This file contains hidden or 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/common.inc b/core/includes/common.inc | |
index 42d9b80d28..f640a90121 100644 | |
--- a/core/includes/common.inc | |
+++ b/core/includes/common.inc | |
@@ -12,6 +12,7 @@ | |
use Drupal\Component\Utility\Html; | |
use Drupal\Component\Utility\SortArray; | |
use Drupal\Core\Cache\Cache; | |
+use Drupal\Core\DrupalKernel; | |
use Drupal\Core\StringTranslation\TranslatableMarkup; | |
/** | |
@@ -460,10 +461,11 @@ function show(&$element) { | |
} | |
/** | |
- * Flushes all persistent caches, resets all variables, and rebuilds all data structures. | |
+ * Rebuilds the container, flushes all persistent caches, resets all variables, and rebuilds all data structures. | |
* | |
* At times, it is necessary to re-initialize the entire system to account for | |
* changed or new code. This function: | |
+ * - Rebuilds the container if $kernel is not passed in. | |
* - Clears all persistent caches: | |
* - The bootstrap cache bin containing base system, module system, and theme | |
* system information. | |
@@ -483,6 +485,10 @@ function show(&$element) { | |
* - The 'active' status of fields is refreshed. | |
* - Rebuilds the menu router. | |
* | |
+ * It's discouraged to call this during a regular page request. | |
+ * If you call this function in tests, every code afterwards should use the new | |
+ * container. | |
+ * | |
* This means the entire system is reset so all caches and static variables are | |
* effectively empty. After that is guaranteed, information about the currently | |
* active code is updated, and rebuild operations are successively called in | |
@@ -512,12 +518,19 @@ function show(&$element) { | |
* cache though.) | |
* @todo Add a global lock to ensure that caches are not primed in concurrent | |
* requests. | |
+ * | |
+ * @param \Drupal\Core\DrupalKernel|array $kernel | |
+ * (optional) The Drupal Kernel. It is the caller's responsibility to rebuild | |
+ * the container if this is passed in. Sometimes drupal_flush_all_caches is | |
+ * used as a batch operation so $kernel will be an array, in this instance it | |
+ * will be treated as if it it NULL. | |
*/ | |
-function drupal_flush_all_caches() { | |
+function drupal_flush_all_caches($kernel = NULL) { | |
+ // This is executed based on old/previously known information if $kernel is | |
+ // not passed in, which is sufficient, since new extensions cannot have any | |
+ // primed caches yet. | |
$module_handler = \Drupal::moduleHandler(); | |
// Flush all persistent caches. | |
- // This is executed based on old/previously known information, which is | |
- // sufficient, since new extensions cannot have any primed caches yet. | |
$module_handler->invokeAll('cache_flush'); | |
foreach (Cache::getBins() as $service_id => $cache_backend) { | |
$cache_backend->deleteAll(); | |
@@ -531,43 +544,26 @@ function drupal_flush_all_caches() { | |
// Reset all static caches. | |
drupal_static_reset(); | |
- // Invalidate the container. | |
- \Drupal::service('kernel')->invalidateContainer(); | |
- | |
// Wipe the Twig PHP Storage cache. | |
\Drupal::service('twig')->invalidate(); | |
- // Rebuild module and theme data. | |
- $module_data = \Drupal::service('extension.list.module')->reset()->getList(); | |
- /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */ | |
- $theme_handler = \Drupal::service('theme_handler'); | |
- $theme_handler->refreshInfo(); | |
+ // Rebuild theme data that is stored in state. | |
+ \Drupal::service('theme_handler')->refreshInfo(); | |
// In case the active theme gets requested later in the same request we need | |
// to reset the theme manager. | |
\Drupal::theme()->resetActiveTheme(); | |
- // Rebuild and reboot a new kernel. A simple DrupalKernel reboot is not | |
- // sufficient, since the list of enabled modules might have been adjusted | |
- // above due to changed code. | |
- $files = []; | |
- $modules = []; | |
- foreach ($module_data as $name => $extension) { | |
- if ($extension->status) { | |
- $files[$name] = $extension; | |
- $modules[$name] = $extension->weight; | |
- } | |
+ if (!$kernel instanceof DrupalKernel) { | |
+ $kernel = \Drupal::service('kernel'); | |
+ $kernel->invalidateContainer(); | |
+ $kernel->rebuildContainer(); | |
} | |
- $modules = module_config_sort($modules); | |
- \Drupal::service('kernel')->updateModules($modules, $files); | |
- // New container, new module handler. | |
- $module_handler = \Drupal::moduleHandler(); | |
- // Ensure that all modules that are currently supposed to be enabled are | |
- // actually loaded. | |
- $module_handler->loadAll(); | |
+ // Rebuild module data that is stored in state. | |
+ \Drupal::service('extension.list.module')->reset(); | |
// Rebuild all information based on new module data. | |
- $module_handler->invokeAll('rebuild'); | |
+ \Drupal::moduleHandler()->invokeAll('rebuild'); | |
// Clear all plugin caches. | |
\Drupal::service('plugin.cache_clearer')->clearCachedDefinitions(); | |
diff --git a/core/includes/utility.inc b/core/includes/utility.inc | |
index 3a6ef0bde2..13975bd18b 100644 | |
--- a/core/includes/utility.inc | |
+++ b/core/includes/utility.inc | |
@@ -5,8 +5,6 @@ | |
* Miscellaneous functions. | |
*/ | |
-use Drupal\Core\PhpStorage\PhpStorageFactory; | |
-use Drupal\Core\Cache\Cache; | |
use Drupal\Core\DrupalKernel; | |
use Symfony\Component\HttpFoundation\Request; | |
@@ -28,12 +26,11 @@ function drupal_rebuild($class_loader, Request $request) { | |
restore_error_handler(); | |
restore_exception_handler(); | |
- // Force kernel to rebuild php cache. | |
- PhpStorageFactory::get('twig')->deleteAll(); | |
- | |
+ // Invalidate the container. | |
// Bootstrap up to where caches exist and clear them. | |
$kernel = new DrupalKernel('prod', $class_loader); | |
$kernel->setSitePath(DrupalKernel::findSitePath($request)); | |
+ $kernel->invalidateContainer(); | |
$kernel->boot(); | |
$kernel->preHandle($request); | |
// Ensure our request includes the session if appropriate. | |
@@ -41,18 +38,11 @@ function drupal_rebuild($class_loader, Request $request) { | |
$request->setSession($kernel->getContainer()->get('session')); | |
} | |
- // Invalidate the container. | |
- $kernel->invalidateContainer(); | |
- | |
- foreach (Cache::getBins() as $bin) { | |
- $bin->deleteAll(); | |
- } | |
+ drupal_flush_all_caches($kernel); | |
// Disable recording of cached pages. | |
\Drupal::service('page_cache_kill_switch')->trigger(); | |
- drupal_flush_all_caches(); | |
- | |
// Restore Drupal's error and exception handlers. | |
// @see \Drupal\Core\DrupalKernel::boot() | |
set_error_handler('_drupal_error_handler'); | |
diff --git a/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.info.yml b/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.info.yml | |
new file mode 100644 | |
index 0000000000..2c82600fd6 | |
--- /dev/null | |
+++ b/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.info.yml | |
@@ -0,0 +1,5 @@ | |
+name: 'Service Provider test' | |
+type: module | |
+description: 'Support module for service provider testing.' | |
+package: Testing | |
+version: VERSION | |
diff --git a/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.routing.yml b/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.routing.yml | |
new file mode 100644 | |
index 0000000000..0382c21dd2 | |
--- /dev/null | |
+++ b/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.routing.yml | |
@@ -0,0 +1,6 @@ | |
+container_rebuild_test.module_path: | |
+ path: '/container_rebuild_test/{module}/{function}' | |
+ defaults: | |
+ _controller: '\Drupal\container_rebuild_test\TestController::showModuleInfo' | |
+ requirements: | |
+ _access: 'TRUE' | |
diff --git a/core/modules/system/tests/modules/container_rebuild_test/src/ContainerRebuildTestServiceProvider.php b/core/modules/system/tests/modules/container_rebuild_test/src/ContainerRebuildTestServiceProvider.php | |
new file mode 100644 | |
index 0000000000..d5f2bb808c | |
--- /dev/null | |
+++ b/core/modules/system/tests/modules/container_rebuild_test/src/ContainerRebuildTestServiceProvider.php | |
@@ -0,0 +1,18 @@ | |
+<?php | |
+ | |
+namespace Drupal\container_rebuild_test; | |
+ | |
+use Drupal\Core\DependencyInjection\ContainerBuilder; | |
+use Drupal\Core\DependencyInjection\ServiceModifierInterface; | |
+ | |
+class ContainerRebuildTestServiceProvider implements ServiceModifierInterface { | |
+ | |
+ /** | |
+ * {@inheritdoc} | |
+ */ | |
+ public function alter(ContainerBuilder $container) { | |
+ $count = $container->get('state')->get('container_rebuild_test.count', 0); | |
+ $container->get('state')->set('container_rebuild_test.count', ++$count); | |
+ } | |
+ | |
+} | |
diff --git a/core/modules/system/tests/modules/container_rebuild_test/src/TestController.php b/core/modules/system/tests/modules/container_rebuild_test/src/TestController.php | |
new file mode 100644 | |
index 0000000000..7fc722facc | |
--- /dev/null | |
+++ b/core/modules/system/tests/modules/container_rebuild_test/src/TestController.php | |
@@ -0,0 +1,37 @@ | |
+<?php | |
+ | |
+namespace Drupal\container_rebuild_test; | |
+ | |
+use Drupal\Core\Controller\ControllerBase; | |
+ | |
+class TestController extends ControllerBase { | |
+ | |
+ /** | |
+ * Displays the path to a module. | |
+ * | |
+ * @param string $module | |
+ * The module name. | |
+ * @param string $function | |
+ * The function to check if it exists. | |
+ * | |
+ * @return string[] | |
+ * A render array. | |
+ */ | |
+ public function showModuleInfo(string $module, string $function) { | |
+ $module_handler = \Drupal::moduleHandler(); | |
+ $module_message = $module . ': '; | |
+ if ($module_handler->moduleExists($module)) { | |
+ $module_message .= \Drupal::moduleHandler()->getModule($module)->getPath(); | |
+ } | |
+ else { | |
+ $module_message .= 'not installed'; | |
+ } | |
+ $function_message = $function . ': ' . var_export(function_exists($function), TRUE); | |
+ | |
+ return [ | |
+ '#theme' => 'item_list', | |
+ '#items' => [$module_message, $function_message], | |
+ ]; | |
+ } | |
+ | |
+} | |
diff --git a/core/modules/system/tests/src/Functional/UpdateSystem/RebuildScriptTest.php b/core/modules/system/tests/src/Functional/UpdateSystem/RebuildScriptTest.php | |
index 33ca0c197a..442476c1ef 100644 | |
--- a/core/modules/system/tests/src/Functional/UpdateSystem/RebuildScriptTest.php | |
+++ b/core/modules/system/tests/src/Functional/UpdateSystem/RebuildScriptTest.php | |
@@ -4,6 +4,7 @@ | |
use Drupal\Core\Url; | |
use Drupal\Tests\BrowserTestBase; | |
+use Symfony\Component\Filesystem\Filesystem; | |
/** | |
* Tests the rebuild script access and functionality. | |
@@ -12,6 +13,11 @@ | |
*/ | |
class RebuildScriptTest extends BrowserTestBase { | |
+ /** | |
+ * {@inheritdoc} | |
+ */ | |
+ protected static $modules = ['module_test', 'container_rebuild_test']; | |
+ | |
/** | |
* {@inheritdoc} | |
*/ | |
@@ -37,9 +43,60 @@ public function testRebuild() { | |
$this->rebuildAll(); | |
$cache->set('rebuild_test', TRUE); | |
+ \Drupal::state()->set('container_rebuild_test.count', 0); | |
+ $this->drupalGet(Url::fromUri('base:core/rebuild.php')); | |
+ $this->assertSession()->addressEquals(new Url('<front>')); | |
+ $this->assertFalse($cache->get('rebuild_test')); | |
+ $this->refreshVariables(); | |
+ $this->assertSame(1, \Drupal::state()->get('container_rebuild_test.count', 0)); | |
+ $this->drupalGet('/container_rebuild_test/module_test/module_test_system_info_alter'); | |
+ $this->assertSession()->pageTextContains('module_test: core/modules/system/tests/modules/module_test'); | |
+ $this->assertSession()->pageTextContains('module_test_system_info_alter: true'); | |
+ | |
+ // Move a module to ensure it does not break the rebuild. | |
+ $file_system = new Filesystem(); | |
+ $file_system->mirror('core/modules/system/tests/modules/module_test', $this->siteDirectory . '/modules/module_test'); | |
+ \Drupal::state()->set('container_rebuild_test.count', 0); | |
+ $this->drupalGet(Url::fromUri('base:core/rebuild.php')); | |
+ $this->assertSession()->addressEquals(new Url('<front>')); | |
+ $this->refreshVariables(); | |
+ $this->assertSame(1, \Drupal::state()->get('container_rebuild_test.count', 0)); | |
+ $this->drupalGet('/container_rebuild_test/module_test/module_test_system_info_alter'); | |
+ $this->assertSession()->pageTextContains('module_test: ' . $this->siteDirectory . '/modules/module_test'); | |
+ $this->assertSession()->pageTextContains('module_test_system_info_alter: true'); | |
+ | |
+ // Disable a module by writing to the core.extension list. | |
+ $this->config('core.extension')->clear('module.module_test')->save(); | |
+ \Drupal::state()->set('container_rebuild_test.count', 0); | |
+ $this->drupalGet(Url::fromUri('base:core/rebuild.php')); | |
+ $this->assertSession()->addressEquals(new Url('<front>')); | |
+ $this->refreshVariables(); | |
+ $this->assertSame(1, \Drupal::state()->get('container_rebuild_test.count', 0)); | |
+ $this->drupalGet('/container_rebuild_test/module_test/module_test_system_info_alter'); | |
+ $this->assertSession()->pageTextContains('module_test: not installed'); | |
+ $this->assertSession()->pageTextContains('module_test_system_info_alter: false'); | |
+ | |
+ // Enable a module by writing to the core.extension list. | |
+ $modules = $this->config('core.extension')->get('module'); | |
+ $modules['module_test'] = 0; | |
+ $this->config('core.extension')->set('module', module_config_sort($modules))->save(); | |
+ \Drupal::state()->set('container_rebuild_test.count', 0); | |
+ $this->drupalGet(Url::fromUri('base:core/rebuild.php')); | |
+ $this->assertSession()->addressEquals(new Url('<front>')); | |
+ $this->refreshVariables(); | |
+ $this->assertSame(1, \Drupal::state()->get('container_rebuild_test.count', 0)); | |
+ $this->drupalGet('/container_rebuild_test/module_test/module_test_system_info_alter'); | |
+ $this->assertSession()->pageTextContains('module_test: ' . $this->siteDirectory . '/modules/module_test'); | |
+ $this->assertSession()->pageTextContains('module_test_system_info_alter: true'); | |
+ | |
+ // Test how many container rebuild occur when there is no cached container. | |
+ \Drupal::state()->set('container_rebuild_test.count', 0); | |
+ \Drupal::service('kernel')->invalidateContainer(); | |
$this->drupalGet(Url::fromUri('base:core/rebuild.php')); | |
$this->assertSession()->addressEquals(new Url('<front>')); | |
$this->assertFalse($cache->get('rebuild_test')); | |
+ $this->refreshVariables(); | |
+ $this->assertSame(1, \Drupal::state()->get('container_rebuild_test.count', 0)); | |
} | |
} | |
diff --git a/core/tests/Drupal/KernelTests/Core/Common/DrupalFlushAllCachesTest.php b/core/tests/Drupal/KernelTests/Core/Common/DrupalFlushAllCachesTest.php | |
index 0953c05a4c..9cb1dc2def 100644 | |
--- a/core/tests/Drupal/KernelTests/Core/Common/DrupalFlushAllCachesTest.php | |
+++ b/core/tests/Drupal/KernelTests/Core/Common/DrupalFlushAllCachesTest.php | |
@@ -2,6 +2,7 @@ | |
namespace Drupal\KernelTests\Core\Common; | |
+use Drupal\Core\DependencyInjection\ContainerBuilder; | |
use Drupal\KernelTests\KernelTestBase; | |
/** | |
@@ -10,6 +11,13 @@ | |
*/ | |
class DrupalFlushAllCachesTest extends KernelTestBase { | |
+ /** | |
+ * Stores the number of container builds. | |
+ * | |
+ * @var int | |
+ */ | |
+ protected $containerBuilds = 0; | |
+ | |
/** | |
* {@inheritdoc} | |
*/ | |
@@ -19,14 +27,30 @@ class DrupalFlushAllCachesTest extends KernelTestBase { | |
* Tests that drupal_flush_all_caches() uses core.extension properly. | |
*/ | |
public function testDrupalFlushAllCachesModuleList() { | |
+ $this->assertFalse(function_exists('system_test_help')); | |
$core_extension = \Drupal::configFactory()->getEditable('core.extension'); | |
$module = $core_extension->get('module'); | |
$module['system_test'] = -10; | |
$core_extension->set('module', module_config_sort($module))->save(); | |
+ $this->containerBuilds = 0; | |
+ drupal_flush_all_caches(); | |
+ $this->assertSame(['system_test', 'system'], array_keys($this->container->getParameter('container.modules'))); | |
+ $this->assertSame(1, $this->containerBuilds); | |
+ $this->assertTrue(function_exists('system_test_help')); | |
+ $core_extension->clear('module.system_test')->save(); | |
+ $this->containerBuilds = 0; | |
drupal_flush_all_caches(); | |
+ $this->assertSame(['system'], array_keys($this->container->getParameter('container.modules'))); | |
+ $this->assertSame(1, $this->containerBuilds); | |
+ } | |
- $this->assertSame(['system_test', 'system'], array_keys($this->container->getParameter('container.modules'))); | |
+ /** | |
+ * {@inheritdoc} | |
+ */ | |
+ public function register(ContainerBuilder $container) { | |
+ parent::register($container); | |
+ $this->containerBuilds++; | |
} | |
} | |
diff --git a/core/includes/common.inc b/core/includes/common.inc | |
index 42d9b80d28..f640a90121 100644 | |
--- a/core/includes/common.inc | |
+++ b/core/includes/common.inc | |
@@ -12,6 +12,7 @@ | |
use Drupal\Component\Utility\Html; | |
use Drupal\Component\Utility\SortArray; | |
use Drupal\Core\Cache\Cache; | |
+use Drupal\Core\DrupalKernel; | |
use Drupal\Core\StringTranslation\TranslatableMarkup; | |
/** | |
@@ -460,10 +461,11 @@ function show(&$element) { | |
} | |
/** | |
- * Flushes all persistent caches, resets all variables, and rebuilds all data structures. | |
+ * Rebuilds the container, flushes all persistent caches, resets all variables, and rebuilds all data structures. | |
* | |
* At times, it is necessary to re-initialize the entire system to account for | |
* changed or new code. This function: | |
+ * - Rebuilds the container if $kernel is not passed in. | |
* - Clears all persistent caches: | |
* - The bootstrap cache bin containing base system, module system, and theme | |
* system information. | |
@@ -483,6 +485,10 @@ function show(&$element) { | |
* - The 'active' status of fields is refreshed. | |
* - Rebuilds the menu router. | |
* | |
+ * It's discouraged to call this during a regular page request. | |
+ * If you call this function in tests, every code afterwards should use the new | |
+ * container. | |
+ * | |
* This means the entire system is reset so all caches and static variables are | |
* effectively empty. After that is guaranteed, information about the currently | |
* active code is updated, and rebuild operations are successively called in | |
@@ -512,12 +518,19 @@ function show(&$element) { | |
* cache though.) | |
* @todo Add a global lock to ensure that caches are not primed in concurrent | |
* requests. | |
+ * | |
+ * @param \Drupal\Core\DrupalKernel|array $kernel | |
+ * (optional) The Drupal Kernel. It is the caller's responsibility to rebuild | |
+ * the container if this is passed in. Sometimes drupal_flush_all_caches is | |
+ * used as a batch operation so $kernel will be an array, in this instance it | |
+ * will be treated as if it it NULL. | |
*/ | |
-function drupal_flush_all_caches() { | |
+function drupal_flush_all_caches($kernel = NULL) { | |
+ // This is executed based on old/previously known information if $kernel is | |
+ // not passed in, which is sufficient, since new extensions cannot have any | |
+ // primed caches yet. | |
$module_handler = \Drupal::moduleHandler(); | |
// Flush all persistent caches. | |
- // This is executed based on old/previously known information, which is | |
- // sufficient, since new extensions cannot have any primed caches yet. | |
$module_handler->invokeAll('cache_flush'); | |
foreach (Cache::getBins() as $service_id => $cache_backend) { | |
$cache_backend->deleteAll(); | |
@@ -531,43 +544,26 @@ function drupal_flush_all_caches() { | |
// Reset all static caches. | |
drupal_static_reset(); | |
- // Invalidate the container. | |
- \Drupal::service('kernel')->invalidateContainer(); | |
- | |
// Wipe the Twig PHP Storage cache. | |
\Drupal::service('twig')->invalidate(); | |
- // Rebuild module and theme data. | |
- $module_data = \Drupal::service('extension.list.module')->reset()->getList(); | |
- /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */ | |
- $theme_handler = \Drupal::service('theme_handler'); | |
- $theme_handler->refreshInfo(); | |
+ // Rebuild theme data that is stored in state. | |
+ \Drupal::service('theme_handler')->refreshInfo(); | |
// In case the active theme gets requested later in the same request we need | |
// to reset the theme manager. | |
\Drupal::theme()->resetActiveTheme(); | |
- // Rebuild and reboot a new kernel. A simple DrupalKernel reboot is not | |
- // sufficient, since the list of enabled modules might have been adjusted | |
- // above due to changed code. | |
- $files = []; | |
- $modules = []; | |
- foreach ($module_data as $name => $extension) { | |
- if ($extension->status) { | |
- $files[$name] = $extension; | |
- $modules[$name] = $extension->weight; | |
- } | |
+ if (!$kernel instanceof DrupalKernel) { | |
+ $kernel = \Drupal::service('kernel'); | |
+ $kernel->invalidateContainer(); | |
+ $kernel->rebuildContainer(); | |
} | |
- $modules = module_config_sort($modules); | |
- \Drupal::service('kernel')->updateModules($modules, $files); | |
- // New container, new module handler. | |
- $module_handler = \Drupal::moduleHandler(); | |
- // Ensure that all modules that are currently supposed to be enabled are | |
- // actually loaded. | |
- $module_handler->loadAll(); | |
+ // Rebuild module data that is stored in state. | |
+ \Drupal::service('extension.list.module')->reset(); | |
// Rebuild all information based on new module data. | |
- $module_handler->invokeAll('rebuild'); | |
+ \Drupal::moduleHandler()->invokeAll('rebuild'); | |
// Clear all plugin caches. | |
\Drupal::service('plugin.cache_clearer')->clearCachedDefinitions(); | |
diff --git a/core/includes/utility.inc b/core/includes/utility.inc | |
index 3a6ef0bde2..13975bd18b 100644 | |
--- a/core/includes/utility.inc | |
+++ b/core/includes/utility.inc | |
@@ -5,8 +5,6 @@ | |
* Miscellaneous functions. | |
*/ | |
-use Drupal\Core\PhpStorage\PhpStorageFactory; | |
-use Drupal\Core\Cache\Cache; | |
use Drupal\Core\DrupalKernel; | |
use Symfony\Component\HttpFoundation\Request; | |
@@ -28,12 +26,11 @@ function drupal_rebuild($class_loader, Request $request) { | |
restore_error_handler(); | |
restore_exception_handler(); | |
- // Force kernel to rebuild php cache. | |
- PhpStorageFactory::get('twig')->deleteAll(); | |
- | |
+ // Invalidate the container. | |
// Bootstrap up to where caches exist and clear them. | |
$kernel = new DrupalKernel('prod', $class_loader); | |
$kernel->setSitePath(DrupalKernel::findSitePath($request)); | |
+ $kernel->invalidateContainer(); | |
$kernel->boot(); | |
$kernel->preHandle($request); | |
// Ensure our request includes the session if appropriate. | |
@@ -41,18 +38,11 @@ function drupal_rebuild($class_loader, Request $request) { | |
$request->setSession($kernel->getContainer()->get('session')); | |
} | |
- // Invalidate the container. | |
- $kernel->invalidateContainer(); | |
- | |
- foreach (Cache::getBins() as $bin) { | |
- $bin->deleteAll(); | |
- } | |
+ drupal_flush_all_caches($kernel); | |
// Disable recording of cached pages. | |
\Drupal::service('page_cache_kill_switch')->trigger(); | |
- drupal_flush_all_caches(); | |
- | |
// Restore Drupal's error and exception handlers. | |
// @see \Drupal\Core\DrupalKernel::boot() | |
set_error_handler('_drupal_error_handler'); | |
diff --git a/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.info.yml b/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.info.yml | |
new file mode 100644 | |
index 0000000000..2c82600fd6 | |
--- /dev/null | |
+++ b/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.info.yml | |
@@ -0,0 +1,5 @@ | |
+name: 'Service Provider test' | |
+type: module | |
+description: 'Support module for service provider testing.' | |
+package: Testing | |
+version: VERSION | |
diff --git a/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.routing.yml b/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.routing.yml | |
new file mode 100644 | |
index 0000000000..0382c21dd2 | |
--- /dev/null | |
+++ b/core/modules/system/tests/modules/container_rebuild_test/container_rebuild_test.routing.yml | |
@@ -0,0 +1,6 @@ | |
+container_rebuild_test.module_path: | |
+ path: '/container_rebuild_test/{module}/{function}' | |
+ defaults: | |
+ _controller: '\Drupal\container_rebuild_test\TestController::showModuleInfo' | |
+ requirements: | |
+ _access: 'TRUE' | |
diff --git a/core/modules/system/tests/modules/container_rebuild_test/src/ContainerRebuildTestServiceProvider.php b/core/modules/system/tests/modules/container_rebuild_test/src/ContainerRebuildTestServiceProvider.php | |
new file mode 100644 | |
index 0000000000..d5f2bb808c | |
--- /dev/null | |
+++ b/core/modules/system/tests/modules/container_rebuild_test/src/ContainerRebuildTestServiceProvider.php | |
@@ -0,0 +1,18 @@ | |
+<?php | |
+ | |
+namespace Drupal\container_rebuild_test; | |
+ | |
+use Drupal\Core\DependencyInjection\ContainerBuilder; | |
+use Drupal\Core\DependencyInjection\ServiceModifierInterface; | |
+ | |
+class ContainerRebuildTestServiceProvider implements ServiceModifierInterface { | |
+ | |
+ /** | |
+ * {@inheritdoc} | |
+ */ | |
+ public function alter(ContainerBuilder $container) { | |
+ $count = $container->get('state')->get('container_rebuild_test.count', 0); | |
+ $container->get('state')->set('container_rebuild_test.count', ++$count); | |
+ } | |
+ | |
+} | |
diff --git a/core/modules/system/tests/modules/container_rebuild_test/src/TestController.php b/core/modules/system/tests/modules/container_rebuild_test/src/TestController.php | |
new file mode 100644 | |
index 0000000000..7fc722facc | |
--- /dev/null | |
+++ b/core/modules/system/tests/modules/container_rebuild_test/src/TestController.php | |
@@ -0,0 +1,37 @@ | |
+<?php | |
+ | |
+namespace Drupal\container_rebuild_test; | |
+ | |
+use Drupal\Core\Controller\ControllerBase; | |
+ | |
+class TestController extends ControllerBase { | |
+ | |
+ /** | |
+ * Displays the path to a module. | |
+ * | |
+ * @param string $module | |
+ * The module name. | |
+ * @param string $function | |
+ * The function to check if it exists. | |
+ * | |
+ * @return string[] | |
+ * A render array. | |
+ */ | |
+ public function showModuleInfo(string $module, string $function) { | |
+ $module_handler = \Drupal::moduleHandler(); | |
+ $module_message = $module . ': '; | |
+ if ($module_handler->moduleExists($module)) { | |
+ $module_message .= \Drupal::moduleHandler()->getModule($module)->getPath(); | |
+ } | |
+ else { | |
+ $module_message .= 'not installed'; | |
+ } | |
+ $function_message = $function . ': ' . var_export(function_exists($function), TRUE); | |
+ | |
+ return [ | |
+ '#theme' => 'item_list', | |
+ '#items' => [$module_message, $function_message], | |
+ ]; | |
+ } | |
+ | |
+} | |
diff --git a/core/modules/system/tests/src/Functional/UpdateSystem/RebuildScriptTest.php b/core/modules/system/tests/src/Functional/UpdateSystem/RebuildScriptTest.php | |
index 33ca0c197a..442476c1ef 100644 | |
--- a/core/modules/system/tests/src/Functional/UpdateSystem/RebuildScriptTest.php | |
+++ b/core/modules/system/tests/src/Functional/UpdateSystem/RebuildScriptTest.php | |
@@ -4,6 +4,7 @@ | |
use Drupal\Core\Url; | |
use Drupal\Tests\BrowserTestBase; | |
+use Symfony\Component\Filesystem\Filesystem; | |
/** | |
* Tests the rebuild script access and functionality. | |
@@ -12,6 +13,11 @@ | |
*/ | |
class RebuildScriptTest extends BrowserTestBase { | |
+ /** | |
+ * {@inheritdoc} | |
+ */ | |
+ protected static $modules = ['module_test', 'container_rebuild_test']; | |
+ | |
/** | |
* {@inheritdoc} | |
*/ | |
@@ -37,9 +43,60 @@ public function testRebuild() { | |
$this->rebuildAll(); | |
$cache->set('rebuild_test', TRUE); | |
+ \Drupal::state()->set('container_rebuild_test.count', 0); | |
+ $this->drupalGet(Url::fromUri('base:core/rebuild.php')); | |
+ $this->assertSession()->addressEquals(new Url('<front>')); | |
+ $this->assertFalse($cache->get('rebuild_test')); | |
+ $this->refreshVariables(); | |
+ $this->assertSame(1, \Drupal::state()->get('container_rebuild_test.count', 0)); | |
+ $this->drupalGet('/container_rebuild_test/module_test/module_test_system_info_alter'); | |
+ $this->assertSession()->pageTextContains('module_test: core/modules/system/tests/modules/module_test'); | |
+ $this->assertSession()->pageTextContains('module_test_system_info_alter: true'); | |
+ | |
+ // Move a module to ensure it does not break the rebuild. | |
+ $file_system = new Filesystem(); | |
+ $file_system->mirror('core/modules/system/tests/modules/module_test', $this->siteDirectory . '/modules/module_test'); | |
+ \Drupal::state()->set('container_rebuild_test.count', 0); | |
+ $this->drupalGet(Url::fromUri('base:core/rebuild.php')); | |
+ $this->assertSession()->addressEquals(new Url('<front>')); | |
+ $this->refreshVariables(); | |
+ $this->assertSame(1, \Drupal::state()->get('container_rebuild_test.count', 0)); | |
+ $this->drupalGet('/container_rebuild_test/module_test/module_test_system_info_alter'); | |
+ $this->assertSession()->pageTextContains('module_test: ' . $this->siteDirectory . '/modules/module_test'); | |
+ $this->assertSession()->pageTextContains('module_test_system_info_alter: true'); | |
+ | |
+ // Disable a module by writing to the core.extension list. | |
+ $this->config('core.extension')->clear('module.module_test')->save(); | |
+ \Drupal::state()->set('container_rebuild_test.count', 0); | |
+ $this->drupalGet(Url::fromUri('base:core/rebuild.php')); | |
+ $this->assertSession()->addressEquals(new Url('<front>')); | |
+ $this->refreshVariables(); | |
+ $this->assertSame(1, \Drupal::state()->get('container_rebuild_test.count', 0)); | |
+ $this->drupalGet('/container_rebuild_test/module_test/module_test_system_info_alter'); | |
+ $this->assertSession()->pageTextContains('module_test: not installed'); | |
+ $this->assertSession()->pageTextContains('module_test_system_info_alter: false'); | |
+ | |
+ // Enable a module by writing to the core.extension list. | |
+ $modules = $this->config('core.extension')->get('module'); | |
+ $modules['module_test'] = 0; | |
+ $this->config('core.extension')->set('module', module_config_sort($modules))->save(); | |
+ \Drupal::state()->set('container_rebuild_test.count', 0); | |
+ $this->drupalGet(Url::fromUri('base:core/rebuild.php')); | |
+ $this->assertSession()->addressEquals(new Url('<front>')); | |
+ $this->refreshVariables(); | |
+ $this->assertSame(1, \Drupal::state()->get('container_rebuild_test.count', 0)); | |
+ $this->drupalGet('/container_rebuild_test/module_test/module_test_system_info_alter'); | |
+ $this->assertSession()->pageTextContains('module_test: ' . $this->siteDirectory . '/modules/module_test'); | |
+ $this->assertSession()->pageTextContains('module_test_system_info_alter: true'); | |
+ | |
+ // Test how many container rebuild occur when there is no cached container. | |
+ \Drupal::state()->set('container_rebuild_test.count', 0); | |
+ \Drupal::service('kernel')->invalidateContainer(); | |
$this->drupalGet(Url::fromUri('base:core/rebuild.php')); | |
$this->assertSession()->addressEquals(new Url('<front>')); | |
$this->assertFalse($cache->get('rebuild_test')); | |
+ $this->refreshVariables(); | |
+ $this->assertSame(1, \Drupal::state()->get('container_rebuild_test.count', 0)); | |
} | |
} | |
diff --git a/core/tests/Drupal/KernelTests/Core/Common/DrupalFlushAllCachesTest.php b/core/tests/Drupal/KernelTests/Core/Common/DrupalFlushAllCachesTest.php | |
index 0953c05a4c..9cb1dc2def 100644 | |
--- a/core/tests/Drupal/KernelTests/Core/Common/DrupalFlushAllCachesTest.php | |
+++ b/core/tests/Drupal/KernelTests/Core/Common/DrupalFlushAllCachesTest.php | |
@@ -2,6 +2,7 @@ | |
namespace Drupal\KernelTests\Core\Common; | |
+use Drupal\Core\DependencyInjection\ContainerBuilder; | |
use Drupal\KernelTests\KernelTestBase; | |
/** | |
@@ -10,6 +11,13 @@ | |
*/ | |
class DrupalFlushAllCachesTest extends KernelTestBase { | |
+ /** | |
+ * Stores the number of container builds. | |
+ * | |
+ * @var int | |
+ */ | |
+ protected $containerBuilds = 0; | |
+ | |
/** | |
* {@inheritdoc} | |
*/ | |
@@ -19,14 +27,30 @@ class DrupalFlushAllCachesTest extends KernelTestBase { | |
* Tests that drupal_flush_all_caches() uses core.extension properly. | |
*/ | |
public function testDrupalFlushAllCachesModuleList() { | |
+ $this->assertFalse(function_exists('system_test_help')); | |
$core_extension = \Drupal::configFactory()->getEditable('core.extension'); | |
$module = $core_extension->get('module'); | |
$module['system_test'] = -10; | |
$core_extension->set('module', module_config_sort($module))->save(); | |
+ $this->containerBuilds = 0; | |
+ drupal_flush_all_caches(); | |
+ $this->assertSame(['system_test', 'system'], array_keys($this->container->getParameter('container.modules'))); | |
+ $this->assertSame(1, $this->containerBuilds); | |
+ $this->assertTrue(function_exists('system_test_help')); | |
+ $core_extension->clear('module.system_test')->save(); | |
+ $this->containerBuilds = 0; | |
drupal_flush_all_caches(); | |
+ $this->assertSame(['system'], array_keys($this->container->getParameter('container.modules'))); | |
+ $this->assertSame(1, $this->containerBuilds); | |
+ } | |
- $this->assertSame(['system_test', 'system'], array_keys($this->container->getParameter('container.modules'))); | |
+ /** | |
+ * {@inheritdoc} | |
+ */ | |
+ public function register(ContainerBuilder $container) { | |
+ parent::register($container); | |
+ $this->containerBuilds++; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment