summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2017-11-06 12:22:32 +0000
committerNathaniel Catchpole2017-11-06 12:22:32 +0000
commit2c2e85c348cc1d71cb82b37d35ae977705fac52c (patch)
tree153d6d95352e6015de90786fa88146bdefb56d05
parent113c6dc25827ec24dcaa5171d47c1c3929d5dff6 (diff)
Issue #2695109 by dpi, willzyx, Sam152, dawehner: Cache bins are not deleted when the module that declares them is uninstalled
-rw-r--r--core/lib/Drupal/Core/Extension/ModuleInstaller.php46
-rw-r--r--core/modules/system/tests/modules/module_cachebin/module_cachebin.info.yml7
-rw-r--r--core/modules/system/tests/modules/module_cachebin/module_cachebin.services.yml7
-rw-r--r--core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php25
4 files changed, 60 insertions, 25 deletions
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index 0f5eded..8792498 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -505,34 +505,30 @@ class ModuleInstaller implements ModuleInstallerInterface {
* The name of the module for which to remove all registered cache bins.
*/
protected function removeCacheBins($module) {
- // Remove any cache bins defined by a module.
$service_yaml_file = drupal_get_path('module', $module) . "/$module.services.yml";
- if (file_exists($service_yaml_file)) {
- $definitions = Yaml::decode(file_get_contents($service_yaml_file));
- if (isset($definitions['services'])) {
- foreach ($definitions['services'] as $id => $definition) {
- if (isset($definition['tags'])) {
- foreach ($definition['tags'] as $tag) {
- // This works for the default cache registration and even in some
- // cases when a non-default "super" factory is used. That should
- // be extremely rare.
- if ($tag['name'] == 'cache.bin' && isset($definition['factory_service']) && isset($definition['factory_method']) && !empty($definition['arguments'])) {
- try {
- $factory = \Drupal::service($definition['factory_service']);
- if (method_exists($factory, $definition['factory_method'])) {
- $backend = call_user_func_array([$factory, $definition['factory_method']], $definition['arguments']);
- if ($backend instanceof CacheBackendInterface) {
- $backend->removeBin();
- }
- }
- }
- catch (\Exception $e) {
- watchdog_exception('system', $e, 'Failed to remove cache bin defined by the service %id.', ['%id' => $id]);
- }
- }
- }
+ if (!file_exists($service_yaml_file)) {
+ return;
+ }
+
+ $definitions = Yaml::decode(file_get_contents($service_yaml_file));
+
+ $cache_bin_services = array_filter(
+ isset($definitions['services']) ? $definitions['services'] : [],
+ function ($definition) {
+ $tags = isset($definition['tags']) ? $definition['tags'] : [];
+ foreach ($tags as $tag) {
+ if (isset($tag['name']) && ($tag['name'] == 'cache.bin')) {
+ return TRUE;
}
}
+ return FALSE;
+ }
+ );
+
+ foreach (array_keys($cache_bin_services) as $service_id) {
+ $backend = $this->kernel->getContainer()->get($service_id);
+ if ($backend instanceof CacheBackendInterface) {
+ $backend->removeBin();
}
}
}
diff --git a/core/modules/system/tests/modules/module_cachebin/module_cachebin.info.yml b/core/modules/system/tests/modules/module_cachebin/module_cachebin.info.yml
new file mode 100644
index 0000000..d255795
--- /dev/null
+++ b/core/modules/system/tests/modules/module_cachebin/module_cachebin.info.yml
@@ -0,0 +1,7 @@
+name: module cache bin tests
+type: module
+description: Test cache bins defined by modules.
+package: Testing
+version: VERSION
+core: 8.x
+hidden: true
diff --git a/core/modules/system/tests/modules/module_cachebin/module_cachebin.services.yml b/core/modules/system/tests/modules/module_cachebin/module_cachebin.services.yml
new file mode 100644
index 0000000..8e14274
--- /dev/null
+++ b/core/modules/system/tests/modules/module_cachebin/module_cachebin.services.yml
@@ -0,0 +1,7 @@
+services:
+ module_cachebin.cache_bin:
+ class: Drupal\Core\Cache\CacheBackendInterface
+ tags:
+ - { name: cache.bin }
+ factory: cache.backend.database:get
+ arguments: [module_cachebin]
diff --git a/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php b/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php
index fa5a9a1..ff183c6 100644
--- a/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php
@@ -60,4 +60,29 @@ class ModuleInstallerTest extends KernelTestBase {
$this->assertEquals(1, $modules['module_handler_test_multiple_child'], 'Weight of module_handler_test_multiple_child is set.');
}
+ /**
+ * Tests cache bins defined by modules are removed when uninstalled.
+ *
+ * @covers ::removeCacheBins
+ */
+ public function testCacheBinCleanup() {
+ $schema = $this->container->get('database')->schema();
+ $table = 'cache_module_cachebin';
+
+ $module_installer = $this->container->get('module_installer');
+ $module_installer->install(['module_cachebin']);
+
+ // Prime the bin.
+ /** @var \Drupal\Core\Cache\CacheBackendInterface $cache_bin */
+ $cache_bin = $this->container->get('module_cachebin.cache_bin');
+ $cache_bin->set('foo', 'bar');
+
+ // A database backend is used so there is a convenient way check whether the
+ // backend is uninstalled.
+ $this->assertTrue($schema->tableExists($table));
+
+ $module_installer->uninstall(['module_cachebin']);
+ $this->assertFalse($schema->tableExists($table));
+ }
+
}