Issue #2155635 by Berdir, tim.plunkett, dawehner: Allow plugin managers to opt in to cache clear during module install.

8.0.x
Nathaniel Catchpole 2014-03-17 11:53:05 +00:00
parent a8a8b2cbcc
commit e1533e2a73
9 changed files with 99 additions and 26 deletions

View File

@ -186,6 +186,8 @@ services:
entity.manager:
class: Drupal\Core\Entity\EntityManager
arguments: ['@container.namespaces', '@service_container', '@module_handler', '@cache.cache', '@language_manager', '@string_translation']
tags:
- { name: plugin_manager_cache_clear }
entity.form_builder:
class: Drupal\Core\Entity\EntityFormBuilder
arguments: ['@entity.manager', '@form_builder']
@ -213,6 +215,8 @@ services:
plugin.manager.menu.contextual_link:
class: Drupal\Core\Menu\ContextualLinkManager
arguments: ['@controller_resolver', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user']
plugin.cache_clearer:
class: Drupal\Core\Plugin\CachedDiscoveryClearer
request:
class: Symfony\Component\HttpFoundation\Request
synthetic: true
@ -257,6 +261,8 @@ services:
parent: default_plugin_manager
calls:
- [setValidationConstraintManager, ['@validation.constraint']]
tags:
- { name: plugin_manager_cache_clear }
validation.constraint:
class: Drupal\Core\Validation\ConstraintManager
parent: default_plugin_manager

View File

@ -24,6 +24,7 @@ use Drupal\Core\DependencyInjection\Compiler\RegisterStringTranslatorsPass;
use Drupal\Core\DependencyInjection\Compiler\RegisterBreadcrumbBuilderPass;
use Drupal\Core\DependencyInjection\Compiler\RegisterAuthenticationPass;
use Drupal\Core\DependencyInjection\Compiler\RegisterTwigExtensionsPass;
use Drupal\Core\Plugin\PluginManagerPass;
use Drupal\Core\Theme\ThemeNegotiatorPass;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
@ -86,6 +87,8 @@ class CoreServiceProvider implements ServiceProviderInterface {
$container->addCompilerPass(new RegisterAuthenticationPass());
// Register Twig extensions.
$container->addCompilerPass(new RegisterTwigExtensionsPass());
// Register plugin managers.
$container->addCompilerPass(new PluginManagerPass());
}
/**

View File

@ -622,12 +622,12 @@ class ModuleHandler implements ModuleHandlerInterface {
// Allow modules to react prior to the installation of a module.
$this->invokeAll('module_preinstall', array($module));
// Clear the entity info cache before importing new configuration.
entity_info_cache_clear();
// Now install the module's schema if necessary.
drupal_install_schema($module);
// Clear plugin manager caches.
\Drupal::getContainer()->get('plugin.cache_clearer')->clearCachedDefinitions();
// Set the schema version to the number of the last update provided by
// the module, or the minimum core schema version.
$version = \Drupal::CORE_MINIMUM_SCHEMA_VERSION;
@ -748,8 +748,7 @@ class ModuleHandler implements ModuleHandlerInterface {
// its statically cached list.
drupal_static_reset('system_rebuild_module_data');
// Clear the entity info cache.
entity_info_cache_clear();
\Drupal::getContainer()->get('plugin.cache_clearer')->clearCachedDefinitions();
// Update the kernel to exclude the uninstalled modules.
\Drupal::service('kernel')->updateModules($module_filenames, $module_filenames);

View File

@ -0,0 +1,46 @@
<?php
/**
* @file
* Contains \Drupal\Core\Plugin\CachedDiscoveryClearer.
*/
namespace Drupal\Core\Plugin;
use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Component\Plugin\PluginManagerInterface;
/**
* Defines a class which is capable of clearing the cache on plugin managers.
*/
class CachedDiscoveryClearer {
/**
* The stored discoveries.
*
* @var \Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface[]
*/
protected $cachedDiscoveries;
/**
* Adds a plugin manager to the active list.
*
* @param \Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface $cached_discovery
* An object that implements the cached discovery interface, typically a
* plugin manager.
*/
public function addCachedDiscovery(CachedDiscoveryInterface $cached_discovery) {
$this->cachedDiscoveries[] = $cached_discovery;
}
/**
* Clears the cache on all cached discoveries.
*/
public function clearCachedDefinitions() {
foreach ($this->cachedDiscoveries as $cached_discovery) {
$cached_discovery->clearCachedDefinitions();
}
}
}

View File

@ -0,0 +1,31 @@
<?php
/**
* @file
* Contains \Drupal\Core\Plugin\PluginManagerPass.
*/
namespace Drupal\Core\Plugin;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
/**
* Registers plugin managers to the plugin.cache_clearer service.
*/
class PluginManagerPass implements CompilerPassInterface {
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container) {
$cache_clearer_definition = $container->getDefinition('plugin.cache_clearer');
foreach ($container->getDefinitions() as $service_id => $definition) {
if (strpos($service_id, 'plugin.manager.') === 0 || $definition->hasTag('plugin_manager_cache_clear')) {
$cache_clearer_definition->addMethodCall('addCachedDiscovery', array(new Reference($service_id)));
}
}
}
}

