function SmartDefaultSettings::selectCandidate

Same name in other branches
  1. 10 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 703

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.