You are here

public function CKEditor5PluginManager::getProvidedElements in Drupal 10

Gets all supported elements for the given plugins and text editor.

Parameters

string[] $plugin_ids: (optional) An array of CKEditor 5 plugin IDs. When not set, gets elements for all plugins.

\Drupal\editor\EditorInterface|null $editor: (optional) A configured text editor object using CKEditor 5. When not set, plugins depending on the text editor cannot provide elements.

bool $resolve_wildcards: (optional) Whether to resolve wildcards. Defaults to TRUE. When set to FALSE, the raw allowed elements will be returned (with no processing applied hence no resolved wildcards).

bool $creatable_elements_only: (optional) Whether to retrieve only the creatable elements. Defaults to FALSE.

Return value

array A nested array with a structure as described in \Drupal\filter\Plugin\FilterInterface::getHTMLRestrictions().

Throws

\LogicException Thrown when an invalid CKEditor5PluginElementsSubsetInterface implementation is encountered.

Overrides CKEditor5PluginManagerInterface::getProvidedElements

See also

\Drupal\ckeditor5\Plugin\CKEditor5PluginDefinition::getCreatableElements()

\Drupal\filter\Plugin\FilterInterface::getHTMLRestrictions()

3 calls to CKEditor5PluginManager::getProvidedElements()
CKEditor5PluginManager::findPluginSupportingElement in core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php
Searches for CKEditor 5 plugin that supports a given tag.
CKEditor5PluginManager::getCKEditor5PluginConfig in core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php
Gets the configuration for the CKEditor 5 plugins enabled in this editor.
CKEditor5PluginManager::getEnabledDefinitions in core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php
Filter list of definitions by enabled plugins only.

File

core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php, line 301

Class

CKEditor5PluginManager
Provides a CKEditor5 plugin manager.

Namespace

Drupal\ckeditor5\Plugin

Code

public function getProvidedElements(array $plugin_ids = [], EditorInterface $editor = NULL, bool $resolve_wildcards = TRUE, bool $creatable_elements_only = FALSE) : array {
  $plugins = $this
    ->getDefinitions();
  if (!empty($plugin_ids)) {
    $plugins = array_intersect_key($plugins, array_flip($plugin_ids));
  }
  $elements = HTMLRestrictions::emptySet();
  foreach ($plugins as $id => $definition) {

    // Some CKEditor 5 plugins only provide functionality, not additional
    // elements.
    if (!$definition
      ->hasElements()) {
      continue;
    }
    $defined_elements = $definition
      ->getElements();
    if (is_a($definition
      ->getClass(), CKEditor5PluginElementsSubsetInterface::class, TRUE)) {

      // ckeditor5_sourceEditing is the edge case here: it is the only plugin
      // that is allowed to return a superset. It's a special case because it
      // is through configuring this particular plugin that additional HTML
      // tags can be allowed.
      // The list of tags it supports is generated dynamically. In its default
      // configuration it does support any HTML tags.
      if ($id === 'ckeditor5_sourceEditing') {
        $defined_elements = !isset($editor) ? [] : $this
          ->getPlugin($id, $editor)
          ->getElementsSubset();
      }
      elseif (isset($editor)) {
        $subset = $this
          ->getPlugin($id, $editor)
          ->getElementsSubset();
        $subset_restrictions = HTMLRestrictions::fromString(implode($subset));
        $defined_restrictions = HTMLRestrictions::fromString(implode($defined_elements));

        // Determine max supported elements by resolving wildcards in the
        // restrictions defined by the plugin.
        $max_supported = $defined_restrictions;
        if (!$defined_restrictions
          ->getWildcardSubset()
          ->allowsNothing()) {
          $concrete_tags_to_use_to_resolve_wildcards = $subset_restrictions
            ->extractPlainTagsSubset();
          $max_supported = $max_supported
            ->merge($concrete_tags_to_use_to_resolve_wildcards)
            ->diff($concrete_tags_to_use_to_resolve_wildcards);
        }
        $not_in_max_supported = $subset_restrictions
          ->diff($max_supported);
        if (!$not_in_max_supported
          ->allowsNothing()) {

          // If the editor is still being configured, the configuration may
          // not yet be valid.
          if ($editor
            ->isNew()) {
            $subset = [];
          }
          else {
            throw new \LogicException(sprintf('The "%s" CKEditor 5 plugin implements ::getElementsSubset() and did not return a subset, the following tags are absent from the plugin definition: "%s".', $id, implode(' ', $not_in_max_supported
              ->toCKEditor5ElementsArray())));
          }
        }

        // Also detect what is technically a valid subset, but has lost the
        // ability to create tags that are still in the subset. This points to
        // a bug in the plugin's ::getElementsSubset() logic.
        $defined_creatable = HTMLRestrictions::fromString(implode($definition
          ->getCreatableElements()));
        $subset_creatable_actual = HTMLRestrictions::fromString(implode(array_filter($subset, [
          CKEditor5PluginDefinition::class,
          'isCreatableElement',
        ])));
        $subset_creatable_needed = $subset_restrictions
          ->extractPlainTagsSubset()
          ->intersect($defined_creatable);
        $missing_creatable_for_subset = $subset_creatable_needed
          ->diff($subset_creatable_actual);
        if (!$missing_creatable_for_subset
          ->allowsNothing()) {
          throw new \LogicException(sprintf('The "%s" CKEditor 5 plugin implements ::getElementsSubset() and did return a subset ("%s") but the following tags can no longer be created: "%s".', $id, implode($subset_restrictions
            ->toCKEditor5ElementsArray()), implode($missing_creatable_for_subset
            ->toCKEditor5ElementsArray())));
        }
        $defined_elements = $subset;
      }
    }
    assert(Inspector::assertAllStrings($defined_elements));
    if ($creatable_elements_only) {

      // @see \Drupal\ckeditor5\Plugin\CKEditor5PluginDefinition::getCreatableElements()
      $defined_elements = array_filter($defined_elements, [
        CKEditor5PluginDefinition::class,
        'isCreatableElement',
      ]);
    }
    foreach ($defined_elements as $element) {
      $additional_elements = HTMLRestrictions::fromString($element);
      $elements = $elements
        ->merge($additional_elements);
    }
  }
  return $elements
    ->getAllowedElements($resolve_wildcards);
}