Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
By Wim Leers on
Change record status:
Published (View all published change records)
Project:
Introduced in branch:
9.4.x
Introduced in version:
9.4.9
Issue links:
Description:
A CKEditor 5 plugin definition can now optionally declare a deriver, to remove the need to abuse hook_ckeditor5_plugin_info_alter()
to dynamically declare multiple plugins dependent on external factors (e.g. configuration, a web service, …), for example to provide one button per supported type of fish:
- Before
-
MYMODULE_embed_herring: ckeditor5: plugins: [foo.Foo] drupal: label: Embed herring library: MYMODULE/LIBRARY class: Drupal\MYMODULE\Plugin\CKEditor5Plugin\FishEmbedder toolbar_items: fish_embedder_herring: label: Embed herring elements: - <fish> - <fish type="herring"> MYMODULE_embed_trout: ckeditor5: plugins: [foo.Foo] drupal: label: Embed trout library: MYMODULE/LIBRARY class: Drupal\MYMODULE\Plugin\CKEditor5Plugin\FishEmbedder toolbar_items: fish_embedder_trout: label: Embed trout elements: - <fish> - <fish type="trout">
- After
-
The plugin annotation key-value pairs that are the same across all derived plugin definitions can be defined in the base plugin definition:
MYMODULE_embed: ckeditor5: plugins: [foo.Foo] drupal: library: MYMODULE/LIBRARY class: Drupal\MYMODULE\Plugin\CKEditor5Plugin\FishEmbedder deriver: Drupal\MYMODULE\Plugin\CKEditor5Plugin\FishEmbedderDeriver elements: - <fish>
+
class FishEmbedderDeriver extends DeriverBase { public function getDerivativeDefinitions($base_plugin_definition) { assert($base_plugin_definition instanceof CKEditor5PluginDefinition); foreach (['herring', 'trout'] as $id) { $definition = $base_plugin_definition->toArray(); $definition['id'] = $id; $definition['drupal']['label'] = sprintf("Embed %s", $id); $definition['drupal']['elements'][] = sprintf('<fish type="%s">', $id); $definition['drupal']['toolbar_items']["fish_embedder_$id"]['label'] = $definition['drupal']['label']; $this->derivatives[$id] = new CKEditor5PluginDefinition($definition); } return $this->derivatives; } }
… and the key-value pairs that are unique to each derived plugin definition can be specified in the deriver.
Note: CKEditor 5 plugin definitions can also be specified on the class annotation, and there too a deriver can be specified:
/**
* @CKEditor5Plugin(
* id = "MYMODULE_embed",
* ckeditor5 = @CKEditor5AspectsOfCKEditor5Plugin(
* plugins = {"foo.Foo"},
* ),
* drupal = @DrupalAspectsOfCKEditor5Plugin(
* elements = {"<fish>"},
* deriver = "Drupal\MYMODULE\Plugin\CKEditor5Plugin\FishEmbedderDeriver",
* )
* )
*/
class Foo extends CKEditor5PluginDefault {
Impacts:
Module developers
Comments
A red herring
Seems a little fishy to me!
ComputerMinds
Usage elaboration
I'd been floundering a bit integrating CKEditor 5 plugins in Drupal, so I'm glad to see this help plugins scale. Here's how I am understanding this change's porpoise:
1. https://www.drupal.org/project/ckeditor5_embedded_content , which defines a *single* CKEditor plugin that can be extended to add more options to that single plugin (see those extensions in ckeditor5_embedded_content_examples/src/Plugin/EmbeddedContent/). This would *not* use a deriver, since there's only one CKEditor plugin (see ckeditor5_embedded_content.ckeditor5.yml )
2. In contrast, some of the plugins in Drupal core (core/modules/ckeditor5/ckeditor5.ckeditor5.yml), perhaps such as those related to images, could use a deriver to register multiple buttons.