.../src/Plugin/CKEditor5PluginDefinition.php | 63 +++++----------------- .../src/Plugin/CKEditor5PluginManager.php | 35 +++++++++++- .../src/Kernel/CKEditor5PluginManagerTest.php | 6 +-- 3 files changed, 49 insertions(+), 55 deletions(-) diff --git a/core/modules/ckeditor5/src/Plugin/CKEditor5PluginDefinition.php b/core/modules/ckeditor5/src/Plugin/CKEditor5PluginDefinition.php index 3ca1ab5e52..3af202c7c1 100644 --- a/core/modules/ckeditor5/src/Plugin/CKEditor5PluginDefinition.php +++ b/core/modules/ckeditor5/src/Plugin/CKEditor5PluginDefinition.php @@ -35,63 +35,22 @@ final class CKEditor5PluginDefinition extends PluginDefinition implements Plugin */ private $drupal; - /** - * Discovered base plugin IDs. - * - * @var string[] - * - * @internal - */ - protected static $basePluginIds = []; - /** * CKEditor5PluginDefinition constructor. * * @param array $definition * An array of values from the annotation/YAML. * - * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \InvalidArgumentException */ public function __construct(array $definition) { - $this->id = $id = !isset($definition['base_id']) - ? $definition['id'] - : sprintf("%s:%s", $definition['base_id'], $definition['id']); - - $expected_prefix = sprintf("%s_", $definition['provider']); - if (strpos($id, $expected_prefix) !== 0) { - throw new InvalidPluginDefinitionException($id, sprintf('The "%s" CKEditor 5 plugin definition must have a plugin ID that starts with "%s".', $id, $expected_prefix)); - } - $this->provider = $definition['provider']; - - try { - static::validateCKEditor5Aspects($id, $definition); - $this->ckeditor5 = $definition['ckeditor5']; - - $this->validateDrupalAspects($id, $definition); - $this->drupal = $definition['drupal']; - } - catch (InvalidPluginDefinitionException $e) { - // If this exception is thrown for a CKEditor 5 plugin definition whose ID - // matches a previously seen base plugin ID, it means the deriver did not - // generate a valid plugin definition. Re-throw the exception, but tweak - // the language for DX: clarify it is for a derived plugin definition. - if (!empty(static::$basePluginIds) && preg_match('/^(' . implode('|', static::$basePluginIds) . ').*/', $this->id)) { - throw new InvalidPluginDefinitionException($e->getPluginId(), str_replace('plugin definition', 'derived plugin definition', $e->getMessage())); + foreach ($definition as $property => $value) { + if (property_exists($this, $property)) { + $this->{$property} = $value; } - - // Allow an invalid plugin definition only if it's yet to be derived. - if (isset($definition['drupal']['deriver']) && class_exists($definition['drupal']['deriver'])) { - // Pass on all information from the base definition, without validation; - // it will be validated later. - $this->ckeditor5 = $definition['ckeditor5'] ?? []; - $this->drupal = $definition['drupal']; - // Track which IDs should be considered base plugin IDs. - static::$basePluginIds[] = $this->id; - return; + else { + throw new \InvalidArgumentException(sprintf('Property %s with value %s does not exist on %s.', $property, $value, __CLASS__)); } - - // Otherwise, the exception was appropriate: re-throw it. - throw $e; } } @@ -118,8 +77,11 @@ public function toArray(): array { * The plugin definition to validate. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * + * @internal + * @see \Drupal\ckeditor5\Plugin\CKEditor5PluginManager::processDefinition() */ - private static function validateCKEditor5Aspects(string $id, array $definition): void { + public static function validateCKEditor5Aspects(string $id, array $definition): void { if (!isset($definition['ckeditor5'])) { throw new InvalidPluginDefinitionException($id, sprintf('The "%s" CKEditor 5 plugin definition must contain a "ckeditor5" key.', $id)); } @@ -159,8 +121,11 @@ private static function validateCKEditor5Aspects(string $id, array $definition): * The plugin definition to validate. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * + * @internal + * @see \Drupal\ckeditor5\Plugin\CKEditor5PluginManager::processDefinition() */ - private function validateDrupalAspects(string $id, array $definition): void { + public function validateDrupalAspects(string $id, array $definition): void { if (!isset($definition['drupal'])) { throw new InvalidPluginDefinitionException($id, sprintf('The "%s" CKEditor 5 plugin definition must contain a "drupal" key.', $id)); } diff --git a/core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php b/core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php index b12b2e2d9a..3558ab407b 100644 --- a/core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php +++ b/core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php @@ -73,10 +73,43 @@ protected function getDiscovery() { * {@inheritdoc} */ public function processDefinition(&$definition, $plugin_id) { - parent::processDefinition($definition, $plugin_id); if (!$definition instanceof CKEditor5PluginDefinition) { throw new InvalidPluginDefinitionException($plugin_id, sprintf('The "%s" CKEditor 5 plugin definition must extend %s', $plugin_id, CKEditor5PluginDefinition::class)); } + + // A derived plugin will still have the ID of the derivative, rather than + // that of the derived plugin ID (`:`). + // Generate an updated CKEditor5PluginDefinition. + // @see \Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator::encodePluginId() + // @todo Remove this in https://www.drupal.org/project/drupal/issues/2458769. + $is_derived = $definition->id() !== $plugin_id; + if ($is_derived) { + $definition = new CKEditor5PluginDefinition(['id' => $plugin_id] + $definition->toArray()); + } + + $expected_prefix = sprintf("%s_", $definition->getProvider()); + $id = $definition->id(); + if (strpos($id, $expected_prefix) !== 0) { + throw new InvalidPluginDefinitionException($id, sprintf('The "%s" CKEditor 5 plugin definition must have a plugin ID that starts with "%s".', $id, $expected_prefix)); + } + + try { + $definition->validateCKEditor5Aspects($id, $definition->toArray()); + $definition->validateDrupalAspects($id, $definition->toArray()); + } + catch (InvalidPluginDefinitionException $e) { + // If this exception is thrown for a derived CKEditor 5 plugin definition, + // it means the deriver did not generate a valid plugin definition. + // Re-throw the exception, but tweak the language for DX: clarify it is + // for a derived plugin definition. + if ($is_derived) { + throw new InvalidPluginDefinitionException($e->getPluginId(), str_replace('plugin definition', 'derived plugin definition', $e->getMessage())); + } + // Otherwise, the exception was appropriate: re-throw it. + throw $e; + } + + parent::processDefinition($definition, $plugin_id); } /** diff --git a/core/modules/ckeditor5/tests/src/Kernel/CKEditor5PluginManagerTest.php b/core/modules/ckeditor5/tests/src/Kernel/CKEditor5PluginManagerTest.php index 003a6b631b..e92f5eda67 100644 --- a/core/modules/ckeditor5/tests/src/Kernel/CKEditor5PluginManagerTest.php +++ b/core/modules/ckeditor5/tests/src/Kernel/CKEditor5PluginManagerTest.php @@ -1589,7 +1589,6 @@ public function getDerivativeDefinitions($base_plugin_definition) { assert($base_plugin_definition instanceof CKEditor5PluginDefinition); foreach (['bar', 'baz'] as $derivative) { $definition = $base_plugin_definition->toArray(); - $definition['base_id'] = $base_plugin_definition->id(); $definition['id'] = $derivative; $definition['drupal']['label'] = sprintf("Foo %s", $derivative); $this->derivatives[$definition['id']] = new CKEditor5PluginDefinition($definition); @@ -1634,7 +1633,7 @@ public function getDerivativeDefinitions($base_plugin_definition) { elements: false deriver: Drupal\ckeditor5_derived_plugin\Plugin\CKEditor5Plugin\SimpleDeriver YAML, - 'The "ckeditor5_derived_plugin_foo:bar" CKEditor 5 derived plugin definition must contain a "ckeditor5.plugins" key.', + 'The "ckeditor5_derived_plugin_foo:bar" CKEditor 5 derived plugin definition must contain a "ckeditor5" key.', $simple_deriver_additional_files, ]; @@ -1662,7 +1661,6 @@ public function getDerivativeDefinitions($base_plugin_definition) { assert($base_plugin_definition instanceof CKEditor5PluginDefinition); foreach (['bar', 'baz'] as $derivative) { $definition = $base_plugin_definition->toArray(); - $definition['base_id'] = $base_plugin_definition->id(); $definition['id'] = $derivative; $definition['drupal']['label'] = sprintf("Foo %s", $derivative); $this->derivatives[$definition['id']] = $definition; @@ -1792,7 +1790,6 @@ public function getDerivativeDefinitions($base_plugin_definition) { assert($base_plugin_definition instanceof CKEditor5PluginDefinition); foreach (['A', 'B'] as $derivative) { $definition = $base_plugin_definition->toArray(); - $definition['base_id'] = $base_plugin_definition->id(); $definition['id'] = $derivative; $definition['drupal']['label'] = sprintf("Foo %s", $derivative); $definition['drupal']['elements'] = FALSE; @@ -1881,7 +1878,6 @@ public function getDerivativeDefinitions($base_plugin_definition) { $authentication_providers = array_keys($this->authenticationCollector->getSortedProviders()); foreach ($authentication_providers as $id) { $definition = $base_plugin_definition->toArray(); - $definition['base_id'] = $base_plugin_definition->id(); $definition['id'] = $id; $definition['drupal']['label'] = sprintf("Foo %s", $id); $this->derivatives[$definition['id']] = new CKEditor5PluginDefinition($definition);