function CKEditor5PluginManager::getProvidedElements

Same name and namespace in other branches
  1. 11.x core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php \Drupal\ckeditor5\Plugin\CKEditor5PluginManager::getProvidedElements()

File

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

Class

CKEditor5PluginManager
Provides a CKEditor 5 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);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.