diff --git a/core/lib/Drupal/Component/Plugin/PluginManagerCachedBase.php b/core/lib/Drupal/Component/Plugin/PluginManagerCachedBase.php new file mode 100644 index 0000000..3285d8f --- /dev/null +++ b/core/lib/Drupal/Component/Plugin/PluginManagerCachedBase.php @@ -0,0 +1,22 @@ +discovery->clearCachedDefinitions(); + } + +} diff --git a/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php b/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php index 7a57395..059cd21 100644 --- a/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php +++ b/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php @@ -110,6 +110,16 @@ protected function setCachedDefinitions($definitions) { } /** + * Clears the cached plugin definitions. + */ + public function clearCachedDefinitions() { + if (isset($this->cacheKey)) { + cache($this->cacheBin)->flush(); + } + $this->definitions = NULL; + } + + /** * Passes through all unknown calls onto the decorated object. */ public function __call($method, $args) { diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index a1522d8..0953ddf 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -7,14 +7,14 @@ namespace Drupal\Core\TypedData; -use Drupal\Component\Plugin\PluginManagerBase; +use Drupal\Component\Plugin\PluginManagerCachedBase; use Drupal\Core\Plugin\Discovery\CacheDecorator; use Drupal\Core\Plugin\Discovery\HookDiscovery; /** * Manages data type plugins. */ -class TypedDataManager extends PluginManagerBase { +class TypedDataManager extends PluginManagerCachedBase { public function __construct() { $this->discovery = new CacheDecorator(new HookDiscovery('data_type_info'), 'typed_data:types'); diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php index 6dc4163..7180a08 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php @@ -7,7 +7,7 @@ namespace Drupal\field\Plugin\Type\Formatter; -use Drupal\Component\Plugin\PluginManagerBase; +use Drupal\Component\Plugin\PluginManagerCachedBase; use Drupal\Core\Plugin\Discovery\CacheDecorator; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; use Drupal\field\Plugin\Type\Formatter\FormatterLegacyDiscoveryDecorator; @@ -16,7 +16,7 @@ /** * Plugin type manager for field formatters. */ -class FormatterPluginManager extends PluginManagerBase { +class FormatterPluginManager extends PluginManagerCachedBase { /** * Overrides Drupal\Component\Plugin\PluginManagerBase:$defaults. @@ -27,41 +27,16 @@ class FormatterPluginManager extends PluginManagerBase { ); /** - * The cache bin used for plugin definitions. - * - * @var string - */ - protected $cache_bin = 'field'; - - /** - * The cache id used for plugin definitions. - * - * @var string - */ - protected $cache_id = 'field_formatter_types'; - - /** * Constructs a FormatterPluginManager object. */ public function __construct() { - $this->baseDiscovery = new AlterDecorator(new FormatterLegacyDiscoveryDecorator(new AnnotatedClassDiscovery('field', 'formatter')), 'field_formatter_info'); - $this->discovery = new CacheDecorator($this->baseDiscovery, $this->cache_id, $this->cache_bin); + $this->discovery = new AlterDecorator(new FormatterLegacyDiscoveryDecorator(new AnnotatedClassDiscovery('field', 'formatter')), 'field_formatter_info'); + $this->discovery = new CacheDecorator($this->discovery, 'field_formatter_types', 'field'); $this->factory = new FormatterFactory($this); } /** - * Clears cached definitions. - * - * @todo Remove when http://drupal.org/node/1764232 is fixed. - */ - public function clearDefinitions() { - // Clear 'static' data by creating a new object. - $this->discovery = new CacheDecorator($this->baseDiscovery, $this->cache_id, $this->cache_bin); - cache($this->cache_bin)->delete($this->cache_id); - } - - /** * Overrides PluginManagerBase::getInstance(). */ public function getInstance(array $options) { diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php index a605129..1c00a47 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php @@ -7,7 +7,7 @@ namespace Drupal\field\Plugin\Type\Widget; -use Drupal\Component\Plugin\PluginManagerBase; +use Drupal\Component\Plugin\PluginManagerCachedBase; use Drupal\Core\Plugin\Discovery\CacheDecorator; use Drupal\Core\Plugin\Discovery\AlterDecorator; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; @@ -16,7 +16,7 @@ /** * Plugin type manager for field widgets. */ -class WidgetPluginManager extends PluginManagerBase { +class WidgetPluginManager extends PluginManagerCachedBase { /** * Overrides Drupal\Component\Plugin\PluginManagerBase:$defaults. @@ -28,41 +28,16 @@ class WidgetPluginManager extends PluginManagerBase { ); /** - * The cache bin used for plugin definitions. - * - * @var string - */ - protected $cache_bin = 'field'; - - /** - * The cache id used for plugin definitions. - * - * @var string - */ - protected $cache_id = 'field_widget_types'; - - /** * Constructs a WidgetPluginManager object. */ public function __construct() { - $this->baseDiscovery = new AlterDecorator(new WidgetLegacyDiscoveryDecorator(new AnnotatedClassDiscovery('field', 'widget')), 'field_widget_info'); - $this->discovery = new CacheDecorator($this->baseDiscovery, $this->cache_id, $this->cache_bin); + $this->discovery = new AlterDecorator(new WidgetLegacyDiscoveryDecorator(new AnnotatedClassDiscovery('field', 'widget')), 'field_widget_info'); + $this->discovery = new CacheDecorator($this->discovery, 'field_widget_types', 'field'); $this->factory = new WidgetFactory($this); } /** - * Clears cached definitions. - * - * @todo Remove when http://drupal.org/node/1764232 is fixed. - */ - public function clearDefinitions() { - // Clear 'static' data by creating a new object. - $this->discovery = new CacheDecorator($this->baseDiscovery, $this->cache_id, $this->cache_bin); - cache($this->cache_bin)->delete($this->cache_id); - } - - /** * Overrides Drupal\Component\Plugin\PluginManagerBase::getInstance(). */ public function getInstance(array $options) { diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php new file mode 100644 index 0000000..89a90a3 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php @@ -0,0 +1,136 @@ + 'CacheDecorator', + 'description' => 'Tests the CacheDecorator.', + 'group' => 'Plugin API', + ); + } + + public function setUp() { + global $conf; + + parent::setUp(); + + // Use a non-db cache backend, so that we can use DiscoveryTestBase (which + // extends UnitTestBase). + $conf['cache_classes'][$this->cacheBin] = 'Drupal\Core\Cache\MemoryBackend'; + + // Create discovery objects to test. + $this->emptyDiscovery = new StaticDiscovery(); + $this->emptyDiscovery = new CacheDecorator($this->emptyDiscovery, $this->cacheKey . '_empty', $this->cacheBin); + + $this->discovery = new StaticDiscovery(); + $this->discovery = new CacheDecorator($this->discovery, $this->cacheKey, $this->cacheBin); + + // Poluplate sample definitions. + $this->expectedDefinitions = array( + 'apple' => array( + 'label' => 'Apple', + 'color' => 'green', + ), + 'cherry' => array( + 'label' => 'Cherry', + 'color' => 'red', + ), + 'orange' => array( + 'label' => 'Orange', + 'color' => 'orange', + ), + ); + foreach ($this->expectedDefinitions as $plugin_id => $definition) { + $this->discovery->setDefinition($plugin_id, $definition); + } + } + + /** + * Tests that discovered definitions are properly cached. + * + * This comes in addition to DiscoveryTestBase::testDiscoveryInterface(), + * that test the basic discovery behavior. + */ + public function testCachedDefinitions() { + $cache = cache($this->cacheBin); + + // Check that nothing is cached initially. + $cached = $cache->get($this->cacheKey); + $this->assertIdentical($cached, FALSE, 'Cache is empty.'); + + // Get the definitions once, and check that they are present in the cache. + $definitions = $this->discovery->getDefinitions(); + $this->assertIdentical($definitions, $this->expectedDefinitions, 'Definitions are correctly retrieved.'); + $cached = $cache->get($this->cacheKey); + $this->assertIdentical($cached->data, $this->expectedDefinitions, 'Definitions are cached.'); + + // Check that the definitions are also cached in memory. Since the + // CacheDecorator::definitions property is protected, this is tested "from + // the outside" by wiping the cache entry, getting the definitions, and + // checking that the cache entry was not regenerated (thus showing that + // defintions were not fetched from the decorated discovery). + $cache->delete($this->cacheKey); + $definitions = $this->discovery->getDefinitions(); + $cached = $cache->get($this->cacheKey); + $this->assertIdentical($cached, FALSE, 'Cache is empty.'); + $this->assertIdentical($definitions, $this->expectedDefinitions, 'Definitions are cached in memory.'); + } + + /** + * Tests CacheDecorator::clearCachedDefinitions(). + */ + public function testClearCachedDefinitions() { + $cache = cache($this->cacheBin); + + // Populate the caches by collecting definitions once. + $this->discovery->getDefinitions(); + + // Add a new definition. + $this->expectedDefinitions['banana'] = array( + 'label' => 'Banana', + 'color' => 'yellow', + ); + $this->discovery->setDefinition('banana', $this->expectedDefinitions['banana']); + + // Check that the new definition is not found. + $definition = $this->discovery->getDefinition('banana'); + $this->assertNull($definition, 'Newly added definition is not found.'); + + // Clear cached definitions, and check that the new definition is found. + $this->discovery->clearCachedDefinitions(); + $cached = $cache->get($this->cacheKey); + $this->assertIdentical($cached, FALSE, 'Cache is empty.'); + $definitions = $this->discovery->getDefinitions(); + $this->assertIdentical($definitions, $this->expectedDefinitions, 'Newly added definition is found.'); + } + +} diff --git a/core/modules/views/lib/Drupal/views/Plugin/Type/JoinManager.php b/core/modules/views/lib/Drupal/views/Plugin/Type/JoinManager.php index eac395b..f39c674 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Type/JoinManager.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Type/JoinManager.php @@ -7,13 +7,13 @@ namespace Drupal\views\Plugin\Type; -use Drupal\Component\Plugin\PluginManagerBase; +use Drupal\Component\Plugin\PluginManagerCachedBase; use Drupal\Component\Plugin\Factory\DefaultFactory; use Drupal\Core\Plugin\Discovery\AlterDecorator; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; use Drupal\Core\Plugin\Discovery\CacheDecorator; -class JoinManager extends PluginManagerBase { +class JoinManager extends PluginManagerCachedBase { /** * Constructs a JoinManager object. diff --git a/core/modules/views/lib/Drupal/views/Plugin/Type/PluginManager.php b/core/modules/views/lib/Drupal/views/Plugin/Type/PluginManager.php index f5f6f6e..0af8469 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Type/PluginManager.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Type/PluginManager.php @@ -7,13 +7,13 @@ namespace Drupal\views\Plugin\Type; -use Drupal\Component\Plugin\PluginManagerBase; +use Drupal\Component\Plugin\PluginManagerCachedBase; use Drupal\Component\Plugin\Factory\DefaultFactory; use Drupal\Core\Plugin\Discovery\AlterDecorator; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; use Drupal\Core\Plugin\Discovery\CacheDecorator; -class PluginManager extends PluginManagerBase { +class PluginManager extends PluginManagerCachedBase { /** * Constructs a PluginManager object. diff --git a/core/modules/views/lib/Drupal/views/Plugin/Type/WizardManager.php b/core/modules/views/lib/Drupal/views/Plugin/Type/WizardManager.php index 96b544f..fdcf867 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Type/WizardManager.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Type/WizardManager.php @@ -7,13 +7,13 @@ namespace Drupal\views\Plugin\Type; -use Drupal\Component\Plugin\PluginManagerBase; +use Drupal\Component\Plugin\PluginManagerCachedBase; use Drupal\Component\Plugin\Factory\DefaultFactory; use Drupal\Core\Plugin\Discovery\AlterDecorator; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; use Drupal\Core\Plugin\Discovery\CacheDecorator; -class WizardManager extends PluginManagerBase { +class WizardManager extends PluginManagerCachedBase { /** * Constructs a WizardManager object.