Issue #3218660 by alexpott: help_topics module can break during module uninstall

merge-requests/54/head
Lee Rowlands 2021-06-24 14:30:05 +10:00
parent 2c57cbec9a
commit 257efe5439
No known key found for this signature in database
GPG Key ID: 2B829A3DF9204DC4
5 changed files with 100 additions and 3 deletions

View File

@ -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();

View File

@ -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.
*

View File

@ -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 }

View File

@ -0,0 +1,47 @@
<?php
namespace Drupal\module_test;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\Core\State\StateInterface;
/**
* Helps test module uninstall.
*/
class PluginManagerCacheClearer extends DefaultPluginManager {
/**
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* An optional service dependency.
*
* @var object|null
*/
protected $optionalService;
/**
* PluginManagerCacheClearer constructor.
*
* @param \Drupal\Core\State\StateInterface $state
* The state service for recording what happens.
* @param null $optional_service
* An optional service for testing.
*/
public function __construct(StateInterface $state, $optional_service = NULL) {
$this->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));
}
}

View File

@ -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));
}
}