Commit 4862ed79 authored by webchick's avatar webchick
Browse files

Issue #2039435 by Xano, Berdir | akshay.swnt22: Convert EntityManager to...

Issue #2039435 by Xano, Berdir | akshay.swnt22: Convert EntityManager to extend DefaultPluginManager.
parent 6131ff1d
......@@ -37,7 +37,7 @@ public function getDefinitions() {
/**
* Sets a plugin definition.
*/
public function setDefinition($plugin, array $definition) {
public function setDefinition($plugin, $definition) {
$this->definitions[$plugin] = $definition;
}
......
......@@ -9,19 +9,14 @@
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Component\Plugin\PluginManagerBase;
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\String;
use Drupal\Core\Field\FieldDefinition;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageManager;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Language\Language;
use Drupal\Core\Plugin\Discovery\AlterDecorator;
use Drupal\Core\Plugin\Discovery\CacheDecorator;
use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
use Drupal\Core\Plugin\Discovery\InfoHookDecorator;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\TypedData\TranslatableInterface;
......@@ -42,7 +37,7 @@
* @see \Drupal\Core\Entity\EntityTypeInterface
* @see hook_entity_type_alter()
*/
class EntityManager extends PluginManagerBase implements EntityManagerInterface, ContainerAwareInterface {
class EntityManager extends DefaultPluginManager implements EntityManagerInterface, ContainerAwareInterface {
use ContainerAwareTrait;
use StringTranslationTrait;
......@@ -61,27 +56,6 @@ class EntityManager extends PluginManagerBase implements EntityManagerInterface,
*/
protected $controllers = array();
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The cache backend to use.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected $cache;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManager
*/
protected $languageManager;
/**
* Static cache of base field definitions.
*
......@@ -106,15 +80,6 @@ class EntityManager extends PluginManagerBase implements EntityManagerInterface,
*/
protected $fieldStorageDefinitions;
/**
* The root paths.
*
* @see self::__construct().
*
* @var \Traversable
*/
protected $namespaces;
/**
* The string translationManager.
*
......@@ -156,25 +121,18 @@ class EntityManager extends PluginManagerBase implements EntityManagerInterface,
* The module handler.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* The cache backend to use.
* @param \Drupal\Core\Language\LanguageManager $language_manager
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation_manager
* The string translationManager.
*/
public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManager $language_manager, TranslationInterface $translation_manager) {
// Allow the plugin definition to be altered by hook_entity_type_alter().
public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, TranslationInterface $translation_manager) {
parent::__construct('Entity', $namespaces, $module_handler, 'Drupal\Core\Entity\Annotation\EntityType');
$this->moduleHandler = $module_handler;
$this->cache = $cache;
$this->languageManager = $language_manager;
$this->namespaces = $namespaces;
$this->translationManager = $translation_manager;
$this->discovery = new AnnotatedClassDiscovery('Entity', $namespaces, 'Drupal\Core\Entity\Annotation\EntityType');
$this->discovery = new InfoHookDecorator($this->discovery, 'entity_type_build');
$this->discovery = new AlterDecorator($this->discovery, 'entity_type');
$this->discovery = new CacheDecorator($this->discovery, 'entity_type:' . $this->languageManager->getCurrentLanguage()->id, 'discovery', Cache::PERMANENT, array('entity_types' => TRUE));
$this->setCacheBackend($cache, $language_manager, 'entity_type:', array('entity_types' => TRUE));
$this->alterInfo('entity_type');
$this->translationManager = $translation_manager;
}
/**
......@@ -188,6 +146,27 @@ public function clearCachedDefinitions() {
$this->extraFields = array();
}
/**
* {@inheritdoc}
*/
protected function findDefinitions() {
$definitions = $this->discovery->getDefinitions();
// Directly call the hook implementations to pass the definitions to them
// by reference, so new entity types can be added.
foreach ($this->moduleHandler->getImplementations('entity_type_build') as $module) {
$function = $module . '_' . 'entity_type_build';
$function($definitions);
}
foreach ($definitions as $plugin_id => $definition) {
$this->processDefinition($definition, $plugin_id);
}
if ($this->alterHook) {
$this->moduleHandler->alter($this->alterHook, $definitions);
}
return $definitions;
}
/**
* {@inheritdoc}
*/
......@@ -330,13 +309,13 @@ public function getBaseFieldDefinitions($entity_type_id) {
if (!isset($this->baseFieldDefinitions[$entity_type_id])) {
// Not prepared, try to load from cache.
$cid = 'entity_base_field_definitions:' . $entity_type_id . ':' . $this->languageManager->getCurrentLanguage()->id;
if ($cache = $this->cache->get($cid)) {
if ($cache = $this->cacheBackend->get($cid)) {
$this->baseFieldDefinitions[$entity_type_id] = $cache->data;
}
else {
// Rebuild the definitions and put it into the cache.
$this->baseFieldDefinitions[$entity_type_id] = $this->buildBaseFieldDefinitions($entity_type_id);
$this->cache->set($cid, $this->baseFieldDefinitions[$entity_type_id], Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE));
$this->cacheBackend->set($cid, $this->baseFieldDefinitions[$entity_type_id], Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE));
}
}
return $this->baseFieldDefinitions[$entity_type_id];
......@@ -426,13 +405,13 @@ public function getFieldDefinitions($entity_type_id, $bundle) {
$base_field_definitions = $this->getBaseFieldDefinitions($entity_type_id);
// Not prepared, try to load from cache.
$cid = 'entity_bundle_field_definitions:' . $entity_type_id . ':' . $bundle . ':' . $this->languageManager->getCurrentLanguage()->id;
if ($cache = $this->cache->get($cid)) {
if ($cache = $this->cacheBackend->get($cid)) {
$bundle_field_definitions = $cache->data;
}
else {
// Rebuild the definitions and put it into the cache.
$bundle_field_definitions = $this->buildBundleFieldDefinitions($entity_type_id, $bundle, $base_field_definitions);
$this->cache->set($cid, $bundle_field_definitions, Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE));
$this->cacheBackend->set($cid, $bundle_field_definitions, Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE));
}
// Field definitions consist of the bundle specific overrides and the
// base fields, merge them together. Use array_replace() to replace base
......@@ -518,13 +497,13 @@ public function getFieldStorageDefinitions($entity_type_id) {
}
// Not prepared, try to load from cache.
$cid = 'entity_field_storage_definitions:' . $entity_type_id . ':' . $this->languageManager->getCurrentLanguage()->id;
if ($cache = $this->cache->get($cid)) {
if ($cache = $this->cacheBackend->get($cid)) {
$field_storage_definitions = $cache->data;
}
else {
// Rebuild the definitions and put it into the cache.
$field_storage_definitions = $this->buildFieldStorageDefinitions($entity_type_id);
$this->cache->set($cid, $field_storage_definitions, Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE));
$this->cacheBackend->set($cid, $field_storage_definitions, Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE));
}
$this->fieldStorageDefinitions[$entity_type_id] += $field_storage_definitions;
}
......@@ -538,7 +517,7 @@ public function getFieldMap() {
if (!$this->fieldMap) {
// Not prepared, try to load from cache.
$cid = 'entity_field_map';
if ($cache = $this->cache->get($cid)) {
if ($cache = $this->cacheBackend->get($cid)) {
$this->fieldMap = $cache->data;
}
else {
......@@ -554,7 +533,7 @@ public function getFieldMap() {
}
}
$this->cache->set($cid, $this->fieldMap, Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE));
$this->cacheBackend->set($cid, $this->fieldMap, Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE));
}
}
return $this->fieldMap;
......@@ -622,7 +601,7 @@ public function getBundleInfo($entity_type) {
public function getAllBundleInfo() {
if (!isset($this->bundleInfo)) {
$langcode = $this->languageManager->getCurrentLanguage()->id;
if ($cache = $this->cache->get("entity_bundle_info:$langcode")) {
if ($cache = $this->cacheBackend->get("entity_bundle_info:$langcode")) {
$this->bundleInfo = $cache->data;
}
else {
......@@ -643,7 +622,7 @@ public function getAllBundleInfo() {
}
}
$this->moduleHandler->alter('entity_bundle_info', $this->bundleInfo);
$this->cache->set("entity_bundle_info:$langcode", $this->bundleInfo, Cache::PERMANENT, array('entity_types' => TRUE));
$this->cacheBackend->set("entity_bundle_info:$langcode", $this->bundleInfo, Cache::PERMANENT, array('entity_types' => TRUE));
}
}
......@@ -663,7 +642,7 @@ public function getExtraFields($entity_type_id, $bundle) {
// hook_entity_extra_field_info_alter() might contain t() calls, we cache
// per language.
$cache_id = 'entity_bundle_extra_fields:' . $entity_type_id . ':' . $bundle . ':' . $this->languageManager->getCurrentLanguage()->id;
$cached = $this->cache->get($cache_id);
$cached = $this->cacheBackend->get($cache_id);
if ($cached) {
$this->extraFields[$entity_type_id][$bundle] = $cached->data;
return $this->extraFields[$entity_type_id][$bundle];
......@@ -679,7 +658,7 @@ public function getExtraFields($entity_type_id, $bundle) {
// Store in the 'static' and persistent caches.
$this->extraFields[$entity_type_id][$bundle] = $info;
$this->cache->set($cache_id, $info, Cache::PERMANENT, array(
$this->cacheBackend->set($cache_id, $info, Cache::PERMANENT, array(
'entity_field_info' => TRUE,
));
......@@ -790,7 +769,7 @@ protected function getAllDisplayModesByEntityType($display_type) {
if (!isset($this->displayModeInfo[$display_type])) {
$key = 'entity_' . $display_type . '_info';
$langcode = $this->languageManager->getCurrentLanguage(Language::TYPE_INTERFACE)->id;
if ($cache = $this->cache->get("$key:$langcode")) {
if ($cache = $this->cacheBackend->get("$key:$langcode")) {
$this->displayModeInfo[$display_type] = $cache->data;
}
else {
......@@ -800,7 +779,7 @@ protected function getAllDisplayModesByEntityType($display_type) {
$this->displayModeInfo[$display_type][$display_mode_entity_type][$display_mode_name] = (array) $display_mode;
}
$this->moduleHandler->alter($key, $this->displayModeInfo[$display_type]);
$this->cache->set("$key:$langcode", $this->displayModeInfo[$display_type], CacheBackendInterface::CACHE_PERMANENT, array('entity_types' => TRUE));
$this->cacheBackend->set("$key:$langcode", $this->displayModeInfo[$display_type], CacheBackendInterface::CACHE_PERMANENT, array('entity_types' => TRUE));
}
}
......
......@@ -270,6 +270,11 @@ protected function findDefinitions() {
// If this plugin was provided by a module that does not exist, remove the
// plugin definition.
foreach ($definitions as $plugin_id => $plugin_definition) {
// If the plugin definition is an object, attempt to convert it to an
// array, if that is not possible, skip further processing.
if (is_object($plugin_definition) && !($plugin_definition = (array) $plugin_definition)) {
continue;
}
if (isset($plugin_definition['provider']) && !in_array($plugin_definition['provider'], array('Core', 'Component')) && !$this->moduleHandler->moduleExists($plugin_definition['provider'])) {
unset($definitions[$plugin_id]);
}
......
......@@ -5,7 +5,7 @@
* Contains \Drupal\Tests\Core\Entity\EntityManagerTest.
*/
namespace Drupal\Tests\Core\Entity;
namespace Drupal\Tests\Core\Entity {
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Core\DependencyInjection\ContainerBuilder;
......@@ -79,13 +79,6 @@ class EntityManagerTest extends UnitTestCase {
*/
protected $translationManager;
/**
* The form builder.
*
* @var \Drupal\Core\Form\FormBuilderInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $formBuilder;
/**
* {@inheritdoc}
*/
......@@ -111,20 +104,19 @@ protected function setUp() {
$this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
$this->languageManager = $this->getMockBuilder('Drupal\Core\Language\LanguageManager')
->disableOriginalConstructor()
->getMock();
$this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
$this->languageManager->expects($this->any())
->method('getCurrentLanguage')
->will($this->returnValue((object) array('id' => 'en')));
$this->languageManager->expects($this->any())
->method('getLanguages')
->will($this->returnValue(array('en' => (object) array('id' => 'en'))));
$this->translationManager = $this->getStringTranslationStub();
$this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface');
$this->container = $this->getContainerWithCacheBins($this->cache);
$this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface');
$this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
}
/**
......@@ -149,7 +141,7 @@ protected function setUpEntityManager($definitions = array()) {
->method('getDefinitions')
->will($this->returnValue($definitions));
$this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cache, $this->languageManager, $this->translationManager, $this->formBuilder);
$this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cache, $this->languageManager, $this->translationManager);
$this->entityManager->setContainer($this->container);
$this->entityManager->setDiscovery($this->discovery);
}
......@@ -162,8 +154,9 @@ protected function setUpEntityManager($definitions = array()) {
*/
public function testClearCachedDefinitions() {
$this->setUpEntityManager();
$this->discovery->expects($this->once())
->method('clearCachedDefinitions');
$this->cache->expects($this->once())
->method('deleteTags')
->with(array('entity_types' => TRUE));
$this->entityManager->clearCachedDefinitions();
}
......@@ -491,15 +484,13 @@ public function testGetFieldStorageDefinitions() {
->method('getName')
->will($this->returnValue('field_storage'));
$this->moduleHandler->expects($this->at(0))
->method('getImplementations')
->with('entity_base_field_info')
->will($this->returnValue(array()));
$this->moduleHandler->expects($this->at(2))
$this->moduleHandler->expects($this->any())
->method('getImplementations')
->with('entity_field_storage_info')
->will($this->returnValue(array('example_module')));
->will($this->returnValueMap(array(
array('entity_type_build', array()),
array('entity_base_field_info', array()),
array('entity_field_storage_info', array('example_module')),
)));
$this->moduleHandler->expects($this->any())
->method('invoke')
......@@ -527,9 +518,17 @@ public function testGetBaseFieldDefinitionsWithCaching() {
->method('get')
->with('entity_base_field_definitions:test_entity_type:en', FALSE)
->will($this->returnValue(FALSE));
$this->cache->expects($this->once())
->method('set');
$this->cache->expects($this->at(1))
->method('get')
->with('entity_type::en', FALSE)
->will($this->returnValue(FALSE));
$this->cache->expects($this->at(2))
->method('set')
->with('entity_type::en');
$this->cache->expects($this->at(3))
->method('set')
->with('entity_base_field_definitions:test_entity_type:en');
$this->cache->expects($this->at(4))
->method('get')
->with('entity_base_field_definitions:test_entity_type:en', FALSE)
->will($this->returnValue((object) array('data' => $expected)));
......@@ -558,12 +557,18 @@ public function testGetFieldDefinitionsWithCaching() {
->with('entity_bundle_field_definitions:test_entity_type:test_bundle:en', FALSE)
->will($this->returnValue(FALSE));
$this->cache->expects($this->at(2))
->method('set');
->method('get')
->with('entity_type::en', FALSE)
->will($this->returnValue(FALSE));
$this->cache->expects($this->at(3))
->method('set');
$this->cache->expects($this->at(4))
->method('set');
$this->cache->expects($this->at(5))
->method('get')
->with('entity_base_field_definitions:test_entity_type:en', FALSE)
->will($this->returnValue((object) array('data' => $expected)));
$this->cache->expects($this->at(4))
$this->cache->expects($this->at(6))
->method('get')
->with('entity_bundle_field_definitions:test_entity_type:test_bundle:en', FALSE)
->will($this->returnValue((object) array('data' => $expected)));
......@@ -587,8 +592,10 @@ public function testGetFieldStorageDefinitionsWithCaching() {
$this->moduleHandler->expects($this->any())
->method('getImplementations')
->with('entity_field_storage_info')
->will($this->returnValue(array('example_module')));
->will($this->returnValueMap(array(
array('entity_field_storage_info', array('example_module')),
array('entity_type_build', array())
)));
$this->moduleHandler->expects($this->once())
->method('invoke')
......@@ -609,12 +616,20 @@ public function testGetFieldStorageDefinitionsWithCaching() {
->with('entity_field_storage_definitions:test_entity_type:en', FALSE)
->will($this->returnValue(FALSE));
$this->cache->expects($this->at(2))
->method('set');
->method('get')
->with('entity_type::en', FALSE)
->will($this->returnValue(FALSE));
$this->cache->expects($this->at(3))
->method('set')
->with('entity_type::en');
$this->cache->expects($this->at(4))
->method('set')
->with('entity_field_storage_definitions:test_entity_type:en');
$this->cache->expects($this->at(5))
->method('get')
->with('entity_base_field_definitions:test_entity_type:en', FALSE)
->will($this->returnValue((object) array('data' => array('id' => $expected['id']))));
$this->cache->expects($this->at(4))
$this->cache->expects($this->at(6))
->method('get')
->with('entity_field_storage_definitions:test_entity_type:en', FALSE)
->will($this->returnValue((object) array('data' => $expected)));
......@@ -809,14 +824,27 @@ public function testGetAllBundleInfo() {
'apple' => $apple,
'banana' => $banana,
));
$this->cache->expects($this->at(0))
->method('get')
->with("entity_bundle_info:en", FALSE)
->will($this->returnValue(FALSE));
$this->cache->expects($this->at(1))
->method('get')
->with("entity_type::en", FALSE)
->will($this->returnValue(FALSE));
$this->cache->expects($this->at(2))
->method('set')
->with("entity_type::en");
$this->cache->expects($this->at(3))
->method('set')
->with("entity_bundle_info:en");
$this->cache->expects($this->at(4))
->method('deleteTags')
->with(array('entity_types' => TRUE));
$this->cache->expects($this->at(5))
->method('get')
->with("entity_bundle_info:en", FALSE)
->will($this->returnValue((object) array('data' => 'cached data')));
$this->cache->expects($this->once())
->method('set');
$expected = array(
'apple' => array(
......@@ -1245,3 +1273,13 @@ public static function create(ContainerInterface $container) {
if (!defined('DRUPAL_ROOT')) {
define('DRUPAL_ROOT', dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__)))));
}
}
namespace {
/**
* Implements hook_entity_type_build().
*/
function entity_manager_test_module_entity_type_build() {
}
}
......@@ -92,6 +92,31 @@ public function testDefaultPluginManagerWithDisabledModule() {
$this->assertEmpty($plugin_manager->getDefinition('cherry'), 'Plugin information of a disabled module is not available');
}
/**
* Tests the plugin manager and object plugin definitions.
*/
public function testDefaultPluginManagerWithObjects() {
$definitions = $this->expectedDefinitions;
$definitions['cherry'] = (object) array(
'id' => 'cherry',
'label' => 'Cherry',
'color' => 'red',
'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Cherry',
'provider' => 'disabled_module',
);
$module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$module_handler->expects($this->once())
->method('moduleExists')
->with('disabled_module')
->will($this->returnValue(FALSE));
$plugin_manager = new TestPluginManager($this->namespaces, $definitions, $module_handler, 'test_alter_hook');
$this->assertEmpty($plugin_manager->getDefinition('cherry'), 'Plugin information is available');
}
/**
* Tests the plugin manager with no cache and altering.
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment