function SmartDefaultSettings::selectCandidate

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

Selects best candidate for each of the still needed restrictions.

Parameters

array $candidates: The output of ::getCandidates().

\Drupal\ckeditor5\HTMLRestrictions $still_needed: The still needed HTML restrictions, unmet by the already enabled CKEditor 5 plugins.

string[] $already_supported_tags: A list of already supported HTML tags, necessary to select the best matching candidate for elements still needed in $still_needed.

Return value

array A nested array with a tree structure, with each key a selected CKEditor 5 plugin ID and its values expressing the reason it was enabled.

1 call to SmartDefaultSettings::selectCandidate()
SmartDefaultSettings::addToolbarItemsToMatchHtmlElementsInFormat in core/modules/ckeditor5/src/SmartDefaultSettings.php
Adds CKEditor 5 toolbar items to match the format's HTML elements.

File

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

Class

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

Namespace

Drupal\ckeditor5

Code

private static function selectCandidate(array $candidates, HTMLRestrictions $still_needed, array $already_supported_tags) : array {
  assert(Inspector::assertAllStrings($already_supported_tags));
  // Make a selection in the candidates: minimize the surplus count, to
  // avoid generating surplus additions whenever possible.
  $selected_plugins = [];
  foreach ($still_needed->getAllowedElements() as $tag_name => $attributes_config) {
    if (!isset($candidates[$tag_name])) {
      // Sadly no plugin found for this tag.
      continue;
    }
    // Non-specific attribute restrictions for tag.
    if (is_bool($attributes_config)) {
      $key = $attributes_config ? '-attributes-any-' : '-attributes-none-';
      if (!isset($candidates[$tag_name][$key])) {
        // Sadly no plugin found for this tag + unspecific attribute.
        continue;
      }
      asort($candidates[$tag_name][$key]);
      $selected_plugin_id = array_keys($candidates[$tag_name][$key])[0];
      $selected_plugins[$selected_plugin_id][$key][$tag_name] = NULL;
      continue;
    }
    // Specific attribute restrictions for tag.
    foreach ($attributes_config as $attribute_name => $attribute_config) {
      if (!isset($candidates[$tag_name][$attribute_name])) {
        // Sadly no plugin found for this tag + attribute.
        continue;
      }
      if (!is_array($attribute_config)) {
        if (!isset($candidates[$tag_name][$attribute_name][$attribute_config])) {
          // Sadly no plugin found for this tag + attribute + config.
          continue;
        }
        asort($candidates[$tag_name][$attribute_name][$attribute_config]);
        $selected_plugin_id = array_keys($candidates[$tag_name][$attribute_name][$attribute_config])[0];
        $selected_plugins[$selected_plugin_id][$attribute_name][$tag_name] = $attribute_config;
        continue;
      }
      else {
        foreach ($attribute_config as $allowed_attribute_value => $allowed_attribute_value_config) {
          if (!isset($candidates[$tag_name][$attribute_name][$allowed_attribute_value][$allowed_attribute_value_config])) {
            // Sadly no plugin found for this tag + attr + value + config.
            continue;
          }
          asort($candidates[$tag_name][$attribute_name][$allowed_attribute_value][$allowed_attribute_value_config]);
          $selected_plugin_id = array_keys($candidates[$tag_name][$attribute_name][$allowed_attribute_value][$allowed_attribute_value_config])[0];
          $selected_plugins[$selected_plugin_id][$attribute_name][$tag_name][$allowed_attribute_value] = $allowed_attribute_value_config;
          continue;
        }
      }
    }
    // If we got to this point, no exact match was found. But selecting a
    // plugin to support the tag at all (when it is not yet supported) is
    // crucial to meet the user's expectations.
    // For example: when `<blockquote cite>` is needed, select at least the
    // plugin that can support `<blockquote>`, then only the `cite` attribute
    // needs to be made possible using the `SourceEditing` plugin.
    if (!in_array($tag_name, $already_supported_tags, TRUE) && isset($candidates[$tag_name]['-attributes-none-'])) {
      asort($candidates[$tag_name]['-attributes-none-']);
      $selected_plugin_id = array_keys($candidates[$tag_name]['-attributes-none-'])[0];
      $selected_plugins[$selected_plugin_id]['-attributes-none-'][$tag_name] = NULL;
    }
  }
  // The above selects all exact matches. It's possible the same plugin is
  // selected for multiple reasons: for supporting the tag at all, but also
  // for supporting more attributes on the tag. Whenever that scenario
  // occurs, keep only the "tag" reason, since that is the most relevant one
  // for the end user. Otherwise a single plugin being selected (and enabled)
  // could generate multiple messages, which would be confusing and
  // overwhelming for the user.
  // For example: when `<a href>` is needed, supporting `<a>` is more
  // relevant to be informed about as an end user than the plugin also being
  // enabled to support the `href` attribute.
  foreach ($selected_plugins as $selected_plugin_id => $reason) {
    if (count($reason) > 1 && isset($reason['-attributes-none-'])) {
      $selected_plugins[$selected_plugin_id] = array_intersect_key($reason, [
        '-attributes-none-' => TRUE,
      ]);
    }
  }
  return $selected_plugins;
}

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