function HTMLRestrictions::doDiff

Same name in other branches
  1. 10 core/modules/ckeditor5/src/HTMLRestrictions.php \Drupal\ckeditor5\HTMLRestrictions::doDiff()
  2. 11.x core/modules/ckeditor5/src/HTMLRestrictions.php \Drupal\ckeditor5\HTMLRestrictions::doDiff()

Computes difference of two HTML restrictions, without wildcard support.

Parameters

\Drupal\ckeditor5\HTMLRestrictions $other: The HTML restrictions to compare to.

Return value

\Drupal\ckeditor5\HTMLRestrictions Returns a new HTML restrictions value object with all the elements that are not allowed in $other.

File

core/modules/ckeditor5/src/HTMLRestrictions.php, line 609

Class

HTMLRestrictions
Represents a set of HTML restrictions.

Namespace

Drupal\ckeditor5

Code

private function doDiff(HTMLRestrictions $other) : HTMLRestrictions {
    $diff_elements = array_filter(DiffArray::diffAssocRecursive($this->elements, $other->elements), function ($value, string $tag) use ($other) {
        // If this HTML restrictions object contains a tag that the other did
        // not contain at all: keep the DiffArray result.
        if (!array_key_exists($tag, $other->elements)) {
            return TRUE;
        }
        // All subsequent checks can assume that $other contains an entry for
        // this tag.
        // If this HTML restrictions object does not allow any attributes for
        // this tag, then the other is at least equally restrictive: drop the
        // DiffArray result.
        if ($value === FALSE) {
            return FALSE;
        }
        // If this HTML restrictions object allows any attributes for this
        // tag, then the other is at most equally permissive: keep the
        // DiffArray result.
        if ($value === TRUE) {
            return TRUE;
        }
        // Otherwise, this HTML restrictions object allows specific attributes
        // only. DiffArray only knows to compare arrays. When the other object
        // has a non-array value for this tag, interpret those values correctly.
        assert(is_array($value));
        // The other object is more restrictive regarding allowed attributes
        // for this tag: keep the DiffArray result.
        if ($other->elements[$tag] === FALSE) {
            return TRUE;
        }
        // The other object is more permissive regarding allowed attributes
        // for this tag: drop the DiffArray result.
        if ($other->elements[$tag] === TRUE) {
            return FALSE;
        }
        // Both objects have lists of allowed attributes: keep the DiffArray
        // result and apply postprocessing after this array_filter() call,
        // because this can only affect tag-level differences.
        // @see ::validateAllowedRestrictionsPhase3()
        assert(is_array($other->elements[$tag]));
        return TRUE;
    }, ARRAY_FILTER_USE_BOTH);
    // Attribute-level postprocessing for two special cases:
    // - wildcard attribute names
    // - per attribute name: attribute value restrictions in $this vs all values
    //   allowed in $other
    foreach ($diff_elements as $tag => $tag_config) {
        // If there are no per-attribute restrictions for this tag in either
        // operand, then no postprocessing is needed.
        if (!is_array($tag_config) || !(isset($other->elements[$tag]) && is_array($other->elements[$tag]))) {
            continue;
        }
        // Special case: wildcard attributes, and the ability to define
        // restrictions for all concrete attributes matching them using:
        // - prefix wildcard, f.e. `*-foo`
        // - infix wildcard, f.e. `*-entity-*`
        // - suffix wildcard, f.e. `data-*`, to match `data-foo`, `data-bar`, etc.
        $wildcard_attributes = array_filter(array_keys($other->elements[$tag]), [
            __CLASS__,
            'isWildcardAttributeName',
        ]);
        foreach ($wildcard_attributes as $wildcard_attribute_name) {
            $regex = self::getRegExForWildCardAttributeName($wildcard_attribute_name);
            foreach ($tag_config as $html_tag_attribute_name => $html_tag_attribute_restrictions) {
                // If a wildcard attribute name (f.e. `data-*`) is allowed in $other
                // with the same attribute value restrictions (e.g. TRUE to allow all
                // attribute values or an array of specific allowed attribute values),
                // then all concrete matches (f.e. `data-foo`, `data-bar`, etc.) are
                // allowed and should be explicitly omitted from the difference.
                if ($html_tag_attribute_restrictions === $other->elements[$tag][$wildcard_attribute_name] && preg_match($regex, $html_tag_attribute_name) === 1) {
                    unset($tag_config[$html_tag_attribute_name]);
                }
            }
        }
        // Attribute value restrictions in $this, all values allowed in $other.
        foreach ($tag_config as $html_tag_attribute_name => $html_tag_attribute_restrictions) {
            if (is_array($html_tag_attribute_restrictions) && isset($other->elements[$tag][$html_tag_attribute_name]) && $other->elements[$tag][$html_tag_attribute_name] === TRUE) {
                unset($tag_config[$html_tag_attribute_name]);
            }
        }
        // Ensure $diff_elements continues to be structured in a way that is valid
        // for a HTMLRestrictions object to be constructed from it.
        if ($tag_config !== []) {
            $diff_elements[$tag] = $tag_config;
        }
        else {
            unset($diff_elements[$tag]);
        }
    }
    return new self($diff_elements);
}

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