
drush generate plugin:manager walk-through
When creating a custom Drupal plugin manager the "drush generate plugin:manager" command is helpful in creating correctly structured boilerplate code for you.
This continues from last week's article, How to create a custom Drupal plugin. I recommend reading that first to understand the purpose of the files that will be generated. I will also be making reference back to the example module and files in those code snippets.
Setup
Obviously you will need to have Drush installed on your Drupal website to use this command, in most cases all you need is to run composer require drush/drush
but otherwise I suggest reading Installing and Upgrading on drush.org.
Then simply run drush generate plugin:manager
The plugin-manager generator will then ask a number of questions to correctly name and locate the necessary boilerplate files additions and updates.
Module Machine Name
$ drush generate plugin:manager
Welcome to plugin-manager generator!
––––––––––––––––––––––––––––––––––––––
Module machine name:
➤
As you can see above, the first question asks for the machine name of the module within which the plugin manager will be defined. The module must already exist and be enabled before you run the command, so perhaps look into using the "drush generate module" command if you require a new custom module. I have written a walk-through article for this command and cheat-sheet-style details can also be found in my new Reference section.
Note that this is the machine name of the module which might be different from the human-readable name. For example, if you were adding a plugin manager to the "Chaos Tools" module, the machine name would be "ctools". The generate command helpfully attempts to autocomplete the machine name so you may only need to type a few characters before pressing enter. In the code snippets of the previous article, the module machine name was "my_module".
Plugin Type
Module machine name:
➤ my_module
Plugin type [my_module]:
➤
Next you need to provide a name for the plugin type you are creating. The generator command offers the module name as a default that can be accepted by simply pressing Enter. Sometimes the module name is a suitable name for the plugin type (e.g. the Token Modifier module), but other times you may wish to change the name, especially if the module is likely to provide multiple plugin types.
Bear in mind that the name of the plugin type will be used in various file names. To match the code snippets of the previous article I will call my plugin type "my_plugin". This results in files being generated with names including:
- MyPluginInterface.php
- MyPluginPluginBase.php
- MyPluginPluginManager
(with hindsight, perhaps it is better to not include the word "plugin" in the name of the plugin type)
Discovery Type
Module machine name:
➤ my_module
Plugin type [my_module]:
➤ my_plugin
Discovery type [Annotation]:
[1] Annotation
[2] Attribute
[3] YAML
[4] Hook
➤
The third and final question is what type of discovery to use. Choose [2] Attribute, unless you have good reason not to, because since Drupal 10.2.0, plugins should be defined with PHP attributes (see Attribute-based plugins on drupal.org.
Files
Having answered all three questions you are presented with a list of the files that have been created (or updated):
The following directories and files have been created or updated:
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
• /web/modules/custom/my_module/my_module.services.yml
• /web/modules/custom/my_module/src/MyPluginInterface.php
• /web/modules/custom/my_module/src/MyPluginPluginBase.php
• /web/modules/custom/my_module/src/MyPluginPluginManager.php
• /web/modules/custom/my_module/src/Attribute/MyPlugin.php
• /web/modules/custom/my_module/src/Plugin/MyPlugin/Foo.php
For an in-depth guide to the files needed for a custom plugin type refer to last week's article, How to create a custom Drupal plugin. Here is a brief rundown including some simple changes you may want to make:
Services
services:
plugin.manager.my_plugin:
class: Drupal\my_module\MyPluginPluginManager
parent: default_plugin_manager
If the .services.yml file for the module does not already exist then it is created. The plugin manager is registered as a service. There is no need to make any changes here for a simple plugin type.
Interface
interface MyPluginInterface {
public function label(): string;
}
The plugin interface is created including an example method label(). I would recommend removing this method to restrict your plugin code to only necessary methods (unless you happen to need a label() method). It is highly likely that there are methods and properties that all instances of the plugin type should include - these should be defined here.
PluginBase
abstract class MyPluginPluginBase extends PluginBase implements MyPluginInterface {
public function label(): string {
return (string) $this->pluginDefinition['label'];
}
}
The plugin base is created including and example method label(), in the same way as the interface. Remove this method unless you require it. This is where you define functionality that is common across all plugins of this type.
The label() method demonstrates a handy feature for accessing values in the plugin Attribute using $this->pluginDefinition['label']
where 'label' is the name of an attribute parameter.
Plugin Manager
All of the necessary code for the plugin manager is auto-generated; there is no need to make any changes here for a simple plugin type.
Attribute
The attribute file is created including the required $id parameter and a couple of suggested parameters: $label and $description. Do not remove the $id parameter, but the optional parameters can be removed as required. If you wish to include additional required parameters then replicate $id and if you wish to include additional optional parameters then replicate $description.
Example Plugin
#[MyPlugin(
id: 'foo',
label: new TranslatableMarkup('Foo'),
description: new TranslatableMarkup('Foo description.'),
)]
final class Foo extends MyPluginPluginBase {
}
The plugin manager generator also creates an example plugin of this new type. This demonstrates the required file location of any plugins of this type and the required content, particularly the attribute.
It is highly unlikely that you want a plugin called "Foo" so rename this file and update the class name and attribute details accordingly.
Command Options
It is possible to use the command with three "--answer" options, now that we know the three inputs required for the plugin manager generator, as follows:
drush generate plugin:manager \
--answer=my_module \
--answer=my_plugin \
--answer=Attribute
Reference
Details of this command can be found in my new Reference section.
Note that the details of this article are based on Drush 13.x (tested on Drush 13.6.2). Be aware that the questions (and their order) could differ in past and future versions of Drush.