diff --git a/core/lib/Drupal/Component/Annotation/Plugin.php b/core/lib/Drupal/Component/Annotation/Plugin.php index 115e94b77a60c1d5fb057fbae4ad04b4bb6c4634..044043410d8972f1e42fa018fac951aeda317cd6 100644 --- a/core/lib/Drupal/Component/Annotation/Plugin.php +++ b/core/lib/Drupal/Component/Annotation/Plugin.php @@ -18,6 +18,8 @@ * of a class to be located with the class itself, rather than in module-based * info hooks. * + * @ingroup plugin_api + * * @Annotation */ class Plugin implements AnnotationInterface { diff --git a/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php b/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php index 23311b6d06931d2e0446b640c7856a4960dbb349..2b095c1e1cc2a70c8d9b88327598745dd3b955ed 100644 --- a/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php +++ b/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php @@ -9,6 +9,8 @@ /** * Provides an interface for a configurable plugin. + * + * @ingroup plugin_api */ interface ConfigurablePluginInterface { diff --git a/core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php b/core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php index 2d1aa8a6b67b164f95019cd51055bfd05e8662ab..f29119da6f8f1980f617d60fb2827ad0359c5551 100644 --- a/core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php +++ b/core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php @@ -14,6 +14,8 @@ * * Context aware plugins can specify an array of context definitions keyed by * context name at the plugin definition under the "context" key. + * + * @ingroup plugin_api */ interface ContextAwarePluginInterface extends PluginInspectionInterface { diff --git a/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php b/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php index b32438fd675a73b21d2224b81259411da2fc09b4..e4b92b0a1e5df46092dc9dac0c57c156f902a088 100644 --- a/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php +++ b/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php @@ -9,6 +9,8 @@ /** * Plugin interface for derivative plugin handling. + * + * @ingroup plugin_api */ interface DerivativeInterface { diff --git a/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryInterface.php b/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryInterface.php index d7e0798e45d0d4a3677c86f72c30e6b73f1408d1..5b44bf93bfce06bf2e5fad1e1e72d640a8c7f4ca 100644 --- a/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryInterface.php +++ b/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryInterface.php @@ -10,6 +10,8 @@ /** * An interface defining the minimum requirements of building a plugin * discovery component. + * + * @ingroup plugin_api */ interface DiscoveryInterface { diff --git a/core/lib/Drupal/Component/Plugin/PluginBag.php b/core/lib/Drupal/Component/Plugin/PluginBag.php index 9631e22cc0c1c7e0e698b2d94f7cfa67e5617808..2625201a9c827da98c96966444658fa87e478db1 100644 --- a/core/lib/Drupal/Component/Plugin/PluginBag.php +++ b/core/lib/Drupal/Component/Plugin/PluginBag.php @@ -9,6 +9,8 @@ /** * Defines an object which stores multiple plugin instances to lazy load them. + * + * @ingroup plugin_api */ abstract class PluginBag implements \Iterator, \Countable { diff --git a/core/lib/Drupal/Component/Plugin/PluginInspectionInterface.php b/core/lib/Drupal/Component/Plugin/PluginInspectionInterface.php index 925c01565275f81782a3c5c2aeb0ac49cfe842a3..64a196c29cb818e75525095c686ca680e4e77e24 100644 --- a/core/lib/Drupal/Component/Plugin/PluginInspectionInterface.php +++ b/core/lib/Drupal/Component/Plugin/PluginInspectionInterface.php @@ -11,6 +11,8 @@ * * This interface provides some simple tools for code receiving a plugin to * interact with the plugin system. + * + * @ingroup plugin_api */ interface PluginInspectionInterface { diff --git a/core/lib/Drupal/Component/Plugin/PluginManagerInterface.php b/core/lib/Drupal/Component/Plugin/PluginManagerInterface.php index ec82dc35e6a1f5f980be94cad426ca8523575885..803682a321e677ee5f2505314bbf4af791df49b2 100644 --- a/core/lib/Drupal/Component/Plugin/PluginManagerInterface.php +++ b/core/lib/Drupal/Component/Plugin/PluginManagerInterface.php @@ -26,6 +26,8 @@ * class, which contains the proxying logic. * * @see \Drupal\Component\Plugin\PluginManagerBase + * + * @ingroup plugin_api */ interface PluginManagerInterface extends DiscoveryInterface, FactoryInterface, MapperInterface { } diff --git a/core/lib/Drupal/Core/Entity/EntityWithPluginBagsInterface.php b/core/lib/Drupal/Core/Entity/EntityWithPluginBagsInterface.php index a111c73b13c7fb9cefffa068bc828905218d322f..96eee073f6451585d217ed9af64623ce11e2f64c 100644 --- a/core/lib/Drupal/Core/Entity/EntityWithPluginBagsInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityWithPluginBagsInterface.php @@ -11,6 +11,8 @@ * Provides an interface for an object utilizing a plugin bag. * * @see \Drupal\Component\Plugin\PluginBag + * + * @ingroup plugin_api */ interface EntityWithPluginBagsInterface extends EntityInterface { diff --git a/core/lib/Drupal/Core/Executable/ExecutableInterface.php b/core/lib/Drupal/Core/Executable/ExecutableInterface.php index 30450c0966793b273b7cbedd7d28b288a5aac861..36fbd518d6492e1050602da413cc95f2361009cd 100644 --- a/core/lib/Drupal/Core/Executable/ExecutableInterface.php +++ b/core/lib/Drupal/Core/Executable/ExecutableInterface.php @@ -9,6 +9,8 @@ /** * An interface for executable plugins. + * + * @ingroup plugin_api */ interface ExecutableInterface { diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php index 4f426cc776d7e1e6f3ed486a40f319c1be5ad7e5..4059e100e5993d334ca8dd1b559fd092fb10fe85 100644 --- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php +++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php @@ -23,6 +23,8 @@ /** * Base class for plugin managers. + * + * @ingroup plugin_api */ class DefaultPluginManager extends PluginManagerBase implements PluginManagerInterface, CachedDiscoveryInterface { diff --git a/core/lib/Drupal/Core/Plugin/PluginBase.php b/core/lib/Drupal/Core/Plugin/PluginBase.php index daaf99acc64c5941ea0556be5d95042d5fc01990..1af9b82394ae7cdfc7f704065ccbfc636e895237 100644 --- a/core/lib/Drupal/Core/Plugin/PluginBase.php +++ b/core/lib/Drupal/Core/Plugin/PluginBase.php @@ -13,6 +13,8 @@ /** * Base class for plugins supporting metadata inspection and translation. + * + * @ingroup plugin_api */ abstract class PluginBase extends ComponentPluginBase { use StringTranslationTrait; diff --git a/core/lib/Drupal/Core/Plugin/PluginFormInterface.php b/core/lib/Drupal/Core/Plugin/PluginFormInterface.php index 9ca47e01d692e1e3451c68ea8e1613341e8abf6f..daceeacd260f1fc0398836a7411fc5c3e35b7fa7 100644 --- a/core/lib/Drupal/Core/Plugin/PluginFormInterface.php +++ b/core/lib/Drupal/Core/Plugin/PluginFormInterface.php @@ -9,6 +9,8 @@ /** * Provides an interface for a plugin that contains a form. + * + * @ingroup plugin_api */ interface PluginFormInterface { diff --git a/core/modules/search/search.module b/core/modules/search/search.module index ce71ab5112fb5acb1f951f2182787934bc26e7c0..a59dcc2dff7e90bb2942b8afa2a34ef24e39958f 100644 --- a/core/modules/search/search.module +++ b/core/modules/search/search.module @@ -551,12 +551,7 @@ function search_mark_for_reindex($type, $sid) { * data. Most of the system is handled by the Search module, so this must be * enabled for all of the search features to work. * - * To be discovered, the plugins must implement - * \Drupal\search\Plugin\SearchInterface and be annotated as - * \Drupal\search\Annotation\SearchPlugin plugins. Defining a plugin will allow - * administrators to set up one or more search pages using this plugin. - * - * There are three ways to interact with the search system: + * There are two ways to interact with the search system: * - Specifically for searching nodes, you can implement * hook_node_update_index() and hook_node_search_result(). However, note that * the search system already indexes all visible output of a node; i.e., @@ -569,12 +564,16 @@ function search_mark_for_reindex($type, $sid) { * Each of these corresponds to a tab on the /search page, which can be * used to perform searches. You will also need to implement the execute() * method from the interface to perform the search. A base class is provided - * in \Drupal\search\Plugin\SearchPluginBase. + * in \Drupal\search\Plugin\SearchPluginBase. For more information about + * plugins, see the @link plugin_api Plugin API topic. @endlink * * If your module needs to provide a more complicated search form, then you * need to implement it yourself. In that case, you may wish to define it as a * local task (tab) under the /search page (e.g. /search/mymodule) so that users * can easily find it. + * + * @see plugin_api + * @see annotation */ /** diff --git a/core/modules/system/core.api.php b/core/modules/system/core.api.php index 5dabffe6f02d68bb2cfac01e3f37f166f2d95932..ef0c0a1ce80dc05ed741255ff32f1b42a147530d 100644 --- a/core/modules/system/core.api.php +++ b/core/modules/system/core.api.php @@ -41,6 +41,7 @@ * * @section other_essentials Other essential APIs * + * - @link plugin_api Plugins @endlink * - @link i18n Internationalization @endlink * - @link cache Caching @endlink * - @link utility Utility classes and functions @endlink @@ -287,7 +288,7 @@ * * @section define Defining an entity type * Entity types are defined by modules, using Drupal's Plugin API (see the - * @link plugins Plugin API topic @endlink for more information about plugins + * @link plugin_api Plugin API topic @endlink for more information about plugins * in general). Here are the steps to follow to define a new entity type: * - Choose a unique machine name, or ID, for your entity type. This normally * starts with (or is the same as) your module's machine name. It should be @@ -986,7 +987,7 @@ * See the @link hooks Hooks topic @endlink for more information. * - Plugins: Classes that a module defines, which are discovered and * instantiated at specific times to add functionality. See the - * @link plugins Plugin API topic @endlink for more information. + * @link plugin_api Plugin API topic @endlink for more information. * - Entities: Special plugins that define entity types for storing new types * of content or configuration in Drupal. See the * @link entity_api Entity API topic @endlink for more information. @@ -1001,17 +1002,189 @@ */ /** - * @defgroup plugins Plugin API + * @defgroup plugin_api Plugin API * @{ - * Overview of the Plugin API + * Using the Plugin API * - * @todo write this - * - * Additional documentation paragraphs need to be written, and functions, - * classes, and interfaces need to be added to this topic. + * @section sec_overview Overview and terminology + + * The basic idea of plugins is to allow a particular module or subsystem of + * Drupal to provide functionality in an extensible, object-oriented way. The + * controlling module or subsystem defines the basic framework (interface) for + * the functionality, and other modules can create plugins (implementing the + * interface) with particular behaviors. The controlling module instantiates + * existing plugins as needed, and calls methods to invoke their functionality. + * Examples of functionality in Drupal Core that use plugins include: the block + * system (block types are plugins), the entity/field system (entity types, + * field types, field formatters, and field widgets are plugins), the image + * manipulation system (image effects and image toolkits are plugins), and the + * search system (search page types are plugins). + * + * Plugins are grouped into plugin types, each generally defined by an + * interface. Each plugin type is managed by a plugin manager service, which + * uses a plugin discovery method to discover provided plugins of that type and + * instantiate them using a plugin factory. + * + * Some plugin types make use of the following concepts or components: + * - Plugin derivatives: Allows a single plugin class to present itself as + * multiple plugins. Example: the Menu module provides a block for each + * defined menu via a block plugin derivative. + * - Plugin mapping: Allows a plugin class to map a configuration string to an + * instance, and have the plugin automatically instantiated without writing + * additional code. + * - Plugin bags: Provide a way to lazily instantiate a set of plugin + * instances from a single plugin definition. + * + * There are several things a module developer may need to do with plugins: + * - Define a completely new plugin type: see @ref sec_define below. + * - Create a plugin of an existing plugin type: see @ref sec_create below. + * - Perform tasks that involve plugins: see @ref sec_use below. + * + * See https://drupal.org/developing/api/8/plugins for more detailed + * documentation on the plugin system. There are also topics for a few + * of the many existing types of plugins: + * - @link block_api Block API @endlink + * - @link entity_api Entity API @endlink + * - @link field Various types of field-related plugins @endlink + * - @link views_plugins Views plugins @endlink (has links to topics covering + * various specific types of Views plugins). + * - @link search Search page plugins @endlink + * + * @section sec_define Defining a new plugin type + * To define a new plugin type: + * - Define an interface for the plugin. This describes the common set of + * behavior, and the methods you will call on each plugin class that is + * instantiated. Usually this interface will extend one or more of the + * following interfaces: + * - \Drupal\Component\Plugin\PluginInspectionInterface + * - \Drupal\Component\Plugin\ConfigurablePluginInterface + * - \Drupal\Component\Plugin\ContextAwarePluginInterface + * - \Drupal\Core\Plugin\PluginFormInterface + * - \Drupal\Core\Executable\ExecutableInterface + * - (optional) Create a base class that provides a partial implementation of + * the interface, for the convenience of developers wishing to create plugins + * of your type. The base class usually extends + * \Drupal\Core\Plugin\PluginBase, or one of the base classes that extends + * this class. + * - Choose a method for plugin discovery, and define classes as necessary. + * See @ref sub_discovery below. + * - Create a plugin manager/factory class and service, which will discover and + * instantiate plugins. See @ref sub_manager below. + * - Use the plugin manager to instantiate plugins. Call methods on your plugin + * interface to perform the tasks of your plugin type. + * - (optional) If appropriate, define a plugin bag. See @ref sub_bag below + * for more information. * - * See https://drupal.org/developing/api/8/plugins and links therein for - * references. This should be an overview and link to details. + * @subsection sub_discovery Plugin discovery + * Plugin discovery is the process your plugin manager uses to discover the + * individual plugins of your type that have been defined by your module and + * other modules. Plugin discovery methods are classes that implement + * \Drupal\Component\Plugin\Discovery\DiscoveryInterface. Most plugin types use + * one of the following discovery mechanisms: + * - Annotation: Plugin classes are annotated and placed in a defined namespace + * subdirectory. Most Drupal Core plugins use this method of discovery. + * - Hook: Plugin modules need to implement a hook to tell the manager about + * their plugins. + * - YAML: Plugins are listd in YAML files. Drupal Core uses this method for + * discovering local tasks and local actions. This is mainly useful if all + * plugins use the same class, so it is kind of like a global derivative. + * - Static: Plugin classes are registered within the plugin manager class + * itself. Static discovery is only useful if modules cannot define new + * plugins of this type (if the list of available plugins is static). + * + * It is also possible to define your own custom discovery mechanism or mix + * methods together. And there are many more details, such as annotation + * decorators, that apply to some of the discovery methods. See + * https://drupal.org/developing/api/8/plugins for more details. + * + * The remainder of this documentation will assume Annotation-based discovery, + * since this is the most common method. + * + * @subsection sub_manager Defining a plugin manager class and service + * To define an annotation-based plugin manager: + * - Choose a namespace subdirectory for your plugin. For example, search page + * plugins go in directory Plugin/Search under the module namespace. + * - Define an annotation class for your plugin type. This class should extend + * \Drupal\Component\Annotation\Plugin, and for most plugin types, it should + * contain member variables corresponding to the annotations plugins will + * need to provide. All plugins have at least $id: a unique string + * identifier. + * - Define an alter hook for altering the discovered plugin definitions. You + * should document the hook in a *.api.php file. + * - Define a plugin manager class. This class should implement + * \Drupal\Component\Plugin\PluginManagerInterface; most plugin managers do + * this by extending \Drupal\Core\Plugin\DefaultPluginManager. If you do + * extend the default plugin manager, the only method you will probably need + * to define is the class constructor, which will need to call the parent + * constructor to provide information about the annotation class and plugin + * namespace for discovery, set up the alter hook, and possibly set up + * caching. See classes that extend DefaultPluginManager for examples. + * - Define a service for your plugin manager. See the + * @link container Services topic for more information. @endlink Your service + * definition should look something like this, referencing your manager + * class and the parent (default) plugin manager service to inherit + * constructor arguments: + * @code + * plugin.manager.mymodule: + * class: Drupal\mymodule\MyPluginManager + * parent: default_plugin_manager + * @endcode + * - If your plugin is configurable, you will also need to define the + * configuration schema and possibly a configuration entity type. See the + * @link config_api Configuration API topic @endlink for more information. + * + * @subsection sub_bag Defining a plugin bag + * Some configurable plugin types allow administrators to create zero or more + * instances of each plugin, each with its own configuration. For example, + * a single block plugin can be configured several times, to display in + * different regions of a theme, with different visibility settings, a + * different title, or other plugin-specific settings. To make this possible, + * a plugin type can make use of what's known as a plugin bag. + * + * A plugin bag is a class that extends \Drupal\Component\Plugin\PluginBag or + * one of its subclasses; there are several examples in Drupal Core. If your + * plugin type uses a plugin bag, it will usually also have a configuration + * entity, and the entity class should implement + * \Drupal\Core\Entity\EntityWithPluginBagsInterface. Again, + * there are several examples in Drupal Core; see also the + * @link config_api Configuration API topic @endlink for more information about + * configuration entities. + * + * @section sec_create Creating a plugin of an existing type + * Assuming the plugin type uses annotation-based discovery, in order to create + * a plugin of an existing type, you will be creating a class. This class must: + * - Implement the plugin interface, so that it has the required methods + * defined. Usually, you'll want to extend the plugin base class, if one has + * been provided. + * - Have the right annotation in its documentation header. See the + * @link annotation Annotation topic @endlink for more information about + * annotation. + * - Be in the right plugin namespace, in order to be discovered. + * Often, the easiest way to make sure this happens is to find an existing + * example of a working plugin class of the desired type, and copy it into your + * module as a starting point. + * + * You can also create a plugin derivative, which allows your plugin class + * to present itself to the user interface as multiple plugins. To do this, + * in addition to the plugin class, you'll need to create a separate plugin + * derivative class implementing + * \Drupal\Component\Plugin\Derivative\DerivativeInterface. The classes + * \Drupal\system\Plugin\Block\SystemMenuBlock (plugin class) and + * \Drupal\system\Plugin\Derivative\SystemMenuBlock (derivative class) are a + * good example to look at. + * + * @sec sec_use Performing tasks involving plugins + * Here are the steps to follow to perform a task that involves plugins: + * - Locate the machine name of the plugin manager service, and instantiate the + * service. See the @link container Services topic @endlink for more + * information on how to do this. + * - On the plugin manager class, use methods like getDefinition(), + * getDefinitions(), or other methods specific to particular plugin managers + * to retrieve information about either specific plugins or the entire list of + * defined plugins. + * - Call the createInstance() method on the plugin manager to instantiate + * individual plugin objects. + * - Call methods on the plugin objects to perform the desired tasks. * * @see annotation * @} diff --git a/core/modules/views/views.api.php b/core/modules/views/views.api.php index ecc9f723ecaa1517747f4ec325626e7f7813321c..7f87fa9c2e8cb346a91e2614d03ef6b63210b043 100644 --- a/core/modules/views/views.api.php +++ b/core/modules/views/views.api.php @@ -12,7 +12,8 @@ * * Views plugins are objects that are used to build and render the view. * Plugins are registered by extending one of the Views base plugin classes - * and defining settings in the plugin annotation. + * and defining settings in the plugin annotation. For more information about + * plugins, see the @link plugin_api Plugin API topic. @endlink * * Views has the following types of plugins: * - Access: Access plugins are responsible for controlling access to the @@ -83,7 +84,6 @@ * \Drupal\views\Plugin\views\style\StylePluginBase. * * @todo Add an explanation for each type of handler. - * @todo Document how to use annotations and what goes in them. * @todo Add @ingroup to all the base plugins for this group. * @todo Add a separate @ingroup for all plugins? * @todo Document specific options on the appropriate plugin base classes. @@ -91,6 +91,8 @@ * * @see \Drupal\views\Plugin\views\PluginBase * @see \Drupal\views\Plugin\views\HandlerBase + * @see plugin_api + * @see annotation */ /**