You are here

private function FundamentalCompatibilityConstraintValidator::checkAllHtmlTagsAreCreatable in Drupal 10

Checks all HTML tags supported by enabled CKEditor 5 plugins are creatable.

Parameters

\Drupal\editor\EditorInterface $text_editor: The text editor to validate.

\Drupal\ckeditor5\Plugin\Validation\Constraint\FundamentalCompatibilityConstraint $constraint: The constraint to validate.

1 call to FundamentalCompatibilityConstraintValidator::checkAllHtmlTagsAreCreatable()
FundamentalCompatibilityConstraintValidator::validate in core/modules/ckeditor5/src/Plugin/Validation/Constraint/FundamentalCompatibilityConstraintValidator.php

File

core/modules/ckeditor5/src/Plugin/Validation/Constraint/FundamentalCompatibilityConstraintValidator.php, line 185

Class

FundamentalCompatibilityConstraintValidator
Validates fundamental compatibility of CKEditor 5 with the given text format.

Namespace

Drupal\ckeditor5\Plugin\Validation\Constraint

Code

private function checkAllHtmlTagsAreCreatable(EditorInterface $text_editor, FundamentalCompatibilityConstraint $constraint) : void {
  $enabled_definitions = $this->pluginManager
    ->getEnabledDefinitions($text_editor);
  $enabled_plugins = array_keys($enabled_definitions);

  // When arbitrary HTML is supported, all tags are creatable.
  if (in_array('ckeditor5_arbitraryHtmlSupport', $enabled_plugins, TRUE)) {
    return;
  }
  $tags_and_attributes = new HTMLRestrictions($this->pluginManager
    ->getProvidedElements($enabled_plugins, $text_editor));
  $creatable_tags = new HTMLRestrictions($this->pluginManager
    ->getProvidedElements($enabled_plugins, $text_editor, FALSE, TRUE));
  $needed_tags = $tags_and_attributes
    ->extractPlainTagsSubset();
  $non_creatable_tags = $needed_tags
    ->diff($creatable_tags);
  if (!$non_creatable_tags
    ->allowsNothing()) {
    foreach ($non_creatable_tags
      ->toCKEditor5ElementsArray() as $non_creatable_tag) {

      // Find the plugin which has a non-creatable tag.
      $needle = HTMLRestrictions::fromString($non_creatable_tag);
      $matching_plugins = array_filter($enabled_definitions, function (CKEditor5PluginDefinition $d) use ($needle, $text_editor) {
        if (!$d
          ->hasElements()) {
          return FALSE;
        }
        $haystack = new HTMLRestrictions($this->pluginManager
          ->getProvidedElements([
          $d
            ->id(),
        ], $text_editor, FALSE, FALSE));
        return !$haystack
          ->extractPlainTagsSubset()
          ->intersect($needle)
          ->allowsNothing();
      });
      assert(count($matching_plugins) === 1);
      $plugin_definition = reset($matching_plugins);
      assert($plugin_definition instanceof CKEditor5PluginDefinition);

      // Compute which attributes it would be able to create on this tag.
      $provided_elements = new HTMLRestrictions($this->pluginManager
        ->getProvidedElements([
        $plugin_definition
          ->id(),
      ], $text_editor, FALSE, FALSE));
      $attributes_on_tag = $provided_elements
        ->intersect(new HTMLRestrictions(array_fill_keys(array_keys($needle
        ->getAllowedElements()), TRUE)));
      $violation = $this->context
        ->buildViolation($constraint->nonCreatableTagMessage)
        ->setParameter('@non_creatable_tag', $non_creatable_tag)
        ->setParameter('%plugin', $plugin_definition
        ->label())
        ->setParameter('@attributes_on_tag', implode(', ', $attributes_on_tag
        ->toCKEditor5ElementsArray()));

      // If this plugin has a configurable subset, associate the violation
      // with the property path pointing to this plugin's settings form.
      if (is_a($plugin_definition
        ->getClass(), CKEditor5PluginElementsSubsetInterface::class, TRUE)) {
        $violation
          ->atPath(sprintf('settings.plugins.%s', $plugin_definition
          ->id()));
      }
      elseif ($plugin_definition
        ->hasToolbarItems()) {
        $toolbar_items = $plugin_definition
          ->getToolbarItems();
        $active_toolbar_items = array_intersect($text_editor
          ->getSettings()['toolbar']['items'], array_keys($toolbar_items));
        $violation
          ->atPath(sprintf('settings.toolbar.items.%d', array_keys($active_toolbar_items)[0]));
      }
      $violation
        ->addViolation();
    }
  }
}