Change record status: 
Project: 
Introduced in branch: 
9.3.x
Introduced in version: 
9.3.0
Description: 

Some plugins have associated twig templates, such as Help Topics (the topic body is written in Twig) and Layouts (the layout is defined in a Twig template). It is now possible to put plugin meta-data into the Twig Template using YAML-based FrontMatter, and use the new \Drupal\Core\Plugin\Discovery\TemplateDiscovery class for plugin discovery, rather than putting the meta-data into a separate YAML file.

To do this:

  • Create classes for your plugin object and plugin manager.
  • Define the front-matter for plugin meta-data that plugins of your type will need to have in their Twig templates. The plugin ID is derived from the template file name (without the extension). Sample front matter that provides a label for the plugin:
    ---
    label: 'My plugin label'
    ---
    
  • Extend the \Drupal\Core\Plugin\Discovery\TemplateDiscovery abstract class to make a discovery class. You'll need to write a validateAndSaveFrontMatter() method, and you may want to override the constructor. Sample code for the validateAndSaveFrontMatter() method:
    $data['class'] = MyPluginClass::class;
    foreach ($front_matter as $key => $value) {
      case 'label':
        $data[$key] = new TranslatableMarkup($value);
        break;
      default:
        throw new DiscoveryException("$file contains invalid key='$key'");
    }
    if (!isset($data['label'])) {
      throw new DiscoveryException("$file has no label attribute");
    }
    return $data;
    
  • In your plugin manager's getDiscovery() method, use the module handler and/or theme manager service to find the directories where your plugin Twig templates are located. Then instantiate your discovery class (passing the list of directories to the constructor), and optionally decorate it to allow derivatives. Sample code for a plugin manager's getDiscovery() method:
    if (!isset($this->discovery)) {
      $directories = $this->moduleHandler->getModuleDirectories();
      $directories = array_map(function ($dir) {
        return [$dir . '/my_plugin_subdirectory'];
      }, $directories);
     $discovery = new MyPluginDiscovery(directories, 'my_plugin_cache_key');
     $discovery = new YamlDiscoveryDecorator($discovery, 'my_derivative_suffix', $directories);
     $this->discovery = $discovery;
    }
    return $this->discovery;
    

For more information, see the Plugin API documentation.

Impacts: 
Module developers