Quantcast
Viewing all articles
Browse latest Browse all 8

D8 Plugin types (plugin managers)

The plugin manager is the central controlling class that defines how the plugins of a particular type will be discovered and instantiated. This class is called directly in any module wishing to invoke a plugin type.

This documentation will require an understanding of PSR-0.

Defining the Plugin Manager

There are only two requirements for defining a new plugin manager:

  1. You must define a discovery method.
  2. You must define a factory.

Everything else within the plugin system is situational and based upon your use case. For this plugin type, we will use the hook discovery and the default factory.

<?php
namespace Drupal\components\Plugin\Manager;

use
Drupal\Component\Plugin\PluginManagerBase;
use
Drupal\Core\Plugin\Discovery\HookDiscovery;
use
Drupal\Component\Plugin\Factory\DefaultFactory;

/**
* Defines the plugin manager for Components plugins.
*/
class ComponentsPluginManagerBase extends PluginManagerBase {

 
/**
   * Constructs a new Components plugin manager object.
  */
 
public function __construct() {
   
$this->discovery = new HookDiscovery('component_info');
   
$this->factory = new DefaultFactory($this);
  }
}
?>

This plugin type tells the system we'll be asking Drupal for any available hook_component_info() implementations and using that as our basic discovery methodology. We then tell it we'll be using the DefaultFactory class to instantiate our plugins.

Note that DefaultFactory class expects the first parameter to be a DiscoveryInterface implementation, but we've passed it a PluginManagerBase-extending class. This is the right thing to do in most use cases for the following reasons:

  • The PluginManagerBaseInterface (which the PluginManagerBase class implements) actually extends DiscoveryInterface, FactoryInterface and MapperInterface so it will work for any type-hinted parameters that expect any of these interfaces.
  • The plugin type actually proxies the methods defined by all of these interfaces and adds some additional logic on them for the more robust use cases.

Each factory can define its own constructor as necessary since FactoryInterface does not define a __construct() method. For developers writing custom Factories this can be very helpful.

Discovery Decorators

In example above we find all implementations of hook_component_info() to discover all our plugins. But usually we also expect to have hook_component_info_alter() to be able to alter already declared plugins. This is where Discovery Decorators take their role. This is a mechanism to wrap Discovery class and modify its behavior.

For example here is plugin manager constructor of entities:

<?php
/**
   * Constructs a new Entity plugin manager.
   *
   * @param array $namespaces
   *   An array of paths keyed by it's corresponding namespaces.
   */
 
public function __construct(array $namespaces) {
   
// Allow the plugin definition to be altered by hook_entity_info_alter().
   
$annotation_namespaces = array(
     
'Drupal\Core\Entity\Annotation'=> DRUPAL_ROOT . '/core/lib',
    );
   
$this->discovery = new AnnotatedClassDiscovery('Core', 'Entity', $namespaces, $annotation_namespaces, 'Drupal\Core\Entity\Annotation\EntityType');
   
$this->discovery = new InfoHookDecorator($this->discovery, 'entity_info');
   
$this->discovery = new AlterDecorator($this->discovery, 'entity_info');
   
$this->discovery = new CacheDecorator($this->discovery, 'entity_info:'. language(LANGUAGE_TYPE_INTERFACE)->langcode, 'cache', CacheBackendInterface::CACHE_PERMANENT, array('entity_info'=> TRUE));

   
$this->factory = new DefaultFactory($this->discovery);
  }
?>

As you can see after retrieving all plugins using AnnotatedClassDiscovery we wrap it with three decorators (InfoHookDecorator -- invokes hook_entity_info(), AlterDecorator -- invokes hook_entity_info_alter() and CacheDecorator does caching

Using the Plugin Manager:

Assuming that our plugin type is all wired up, using it becomes fairly easy. First we must invoke the plugin class:

<?php
use Drupal\components\Plugin\Type\ComponentsPluginManagerBase;

$type = new ComponentsPluginManagerBase();
?>

Get a list of available plugins:

<?php
$plugin_definitions
= $type->getDefinitions();
?>

Get a specific plugin:

<?php
$plugin_definition
= $type->getDefinition('plugin_id');
?>

Create a preconfigured instance of a plugin:

<?php
$plugin
= $type->createInstance('plugin_id', array('of'=> 'configuration values'));
?>

Viewing all articles
Browse latest Browse all 8

Trending Articles