diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php index 83cf8bed678f..4d2290c35e0f 100644 --- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php +++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php @@ -523,12 +523,12 @@ class ModuleInstaller implements ModuleInstallerInterface { // into its statically cached list. \Drupal::service('extension.list.module')->reset(); - // Clear plugin manager caches. - \Drupal::getContainer()->get('plugin.cache_clearer')->clearCachedDefinitions(); - // Update the kernel to exclude the uninstalled modules. $this->updateKernel($module_filenames); + // Clear plugin manager caches. + \Drupal::getContainer()->get('plugin.cache_clearer')->clearCachedDefinitions(); + // Update the theme registry to remove the newly uninstalled module. drupal_theme_rebuild(); diff --git a/core/modules/help_topics/tests/src/Functional/HelpTopicSearchTest.php b/core/modules/help_topics/tests/src/Functional/HelpTopicSearchTest.php index dfb747f854d1..84e34b3af4fe 100644 --- a/core/modules/help_topics/tests/src/Functional/HelpTopicSearchTest.php +++ b/core/modules/help_topics/tests/src/Functional/HelpTopicSearchTest.php @@ -263,6 +263,28 @@ class HelpTopicSearchTest extends HelpTopicTranslatedTestBase { $this->assertSession()->statusCodeEquals(200); } + /** + * Tests uninstalling the search module. + */ + public function testUninstallSearch() { + // Ensure we can uninstall search and use the help system without + // breaking. + $this->drupalLogin($this->rootUser); + $edit = []; + $edit['uninstall[search]'] = TRUE; + $this->drupalGet('admin/modules/uninstall'); + $this->submitForm($edit, 'Uninstall'); + $this->submitForm([], 'Uninstall'); + $this->assertSession()->pageTextContains('The selected modules have been uninstalled.'); + $this->drupalGet('admin/help'); + $this->assertSession()->statusCodeEquals(200); + + // Rebuild the container to reflect the latest changes. + $this->rebuildContainer(); + $this->assertTrue(\Drupal::moduleHandler()->moduleExists('help_topics'), 'The help_topics module is still installed.'); + $this->assertFalse(\Drupal::moduleHandler()->moduleExists('search'), 'The search module is uninstalled.'); + } + /** * Asserts that help search returned the expected number of results. * diff --git a/core/modules/system/tests/modules/module_test/module_test.services.yml b/core/modules/system/tests/modules/module_test/module_test.services.yml new file mode 100644 index 000000000000..58fe6bf765c6 --- /dev/null +++ b/core/modules/system/tests/modules/module_test/module_test.services.yml @@ -0,0 +1,7 @@ +services: + # Tests module uninstall + plugin.manager.module_test.cache_clear_test: + class: Drupal\module_test\PluginManagerCacheClearer + arguments: ['@state', '@?logger.dblog'] + tags: + - { name: plugin_manager_cache_clear } diff --git a/core/modules/system/tests/modules/module_test/src/PluginManagerCacheClearer.php b/core/modules/system/tests/modules/module_test/src/PluginManagerCacheClearer.php new file mode 100644 index 000000000000..fbfb4fed8c7a --- /dev/null +++ b/core/modules/system/tests/modules/module_test/src/PluginManagerCacheClearer.php @@ -0,0 +1,47 @@ +state = $state; + $this->optionalService = $optional_service; + } + + /** + * Tests call to CachedDiscoveryInterface::clearCachedDefinitions(). + * + * @see \Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface::clearCachedDefinitions() + */ + public function clearCachedDefinitions() { + $this->state->set(self::class, isset($this->optionalService)); + } + +} diff --git a/core/modules/system/tests/src/Kernel/Installer/UninstallKernelTest.php b/core/modules/system/tests/src/Kernel/Installer/UninstallKernelTest.php index 12f050c8d4ca..81b1556113c5 100644 --- a/core/modules/system/tests/src/Kernel/Installer/UninstallKernelTest.php +++ b/core/modules/system/tests/src/Kernel/Installer/UninstallKernelTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\system\Kernel\Installer; use Drupal\KernelTests\KernelTestBase; +use Drupal\module_test\PluginManagerCacheClearer; /** * Tests the uninstallation of modules. @@ -48,4 +49,24 @@ class UninstallKernelTest extends KernelTestBase { \Drupal::service('module_installer')->uninstall(['file']); } + /** + * Tests uninstalling a module with a plugin cache clearer service. + */ + public function testUninstallPluginCacheClear() { + \Drupal::service('module_installer')->install(['module_test']); + $this->assertFalse($this->container->get('state')->get(PluginManagerCacheClearer::class)); + \Drupal::service('module_installer')->install(['dblog']); + $this->assertTrue($this->container->get('state')->get(PluginManagerCacheClearer::class)); + + // The plugin cache clearer service should be called during dblog uninstall + // without the dependency. + \Drupal::service('module_installer')->uninstall(['dblog']); + $this->assertFalse($this->container->get('state')->get(PluginManagerCacheClearer::class)); + + // The service should not be called during module_test uninstall. + $this->container->get('state')->delete(PluginManagerCacheClearer::class); + \Drupal::service('module_installer')->uninstall(['module_test']); + $this->assertNull($this->container->get('state')->get(PluginManagerCacheClearer::class)); + } + }