View File

@ -253,7 +253,7 @@ function comment_field_instance_config_update(FieldInstanceConfigInterface $inst
function comment_field_config_delete(FieldConfigInterface $field) {
if ($field->getType() == 'comment') {
// Delete all fields and displays attached to the comment bundle.
entity_invoke_bundle_hook('delete', 'comment', $field->getName());
entity_invoke_bundle_hook('delete', 'comment', $field->entity_type . '__' . $field->getName());
}
}

View File

@ -7,6 +7,7 @@
namespace Drupal\comment\Tests;
use Drupal\field\Field;
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
/**

View File

@ -175,31 +175,30 @@ class FieldInfoTest extends FieldUnitTestBase {
* Test that instances on disabled entity types are filtered out.
*/
function testInstanceDisabledEntityType() {
// Disabling the comment module invokes user_modules_uninstalled() and calls
// Disabling a module invokes user_modules_uninstalled() and calls
// drupal_flush_all_caches(). Install the necessary schema to support this.
$this->installSchema('user', array('users_data'));
$this->installSchema('system', array('router'));
// For this test the field type and the entity type must be exposed by
// different modules.
$this->enableModules(array('node', 'comment'));
$field_definition = array(
'name' => 'field',
'entity_type' => 'comment',
'entity_type' => 'entity_test',
'type' => 'test_field',
);
entity_create('field_config', $field_definition)->save();
$instance_definition = array(
'field_name' => 'field',
'entity_type' => 'comment',
'bundle' => 'comment_node_article',
'entity_type' => 'entity_test',
'bundle' => 'entity_test',
);
entity_create('field_instance_config', $instance_definition)->save();
$this->assertNotNull(field_info_instance('comment', 'field', 'comment_node_article'), 'Instance is returned on enabled entity types.');
$this->assertNotNull(field_info_instance('entity_test', 'field', 'entity_test'), 'Instance is returned on enabled entity types.');
// Disable comment module. This clears field_info cache.
module_uninstall(array('comment'));
$this->assertNull(field_info_instance('comment', 'field', 'comment_node_article'), 'No instances are returned on disabled entity types.');
module_uninstall(array('entity_test'));
$this->assertNull(field_info_instance('entity_test', 'field', 'entity_test'), 'No instances are returned on disabled entity types.');
}
/**

View File

@ -85,18 +85,6 @@ function forum_install() {
}
}
/**
* Implements hook_module_preinstall().
*/
function forum_module_preinstall($module) {
$list_boolean = \Drupal::service('plugin.manager.field.field_type')->getDefinition('list_boolean');
if (empty($list_boolean) && $module == 'forum') {
// Make sure that the list_boolean field type is available before our
// default config is installed.
field_info_cache_clear();
}
}
/**
* Implements hook_uninstall().
*/