diff --git a/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php b/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php index 337e503..2315a7f 100644 --- a/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php +++ b/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php @@ -8,7 +8,6 @@ use Drupal\Component\Plugin\Discovery\DiscoveryInterface; use Drupal\Component\Plugin\Exception\PluginException; -use Drupal\Component\Plugin\Derivative\DeriverInterface; /** * Default plugin factory. @@ -31,10 +30,23 @@ class DefaultFactory implements FactoryInterface { protected $discovery; /** + * Defines an interface each plugin should implement. + * + * @var string|null + */ + protected $interface; + + /** * Constructs a Drupal\Component\Plugin\Factory\DefaultFactory object. + * + * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $discovery + * The plugin discovery. + * @param string|null $plugin_interface + * (optional) The interface each plugin should implement. */ - public function __construct(DiscoveryInterface $discovery) { + public function __construct(DiscoveryInterface $discovery, $plugin_interface = NULL) { $this->discovery = $discovery; + $this->interface = $plugin_interface; } /** @@ -42,7 +54,7 @@ public function __construct(DiscoveryInterface $discovery) { */ public function createInstance($plugin_id, array $configuration = array()) { $plugin_definition = $this->discovery->getDefinition($plugin_id); - $plugin_class = static::getPluginClass($plugin_id, $plugin_definition); + $plugin_class = static::getPluginClass($plugin_id, $plugin_definition, $this->interface); return new $plugin_class($configuration, $plugin_id, $plugin_definition); } @@ -53,13 +65,18 @@ public function createInstance($plugin_id, array $configuration = array()) { * The id of a plugin. * @param mixed $plugin_definition * The plugin definition associated with the plugin ID. + * @param string $required_interface + * (optional) THe required plugin interface. * * @return string * The appropriate class name. * * @throws \Drupal\Component\Plugin\Exception\PluginException + * Thrown when there is no class specified, the class doesn't exist, or + * the class does not implement the specified required interface. + * */ - public static function getPluginClass($plugin_id, $plugin_definition = NULL) { + public static function getPluginClass($plugin_id, $plugin_definition = NULL, $required_interface = NULL) { if (empty($plugin_definition['class'])) { throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $plugin_id)); } @@ -70,6 +87,10 @@ public static function getPluginClass($plugin_id, $plugin_definition = NULL) { throw new PluginException(sprintf('Plugin (%s) instance class "%s" does not exist.', $plugin_id, $class)); } + if ($required_interface && !is_subclass_of($plugin_definition['class'], $required_interface)) { + throw new PluginException(sprintf('Plugin "%s" (%s) in %s should implement interface %s.', $plugin_id, $plugin_definition['class'], $plugin_definition['provider'], $required_interface)); + } + return $class; } } diff --git a/core/lib/Drupal/Component/Plugin/Factory/ReflectionFactory.php b/core/lib/Drupal/Component/Plugin/Factory/ReflectionFactory.php index 3fce8be..ae9dfe1 100644 --- a/core/lib/Drupal/Component/Plugin/Factory/ReflectionFactory.php +++ b/core/lib/Drupal/Component/Plugin/Factory/ReflectionFactory.php @@ -19,7 +19,7 @@ class ReflectionFactory extends DefaultFactory { */ public function createInstance($plugin_id, array $configuration = array()) { $plugin_definition = $this->discovery->getDefinition($plugin_id); - $plugin_class = static::getPluginClass($plugin_id, $plugin_definition); + $plugin_class = static::getPluginClass($plugin_id, $plugin_definition, $this->interface); // Lets figure out of there's a constructor for this class and pull // arguments from the $options array if so to populate it. diff --git a/core/lib/Drupal/Core/Action/ActionManager.php b/core/lib/Drupal/Core/Action/ActionManager.php index d3a4c0a..1baf427 100644 --- a/core/lib/Drupal/Core/Action/ActionManager.php +++ b/core/lib/Drupal/Core/Action/ActionManager.php @@ -33,7 +33,7 @@ class ActionManager extends DefaultPluginManager { * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/Action', $namespaces, $module_handler, 'Drupal\Core\Annotation\Action'); + parent::__construct('Plugin/Action', $namespaces, $module_handler, 'Drupal\Core\Action\ActionInterface', 'Drupal\Core\Annotation\Action'); $this->alterInfo('action_info'); $this->setCacheBackend($cache_backend, 'action_info'); } diff --git a/core/lib/Drupal/Core/Archiver/ArchiverManager.php b/core/lib/Drupal/Core/Archiver/ArchiverManager.php index b161bd9..b8ac88c 100644 --- a/core/lib/Drupal/Core/Archiver/ArchiverManager.php +++ b/core/lib/Drupal/Core/Archiver/ArchiverManager.php @@ -1,6 +1,7 @@ alterInfo('archiver_info'); $this->setCacheBackend($cache_backend, 'archiver_info_plugins'); } @@ -42,7 +43,7 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac */ public function createInstance($plugin_id, array $configuration = array()) { $plugin_definition = $this->getDefinition($plugin_id); - $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition); + $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition, 'Drupal\Core\Archiver\ArchiverInterface'); return new $plugin_class($configuration['filepath']); } diff --git a/core/lib/Drupal/Core/Block/BlockManager.php b/core/lib/Drupal/Core/Block/BlockManager.php index e65d2f6..8cde728 100644 --- a/core/lib/Drupal/Core/Block/BlockManager.php +++ b/core/lib/Drupal/Core/Block/BlockManager.php @@ -44,7 +44,7 @@ class BlockManager extends DefaultPluginManager implements BlockManagerInterface * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/Block', $namespaces, $module_handler, 'Drupal\Core\Block\Annotation\Block'); + parent::__construct('Plugin/Block', $namespaces, $module_handler, 'Drupal\Core\Block\BlockPluginInterface', 'Drupal\Core\Block\Annotation\Block'); $this->alterInfo('block'); $this->setCacheBackend($cache_backend, 'block_plugins'); diff --git a/core/lib/Drupal/Core/Condition/ConditionManager.php b/core/lib/Drupal/Core/Condition/ConditionManager.php index db0fa43..c1e309a 100644 --- a/core/lib/Drupal/Core/Condition/ConditionManager.php +++ b/core/lib/Drupal/Core/Condition/ConditionManager.php @@ -42,7 +42,7 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac $this->alterInfo('condition_info'); $this->setCacheBackend($cache_backend, 'condition_plugins'); - parent::__construct('Plugin/Condition', $namespaces, $module_handler, 'Drupal\Core\Condition\Annotation\Condition'); + parent::__construct('Plugin/Condition', $namespaces, $module_handler, 'Drupal\Core\Condition\ConditionInterface', 'Drupal\Core\Condition\Annotation\Condition'); } /** diff --git a/core/lib/Drupal/Core/Display/VariantManager.php b/core/lib/Drupal/Core/Display/VariantManager.php old mode 100755 new mode 100644 index 7f18a29..b591508 --- a/core/lib/Drupal/Core/Display/VariantManager.php +++ b/core/lib/Drupal/Core/Display/VariantManager.php @@ -31,7 +31,7 @@ class VariantManager extends DefaultPluginManager { * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/DisplayVariant', $namespaces, $module_handler, 'Drupal\Core\Display\Annotation\DisplayVariant'); + parent::__construct('Plugin/DisplayVariant', $namespaces, $module_handler, 'Drupal\Core\Display\VariantInterface', 'Drupal\Core\Display\Annotation\DisplayVariant'); $this->setCacheBackend($cache_backend, 'variant_plugins'); $this->alterInfo('display_variant_plugin'); diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index e3acce9..2d3fa7a 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -171,7 +171,7 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa * The class resolver. */ public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, TranslationInterface $translation_manager, ClassResolverInterface $class_resolver, TypedDataManager $typed_data_manager) { - parent::__construct('Entity', $namespaces, $module_handler, 'Drupal\Core\Entity\Annotation\EntityType'); + parent::__construct('Entity', $namespaces, $module_handler, 'Drupal\Core\Entity\EntityInterface', 'Drupal\Core\Entity\Annotation\EntityType'); $this->setCacheBackend($cache, 'entity_type', array('entity_types' => TRUE)); $this->alterInfo('entity_type'); diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php index 1595012..9917fd1 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php @@ -23,6 +23,7 @@ use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\Language\LanguageManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -121,6 +122,13 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt protected $cacheBackend; /** + * The language manager. + * + * @var \Drupal\Core\Language\LanguageManagerInterface + */ + protected $languageManager; + + /** * {@inheritdoc} */ public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { @@ -128,7 +136,8 @@ public static function createInstance(ContainerInterface $container, EntityTypeI $entity_type, $container->get('database'), $container->get('entity.manager'), - $container->get('cache.entity') + $container->get('cache.entity'), + $container->get('language_manager') ); } @@ -154,13 +163,16 @@ public function getFieldStorageDefinitions() { * The entity manager. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * The cache backend to be used. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * The language manager. */ - public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache) { + public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache, LanguageManagerInterface $language_manager) { parent::__construct($entity_type); $this->database = $database; $this->entityManager = $entity_manager; $this->cacheBackend = $cache; + $this->languageManager = $language_manager; // @todo Remove table names from the entity type definition in // https://drupal.org/node/2232465 @@ -253,8 +265,8 @@ public function getTableMapping() { $key_fields = array_values(array_filter(array($this->idKey, $this->revisionKey, $this->bundleKey, $this->uuidKey, $this->langcodeKey))); $all_fields = array_keys($definitions); $revisionable_fields = array_keys(array_filter($definitions, function (FieldStorageDefinitionInterface $definition) { - return $definition->isRevisionable(); - })); + return $definition->isRevisionable(); + })); // Make sure the key fields come first in the list of fields. $all_fields = array_merge($key_fields, array_diff($all_fields, $key_fields)); @@ -266,7 +278,7 @@ public function getTableMapping() { 'revision_timestamp', 'revision_uid', 'revision_log', - ), $all_fields); + ), $all_fields); $revisionable = $this->entityType->isRevisionable(); // @todo Remove the data table check once all entity types are using @@ -295,12 +307,12 @@ public function getTableMapping() { // performant queries. This means that only the UUID is not stored on // the data table. $this->tableMapping - ->setFieldNames($this->baseTable, $key_fields) - ->setFieldNames($this->dataTable, array_values(array_diff($all_fields, array($this->uuidKey)))) - // Add the denormalized 'default_langcode' field to the mapping. Its - // value is identical to the query expression - // "base_table.langcode = data_table.langcode" - ->setExtraColumns($this->dataTable, array('default_langcode')); + ->setFieldNames($this->baseTable, $key_fields) + ->setFieldNames($this->dataTable, array_values(array_diff($all_fields, array($this->uuidKey)))) + // Add the denormalized 'default_langcode' field to the mapping. Its + // value is identical to the query expression + // "base_table.langcode = data_table.langcode" + ->setExtraColumns($this->dataTable, array('default_langcode')); } elseif ($revisionable && $translatable) { // The revisionable multilingual layout stores key field values in the @@ -317,12 +329,12 @@ public function getTableMapping() { // fields in the data table. $data_fields = array_values(array_diff($all_fields, array($this->uuidKey), $revision_metadata_fields)); $this->tableMapping - ->setFieldNames($this->dataTable, $data_fields) - // Add the denormalized 'default_langcode' field to the mapping. Its - // value is identical to the query expression - // "base_langcode = data_table.langcode" where "base_langcode" is - // the language code of the default revision. - ->setExtraColumns($this->dataTable, array('default_langcode')); + ->setFieldNames($this->dataTable, $data_fields) + // Add the denormalized 'default_langcode' field to the mapping. Its + // value is identical to the query expression + // "base_langcode = data_table.langcode" where "base_langcode" is + // the language code of the default revision. + ->setExtraColumns($this->dataTable, array('default_langcode')); $revision_base_fields = array_merge(array($this->idKey, $this->revisionKey, $this->langcodeKey), $revision_metadata_fields); $this->tableMapping->setFieldNames($this->revisionTable, $revision_base_fields); @@ -330,11 +342,11 @@ public function getTableMapping() { $revision_data_key_fields = array($this->idKey, $this->revisionKey, $this->langcodeKey); $revision_data_fields = array_diff($revisionable_fields, $revision_metadata_fields); $this->tableMapping - ->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields)) - // Add the denormalized 'default_langcode' field to the mapping. Its - // value is identical to the query expression - // "revision_table.langcode = data_table.langcode". - ->setExtraColumns($this->revisionDataTable, array('default_langcode')); + ->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields)) + // Add the denormalized 'default_langcode' field to the mapping. Its + // value is identical to the query expression + // "revision_table.langcode = data_table.langcode". + ->setExtraColumns($this->revisionDataTable, array('default_langcode')); } } @@ -565,11 +577,11 @@ protected function attachPropertyData(array &$entities) { if ($this->dataTable) { // If a revision table is available, we need all the properties of the // latest revision. Otherwise we fall back to the data table. - $table = $this->revisionDataTable ?: $this->dataTable; + $table = $this->revisionDataTable ? : $this->dataTable; $query = $this->database->select($table, 'data', array('fetch' => \PDO::FETCH_ASSOC)) - ->fields('data') - ->condition($this->idKey, array_keys($entities)) - ->orderBy('data.' . $this->idKey); + ->fields('data') + ->condition($this->idKey, array_keys($entities)) + ->orderBy('data.' . $this->idKey); if ($this->revisionDataTable) { // Get the revision IDs. @@ -649,8 +661,8 @@ public function deleteRevision($revision_id) { } $this->database->delete($this->revisionTable) - ->condition($this->revisionKey, $revision->getRevisionId()) - ->execute(); + ->condition($this->revisionKey, $revision->getRevisionId()) + ->execute(); $this->invokeFieldMethod('deleteRevision', $revision); $this->deleteFieldItemsRevision($revision); $this->invokeHook('revision_delete', $revision); @@ -776,25 +788,25 @@ protected function doDelete($entities) { $ids = array_keys($entities); $this->database->delete($this->entityType->getBaseTable()) - ->condition($this->idKey, $ids) - ->execute(); + ->condition($this->idKey, $ids) + ->execute(); if ($this->revisionTable) { $this->database->delete($this->revisionTable) - ->condition($this->idKey, $ids) - ->execute(); + ->condition($this->idKey, $ids) + ->execute(); } if ($this->dataTable) { $this->database->delete($this->dataTable) - ->condition($this->idKey, $ids) - ->execute(); + ->condition($this->idKey, $ids) + ->execute(); } if ($this->revisionDataTable) { $this->database->delete($this->revisionDataTable) - ->condition($this->idKey, $ids) - ->execute(); + ->condition($this->idKey, $ids) + ->execute(); } foreach ($entities as $entity) { @@ -836,10 +848,10 @@ protected function doSave($id, EntityInterface $entity) { if (!$is_new) { if ($entity->isDefaultRevision()) { $this->database - ->update($this->baseTable) - ->fields((array) $record) - ->condition($this->idKey, $record->{$this->idKey}) - ->execute(); + ->update($this->baseTable) + ->fields((array) $record) + ->condition($this->idKey, $record->{$this->idKey}) + ->execute(); $return = SAVED_UPDATED; } else { @@ -865,9 +877,9 @@ protected function doSave($id, EntityInterface $entity) { // while storing its data. $entity->enforceIsNew(); $insert_id = $this->database - ->insert($this->baseTable, array('return' => Database::RETURN_INSERT_ID)) - ->fields((array) $record) - ->execute(); + ->insert($this->baseTable, array('return' => Database::RETURN_INSERT_ID)) + ->fields((array) $record) + ->execute(); // Even if this is a new entity the ID key might have been set, in which // case we should not override the provided ID. An ID key that is not set // to any value is interpreted as NULL (or DEFAULT) and thus overridden. @@ -927,8 +939,8 @@ protected function savePropertyData(EntityInterface $entity, $table_name = NULL) $value = $revision ? $entity->getRevisionId() : $entity->id(); // Delete and insert to handle removed values. $this->database->delete($table_name) - ->condition($key, $value) - ->execute(); + ->condition($key, $value) + ->execute(); } $query = $this->database->insert($table_name); @@ -938,8 +950,8 @@ protected function savePropertyData(EntityInterface $entity, $table_name = NULL) $record = $this->mapToDataStorageRecord($translation, $table_name); $values = (array) $record; $query - ->fields(array_keys($values)) - ->values($values); + ->fields(array_keys($values)) + ->values($values); } $query->execute(); @@ -1077,9 +1089,9 @@ protected function saveRevision(EntityInterface $entity) { if ($entity->isNewRevision()) { $insert_id = $this->database - ->insert($this->revisionTable, array('return' => Database::RETURN_INSERT_ID)) - ->fields((array) $record) - ->execute(); + ->insert($this->revisionTable, array('return' => Database::RETURN_INSERT_ID)) + ->fields((array) $record) + ->execute(); // Even if this is a new revsision, the revision ID key might have been // set in which case we should not override the provided revision ID. if (!isset($record->{$this->revisionKey})) { @@ -1087,17 +1099,17 @@ protected function saveRevision(EntityInterface $entity) { } if ($entity->isDefaultRevision()) { $this->database->update($this->entityType->getBaseTable()) - ->fields(array($this->revisionKey => $record->{$this->revisionKey})) - ->condition($this->idKey, $record->{$this->idKey}) - ->execute(); + ->fields(array($this->revisionKey => $record->{$this->revisionKey})) + ->condition($this->idKey, $record->{$this->idKey}) + ->execute(); } } else { $this->database - ->update($this->revisionTable) - ->fields((array) $record) - ->condition($this->revisionKey, $record->{$this->revisionKey}) - ->execute(); + ->update($this->revisionTable) + ->fields((array) $record) + ->condition($this->revisionKey, $record->{$this->revisionKey}) + ->execute(); } // Make sure to update the new revision key for the entity. @@ -1161,7 +1173,7 @@ protected function loadFieldItems(array $entities) { } // Load field data. - $langcodes = array_keys(\Drupal::languageManager()->getLanguages(LanguageInterface::STATE_ALL)); + $langcodes = array_keys($this->languageManager->getLanguages(LanguageInterface::STATE_ALL)); foreach ($storage_definitions as $field_name => $storage_definition) { $table = $load_current ? $table_mapping->getDedicatedDataTableName($storage_definition) : $table_mapping->getDedicatedRevisionTableName($storage_definition); @@ -1169,12 +1181,12 @@ protected function loadFieldItems(array $entities) { // are loading values for multiple entities, we cannot limit the query to // the available translations. $results = $this->database->select($table, 't') - ->fields('t') - ->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN') - ->condition('deleted', 0) - ->condition('langcode', $langcodes, 'IN') - ->orderBy('delta') - ->execute(); + ->fields('t') + ->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN') + ->condition('deleted', 0) + ->condition('langcode', $langcodes, 'IN') + ->orderBy('delta') + ->execute(); $delta_count = array(); foreach ($results as $row) { @@ -1241,13 +1253,13 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) { // of an entity. if ($entity->isDefaultRevision()) { $this->database->delete($table_name) - ->condition('entity_id', $id) - ->execute(); + ->condition('entity_id', $id) + ->execute(); } $this->database->delete($revision_name) - ->condition('entity_id', $id) - ->condition('revision_id', $vid) - ->execute(); + ->condition('entity_id', $id) + ->condition('revision_id', $vid) + ->execute(); } // Prepare the multi-insert query. @@ -1316,11 +1328,11 @@ protected function deleteFieldItems(EntityInterface $entity) { $table_name = $table_mapping->getDedicatedDataTableName($storage_definition); $revision_name = $table_mapping->getDedicatedRevisionTableName($storage_definition); $this->database->delete($table_name) - ->condition('entity_id', $entity->id()) - ->execute(); + ->condition('entity_id', $entity->id()) + ->execute(); $this->database->delete($revision_name) - ->condition('entity_id', $entity->id()) - ->execute(); + ->condition('entity_id', $entity->id()) + ->execute(); } } @@ -1341,9 +1353,9 @@ protected function deleteFieldItemsRevision(EntityInterface $entity) { } $revision_name = $table_mapping->getDedicatedRevisionTableName($storage_definition); $this->database->delete($revision_name) - ->condition('entity_id', $entity->id()) - ->condition('revision_id', $vid) - ->execute(); + ->condition('entity_id', $entity->id()) + ->condition('revision_id', $vid) + ->execute(); } } } @@ -1490,8 +1502,8 @@ public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $ $table = $table_mapping->getDedicatedDataTableName($storage_definition); $revision_table = $table_mapping->getDedicatedRevisionTableName($storage_definition); $this->database->update($table) - ->fields(array('deleted' => 1)) - ->execute(); + ->fields(array('deleted' => 1)) + ->execute(); // Move the table to a unique name while the table contents are being // deleted. @@ -1511,13 +1523,13 @@ public function onFieldDefinitionDelete(FieldDefinitionInterface $field_definiti $table_name = $table_mapping->getDedicatedDataTableName($storage_definition); $revision_name = $table_mapping->getDedicatedRevisionTableName($storage_definition); $this->database->update($table_name) - ->fields(array('deleted' => 1)) - ->condition('bundle', $field_definition->getBundle()) - ->execute(); + ->fields(array('deleted' => 1)) + ->condition('bundle', $field_definition->getBundle()) + ->execute(); $this->database->update($revision_name) - ->fields(array('deleted' => 1)) - ->condition('bundle', $field_definition->getBundle()) - ->execute(); + ->fields(array('deleted' => 1)) + ->condition('bundle', $field_definition->getBundle()) + ->execute(); } /** @@ -1541,13 +1553,13 @@ public function onBundleRename($bundle, $bundle_new) { $table_name = $table_mapping->getDedicatedDataTableName($storage_definition, $is_deleted); $revision_name = $table_mapping->getDedicatedRevisionTableName($storage_definition, $is_deleted); $this->database->update($table_name) - ->fields(array('bundle' => $bundle_new)) - ->condition('bundle', $bundle) - ->execute(); + ->fields(array('bundle' => $bundle_new)) + ->condition('bundle', $bundle) + ->execute(); $this->database->update($revision_name) - ->fields(array('bundle' => $bundle_new)) - ->condition('bundle', $bundle) - ->execute(); + ->fields(array('bundle' => $bundle_new)) + ->condition('bundle', $bundle) + ->execute(); } } } @@ -1570,10 +1582,10 @@ protected function readFieldItemsToPurge(FieldDefinitionInterface $field_definit $or->isNotNull($table_mapping->getFieldColumnName($storage_definition, $column_name)); } $entity_query - ->distinct(TRUE) - ->fields('t', array('entity_id')) - ->condition('bundle', $field_definition->getBundle()) - ->range(0, $batch_size); + ->distinct(TRUE) + ->fields('t', array('entity_id')) + ->condition('bundle', $field_definition->getBundle()) + ->range(0, $batch_size); // Create a map of field data table column names to field column names. $column_map = array(); @@ -1585,9 +1597,9 @@ protected function readFieldItemsToPurge(FieldDefinitionInterface $field_definit $items_by_entity = array(); foreach ($entity_query->execute() as $row) { $item_query = $this->database->select($table_name, 't', array('fetch' => \PDO::FETCH_ASSOC)) - ->fields('t') - ->condition('entity_id', $row['entity_id']) - ->orderBy('delta'); + ->fields('t') + ->condition('entity_id', $row['entity_id']) + ->orderBy('delta'); foreach ($item_query->execute() as $item_row) { if (!isset($entities[$item_row['revision_id']])) { @@ -1623,11 +1635,11 @@ protected function purgeFieldItems(ContentEntityInterface $entity, FieldDefiniti $revision_name = $table_mapping->getDedicatedRevisionTableName($storage_definition, $is_deleted); $revision_id = $this->entityType->isRevisionable() ? $entity->getRevisionId() : $entity->id(); $this->database->delete($table_name) - ->condition('revision_id', $revision_id) - ->execute(); + ->condition('revision_id', $revision_id) + ->execute(); $this->database->delete($revision_name) - ->condition('revision_id', $revision_id) - ->execute(); + ->condition('revision_id', $revision_id) + ->execute(); } /** @@ -1655,9 +1667,9 @@ public function countFieldData($storage_definition, $as_bool = FALSE) { $or->isNotNull($table_mapping->getFieldColumnName($storage_definition, $column_name)); } $query - ->condition($or) - ->fields('t', array('entity_id')) - ->distinct(TRUE); + ->condition($or) + ->fields('t', array('entity_id')) + ->distinct(TRUE); // If we are performing the query just to check if the field has data // limit the number of rows. if ($as_bool) { diff --git a/core/lib/Drupal/Core/Field/FieldTypePluginManager.php b/core/lib/Drupal/Core/Field/FieldTypePluginManager.php index 6a5f39a..f3fb059 100644 --- a/core/lib/Drupal/Core/Field/FieldTypePluginManager.php +++ b/core/lib/Drupal/Core/Field/FieldTypePluginManager.php @@ -31,7 +31,7 @@ class FieldTypePluginManager extends DefaultPluginManager implements FieldTypePl * The module handler. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/Field/FieldType', $namespaces, $module_handler, 'Drupal\Core\Field\Annotation\FieldType'); + parent::__construct('Plugin/Field/FieldType', $namespaces, $module_handler, 'Drupal\Core\Field\FieldItemInterface', 'Drupal\Core\Field\Annotation\FieldType'); $this->alterInfo('field_info'); $this->setCacheBackend($cache_backend, 'field_types_plugins'); } diff --git a/core/lib/Drupal/Core/Field/FormatterPluginManager.php b/core/lib/Drupal/Core/Field/FormatterPluginManager.php index 5d5cea2..b7b297b 100644 --- a/core/lib/Drupal/Core/Field/FormatterPluginManager.php +++ b/core/lib/Drupal/Core/Field/FormatterPluginManager.php @@ -47,8 +47,7 @@ class FormatterPluginManager extends DefaultPluginManager { * The 'field type' plugin manager. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, FieldTypePluginManagerInterface $field_type_manager) { - - parent::__construct('Plugin/Field/FieldFormatter', $namespaces, $module_handler, 'Drupal\Core\Field\Annotation\FieldFormatter'); + parent::__construct('Plugin/Field/FieldFormatter', $namespaces, $module_handler, 'Drupal\Core\Field\FormatterInterface', 'Drupal\Core\Field\Annotation\FieldFormatter'); $this->setCacheBackend($cache_backend, 'field_formatter_types_plugins'); $this->alterInfo('field_formatter_info'); diff --git a/core/lib/Drupal/Core/Field/WidgetFactory.php b/core/lib/Drupal/Core/Field/WidgetFactory.php index 9e9408f..db8c291 100644 --- a/core/lib/Drupal/Core/Field/WidgetFactory.php +++ b/core/lib/Drupal/Core/Field/WidgetFactory.php @@ -19,7 +19,7 @@ class WidgetFactory extends DefaultFactory { */ public function createInstance($plugin_id, array $configuration = array()) { $plugin_definition = $this->discovery->getDefinition($plugin_id); - $plugin_class = static::getPluginClass($plugin_id, $plugin_definition); + $plugin_class = static::getPluginClass($plugin_id, $plugin_definition, $this->interface); return new $plugin_class($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings']); } } diff --git a/core/lib/Drupal/Core/Field/WidgetPluginManager.php b/core/lib/Drupal/Core/Field/WidgetPluginManager.php index 207b5e3..8aa4434 100644 --- a/core/lib/Drupal/Core/Field/WidgetPluginManager.php +++ b/core/lib/Drupal/Core/Field/WidgetPluginManager.php @@ -47,7 +47,7 @@ class WidgetPluginManager extends DefaultPluginManager { * The 'field type' plugin manager. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, FieldTypePluginManagerInterface $field_type_manager) { - parent::__construct('Plugin/Field/FieldWidget', $namespaces, $module_handler, 'Drupal\Core\Field\Annotation\FieldWidget'); + parent::__construct('Plugin/Field/FieldWidget', $namespaces, $module_handler, 'Drupal\Core\Field\WidgetInterface', 'Drupal\Core\Field\Annotation\FieldWidget'); $this->setCacheBackend($cache_backend, 'field_widget_types_plugins'); $this->alterInfo('field_widget_info'); diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitManager.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitManager.php index 27eaa14..2857bbd 100644 --- a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitManager.php +++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitManager.php @@ -43,7 +43,7 @@ class ImageToolkitManager extends DefaultPluginManager { * The config factory. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory) { - parent::__construct('Plugin/ImageToolkit', $namespaces, $module_handler, 'Drupal\Core\ImageToolkit\Annotation\ImageToolkit'); + parent::__construct('Plugin/ImageToolkit', $namespaces, $module_handler, 'Drupal\Core\ImageToolkit\ImageToolkitInterface', 'Drupal\Core\ImageToolkit\Annotation\ImageToolkit'); $this->setCacheBackend($cache_backend, 'image_toolkit_plugins'); $this->configFactory = $config_factory; diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php index ae7d0dd..dc4abaa 100644 --- a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php +++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php @@ -46,7 +46,7 @@ class ImageToolkitOperationManager extends DefaultPluginManager implements Image * A logger instance. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, LoggerInterface $logger) { - parent::__construct('Plugin/ImageToolkit/Operation', $namespaces, $module_handler, 'Drupal\Core\ImageToolkit\Annotation\ImageToolkitOperation'); + parent::__construct('Plugin/ImageToolkit/Operation', $namespaces, $module_handler, 'Drupal\Core\ImageToolkit\ImageToolkitOperationInterface', 'Drupal\Core\ImageToolkit\Annotation\ImageToolkitOperation'); $this->alterInfo('image_toolkit_operation'); $this->setCacheBackend($cache_backend, 'image_toolkit_operation_plugins'); diff --git a/core/lib/Drupal/Core/Mail/MailManager.php b/core/lib/Drupal/Core/Mail/MailManager.php index 48e53cf..decbeed 100644 --- a/core/lib/Drupal/Core/Mail/MailManager.php +++ b/core/lib/Drupal/Core/Mail/MailManager.php @@ -12,8 +12,6 @@ use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Component\Utility\String; -use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; @@ -67,7 +65,7 @@ class MailManager extends DefaultPluginManager implements MailManagerInterface { * The string translation service. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory, LoggerChannelFactoryInterface $logger_factory, TranslationInterface $string_translation) { - parent::__construct('Plugin/Mail', $namespaces, $module_handler, 'Drupal\Core\Annotation\Mail'); + parent::__construct('Plugin/Mail', $namespaces, $module_handler, 'Drupal\Core\Mail\MailInterface', 'Drupal\Core\Annotation\Mail'); $this->alterInfo('mail_backend_info'); $this->setCacheBackend($cache_backend, 'mail_backend_plugins'); $this->configFactory = $config_factory; @@ -149,16 +147,7 @@ public function getInstance(array $options) { } if (empty($this->instances[$plugin_id])) { - $plugin = $this->createInstance($plugin_id); - if (is_subclass_of($plugin, '\Drupal\Core\Mail\MailInterface')) { - $this->instances[$plugin_id] = $plugin; - } - else { - throw new InvalidPluginDefinitionException($plugin_id, String::format('Class %class does not implement interface %interface', array( - '%class' => get_class($plugin), - '%interface' => 'Drupal\Core\Mail\MailInterface', - ))); - } + $this->instances[$plugin_id] = $this->createInstance($plugin_id); } return $this->instances[$plugin_id]; } diff --git a/core/lib/Drupal/Core/Menu/ContextualLinkManager.php b/core/lib/Drupal/Core/Menu/ContextualLinkManager.php index 8c33949..b99c11f 100644 --- a/core/lib/Drupal/Core/Menu/ContextualLinkManager.php +++ b/core/lib/Drupal/Core/Menu/ContextualLinkManager.php @@ -105,7 +105,7 @@ class ContextualLinkManager extends DefaultPluginManager implements ContextualLi public function __construct(ControllerResolverInterface $controller_resolver, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account, RequestStack $request_stack) { $this->discovery = new YamlDiscovery('links.contextual', $module_handler->getModuleDirectories()); $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery); - $this->factory = new ContainerFactory($this); + $this->factory = new ContainerFactory($this, '\Drupal\Core\Menu\ContextualLinkInterface'); $this->controllerResolver = $controller_resolver; $this->accessManager = $access_manager; diff --git a/core/lib/Drupal/Core/Menu/LocalActionManager.php b/core/lib/Drupal/Core/Menu/LocalActionManager.php index 43f0e19..1033d79 100644 --- a/core/lib/Drupal/Core/Menu/LocalActionManager.php +++ b/core/lib/Drupal/Core/Menu/LocalActionManager.php @@ -116,7 +116,7 @@ public function __construct(ControllerResolverInterface $controller_resolver, Re // discovery. $this->discovery = new YamlDiscovery('links.action', $module_handler->getModuleDirectories()); $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery); - $this->factory = new ContainerFactory($this); + $this->factory = new ContainerFactory($this, 'Drupal\Core\Menu\LocalActionInterface'); $this->controllerResolver = $controller_resolver; $this->requestStack = $request_stack; $this->routeProvider = $route_provider; diff --git a/core/lib/Drupal/Core/Menu/LocalTaskManager.php b/core/lib/Drupal/Core/Menu/LocalTaskManager.php index a6bc10e..862050c 100644 --- a/core/lib/Drupal/Core/Menu/LocalTaskManager.php +++ b/core/lib/Drupal/Core/Menu/LocalTaskManager.php @@ -126,7 +126,7 @@ class LocalTaskManager extends DefaultPluginManager implements LocalTaskManagerI public function __construct(ControllerResolverInterface $controller_resolver, RequestStack $request_stack, RouteProviderInterface $route_provider, RouteBuilderInterface $route_builder, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account) { $this->discovery = new YamlDiscovery('links.task', $module_handler->getModuleDirectories()); $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery); - $this->factory = new ContainerFactory($this); + $this->factory = new ContainerFactory($this, '\Drupal\Core\Menu\LocalTaskInterface'); $this->controllerResolver = $controller_resolver; $this->requestStack = $request_stack; $this->routeProvider = $route_provider; diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php index e1d0731..a2d4cf2 100644 --- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php +++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php @@ -9,7 +9,6 @@ use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface; use Drupal\Component\Plugin\Discovery\DiscoveryCachedTrait; -use Drupal\Component\Plugin\Exception\PluginNotFoundException; use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator; use Drupal\Component\Plugin\PluginManagerBase; use Drupal\Component\Plugin\PluginManagerInterface; @@ -17,7 +16,6 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; use Drupal\Core\Plugin\Factory\ContainerFactory; @@ -92,15 +90,17 @@ class DefaultPluginManager extends PluginManagerBase implements PluginManagerInt * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. + * @param string|null $plugin_interface + * (optional) The interface each plugin should implement. * @param string $plugin_definition_annotation_name * (optional) The name of the annotation that contains the plugin definition. * Defaults to 'Drupal\Component\Annotation\Plugin'. */ - public function __construct($subdir, \Traversable $namespaces, ModuleHandlerInterface $module_handler, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') { + public function __construct($subdir, \Traversable $namespaces, ModuleHandlerInterface $module_handler, $plugin_interface = NULL, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') { $this->subdir = $subdir; $this->discovery = new AnnotatedClassDiscovery($subdir, $namespaces, $plugin_definition_annotation_name); $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery); - $this->factory = new ContainerFactory($this); + $this->factory = new ContainerFactory($this, $plugin_interface); $this->moduleHandler = $module_handler; } diff --git a/core/lib/Drupal/Core/Plugin/Factory/ContainerFactory.php b/core/lib/Drupal/Core/Plugin/Factory/ContainerFactory.php index 702e640..16191f8 100644 --- a/core/lib/Drupal/Core/Plugin/Factory/ContainerFactory.php +++ b/core/lib/Drupal/Core/Plugin/Factory/ContainerFactory.php @@ -18,7 +18,7 @@ class ContainerFactory extends DefaultFactory { */ public function createInstance($plugin_id, array $configuration = array()) { $plugin_definition = $this->discovery->getDefinition($plugin_id); - $plugin_class = static::getPluginClass($plugin_id, $plugin_definition); + $plugin_class = static::getPluginClass($plugin_id, $plugin_definition, $this->interface); // If the plugin provides a factory method, pass the container to it. if (is_subclass_of($plugin_class, 'Drupal\Core\Plugin\ContainerFactoryPluginInterface')) { diff --git a/core/lib/Drupal/Core/Render/Element/Page.php b/core/lib/Drupal/Core/Render/Element/Page.php index 4156ab4..f12c8f3 100644 --- a/core/lib/Drupal/Core/Render/Element/Page.php +++ b/core/lib/Drupal/Core/Render/Element/Page.php @@ -12,7 +12,7 @@ * * @RenderElement("page") */ -class Page { +class Page extends RenderElement { /** * {@inheritdoc} diff --git a/core/lib/Drupal/Core/Render/ElementInfoManager.php b/core/lib/Drupal/Core/Render/ElementInfoManager.php index b9f78fc..784fdef 100644 --- a/core/lib/Drupal/Core/Render/ElementInfoManager.php +++ b/core/lib/Drupal/Core/Render/ElementInfoManager.php @@ -46,7 +46,7 @@ class ElementInfoManager extends DefaultPluginManager implements ElementInfoMana public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { $this->setCacheBackend($cache_backend, 'element_info'); - parent::__construct('Element', $namespaces, $module_handler, 'Drupal\Core\Render\Annotation\RenderElement'); + parent::__construct('Element', $namespaces, $module_handler, 'Drupal\Core\Render\Element\ElementInterface', 'Drupal\Core\Render\Annotation\RenderElement'); } /** diff --git a/core/lib/Drupal/Core/Session/UserSession.php b/core/lib/Drupal/Core/Session/UserSession.php index a40cfd1..1ce8e20 100644 --- a/core/lib/Drupal/Core/Session/UserSession.php +++ b/core/lib/Drupal/Core/Session/UserSession.php @@ -7,6 +7,8 @@ namespace Drupal\Core\Session; +use Drupal\Core\Language\LanguageManagerInterface; + /** * An implementation of the user account interface for the global user. * @@ -101,12 +103,22 @@ class UserSession implements AccountInterface { protected $hostname = ''; /** + * The language manager. + * + * @var \Drupal\Core\Language\LanguageManagerInterface + */ + protected $languageManager; + + /** * Constructs a new user session. * * @param array $values * Array of initial values for the user session. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * The language manager. */ - public function __construct(array $values = array()) { + public function __construct(array $values = array(), LanguageManagerInterface $language_manager) { + $this->languageManager = $language_manager; foreach ($values as $key => $value) { $this->$key = $value; } @@ -183,7 +195,7 @@ public function isAnonymous() { * {@inheritdoc} */ function getPreferredLangcode($fallback_to_default = TRUE) { - $language_list = \Drupal::languageManager()->getLanguages(); + $language_list = $this->languageManager->getLanguages(); if (!empty($this->preferred_langcode) && isset($language_list[$this->preferred_langcode])) { return $language_list[$this->preferred_langcode]->id; } @@ -196,7 +208,7 @@ function getPreferredLangcode($fallback_to_default = TRUE) { * {@inheritdoc} */ function getPreferredAdminLangcode($fallback_to_default = TRUE) { - $language_list = \Drupal::languageManager()->getLanguages(); + $language_list = $this->languageManager->getLanguages(); if (!empty($this->preferred_admin_langcode) && isset($language_list[$this->preferred_admin_langcode])) { return $language_list[$this->preferred_admin_langcode]->id; } diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index c9afe86..d8b70f6 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -59,7 +59,7 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac $this->alterInfo('data_type_info'); $this->setCacheBackend($cache_backend, 'typed_data_types_plugins'); - parent::__construct('Plugin/DataType', $namespaces, $module_handler, 'Drupal\Core\TypedData\Annotation\DataType'); + parent::__construct('Plugin/DataType', $namespaces, $module_handler, NULL, 'Drupal\Core\TypedData\Annotation\DataType'); } /** diff --git a/core/modules/aggregator/src/Plugin/AggregatorPluginManager.php b/core/modules/aggregator/src/Plugin/AggregatorPluginManager.php index 53c3acd..e1cccc7 100644 --- a/core/modules/aggregator/src/Plugin/AggregatorPluginManager.php +++ b/core/modules/aggregator/src/Plugin/AggregatorPluginManager.php @@ -44,8 +44,13 @@ public function __construct($type, \Traversable $namespaces, CacheBackendInterfa 'parser' => 'Drupal\aggregator\Annotation\AggregatorParser', 'processor' => 'Drupal\aggregator\Annotation\AggregatorProcessor', ); + $plugin_interfaces = array( + 'fetcher' => 'Drupal\aggregator\Plugin\FetcherInterface', + 'parser' => 'Drupal\aggregator\Plugin\ParserInterface', + 'processor' => 'Drupal\aggregator\Plugin\ProcessorInterface', + ); - parent::__construct("Plugin/aggregator/$type", $namespaces, $module_handler, $type_annotations[$type]); + parent::__construct("Plugin/aggregator/$type", $namespaces, $module_handler, $plugin_interfaces[$type], $type_annotations[$type]); $this->setCacheBackend($cache_backend, 'aggregator_' . $type . '_plugins'); } diff --git a/core/modules/ckeditor/src/CKEditorPluginManager.php b/core/modules/ckeditor/src/CKEditorPluginManager.php index 289c906..1f05833 100644 --- a/core/modules/ckeditor/src/CKEditorPluginManager.php +++ b/core/modules/ckeditor/src/CKEditorPluginManager.php @@ -39,7 +39,7 @@ class CKEditorPluginManager extends DefaultPluginManager { * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/CKEditorPlugin', $namespaces, $module_handler, 'Drupal\ckeditor\Annotation\CKEditorPlugin'); + parent::__construct('Plugin/CKEditorPlugin', $namespaces, $module_handler, 'Drupal\ckeditor\CKEditorPluginInterface', 'Drupal\ckeditor\Annotation\CKEditorPlugin'); $this->alterInfo('ckeditor_plugin_info'); $this->setCacheBackend($cache_backend, 'ckeditor_plugins'); } diff --git a/core/modules/comment/src/CommentStorage.php b/core/modules/comment/src/CommentStorage.php index 714b4c1..d7e5efb 100644 --- a/core/modules/comment/src/CommentStorage.php +++ b/core/modules/comment/src/CommentStorage.php @@ -15,6 +15,7 @@ use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\Sql\SqlContentEntityStorage; use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Language\LanguageManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -46,8 +47,8 @@ class CommentStorage extends SqlContentEntityStorage implements CommentStorageIn * @param \Drupal\Core\Session\AccountInterface $current_user * The current user. */ - public function __construct(EntityTypeInterface $entity_info, Connection $database, EntityManagerInterface $entity_manager, AccountInterface $current_user, CacheBackendInterface $cache) { - parent::__construct($entity_info, $database, $entity_manager, $cache); + public function __construct(EntityTypeInterface $entity_info, Connection $database, EntityManagerInterface $entity_manager, AccountInterface $current_user, CacheBackendInterface $cache, LanguageManagerInterface $language_manager) { + parent::__construct($entity_info, $database, $entity_manager, $cache, $language_manager); $this->currentUser = $current_user; } @@ -60,7 +61,8 @@ public static function createInstance(ContainerInterface $container, EntityTypeI $container->get('database'), $container->get('entity.manager'), $container->get('current_user'), - $container->get('cache.entity') + $container->get('cache.entity'), + $container->get('language_manager') ); } diff --git a/core/modules/config_translation/src/ConfigMapperManager.php b/core/modules/config_translation/src/ConfigMapperManager.php index 8eb3735..6c99ce1 100644 --- a/core/modules/config_translation/src/ConfigMapperManager.php +++ b/core/modules/config_translation/src/ConfigMapperManager.php @@ -90,7 +90,7 @@ public function __construct(CacheBackendInterface $cache_backend, LanguageManage $this->discovery = new InfoHookDecorator($this->discovery, 'config_translation_info'); $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery); - $this->factory = new ContainerFactory($this); + $this->factory = new ContainerFactory($this, '\Drupal\config_translation\ConfigMapperInterface'); // Let others alter definitions with hook_config_translation_info_alter(). $this->moduleHandler = $module_handler; diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php index 92f0380..22c13b7 100644 --- a/core/modules/content_translation/src/ContentTranslationHandler.php +++ b/core/modules/content_translation/src/ContentTranslationHandler.php @@ -11,6 +11,7 @@ use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Render\Element; /** @@ -35,14 +36,24 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface { protected $entityType; /** + * The language manager. + * + * @var \Drupal\Core\Language\LanguageManagerInterface + */ + protected $languageManager; + + /** * Initializes an instance of the content translation controller. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type * The info array of the given entity type. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * The language manager. */ - public function __construct(EntityTypeInterface $entity_type) { + public function __construct(EntityTypeInterface $entity_type, LanguageManagerInterface $language_manager) { $this->entityTypeId = $entity_type->id(); $this->entityType = $entity_type; + $this->languageManager = $language_manager; } /** @@ -100,7 +111,7 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En // Adjust page title to specify the current language being edited, if we // have at least one translation. - $languages = \Drupal::languageManager()->getLanguages(); + $languages = $this->languageManager->getLanguages(); if (isset($languages[$form_langcode]) && ($has_translations || $new_translation)) { $title = $this->entityFormTitle($entity); // When editing the original values display just the entity label. @@ -133,7 +144,7 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En '#submit' => array(array($this, 'entityFormSourceChange')), ), ); - foreach (\Drupal::languageManager()->getLanguages(LanguageInterface::STATE_CONFIGURABLE) as $language) { + foreach ($this->languageManager->getLanguages() as $language) { if (isset($translations[$language->id])) { $form['source_langcode']['source']['#options'][$language->id] = $language->name; } @@ -146,7 +157,7 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En $language_widget = isset($form['langcode']) && $form['langcode']['#type'] == 'language_select'; if ($language_widget && $has_translations) { $form['langcode']['#options'] = array(); - foreach (\Drupal::languageManager()->getLanguages(LanguageInterface::STATE_CONFIGURABLE) as $language) { + foreach ($this->languageManager->getLanguages() as $language) { if (empty($translations[$language->id]) || $language->id == $entity_langcode) { $form['langcode']['#options'][$language->id] = $language->name; } @@ -445,7 +456,7 @@ public function entityFormSourceChange($form, FormStateInterface $form_state) { 'source' => $source, 'target' => $form_object->getFormLangcode($form_state), )); - $languages = \Drupal::languageManager()->getLanguages(); + $languages = $this->languageManager->getLanguages(); drupal_set_message(t('Source language set to: %language', array('%language' => $languages[$source]->name))); } diff --git a/core/modules/editor/src/Plugin/EditorManager.php b/core/modules/editor/src/Plugin/EditorManager.php index 1dd6df2..da0081e 100644 --- a/core/modules/editor/src/Plugin/EditorManager.php +++ b/core/modules/editor/src/Plugin/EditorManager.php @@ -33,7 +33,7 @@ class EditorManager extends DefaultPluginManager { * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/Editor', $namespaces, $module_handler, 'Drupal\editor\Annotation\Editor'); + parent::__construct('Plugin/Editor', $namespaces, $module_handler, 'Drupal\editor\Plugin\EditorPluginInterface', 'Drupal\editor\Annotation\Editor'); $this->alterInfo('editor_info'); $this->setCacheBackend($cache_backend, 'editor_plugins'); } diff --git a/core/modules/entity_reference/src/Plugin/Type/SelectionPluginManager.php b/core/modules/entity_reference/src/Plugin/Type/SelectionPluginManager.php index ce5ff83..b4e17a1 100644 --- a/core/modules/entity_reference/src/Plugin/Type/SelectionPluginManager.php +++ b/core/modules/entity_reference/src/Plugin/Type/SelectionPluginManager.php @@ -36,7 +36,7 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac // We're not using the parent constructor because we use a different factory // method and don't need the derivative discovery decorator. - $this->factory = new ReflectionFactory($this); + $this->factory = new ReflectionFactory($this, '\Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface'); $this->moduleHandler = $module_handler; $this->alterInfo('entity_reference_selection'); diff --git a/core/modules/filter/src/FilterPluginManager.php b/core/modules/filter/src/FilterPluginManager.php index 77a3c71..8eb1144 100644 --- a/core/modules/filter/src/FilterPluginManager.php +++ b/core/modules/filter/src/FilterPluginManager.php @@ -34,7 +34,7 @@ class FilterPluginManager extends DefaultPluginManager { * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/Filter', $namespaces, $module_handler, 'Drupal\filter\Annotation\Filter'); + parent::__construct('Plugin/Filter', $namespaces, $module_handler, 'Drupal\filter\Plugin\FilterInterface', 'Drupal\filter\Annotation\Filter'); $this->alterInfo('filter_info'); $this->setCacheBackend($cache_backend, 'filter_plugins', array('filter_formats' => TRUE)); } diff --git a/core/modules/image/src/ImageEffectManager.php b/core/modules/image/src/ImageEffectManager.php index 762f947..aa4c24b 100644 --- a/core/modules/image/src/ImageEffectManager.php +++ b/core/modules/image/src/ImageEffectManager.php @@ -36,7 +36,7 @@ class ImageEffectManager extends DefaultPluginManager { * The module handler. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/ImageEffect', $namespaces, $module_handler, 'Drupal\image\Annotation\ImageEffect'); + parent::__construct('Plugin/ImageEffect', $namespaces, $module_handler, 'Drupal\image\ImageEffectInterface', 'Drupal\image\Annotation\ImageEffect'); $this->alterInfo('image_effect_info'); $this->setCacheBackend($cache_backend, 'image_effect_plugins'); diff --git a/core/modules/language/src/LanguageNegotiationMethodManager.php b/core/modules/language/src/LanguageNegotiationMethodManager.php index 681c67c..b263ed5 100644 --- a/core/modules/language/src/LanguageNegotiationMethodManager.php +++ b/core/modules/language/src/LanguageNegotiationMethodManager.php @@ -28,7 +28,7 @@ class LanguageNegotiationMethodManager extends DefaultPluginManager { * An object that implements ModuleHandlerInterface */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/LanguageNegotiation', $namespaces, $module_handler); + parent::__construct('Plugin/LanguageNegotiation', $namespaces, $module_handler, 'Drupal\language\LanguageNegotiationMethodInterface'); $this->cacheBackend = $cache_backend; $this->cacheKeyPrefix = 'language_negotiation_plugins'; $this->cacheKey = 'language_negotiation_plugins'; diff --git a/core/modules/language/src/Plugin/Condition/Language.php b/core/modules/language/src/Plugin/Condition/Language.php index 7b10a81..6f62ac5 100644 --- a/core/modules/language/src/Plugin/Condition/Language.php +++ b/core/modules/language/src/Plugin/Condition/Language.php @@ -29,9 +29,10 @@ class Language extends ConditionPluginBase { * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - if (\Drupal::languageManager()->isMultilingual()) { + $language_manager = \Drupal::languageManager(); + if ($language_manager->isMultilingual()) { // Fetch languages. - $languages = \Drupal::languageManager()->getLanguages(LanguageInterface::STATE_CONFIGURABLE); + $languages = $language_manager->getLanguages(LanguageInterface::STATE_CONFIGURABLE); $langcodes_options = array(); foreach ($languages as $language) { $langcodes_options[$language->id] = $language->getName(); diff --git a/core/modules/migrate/src/Plugin/MigratePluginManager.php b/core/modules/migrate/src/Plugin/MigratePluginManager.php index 0ae77be..67cce89 100644 --- a/core/modules/migrate/src/Plugin/MigratePluginManager.php +++ b/core/modules/migrate/src/Plugin/MigratePluginManager.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\migrate\MigraterPluginManager. + * Contains \Drupal\migrate\Plugin\MigratePluginManager. */ namespace Drupal\migrate\Plugin; @@ -46,7 +46,15 @@ class MigratePluginManager extends DefaultPluginManager { * The annotation class name. */ public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, $annotation = 'Drupal\Component\Annotation\PluginID') { - parent::__construct("Plugin/migrate/$type", $namespaces, $module_handler, $annotation); + $plugin_interface_map = array( + 'destination' => 'Drupal\migrate\Plugin\MigrateDestinationInterface', + 'process' => 'Drupal\migrate\Plugin\MigrateProcessInterface', + 'source' => 'Drupal\migrate\Plugin\MigrateSourceInterface', + 'id_map' => 'Drupal\migrate\Plugin\MigrateIdMapInterface', + 'entity_field' => 'Drupal\migrate\Plugin\MigrateEntityDestinationFieldInterface', + ); + $plugin_interface = isset($plugin_interface_map[$type]) ? $plugin_interface_map[$type] : NULL; + parent::__construct("Plugin/migrate/$type", $namespaces, $module_handler, $plugin_interface, $annotation); $this->alterInfo('migrate_' . $type . '_info'); $this->setCacheBackend($cache_backend, 'migrate_plugins_' . $type); } diff --git a/core/modules/migrate_drupal/migrate_drupal.services.yml b/core/modules/migrate_drupal/migrate_drupal.services.yml index 6dd03c0..2c8f00c 100644 --- a/core/modules/migrate_drupal/migrate_drupal.services.yml +++ b/core/modules/migrate_drupal/migrate_drupal.services.yml @@ -1,4 +1,4 @@ services: plugin.manager.migrate.load: - class: Drupal\migrate\Plugin\MigratePluginManager + class: Drupal\migrate_drupal\Plugin\MigratePluginManager arguments: [load, '@container.namespaces', '@cache.discovery', '@module_handler'] diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateLoadInterface.php b/core/modules/migrate_drupal/src/Plugin/MigrateLoadInterface.php index 34dd07b..ce3ed83 100644 --- a/core/modules/migrate_drupal/src/Plugin/MigrateLoadInterface.php +++ b/core/modules/migrate_drupal/src/Plugin/MigrateLoadInterface.php @@ -2,11 +2,12 @@ /** * @file - * Contains Drupal\migrate\Plugin\MigrateLoadInterface + * Contains Drupal\migrate_drupal\Plugin\MigrateLoadInterface */ namespace Drupal\migrate_drupal\Plugin; +use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Core\Entity\EntityStorageInterface; /** @@ -16,7 +17,7 @@ * * @ingroup migration */ -interface MigrateLoadInterface { +interface MigrateLoadInterface extends PluginInspectionInterface { /** * Load an additional migration. diff --git a/core/modules/migrate_drupal/src/Plugin/MigratePluginManager.php b/core/modules/migrate_drupal/src/Plugin/MigratePluginManager.php new file mode 100644 index 0000000..c93ff07 --- /dev/null +++ b/core/modules/migrate_drupal/src/Plugin/MigratePluginManager.php @@ -0,0 +1,34 @@ +factory = new ContainerFactory($this, 'Drupal\migrate_drupal\Plugin\MigrateLoadInterface'); + } + + +} diff --git a/core/modules/quickedit/src/Plugin/InPlaceEditorManager.php b/core/modules/quickedit/src/Plugin/InPlaceEditorManager.php index 876da2d..210f675 100644 --- a/core/modules/quickedit/src/Plugin/InPlaceEditorManager.php +++ b/core/modules/quickedit/src/Plugin/InPlaceEditorManager.php @@ -35,7 +35,7 @@ class InPlaceEditorManager extends DefaultPluginManager { * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/InPlaceEditor', $namespaces, $module_handler, 'Drupal\quickedit\Annotation\InPlaceEditor'); + parent::__construct('Plugin/InPlaceEditor', $namespaces, $module_handler, 'Drupal\quickedit\Plugin\InPlaceEditorInterface', 'Drupal\quickedit\Annotation\InPlaceEditor'); $this->alterInfo('quickedit_editor'); $this->setCacheBackend($cache_backend, 'quickedit:editor'); } diff --git a/core/modules/rest/src/Plugin/Type/ResourcePluginManager.php b/core/modules/rest/src/Plugin/Type/ResourcePluginManager.php index ec9cb9f..97594c4 100644 --- a/core/modules/rest/src/Plugin/Type/ResourcePluginManager.php +++ b/core/modules/rest/src/Plugin/Type/ResourcePluginManager.php @@ -33,7 +33,7 @@ class ResourcePluginManager extends DefaultPluginManager { * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/rest/resource', $namespaces, $module_handler, 'Drupal\rest\Annotation\RestResource'); + parent::__construct('Plugin/rest/resource', $namespaces, $module_handler, 'Drupal\rest\Plugin\ResourceInterface', 'Drupal\rest\Annotation\RestResource'); $this->setCacheBackend($cache_backend, 'rest_plugins'); $this->alterInfo('rest_resource'); diff --git a/core/modules/search/src/SearchPluginManager.php b/core/modules/search/src/SearchPluginManager.php index 5670e71..bad133a 100644 --- a/core/modules/search/src/SearchPluginManager.php +++ b/core/modules/search/src/SearchPluginManager.php @@ -28,7 +28,7 @@ class SearchPluginManager extends DefaultPluginManager { * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/Search', $namespaces, $module_handler, 'Drupal\search\Annotation\SearchPlugin'); + parent::__construct('Plugin/Search', $namespaces, $module_handler, 'Drupal\search\Plugin\SearchInterface', 'Drupal\search\Annotation\SearchPlugin'); $this->setCacheBackend($cache_backend, 'search_plugins'); $this->alterInfo('search_plugin'); } diff --git a/core/modules/system/src/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php b/core/modules/system/src/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php index 941a93a..101dee6 100644 --- a/core/modules/system/src/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php +++ b/core/modules/system/src/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php @@ -43,6 +43,13 @@ protected function setUp() { 'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Cherry', 'provider' => 'plugin_test', ), + 'kale' => array( + 'id' => 'kale', + 'label' => 'Kale', + 'color' => 'green', + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Kale', + 'provider' => 'plugin_test', + ), 'orange' => array( 'id' => 'orange', 'label' => 'Orange', diff --git a/core/modules/system/src/Tests/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php b/core/modules/system/src/Tests/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php index aa29a09..92a73f3 100644 --- a/core/modules/system/src/Tests/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php +++ b/core/modules/system/src/Tests/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php @@ -57,6 +57,13 @@ protected function setUp() { 'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Cherry', 'provider' => 'plugin_test', ), + 'kale' => array( + 'id' => 'kale', + 'label' => 'Kale', + 'color' => 'green', + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Kale', + 'provider' => 'plugin_test', + ), 'orange' => array( 'id' => 'orange', 'label' => 'Orange', diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/DefaultsTestPluginManager.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/DefaultsTestPluginManager.php index e81c39e..bda80fa 100644 --- a/core/modules/system/tests/modules/plugin_test/src/Plugin/DefaultsTestPluginManager.php +++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/DefaultsTestPluginManager.php @@ -29,7 +29,7 @@ public function __construct(ModuleHandlerInterface $module_handler) { // discovery implementation, but StaticDiscovery lets us add some simple // mock plugins for unit testing. $this->discovery = new StaticDiscovery(); - $this->factory = new DefaultFactory($this); + $this->factory = new DefaultFactory($this, 'Drupal\Component\Plugin\PluginInspectionInterface'); $this->moduleHandler = $module_handler; // Specify default values. diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Apple.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Apple.php index 9aabeca..d81b6ba 100644 --- a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Apple.php +++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Apple.php @@ -14,4 +14,4 @@ * color = "green" * ) */ -class Apple {} +class Apple implements FruitInterface {} diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Banana.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Banana.php index 4801da5..5e4d180 100644 --- a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Banana.php +++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Banana.php @@ -17,6 +17,6 @@ * } * ) */ -class Banana { +class Banana implements FruitInterface { } diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Cherry.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Cherry.php index d22b90a..30db552 100644 --- a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Cherry.php +++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Cherry.php @@ -14,4 +14,4 @@ * color = "red" * ) */ -class Cherry {} +class Cherry implements FruitInterface {} diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/FruitInterface.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/FruitInterface.php new file mode 100644 index 0000000..4c26071 --- /dev/null +++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/FruitInterface.php @@ -0,0 +1,14 @@ +moduleExists('entity_reference')) { + unset($info['entity_reference_rss_category']); + } } /** diff --git a/core/modules/tour/src/TipPluginManager.php b/core/modules/tour/src/TipPluginManager.php index 6f98f62..bcd2c78 100644 --- a/core/modules/tour/src/TipPluginManager.php +++ b/core/modules/tour/src/TipPluginManager.php @@ -33,7 +33,7 @@ class TipPluginManager extends DefaultPluginManager { * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/tour/tip', $namespaces, $module_handler, 'Drupal\tour\Annotation\Tip'); + parent::__construct('Plugin/tour/tip', $namespaces, $module_handler, 'Drupal\tour\TipPluginInterface', 'Drupal\tour\Annotation\Tip'); $this->alterInfo('tour_tips_info'); $this->setCacheBackend($cache_backend, 'tour_plugins'); diff --git a/core/modules/update/tests/modules/update_test/src/Plugin/Archiver/UpdateTestArchiver.php b/core/modules/update/tests/modules/update_test/src/Plugin/Archiver/UpdateTestArchiver.php new file mode 100644 index 0000000..330d8ab --- /dev/null +++ b/core/modules/update/tests/modules/update_test/src/Plugin/Archiver/UpdateTestArchiver.php @@ -0,0 +1,51 @@ + array('update-test-extension'), - ); -} - -/** * Implements hook_filetransfer_info(). */ function update_test_filetransfer_info() { diff --git a/core/modules/user/src/UserStorage.php b/core/modules/user/src/UserStorage.php index 9aa844e..6ea5377 100644 --- a/core/modules/user/src/UserStorage.php +++ b/core/modules/user/src/UserStorage.php @@ -15,6 +15,7 @@ use Drupal\Core\Entity\Sql\SqlContentEntityStorage; use Drupal\Core\Password\PasswordInterface; use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Language\LanguageManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -45,9 +46,11 @@ class UserStorage extends SqlContentEntityStorage implements UserStorageInterfac * Cache backend instance to use. * @param \Drupal\Core\Password\PasswordInterface $password * The password hashing service. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * The language manager. */ - public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache, PasswordInterface $password) { - parent::__construct($entity_type, $database, $entity_manager, $cache); + public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache, PasswordInterface $password, LanguageManagerInterface $language_manager) { + parent::__construct($entity_type, $database, $entity_manager, $cache, $language_manager); $this->password = $password; } @@ -61,7 +64,8 @@ public static function createInstance(ContainerInterface $container, EntityTypeI $container->get('database'), $container->get('entity.manager'), $container->get('cache.entity'), - $container->get('password') + $container->get('password'), + $container->get('language_manager') ); } diff --git a/core/modules/views/src/Form/ViewsExposedForm.php b/core/modules/views/src/Form/ViewsExposedForm.php index 618a737..6b6d610 100644 --- a/core/modules/views/src/Form/ViewsExposedForm.php +++ b/core/modules/views/src/Form/ViewsExposedForm.php @@ -81,7 +81,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { // Go through each handler and let it generate its exposed widget. foreach ($view->display_handler->handlers as $type => $value) { - /** @var \Drupal\views\Plugin\views\HandlerBase $handler */ + /** @var \Drupal\views\Plugin\views\ViewsHandlerInterface $handler */ foreach ($view->$type as $id => $handler) { if ($handler->canExpose() && $handler->isExposed()) { // Grouped exposed filters have their own forms. @@ -134,7 +134,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { */ public function validateForm(array &$form, FormStateInterface $form_state) { foreach (array('field', 'filter') as $type) { - /** @var \Drupal\views\Plugin\views\HandlerBase[] $handlers */ + /** @var \Drupal\views\Plugin\views\ViewsHandlerInterface[] $handlers */ $handlers = &$form_state['view']->$type; foreach ($handlers as $key => $handler) { $handlers[$key]->validateExposed($form, $form_state); @@ -150,7 +150,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) { */ public function submitForm(array &$form, FormStateInterface $form_state) { foreach (array('field', 'filter') as $type) { - /** @var \Drupal\views\Plugin\views\HandlerBase[] $handlers */ + /** @var \Drupal\views\Plugin\views\ViewsHandlerInterface[] $handlers */ $handlers = &$form_state['view']->$type; foreach ($handlers as $key => $info) { $handlers[$key]->submitExposed($form, $form_state); diff --git a/core/modules/views/src/Plugin/ViewsHandlerManager.php b/core/modules/views/src/Plugin/ViewsHandlerManager.php index 7b7b76e..e7e1c89 100644 --- a/core/modules/views/src/Plugin/ViewsHandlerManager.php +++ b/core/modules/views/src/Plugin/ViewsHandlerManager.php @@ -52,7 +52,11 @@ class ViewsHandlerManager extends DefaultPluginManager { */ public function __construct($handler_type, \Traversable $namespaces, ViewsData $views_data, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { $plugin_definition_annotation_name = 'Drupal\views\Annotation\Views' . Container::camelize($handler_type); - parent::__construct("Plugin/views/$handler_type", $namespaces, $module_handler, $plugin_definition_annotation_name); + $plugin_interface = 'Drupal\views\Plugin\views\ViewsHandlerInterface'; + if ($handler_type == 'join') { + $plugin_interface = 'Drupal\views\Plugin\views\join\JoinPluginInterface'; + } + parent::__construct("Plugin/views/$handler_type", $namespaces, $module_handler, $plugin_interface, $plugin_definition_annotation_name); $this->setCacheBackend($cache_backend, "views:$handler_type", array('extension' => array(TRUE, 'views'))); @@ -74,7 +78,7 @@ public function __construct($handler_type, \Traversable $namespaces, ViewsData $ * (optional) Override the actual handler object with this plugin ID. Used for * aggregation when the handler is redirected to the aggregation handler. * - * @return \Drupal\views\Plugin\views\HandlerBase + * @return \Drupal\views\Plugin\views\ViewsHandlerInterface * An instance of a handler object. May be a broken handler instance. */ public function getHandler($item, $override = NULL) { diff --git a/core/modules/views/src/Plugin/ViewsPluginManager.php b/core/modules/views/src/Plugin/ViewsPluginManager.php index ca98555..3b43981 100644 --- a/core/modules/views/src/Plugin/ViewsPluginManager.php +++ b/core/modules/views/src/Plugin/ViewsPluginManager.php @@ -34,7 +34,7 @@ class ViewsPluginManager extends DefaultPluginManager { */ public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { $plugin_definition_annotation_name = 'Drupal\views\Annotation\Views' . Container::camelize($type); - parent::__construct("Plugin/views/$type", $namespaces, $module_handler, $plugin_definition_annotation_name); + parent::__construct("Plugin/views/$type", $namespaces, $module_handler, 'Drupal\views\Plugin\views\ViewsPluginInterface', $plugin_definition_annotation_name); $this->defaults += array( 'parent' => 'parent', diff --git a/core/modules/views/src/Plugin/views/HandlerBase.php b/core/modules/views/src/Plugin/views/HandlerBase.php index ce31f43..27d24d7 100644 --- a/core/modules/views/src/Plugin/views/HandlerBase.php +++ b/core/modules/views/src/Plugin/views/HandlerBase.php @@ -16,7 +16,6 @@ use Drupal\Core\Render\Element; use Drupal\Core\Session\AccountInterface; use Drupal\views\Plugin\views\display\DisplayPluginBase; -use Drupal\views\Plugin\views\PluginBase; use Drupal\views\ViewExecutable; use Drupal\Core\Database\Database; use Drupal\views\Views; @@ -27,7 +26,7 @@ * * @ingroup views_plugins */ -abstract class HandlerBase extends PluginBase { +abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface { /** * Where the $query object will reside: @@ -109,7 +108,7 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition } /** - * Overrides \Drupal\views\Plugin\views\PluginBase::init(). + * {@inheritdoc} */ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { parent::init($view, $display, $options); @@ -172,7 +171,7 @@ protected function defineOptions() { } /** - * Return a string representing this handler's name in the UI. + * {@inheritdoc} */ public function adminLabel($short = FALSE) { if (!empty($this->options['admin_label'])) { @@ -184,11 +183,7 @@ public function adminLabel($short = FALSE) { } /** - * Shortcut to get a handler's raw field value. - * - * This should be overridden for handlers with formulae or other - * non-standard fields. Because this takes an argument, fields - * overriding this can just call return parent::getField($formula) + * {@inheritdoc} */ public function getField($field = NULL) { if (!isset($field)) { @@ -218,15 +213,7 @@ public function getField($field = NULL) { } /** - * Sanitize the value for output. - * - * @param $value - * The value being rendered. - * @param $type - * The type of sanitization needed. If not provided, String::checkPlain() is used. - * - * @return string - * Returns the safe value. + * {@inheritdoc} */ public function sanitizeValue($value, $type = NULL) { switch ($type) { @@ -277,7 +264,7 @@ protected function caseTransform($string, $option) { } /** - * Build the options form. + * {@inheritdoc} */ public function buildOptionsForm(&$form, FormStateInterface $form_state) { // Some form elements belong in a fieldset for presentation, but can't @@ -483,10 +470,7 @@ public function showExposeForm(&$form, FormStateInterface $form_state) { } /** - * Check whether current user has access to this handler. - * - * @param AccountInterface $account - * @return boolean + * {@inheritdoc} */ public function access(AccountInterface $account) { if (isset($this->definition['access callback']) && function_exists($this->definition['access callback'])) { @@ -500,26 +484,19 @@ public function access(AccountInterface $account) { } /** - * Run before the view is built. - * - * This gives all the handlers some time to set up before any handler has - * been fully run. + * {@inheritdoc} */ public function preQuery() { } /** - * Don't run a query by default. + * {@inheritdoc} */ public function query() { } /** - * Run after the view is executed, before the result is cached. - * - * This gives all the handlers some time to modify values. This is primarily - * used so that handlers that pull up secondary data can put it in the - * $values so that the raw data can be utilized externally. + * {@inheritdoc} */ public function postExecute(&$values) { } @@ -534,8 +511,7 @@ protected function placeholder() { } /** - * Called just prior to query(), this lets a handler set up any relationship - * it needs. + * {@inheritdoc} */ public function setRelationship() { // Ensure this gets set to something. @@ -564,8 +540,7 @@ public function setRelationship() { } /** - * Ensure the main table for this handler is in the query. This is used - * a lot. + * {@inheritdoc} */ public function ensureMyTable() { if (!isset($this->tableAlias)) { @@ -575,7 +550,7 @@ public function ensureMyTable() { } /** - * Provide text for the administrative summary. + * {@inheritdoc} */ public function adminSummary() { } @@ -612,11 +587,7 @@ public function acceptExposedInput($input) { return TRUE; } public function storeExposedInput($input, $status) { return TRUE; } /** - * Get the join object that should be used for this handler. - * - * This method isn't used a great deal, but it's very handy for easily - * getting the join if it is necessary to make some changes to it, such - * as adding an 'extra'. + * {@inheritdoc} */ public function getJoin() { // get the join from this table that links back to the base table. @@ -635,21 +606,12 @@ public function getJoin() { } /** - * Validates the handler against the complete View. - * - * This is called when the complete View is being validated. For validating - * the handler options form use validateOptionsForm(). - * - * @see views_handler::validateOptionsForm() - * - * @return - * Empty array if the handler is valid; an array of error strings if it is not. + * {@inheritdoc} */ public function validate() { return array(); } /** - * Determines if the handler is considered 'broken', meaning it's a - * a placeholder used when a handler can't be found. + * {@inheritdoc} */ public function broken() { return FALSE; @@ -692,24 +654,14 @@ protected function getViewsData() { } /** - * Sets the views data service. - * - * @param \Drupal\views\ViewsData $views_data - * The views data. + * {@inheritdoc} */ public function setViewsData(ViewsData $views_data) { $this->viewsData = $views_data; } /** - * Fetches a handler to join one table to a primary table from the data cache. - * - * @param string $table - * The table to join from. - * @param string $base_table - * The table to join to. - * - * @return \Drupal\views\Plugin\views\join\JoinPluginBase + * {@inheritdoc} */ public static function getTableJoin($table, $base_table) { $data = Views::viewsData()->get($table); @@ -745,13 +697,7 @@ public static function getTableJoin($table, $base_table) { } /** - * Determines the entity type used by this handler. - * - * If this handler uses a relationship, the base class of the relationship is - * taken into account. - * - * @return string - * The machine name of the entity type. + * {@inheritdoc} */ public function getEntityType() { // If the user has configured a relationship on the handler take that into @@ -772,15 +718,7 @@ public function getEntityType() { } /** - * Breaks x,y,z and x+y+z into an array. - * - * @param string $str - * The string to split. - * @param bool $force_int - * Enforce a numeric check. - * - * @return \stdClass - * A stdClass object containing value and operator properties. + * {@inheritdoc} */ public static function breakString($str, $force_int = FALSE) { $operator = NULL; diff --git a/core/modules/views/src/Plugin/views/PluginBase.php b/core/modules/views/src/Plugin/views/PluginBase.php index b66578b..a92027d 100644 --- a/core/modules/views/src/Plugin/views/PluginBase.php +++ b/core/modules/views/src/Plugin/views/PluginBase.php @@ -42,7 +42,7 @@ * * @ingroup views_plugins */ -abstract class PluginBase extends ComponentPluginBase implements ContainerFactoryPluginInterface { +abstract class PluginBase extends ComponentPluginBase implements ContainerFactoryPluginInterface, ViewsPluginInterface { /** * Include negotiated languages when listing languages. @@ -108,14 +108,7 @@ public static function create(ContainerInterface $container, array $configuratio } /** - * Initialize the plugin. - * - * @param \Drupal\views\ViewExecutable $view - * The view object. - * @param \Drupal\views\Plugin\views\display\DisplayPluginBase $display - * The display handler. - * @param array $options - * The options configured for this plugin. + * {@inheritdoc} */ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { $this->view = $view; @@ -171,8 +164,7 @@ protected function setOptionDefaults(array &$storage, array $options) { } /** - * Unpack options over our existing defaults, drilling down into arrays - * so that defaults don't get totally blown away. + * {@inheritdoc} */ public function unpackOptions(&$storage, $options, $definition = NULL, $all = TRUE, $check = TRUE) { if ($check && !is_array($options)) { @@ -211,19 +203,14 @@ public function unpackOptions(&$storage, $options, $definition = NULL, $all = TR } /** - * Clears a plugin. + * {@inheritdoc} */ public function destroy() { unset($this->view, $this->display, $this->query); } /** - * Init will be called after construct, when the plugin is attached to a - * view and a display. - */ - - /** - * Provide a form to edit options for this plugin. + * {@inheritdoc} */ public function buildOptionsForm(&$form, FormStateInterface $form_state) { // Some form elements belong in a fieldset for presentation, but can't @@ -234,47 +221,41 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { } /** - * Validate the options form. + * {@inheritdoc} */ public function validateOptionsForm(&$form, FormStateInterface $form_state) { } /** - * Handle any special handling on the validate form. + * {@inheritdoc} */ public function submitOptionsForm(&$form, FormStateInterface $form_state) { } /** - * Add anything to the query that we might need to. + * {@inheritdoc} */ public function query() { } /** - * Provide a full list of possible theme templates used by this style. + * {@inheritdoc} */ public function themeFunctions() { return $this->view->buildThemeFunctions($this->definition['theme']); } /** - * Validate that the plugin is correct and can be saved. - * - * @return - * An array of error strings to tell the user what is wrong with this - * plugin. + * {@inheritdoc} */ public function validate() { return array(); } /** - * Returns the summary of the settings in the display. + * {@inheritdoc} */ public function summaryTitle() { return t('Settings'); } /** - * Return the human readable name of the display. - * - * This appears on the ui beside each plugin and beside the settings link. + * {@inheritdoc} */ public function pluginTitle() { // Short_title is optional so its defaults to an empty string. @@ -285,39 +266,21 @@ public function pluginTitle() { } /** - * Returns the usesOptions property. + * {@inheritdoc} */ public function usesOptions() { return $this->usesOptions; } /** - * Returns a string with any core tokens replaced. - * - * @param string $string - * The string to preform the token replacement on. - * @param array $options - * An array of options, as passed to \Drupal\Core\Utility\Token::replace(). - * - * @return string - * The tokenized string. + * {@inheritdoc} */ public function globalTokenReplace($string = '', array $options = array()) { return \Drupal::token()->replace($string, array('view' => $this->view), $options); } /** - * Returns an array of available token replacements. - * - * @param bool $prepared - * Whether to return the raw token info for each token or an array of - * prepared tokens for each type. E.g. "[view:name]". - * @param array $types - * An array of additional token types to return, defaults to 'site' and - * 'view'. - * - * @return array - * An array of available token replacement info or tokens, grouped by type. + * {@inheritdoc} */ public function getAvailableGlobalTokens($prepared = FALSE, array $types = array()) { $info = \Drupal::token()->getInfo(); @@ -341,12 +304,7 @@ public function getAvailableGlobalTokens($prepared = FALSE, array $types = array } /** - * Adds elements for available core tokens to a form. - * - * @param array $form - * The form array to alter, passed by reference. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. + * {@inheritdoc} */ public function globalTokenForm(&$form, FormStateInterface $form_state) { $token_items = array(); @@ -377,19 +335,7 @@ public function globalTokenForm(&$form, FormStateInterface $form_state) { } /** - * Moves form elements into fieldsets for presentation purposes. - * - * Many views forms use #tree = TRUE to keep their values in a hierarchy for - * easier storage. Moving the form elements into fieldsets during form - * building would break up that hierarchy. Therefore, we wait until the - * pre_render stage, where any changes we make affect presentation only and - * aren't reflected in $form_state->getValues(). - * - * @param array $form - * The form build array to alter. - * - * @return array - * The form build array. + * {@inheritdoc} */ public static function preRenderAddFieldsetMarkup(array $form) { foreach (Element::children($form) as $key) { @@ -408,17 +354,7 @@ public static function preRenderAddFieldsetMarkup(array $form) { } /** - * Flattens the structure of form elements. - * - * If a form element has #flatten = TRUE, then all of it's children get moved - * to the same level as the element itself. So $form['to_be_flattened'][$key] - * becomes $form[$key], and $form['to_be_flattened'] gets unset. - * - * @param array $form - * The form build array to alter. - * - * @return array - * The form build array. + * {@inheritdoc} */ public static function preRenderFlattenData($form) { foreach (Element::children($form) as $key) { @@ -436,12 +372,7 @@ public static function preRenderFlattenData($form) { } /** - * Returns an array of module dependencies for this plugin. - * - * Dependencies are a list of module names, which might depend on the - * configuration. - * - * @return array + * {@inheritdoc} */ public function getDependencies() { return array(); diff --git a/core/modules/views/src/Plugin/views/ViewsHandlerInterface.php b/core/modules/views/src/Plugin/views/ViewsHandlerInterface.php new file mode 100644 index 0000000..4a48372 --- /dev/null +++ b/core/modules/views/src/Plugin/views/ViewsHandlerInterface.php @@ -0,0 +1,144 @@ +getValues(). + * + * @param array $form + * The form build array to alter. + * + * @return array + * The form build array. + */ + public static function preRenderAddFieldsetMarkup(array $form); + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition); + + /** + * Initialize the plugin. + * + * @param \Drupal\views\ViewExecutable $view + * The view object. + * @param \Drupal\views\Plugin\views\display\DisplayPluginBase $display + * The display handler. + * @param array $options + * The options configured for this plugin. + */ + public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL); + + /** + * Handle any special handling on the validate form. + */ + public function submitOptionsForm(&$form, FormStateInterface $form_state); + + /** + * Adds elements for available core tokens to a form. + * + * @param array $form + * The form array to alter, passed by reference. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + */ + public function globalTokenForm(&$form, FormStateInterface $form_state); + + /** + * Returns an array of available token replacements. + * + * @param bool $prepared + * Whether to return the raw token info for each token or an array of + * prepared tokens for each type. E.g. "[view:name]". + * @param array $types + * An array of additional token types to return, defaults to 'site' and + * 'view'. + * + * @return array + * An array of available token replacement info or tokens, grouped by type. + */ + public function getAvailableGlobalTokens($prepared = FALSE, array $types = array()); + + /** + * Flattens the structure of form elements. + * + * If a form element has #flatten = TRUE, then all of it's children get moved + * to the same level as the element itself. So $form['to_be_flattened'][$key] + * becomes $form[$key], and $form['to_be_flattened'] gets unset. + * + * @param array $form + * The form build array to alter. + * + * @return array + * The form build array. + */ + public static function preRenderFlattenData($form); + + /** + * Returns a string with any core tokens replaced. + * + * @param string $string + * The string to preform the token replacement on. + * @param array $options + * An array of options, as passed to \Drupal\Core\Utility\Token::replace(). + * + * @return string + * The tokenized string. + */ + public function globalTokenReplace($string = '', array $options = array()); + + /** + * Clears a plugin. + */ + public function destroy(); + + /** + * Validate that the plugin is correct and can be saved. + * + * @return + * An array of error strings to tell the user what is wrong with this + * plugin. + */ + public function validate(); + + /** + * Add anything to the query that we might need to. + */ + public function query(); + + /** + * Unpack options over our existing defaults, drilling down into arrays + * so that defaults don't get totally blown away. + */ + public function unpackOptions(&$storage, $options, $definition = NULL, $all = TRUE, $check = TRUE); + + /** + * Provide a form to edit options for this plugin. + */ + public function buildOptionsForm(&$form, FormStateInterface $form_state); + + /** + * Provide a full list of possible theme templates used by this style. + */ + public function themeFunctions(); + +} diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index 7d3232f..d7d5ea4 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -837,7 +837,7 @@ public function usesFields() { * @param string $type * The type of the plugin. * - * @return \Drupal\views\Plugin\views\PluginBase + * @return \Drupal\views\Plugin\views\ViewsPluginInterface */ public function getPlugin($type) { // Look up the plugin name to use for this instance. @@ -890,7 +890,7 @@ public function &getHandler($type, $id) { /** * Get a full array of handlers for $type. This caches them. * - * @return \Drupal\views\Plugin\views\HandlerBase[] + * @return \Drupal\views\Plugin\views\ViewsHandlerInterface[] */ public function getHandlers($type) { if (!isset($this->handlers[$type])) { diff --git a/core/modules/views/src/Plugin/views/join/JoinPluginBase.php b/core/modules/views/src/Plugin/views/join/JoinPluginBase.php index cd1dda3..d282f39 100644 --- a/core/modules/views/src/Plugin/views/join/JoinPluginBase.php +++ b/core/modules/views/src/Plugin/views/join/JoinPluginBase.php @@ -58,7 +58,7 @@ * * Extensions of this class can be used to create more interesting joins. */ -class JoinPluginBase extends PluginBase { +class JoinPluginBase extends PluginBase implements JoinPluginInterface { /** * The table to join (right table). @@ -181,16 +181,7 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition } /** - * Builds the SQL for the join this object represents. - * - * When possible, try to use table alias instead of table names. - * - * @param $select_query - * An select query object. - * @param $table - * The base table to join. - * @param \Drupal\views\Plugin\views\query\QueryPluginBase $view_query - * The source views query. + * {@inheritdoc} */ public function buildJoin($select_query, $table, $view_query) { if (empty($this->configuration['table formula'])) { diff --git a/core/modules/views/src/Plugin/views/join/JoinPluginInterface.php b/core/modules/views/src/Plugin/views/join/JoinPluginInterface.php new file mode 100644 index 0000000..03fefb2 --- /dev/null +++ b/core/modules/views/src/Plugin/views/join/JoinPluginInterface.php @@ -0,0 +1,31 @@ +display_handler->getOption($type)); $this->assertIdentical($original_order[$type], $loaded_order); } - } - /** * Check to see if a value is the same as the value on a certain handler. * * @param $expected * The expected value to check. - * @param \Drupal\views\Plugin\views\HandlerBase $handler + * @param \Drupal\views\Plugin\views\ViewsHandlerInterface $handler * The handler that has the $handler->value property to compare with first. * @param string $message * The message to display along with the assertion. diff --git a/core/tests/Drupal/Tests/Component/Plugin/DefaultFactoryTest.php b/core/tests/Drupal/Tests/Component/Plugin/DefaultFactoryTest.php new file mode 100644 index 0000000..21dcf7c --- /dev/null +++ b/core/tests/Drupal/Tests/Component/Plugin/DefaultFactoryTest.php @@ -0,0 +1,70 @@ + $plugin_class]); + + $this->assertEquals($plugin_class, $class); + } + + /** + * Tests getPluginClass() with a missing class definition. + * + * @expectedException \Drupal\Component\Plugin\Exception\PluginException + * @expectedExceptionMessage The plugin (cherry) did not specify an instance class. + */ + public function testGetPluginClassWithMissingClass() { + DefaultFactory::getPluginClass('cherry', []); + } + + /** + * Tests getPluginClass() with a not existing class definition. + * + * @expectedException \Drupal\Component\Plugin\Exception\PluginException + * @expectedExceptionMessage Plugin (kiwifruit) instance class "\Drupal\plugin_test\Plugin\plugin_test\fruit\Kiwifruit" does not exist. + */ + public function testGetPluginClassWithNotExistingClass() { + DefaultFactory::getPluginClass('kiwifruit', ['class' => '\Drupal\plugin_test\Plugin\plugin_test\fruit\Kiwifruit']); + } + + /** + * Tests getPluginClass() with a required interface. + */ + public function testGetPluginClassWithInterface() { + $plugin_class = 'Drupal\plugin_test\Plugin\plugin_test\fruit\Cherry'; + $class = DefaultFactory::getPluginClass('cherry', ['class' => $plugin_class], '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); + + $this->assertEquals($plugin_class, $class); + } + + /** + * Tests getPluginClass() with a required interface but no implementation. + * + * @expectedException \Drupal\Component\Plugin\Exception\PluginException + * @expectedExceptionMessage Plugin "cherry" (Drupal\plugin_test\Plugin\plugin_test\fruit\Kale) in core should implement interface \Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface. + */ + public function testGetPluginClassWithInterfaceAndInvalidClass() { + $plugin_class = 'Drupal\plugin_test\Plugin\plugin_test\fruit\Kale'; + DefaultFactory::getPluginClass('cherry', ['class' => $plugin_class, 'provider' => 'core'], '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); + } + +} + diff --git a/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php b/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php index c1dba2e..2d6390c 100644 --- a/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php @@ -246,7 +246,7 @@ protected function setupLocalTaskManager() { $this->manager = $this ->getMockBuilder('Drupal\Core\Menu\LocalTaskManager') ->disableOriginalConstructor() - ->setMethods(NULL) + ->setMethods(array('enforcePluginInterface')) ->getMock(); $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'controllerResolver'); diff --git a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php index 1eb0d26..274d46d 100644 --- a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php @@ -13,6 +13,8 @@ * Tests the DefaultPluginManager. * * @group Plugin + * + * @coversDefaultClass \Drupal\Core\Plugin\DefaultPluginManager */ class DefaultPluginManagerTest extends UnitTestCase { @@ -76,7 +78,7 @@ public function testDefaultPluginManagerWithDisabledModule() { ->with('disabled_module') ->will($this->returnValue(FALSE)); - $plugin_manager = new TestPluginManager($this->namespaces, $definitions, $module_handler, 'test_alter_hook'); + $plugin_manager = new TestPluginManager($this->namespaces, $definitions, $module_handler, 'test_alter_hook', '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); $this->assertEmpty($plugin_manager->getDefinition('cherry', FALSE), 'Plugin information of a disabled module is not available'); } @@ -101,7 +103,7 @@ public function testDefaultPluginManagerWithObjects() { ->with('disabled_module') ->will($this->returnValue(FALSE)); - $plugin_manager = new TestPluginManager($this->namespaces, $definitions, $module_handler, 'test_alter_hook'); + $plugin_manager = new TestPluginManager($this->namespaces, $definitions, $module_handler, 'test_alter_hook', '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); $this->assertEmpty($plugin_manager->getDefinition('cherry', FALSE), 'Plugin information is available'); } @@ -110,7 +112,7 @@ public function testDefaultPluginManagerWithObjects() { * Tests the plugin manager with no cache and altering. */ public function testDefaultPluginManager() { - $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions); + $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); $this->assertEquals($this->expectedDefinitions, $plugin_manager->getDefinitions()); $this->assertEquals($this->expectedDefinitions['banana'], $plugin_manager->getDefinition('banana')); } @@ -129,7 +131,7 @@ public function testDefaultPluginManagerWithAlter() { ->method('alter') ->with($this->equalTo($alter_hook_name), $this->equalTo($this->expectedDefinitions)); - $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler, $alter_hook_name); + $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler, $alter_hook_name, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); $this->assertEquals($this->expectedDefinitions, $plugin_manager->getDefinitions()); $this->assertEquals($this->expectedDefinitions['banana'], $plugin_manager->getDefinition('banana')); @@ -153,7 +155,7 @@ public function testDefaultPluginManagerWithEmptyCache() { ->method('set') ->with($cid, $this->expectedDefinitions); - $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions); + $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); $plugin_manager->setCacheBackend($cache_backend, $cid); $this->assertEquals($this->expectedDefinitions, $plugin_manager->getDefinitions()); @@ -177,7 +179,7 @@ public function testDefaultPluginManagerWithFilledCache() { ->expects($this->never()) ->method('set'); - $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions); + $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); $plugin_manager->setCacheBackend($cache_backend, $cid); $this->assertEquals($this->expectedDefinitions, $plugin_manager->getDefinitions()); @@ -201,10 +203,83 @@ public function testCacheClearWithTags() { $this->getContainerWithCacheBins($cache_backend); - $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions); + $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); $plugin_manager->setCacheBackend($cache_backend, $cid, array('tag' => TRUE)); $plugin_manager->clearCachedDefinitions(); } + /** + * Tests plugins with the proper interface. + * + * @covers ::createInstance + * @covers ::enforcePluginInterface + */ + public function testCreateInstanceWithJustValidInterfaces() { + $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); + + foreach ($this->expectedDefinitions as $plugin_id => $definition) { + $plugin_manager->createInstance($plugin_id); + } + } + + /** + * Tests plugins without the proper interface. + * + * @covers ::createInstance + * @covers ::enforcePluginInterface + * + * @expectedException \Drupal\Component\Plugin\Exception\PluginException + * @expectedExceptionMessage Plugin "kale" (Drupal\plugin_test\Plugin\plugin_test\fruit\Kale) in plugin_test should implement interface \Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface + */ + public function testCreateInstanceWithInvalidInterfaces() { + $module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); + + $module_handler->expects($this->any()) + ->method('moduleExists') + ->with('plugin_test') + ->willReturn(TRUE); + + $this->expectedDefinitions['kale'] = array( + 'id' => 'kale', + 'label' => 'Kale', + 'color' => 'green', + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Kale', + 'provider' => 'plugin_test', + ); + $this->expectedDefinitions['apple']['provider'] = 'plugin_test'; + $this->expectedDefinitions['banana']['provider'] = 'plugin_test'; + + $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); + $plugin_manager->createInstance('kale'); + } + + /** + * Tests plugins without a required interface. + * + * @covers ::getDefinitions + * @covers ::enforcePluginInterface + */ + public function testGetDefinitionsWithoutRequiredInterface() { + $module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); + + $module_handler->expects($this->any()) + ->method('moduleExists') + ->with('plugin_test') + ->willReturn(FALSE); + + $this->expectedDefinitions['kale'] = array( + 'id' => 'kale', + 'label' => 'Kale', + 'color' => 'green', + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Kale', + 'provider' => 'plugin_test', + ); + $this->expectedDefinitions['apple']['provider'] = 'plugin_test'; + $this->expectedDefinitions['banana']['provider'] = 'plugin_test'; + + $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler, NULL); + $plugin_manager->getDefinitions(); + } + } diff --git a/core/tests/Drupal/Tests/Core/Plugin/TestPluginManager.php b/core/tests/Drupal/Tests/Core/Plugin/TestPluginManager.php index a7ea79d..c1c2d7f 100644 --- a/core/tests/Drupal/Tests/Core/Plugin/TestPluginManager.php +++ b/core/tests/Drupal/Tests/Core/Plugin/TestPluginManager.php @@ -8,6 +8,7 @@ namespace Drupal\Tests\Core\Plugin; use Drupal\Component\Plugin\Discovery\StaticDiscovery; +use Drupal\Component\Plugin\Factory\DefaultFactory; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\DefaultPluginManager; @@ -28,13 +29,16 @@ class TestPluginManager extends DefaultPluginManager { * (optional) The module handler to invoke the alter hook with. * @param string $alter_hook * (optional) Name of the alter hook. + * @param string $interface + * (optional) The interface required for the plugins. */ - public function __construct(\Traversable $namespaces, array $definitions, ModuleHandlerInterface $module_handler = NULL, $alter_hook = NULL) { + public function __construct(\Traversable $namespaces, array $definitions, ModuleHandlerInterface $module_handler = NULL, $alter_hook = NULL, $interface = NULL) { // Create the object that can be used to return definitions for all the // plugins available for this type. Most real plugin managers use a richer // discovery implementation, but StaticDiscovery lets us add some simple // mock plugins for unit testing. $this->discovery = new StaticDiscovery(); + $this->factory = new DefaultFactory($this->discovery, $interface); // Add the static definitions. foreach ($definitions as $key => $definition) {