diff --git a/core/lib/Drupal/Core/Action/ActionManager.php b/core/lib/Drupal/Core/Action/ActionManager.php index 9e5e4d9..2b4002d 100644 --- a/core/lib/Drupal/Core/Action/ActionManager.php +++ b/core/lib/Drupal/Core/Action/ActionManager.php @@ -22,6 +22,11 @@ class ActionManager extends DefaultPluginManager { /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\Core\Action\ActionInterface'; + + /** * Constructs a new class instance. * * @param \Traversable $namespaces @@ -36,8 +41,6 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac parent::__construct('Plugin/Action', $namespaces, $module_handler, 'Drupal\Core\Annotation\Action'); $this->alterInfo('action_info'); $this->setCacheBackend($cache_backend, 'action_info'); - - $this->interface = '\Drupal\Core\Action\ActionInterface'; } /** diff --git a/core/lib/Drupal/Core/Archiver/ArchiverManager.php b/core/lib/Drupal/Core/Archiver/ArchiverManager.php index b161bd9..ac11937 100644 --- a/core/lib/Drupal/Core/Archiver/ArchiverManager.php +++ b/core/lib/Drupal/Core/Archiver/ArchiverManager.php @@ -1,6 +1,7 @@ '', diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php index c3c7121..7fb48fa 100644 --- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php +++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php @@ -246,18 +246,32 @@ protected function findDefinitions() { if (isset($plugin_definition['provider']) && !in_array($plugin_definition['provider'], array('core', 'component')) && !$this->moduleHandler->moduleExists($plugin_definition['provider'])) { unset($definitions[$plugin_id]); } - if (isset($this->interface)) { - $class = $plugin_definition['class']; - if (!is_subclass_of($class, $this->interface)) { - throw new PluginException(String::format('Plugin @plugin_id in @provider should implement interface @interface', array( - '@plugin_id' => $plugin_id, - '@provider' => $plugin_definition['provider'], - '@interface' => $this->interface, - ))); - } - } + $this->enforcePluginInterface($plugin_id, $plugin_definition); } return $definitions; } + /** + * Enforces that a plugin implements the required interface. + * + * @param string $plugin_id + * @param array $plugin_definition + * + * @throws \Drupal\Component\Plugin\Exception\PluginException + */ + protected function enforcePluginInterface($plugin_id, $plugin_definition) { + // If there are multiple valid interfaces, check for at least one. + if (is_array($this->interface) && array_intersect(class_implements($plugin_definition['class']), $this->interface)) { + return; + } + elseif (is_string($this->interface) && is_subclass_of($plugin_definition['class'], $this->interface)) { + return; + } + throw new PluginException(String::format('Plugin @plugin_id in @provider should implement interface @interface', array( + '@plugin_id' => $plugin_id, + '@provider' => $plugin_definition['provider'], + '@interface' => is_array($this->interface) ? implode(', ', $this->interface) : $this->interface, + ))); + } + } diff --git a/core/lib/Drupal/Core/Render/ElementInfoManager.php b/core/lib/Drupal/Core/Render/ElementInfoManager.php index 1dd2be4..a0264d2 100644 --- a/core/lib/Drupal/Core/Render/ElementInfoManager.php +++ b/core/lib/Drupal/Core/Render/ElementInfoManager.php @@ -26,6 +26,11 @@ class ElementInfoManager extends DefaultPluginManager implements ElementInfoManagerInterface { /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\Core\Render\Element\ElementInterface'; + + /** * Stores the available element information. * * @var array diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index c9afe86..7889be1 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -395,4 +395,11 @@ public function clearCachedDefinitions() { $this->prototypes = array(); } + /** + * {@inheritdoc} + */ + protected function enforcePluginInterface($plugin_id, $plugin_definition) { + // Do not enforce an interface for typed data plugins. + } + } diff --git a/core/lib/Drupal/Core/Validation/ConstraintManager.php b/core/lib/Drupal/Core/Validation/ConstraintManager.php index a2b46d3..70adb95 100644 --- a/core/lib/Drupal/Core/Validation/ConstraintManager.php +++ b/core/lib/Drupal/Core/Validation/ConstraintManager.php @@ -138,4 +138,12 @@ public function getDefinitionsByType($type) { } return $definitions; } + + /** + * {@inheritdoc} + */ + protected function enforcePluginInterface($plugin_id, $plugin_definition) { + // Do not enforce an interface for constraint plugins. + } + } diff --git a/core/modules/aggregator/src/Plugin/AggregatorPluginManager.php b/core/modules/aggregator/src/Plugin/AggregatorPluginManager.php index 53c3acd..619e125 100644 --- a/core/modules/aggregator/src/Plugin/AggregatorPluginManager.php +++ b/core/modules/aggregator/src/Plugin/AggregatorPluginManager.php @@ -7,6 +7,8 @@ namespace Drupal\aggregator\Plugin; +use Drupal\Component\Plugin\Exception\PluginException; +use Drupal\Component\Utility\String; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\DefaultPluginManager; @@ -26,6 +28,15 @@ class AggregatorPluginManager extends DefaultPluginManager { /** + * {@inheritdoc} + */ + protected $interface = array( + 'Drupal\aggregator\Plugin\FetcherInterface', + 'Drupal\aggregator\Plugin\ParserInterface', + 'Drupal\aggregator\Plugin\ProcessorInterface', + ); + + /** * Constructs a AggregatorPluginManager object. * * @param string $type diff --git a/core/modules/block/src/BlockManager.php b/core/modules/block/src/BlockManager.php index 706af51..d86cfe9 100644 --- a/core/modules/block/src/BlockManager.php +++ b/core/modules/block/src/BlockManager.php @@ -27,6 +27,11 @@ class BlockManager extends DefaultPluginManager implements BlockManagerInterface use ContextAwarePluginManagerTrait; /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\block\BlockPluginInterface'; + + /** * An array of all available modules and their data. * * @var array diff --git a/core/modules/ckeditor/src/CKEditorPluginManager.php b/core/modules/ckeditor/src/CKEditorPluginManager.php index 289c906..c79c580 100644 --- a/core/modules/ckeditor/src/CKEditorPluginManager.php +++ b/core/modules/ckeditor/src/CKEditorPluginManager.php @@ -28,6 +28,11 @@ class CKEditorPluginManager extends DefaultPluginManager { /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\ckeditor\CKEditorPluginInterface'; + + /** * Constructs a CKEditorPluginManager object. * * @param \Traversable $namespaces diff --git a/core/modules/config_translation/src/ConfigMapperManager.php b/core/modules/config_translation/src/ConfigMapperManager.php index 8eb3735..9dee11a 100644 --- a/core/modules/config_translation/src/ConfigMapperManager.php +++ b/core/modules/config_translation/src/ConfigMapperManager.php @@ -29,6 +29,11 @@ class ConfigMapperManager extends DefaultPluginManager implements ConfigMapperManagerInterface { /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\config_translation\ConfigMapperInterface'; + + /** * The typed config manager. * * @var \Drupal\Core\Config\TypedConfigManagerInterface diff --git a/core/modules/editor/src/Plugin/EditorManager.php b/core/modules/editor/src/Plugin/EditorManager.php index 1dd6df2..332e4dc 100644 --- a/core/modules/editor/src/Plugin/EditorManager.php +++ b/core/modules/editor/src/Plugin/EditorManager.php @@ -22,6 +22,11 @@ class EditorManager extends DefaultPluginManager { /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\editor\Plugin\EditorPluginInterface'; + + /** * Constructs an EditorManager object. * * @param \Traversable $namespaces diff --git a/core/modules/entity_reference/src/Plugin/Type/SelectionPluginManager.php b/core/modules/entity_reference/src/Plugin/Type/SelectionPluginManager.php index ce5ff83..c40dde0 100644 --- a/core/modules/entity_reference/src/Plugin/Type/SelectionPluginManager.php +++ b/core/modules/entity_reference/src/Plugin/Type/SelectionPluginManager.php @@ -31,6 +31,11 @@ class SelectionPluginManager extends DefaultPluginManager { /** * {@inheritdoc} */ + protected $interface = '\Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface'; + + /** + * {@inheritdoc} + */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { $this->discovery = new AnnotatedClassDiscovery('Plugin/entity_reference/selection', $namespaces, 'Drupal\entity_reference\Annotation\EntityReferenceSelection'); diff --git a/core/modules/filter/src/FilterPluginManager.php b/core/modules/filter/src/FilterPluginManager.php index 77a3c71..650d99a 100644 --- a/core/modules/filter/src/FilterPluginManager.php +++ b/core/modules/filter/src/FilterPluginManager.php @@ -23,6 +23,11 @@ class FilterPluginManager extends DefaultPluginManager { /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\filter\Plugin\FilterInterface'; + + /** * Constructs a FilterPluginManager object. * * @param \Traversable $namespaces diff --git a/core/modules/image/src/ImageEffectManager.php b/core/modules/image/src/ImageEffectManager.php index 4885450..3d5a6c0 100644 --- a/core/modules/image/src/ImageEffectManager.php +++ b/core/modules/image/src/ImageEffectManager.php @@ -17,6 +17,11 @@ class ImageEffectManager extends DefaultPluginManager { /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\image\ImageEffectInterface'; + + /** * Constructs a new ImageEffectManager. * * @param \Traversable $namespaces diff --git a/core/modules/language/src/LanguageNegotiationMethodManager.php b/core/modules/language/src/LanguageNegotiationMethodManager.php index 681c67c..14201b7 100644 --- a/core/modules/language/src/LanguageNegotiationMethodManager.php +++ b/core/modules/language/src/LanguageNegotiationMethodManager.php @@ -17,6 +17,11 @@ class LanguageNegotiationMethodManager extends DefaultPluginManager { /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\language\LanguageNegotiationMethodInterface'; + + /** * Constructs a new LanguageNegotiationMethodManager object. * * @param \Traversable $namespaces diff --git a/core/modules/migrate/src/Plugin/MigrateEntityDestinationFieldInterface.php b/core/modules/migrate/src/Plugin/MigrateEntityDestinationFieldInterface.php index 4cefa2f..7d2696f 100644 --- a/core/modules/migrate/src/Plugin/MigrateEntityDestinationFieldInterface.php +++ b/core/modules/migrate/src/Plugin/MigrateEntityDestinationFieldInterface.php @@ -6,12 +6,13 @@ namespace Drupal\migrate\Plugin; +use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Core\Field\FieldDefinitionInterface; /** * Handle the importing of a specific configurable field type. */ -interface MigrateEntityDestinationFieldInterface { +interface MigrateEntityDestinationFieldInterface extends PluginInspectionInterface { /** * Convert an array of values into an array structure fit for entity_create. diff --git a/core/modules/migrate/src/Plugin/MigratePluginManager.php b/core/modules/migrate/src/Plugin/MigratePluginManager.php index 0ae77be..7cfe943 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; @@ -30,6 +30,17 @@ class MigratePluginManager extends DefaultPluginManager { /** + * {@inheritdoc} + */ + protected $interface = array( + 'Drupal\migrate\Plugin\MigrateDestinationInterface', + 'Drupal\migrate\Plugin\MigrateProcessInterface', + 'Drupal\migrate\Plugin\MigrateSourceInterface', + 'Drupal\migrate\Plugin\MigrateIdMapInterface', + 'Drupal\migrate\Plugin\MigrateEntityDestinationFieldInterface', + ); + + /** * Constructs a MigratePluginManager object. * * @param string $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..f5545e8 100644 --- a/core/modules/migrate_drupal/src/Plugin/MigrateLoadInterface.php +++ b/core/modules/migrate_drupal/src/Plugin/MigrateLoadInterface.php @@ -7,6 +7,7 @@ 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..1a1f881 --- /dev/null +++ b/core/modules/migrate_drupal/src/Plugin/MigratePluginManager.php @@ -0,0 +1,26 @@ +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..0024a30 100644 --- a/core/modules/views/src/Plugin/ViewsHandlerManager.php +++ b/core/modules/views/src/Plugin/ViewsHandlerManager.php @@ -20,6 +20,11 @@ class ViewsHandlerManager extends DefaultPluginManager { /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\views\Plugin\views\ViewsHandlerInterface'; + + /** * The views data cache. * * @var \Drupal\views\ViewsData @@ -74,7 +79,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..ce70426 100644 --- a/core/modules/views/src/Plugin/ViewsPluginManager.php +++ b/core/modules/views/src/Plugin/ViewsPluginManager.php @@ -20,6 +20,11 @@ class ViewsPluginManager extends DefaultPluginManager { /** + * {@inheritdoc} + */ + protected $interface = '\Drupal\views\Plugin\views\ViewsPluginInterface'; + + /** * Constructs a ViewsPluginManager object. * * @param string $type diff --git a/core/modules/views/src/Plugin/views/HandlerBase.php b/core/modules/views/src/Plugin/views/HandlerBase.php index ce31f43..ef9759d 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 @@ -332,23 +319,21 @@ protected function getModuleHandler() { } /** - * Sets the module handler. - * - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler. + * {@inheritdoc} */ public function setModuleHandler(ModuleHandlerInterface $module_handler) { $this->moduleHandler = $module_handler; } /** - * Provides the handler some groupby. + * {@inheritdoc} */ public function usesGroupBy() { return TRUE; } + /** - * Provide a form for aggregation settings. + * {@inheritdoc} */ public function buildGroupByForm(&$form, FormStateInterface $form_state) { $display_id = $form_state['display_id']; @@ -373,94 +358,89 @@ public function buildGroupByForm(&$form, FormStateInterface $form_state) { } /** - * Perform any necessary changes to the form values prior to storage. - * There is no need for this function to actually store the data. + * {@inheritdoc} */ public function submitGroupByForm(&$form, FormStateInterface $form_state) { $form_state['handler']->options['group_type'] = $form_state->getValue(array('options', 'group_type')); } /** - * If a handler has 'extra options' it will get a little settings widget and - * another form called extra_options. + * {@inheritdoc} */ public function hasExtraOptions() { return FALSE; } /** - * Provide defaults for the handler. + * {@inheritdoc} */ public function defineExtraOptions(&$option) { } /** - * Provide a form for setting options. + * {@inheritdoc} */ public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) { } /** - * Validate the options form. + * {@inheritdoc} */ public function validateExtraOptionsForm($form, FormStateInterface $form_state) { } /** - * Perform any necessary changes to the form values prior to storage. - * There is no need for this function to actually store the data. + * {@inheritdoc} */ public function submitExtraOptionsForm($form, FormStateInterface $form_state) { } /** - * Determine if a handler can be exposed. + * {@inheritdoc} */ public function canExpose() { return FALSE; } /** - * Set new exposed option defaults when exposed setting is flipped - * on. + * {@inheritdoc} */ public function defaultExposeOptions() { } /** - * Get information about the exposed form for the form renderer. + * {@inheritdoc} */ public function exposedInfo() { } /** - * Render our chunk of the exposed handler form when selecting + * {@inheritdoc} */ public function buildExposedForm(&$form, FormStateInterface $form_state) { } /** - * Validate the exposed handler form + * {@inheritdoc} */ public function validateExposed(&$form, FormStateInterface $form_state) { } /** - * Submit the exposed handler form + * {@inheritdoc} */ public function submitExposed(&$form, FormStateInterface $form_state) { } /** - * Form for exposed handler options. + * {@inheritdoc} */ public function buildExposeForm(&$form, FormStateInterface $form_state) { } /** - * Validate the options form. + * {@inheritdoc} */ public function validateExposeForm($form, FormStateInterface $form_state) { } /** - * Perform any necessary changes to the form exposes prior to storage. - * There is no need for this function to actually store the data. + * {@inheritdoc} */ public function submitExposeForm($form, FormStateInterface $form_state) { } /** - * Shortcut to display the expose/hide button. + * {@inheritdoc} */ public function showExposeButton(&$form, FormStateInterface $form_state) { } /** - * Shortcut to display the exposed options form. + * {@inheritdoc} */ public function showExposeForm(&$form, FormStateInterface $form_state) { if (empty($this->options['exposed'])) { @@ -483,10 +463,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 +477,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 +504,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 +533,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,48 +543,39 @@ public function ensureMyTable() { } /** - * Provide text for the administrative summary. + * {@inheritdoc} */ public function adminSummary() { } /** - * Determine if this item is 'exposed', meaning it provides form elements - * to let users modify the view. - * - * @return TRUE/FALSE + * {@inheritdoc} */ public function isExposed() { return !empty($this->options['exposed']); } /** - * Returns TRUE if the exposed filter works like a grouped filter. + * {@inheritdoc} */ public function isAGroup() { return FALSE; } /** - * Define if the exposed input has to be submitted multiple times. - * This is TRUE when exposed filters grouped are using checkboxes as - * widgets. + * {@inheritdoc} */ public function multipleExposedInput() { return FALSE; } /** - * Take input from exposed handlers and assign to this handler, if necessary. + * {@inheritdoc} */ public function acceptExposedInput($input) { return TRUE; } /** - * If set to remember exposed input in the session, store it there. + * {@inheritdoc} */ 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,44 +594,26 @@ 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; } /** - * Creates cross-database SQL date formatting. - * - * @param string $format - * A format string for the result, like 'Y-m-d H:i:s'. - * - * @return string - * An appropriate SQL string for the DB type and field type. + * {@inheritdoc} */ public function getDateFormat($format) { return $this->query->getDateFormat($this->getDateField(), $format); } /** - * Creates cross-database SQL dates. - * - * @return string - * An appropriate SQL string for the db type and field type. + * {@inheritdoc} */ public function getDateField() { return $this->query->getDateField("$this->tableAlias.$this->realField"); @@ -692,24 +633,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 +676,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 +697,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; @@ -811,7 +728,7 @@ public static function breakString($str, $force_int = FALSE) { } /** - * Displays the Expose form. + * {@inheritdoc} */ public function displayExposedForm($form, FormStateInterface $form_state) { $item = &$this->options; @@ -834,8 +751,7 @@ public function displayExposedForm($form, FormStateInterface $form_state) { } /** - * A submit handler that is used for storing temporary items when using - * multi-step changes, such as ajax requests. + * {@inheritdoc} */ public function submitTemporaryForm($form, FormStateInterface $form_state) { // Run it through the handler's submit function. diff --git a/core/modules/views/src/Plugin/views/PluginBase.php b/core/modules/views/src/Plugin/views/PluginBase.php index 132ceec..ffc8b23 100644 --- a/core/modules/views/src/Plugin/views/PluginBase.php +++ b/core/modules/views/src/Plugin/views/PluginBase.php @@ -41,7 +41,7 @@ * * @ingroup views_plugins */ -abstract class PluginBase extends ComponentPluginBase implements ContainerFactoryPluginInterface { +abstract class PluginBase extends ComponentPluginBase implements ContainerFactoryPluginInterface, ViewsPluginInterface { /** * Options for this plugin will be held here. @@ -100,14 +100,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; @@ -163,8 +156,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)) { @@ -203,19 +195,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 @@ -226,47 +213,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. @@ -277,39 +258,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(); @@ -333,12 +296,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(); @@ -369,19 +327,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) { @@ -400,17 +346,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) { @@ -428,12 +364,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..45181e6 --- /dev/null +++ b/core/modules/views/src/Plugin/views/ViewsHandlerInterface.php @@ -0,0 +1,312 @@ +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 31f30bc..9a3b7bf 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/Tests/Handler/HandlerTest.php b/core/modules/views/src/Tests/Handler/HandlerTest.php index 9c9e038..b182dee 100644 --- a/core/modules/views/src/Tests/Handler/HandlerTest.php +++ b/core/modules/views/src/Tests/Handler/HandlerTest.php @@ -204,16 +204,14 @@ public function testHandlerWeights() { $loaded_order = array_keys($view->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/Core/Plugin/DefaultPluginManagerTest.php b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php index c52b5cb..c337533 100644 --- a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php @@ -78,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'); } @@ -103,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'); } @@ -112,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')); } @@ -131,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')); @@ -155,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()); @@ -179,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()); @@ -203,7 +203,7 @@ 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(); @@ -213,6 +213,7 @@ public function testCacheClearWithTags() { * Tests plugins with the proper interface. * * @covers ::getDefinitions + * @covers ::enforcePluginInterface */ public function testGetDefinitionsWithJustValidInterfaces() { $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); @@ -226,9 +227,10 @@ public function testGetDefinitionsWithJustValidInterfaces() { * Tests plugins without the proper interface. * * @covers ::getDefinitions + * @covers ::enforcePluginInterface * * @expectedException \Drupal\Component\Plugin\Exception\PluginException - * @expectedExceptionMessage Plugin cherry in plugin_test should implement interface \Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface + * @expectedExceptionMessage Plugin kale in plugin_test should implement interface \Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface */ public function testGetDefinitionsWithInvalidInterfaces() { $module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); @@ -238,11 +240,11 @@ public function testGetDefinitionsWithInvalidInterfaces() { ->with('plugin_test') ->willReturn(FALSE); - $this->expectedDefinitions['cherry'] = array( - 'id' => 'cherry', - 'label' => 'Cherry', - 'color' => 'red', - 'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Cherry', + $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';