function SmartDefaultSettings::addToolbarItemsToMatchHtmlElementsInFormat

Same name and namespace in other branches
  1. 9 core/modules/ckeditor5/src/SmartDefaultSettings.php \Drupal\ckeditor5\SmartDefaultSettings::addToolbarItemsToMatchHtmlElementsInFormat()
  2. 11.x core/modules/ckeditor5/src/SmartDefaultSettings.php \Drupal\ckeditor5\SmartDefaultSettings::addToolbarItemsToMatchHtmlElementsInFormat()

Adds CKEditor 5 toolbar items to match the format's HTML elements.

Parameters

\Drupal\filter\FilterFormatInterface $format: The text format for which to compute smart default settings.

\Drupal\editor\EditorInterface $editor: The text editor config entity to update.

Return value

array|null NULL when nothing happened, otherwise an array with four values: 1. a description (for use in a message) of which CKEditor 5 plugins were enabled to match the HTML tags allowed by the text format. 2. a description (for use in a message) of which CKEditor 5 plugins were enabled to match the HTML attributes allowed by the text format. 3. the unsupported elements, in an HTMLRestrictions value object. 4. the list of enabled plugin labels.

1 call to SmartDefaultSettings::addToolbarItemsToMatchHtmlElementsInFormat()
SmartDefaultSettings::computeSmartDefaultSettings in core/modules/ckeditor5/src/SmartDefaultSettings.php
Computes the closest possible equivalent settings for switching to CKEditor 5.

File

core/modules/ckeditor5/src/SmartDefaultSettings.php, line 806

Class

SmartDefaultSettings
Generates CKEditor 5 settings for existing text editors/formats.

Namespace

Drupal\ckeditor5

Code

private function addToolbarItemsToMatchHtmlElementsInFormat(FilterFormatInterface $format, EditorInterface $editor) : ?array {
  $html_restrictions_needed_elements = $format->getHtmlRestrictions();
  if ($html_restrictions_needed_elements === FALSE) {
    return NULL;
  }
  $all_definitions = $this->pluginManager
    ->getDefinitions();
  $enabled_definitions = $this->pluginManager
    ->getEnabledDefinitions($editor);
  $disabled_definitions = array_diff_key($all_definitions, $enabled_definitions);
  $enabled_plugins = array_keys($enabled_definitions);
  $provided_elements = $this->pluginManager
    ->getProvidedElements($enabled_plugins, $editor);
  $provided = new HTMLRestrictions($provided_elements);
  $needed = HTMLRestrictions::fromTextFormat($format);
  // Plugins only supporting <tag attr> cannot create the tag. For that, they
  // must support plain <tag> too. With this being the case, break down what
  // is needed based on what is currently provided.
  // @see \Drupal\ckeditor5\Plugin\CKEditor5PluginDefinition::getCreatableElements()
  // TRICKY: the HTMLRestrictions value object can only convey complete
  // restrictions: merging <foo> and <foo bar> results in just <foo bar>. The
  // list of already provided plain tags must hence be constructed separately.
  $provided_plain_tags = new HTMLRestrictions($this->pluginManager
    ->getProvidedElements($enabled_plugins, NULL, FALSE, TRUE));
  // Determine the still needed plain tags, the still needed attributes, and
  // the union of both.
  $still_needed_plain_tags = $needed->extractPlainTagsSubset()
    ->diff($provided_plain_tags);
  $still_needed_attributes = $needed->diff($provided)
    ->diff($still_needed_plain_tags);
  $still_needed = $still_needed_plain_tags->merge($still_needed_attributes);
  if (!$still_needed->allowsNothing()) {
    // Select plugins for supporting the still needed plain tags.
    $plugin_candidates_plain_tags = self::getCandidates($provided_plain_tags, $still_needed_plain_tags, $disabled_definitions);
    $selected_plugins_plain_tags = self::selectCandidate($plugin_candidates_plain_tags, $still_needed_plain_tags, array_keys($provided_plain_tags->getAllowedElements()));
    // Select plugins for supporting the still needed attributes.
    $plugin_candidates_attributes = self::getCandidates($provided, $still_needed_attributes, $disabled_definitions);
    $selected_plugins_attributes = self::selectCandidate($plugin_candidates_attributes, $still_needed, array_keys($provided->getAllowedElements()));
    // Combine the selection.
    $selected_plugins = array_merge_recursive($selected_plugins_plain_tags, $selected_plugins_attributes);
    // If additional plugins need to be enabled to support attribute config,
    // loop through the list to enable the plugins and build a UI message that
    // will convey this plugin-enabling to the user.
    if (!empty($selected_plugins)) {
      $enabled_for_tags_message_content = '';
      $enabled_for_attributes_message_content = '';
      $editor_settings_to_update = $editor->getSettings();
      // Create new group for all the added toolbar items.
      $editor_settings_to_update['toolbar']['items'][] = '|';
      foreach ($selected_plugins as $plugin_id => $reason_why_enabled) {
        $plugin_definition = $this->pluginManager
          ->getDefinition($plugin_id);
        $label = $plugin_definition->label();
        $plugins_enabled[] = $label;
        if ($plugin_definition->hasToolbarItems()) {
          [
            $net_new,
          ] = self::computeNetNewElementsForPlugin($provided, $still_needed, $plugin_definition);
          $editor_settings_to_update['toolbar']['items'] = array_merge($editor_settings_to_update['toolbar']['items'], array_keys($plugin_definition->getToolbarItems()));
          foreach ($reason_why_enabled as $attribute_name => $attribute_config) {
            // Plugin was selected for tag.
            if (in_array($attribute_name, [
              '-attributes-none-',
              '-attributes-any-',
            ], TRUE)) {
              $tags = array_reduce(array_keys($net_new->getAllowedElements()), function ($carry, $item) {
                return $carry . "<{$item}>";
              });
              $enabled_for_tags_message_content .= "{$label} (for tags: {$tags}) ";
              // This plugin does not add attributes: continue to next plugin.
              continue;
            }
            // Plugin was selected for attribute.
            $enabled_for_attributes_message_content .= "{$label} (";
            foreach ($attribute_config as $tag_name => $attribute_value_config) {
              $enabled_for_attributes_message_content .= " for tag: <{$tag_name}> to support: {$attribute_name}";
              if (is_array($attribute_value_config)) {
                $enabled_for_attributes_message_content .= " with value(s): ";
                foreach (array_keys($attribute_value_config) as $allowed_value) {
                  $enabled_for_attributes_message_content .= " {$allowed_value},";
                }
                $enabled_for_attributes_message_content = substr($enabled_for_attributes_message_content, 0, -1) . '), ';
              }
            }
          }
          // Fewer attributes are still needed.
          $still_needed = $still_needed->diff($net_new);
        }
      }
      $editor->setSettings($editor_settings_to_update);
      // Some plugins enabled, maybe some missing tags or attributes.
      return [
        substr($enabled_for_tags_message_content, 0, -1),
        substr($enabled_for_attributes_message_content, 0, -2),
        $still_needed,
        $plugins_enabled,
      ];
    }
    else {
      // No plugins enabled, maybe some missing tags or attributes.
      return [
        NULL,
        NULL,
        $still_needed,
        NULL,
      ];
    }
  }
  else {
    return NULL;
  }
}

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