function HTMLRestrictions::doIntersect
Same name in other branches
- 9 core/modules/ckeditor5/src/HTMLRestrictions.php \Drupal\ckeditor5\HTMLRestrictions::doIntersect()
- 10 core/modules/ckeditor5/src/HTMLRestrictions.php \Drupal\ckeditor5\HTMLRestrictions::doIntersect()
Computes intersection 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 also allowed in $other.
File
-
core/
modules/ ckeditor5/ src/ HTMLRestrictions.php, line 744
Class
- HTMLRestrictions
- Represents a set of HTML restrictions.
Namespace
Drupal\ckeditor5Code
public function doIntersect(HTMLRestrictions $other) : HTMLRestrictions {
$intersection_based_on_tags = array_intersect_key($this->elements, $other->elements);
$intersection = [];
// Additional filtering is necessary beyond the array_intersect_key that
// computed $intersection_based_on_tags because tag configuration can have
// boolean values that have different logic than array values.
foreach (array_keys($intersection_based_on_tags) as $tag) {
// If either does not allow attributes, neither does the intersection.
if ($this->elements[$tag] === FALSE || $other->elements[$tag] === FALSE) {
$intersection[$tag] = FALSE;
continue;
}
// If both allow all attributes, so does the intersection.
if ($this->elements[$tag] === TRUE && $other->elements[$tag] === TRUE) {
$intersection[$tag] = TRUE;
continue;
}
// If the first allows all attributes, return the second.
if ($this->elements[$tag] === TRUE) {
$intersection[$tag] = $other->elements[$tag];
continue;
}
// And vice versa.
if ($other->elements[$tag] === TRUE) {
$intersection[$tag] = $this->elements[$tag];
continue;
}
// In all other cases, we need to return the most restrictive
// intersection of per-attribute restrictions.
// @see ::validateAllowedRestrictionsPhase3()
assert(is_array($this->elements[$tag]));
assert(is_array($other->elements[$tag]));
$intersection[$tag] = [];
$attributes_intersection = array_intersect_key($this->elements[$tag], $other->elements[$tag]);
foreach (array_keys($attributes_intersection) as $attr) {
// If both allow all attribute values, so does the intersection.
if ($this->elements[$tag][$attr] === TRUE && $other->elements[$tag][$attr] === TRUE) {
$intersection[$tag][$attr] = TRUE;
continue;
}
// If the first allows all attribute values, return the second.
if ($this->elements[$tag][$attr] === TRUE) {
$intersection[$tag][$attr] = $other->elements[$tag][$attr];
continue;
}
// And vice versa.
if ($other->elements[$tag][$attr] === TRUE) {
$intersection[$tag][$attr] = $this->elements[$tag][$attr];
continue;
}
// If either allows no attribute values, nor does the intersection.
if ($this->elements[$tag][$attr] === FALSE || $other->elements[$tag][$attr] === FALSE) {
// Special case: the global attribute `*` HTML tag.
// @see https://html.spec.whatwg.org/multipage/dom.html#global-attributes
// @see validateAllowedRestrictionsPhase2()
// @see validateAllowedRestrictionsPhase4()
assert($tag === '*');
$intersection[$tag][$attr] = FALSE;
continue;
}
assert(is_array($this->elements[$tag][$attr]));
assert(is_array($other->elements[$tag][$attr]));
$intersection[$tag][$attr] = array_intersect_key($this->elements[$tag][$attr], $other->elements[$tag][$attr]);
// It is not permitted to specify an empty attribute value
// restrictions array.
if (empty($intersection[$tag][$attr])) {
unset($intersection[$tag][$attr]);
}
}
// HTML tags must not have an empty array of allowed attributes.
if ($intersection[$tag] === []) {
$intersection[$tag] = FALSE;
// Special case: the global attribute `*` HTML tag.
// @see https://html.spec.whatwg.org/multipage/dom.html#global-attributes
// @see validateAllowedRestrictionsPhase2()
// @see validateAllowedRestrictionsPhase4()
if ($tag === '*') {
unset($intersection[$tag]);
}
}
}
// 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.
foreach ($intersection as $tag => $tag_config) {
// If there are no per-attribute restrictions for this tag in either
// operand, then no wildcard attribute postprocessing is needed.
if (!(is_array($this->elements[$tag]) && is_array($other->elements[$tag]))) {
continue;
}
$other_wildcard_attributes = array_filter(array_keys($other->elements[$tag]), [
__CLASS__,
'isWildcardAttributeName',
]);
$this_wildcard_attributes = array_filter(array_keys($this->elements[$tag]), [
__CLASS__,
'isWildcardAttributeName',
]);
// If the same wildcard attribute restrictions are present in both or
// neither, no adjustment necessary: the intersection is already correct.
$in_both = array_intersect($other_wildcard_attributes, $this_wildcard_attributes);
$other_wildcard_attributes = array_diff($other_wildcard_attributes, $in_both);
$this_wildcard_attributes = array_diff($this_wildcard_attributes, $in_both);
$wildcard_attributes_to_analyze = array_merge($other_wildcard_attributes, $this_wildcard_attributes);
if (empty($wildcard_attributes_to_analyze)) {
continue;
}
// Otherwise, the wildcard attribute name (f.e. `data-*`) is allowed in
// one of the two with the same attribute value restrictions (e.g. TRUE to
// allow all attribute values, or an array of specific allowed attribute
// values), and the intersection must contain the most restrictive
// configuration.
foreach ($wildcard_attributes_to_analyze as $wildcard_attribute_name) {
$other_has_wildcard = isset($other->elements[$tag][$wildcard_attribute_name]);
$wildcard_operand = $other_has_wildcard ? $other : $this;
$concrete_operand = $other_has_wildcard ? $this : $other;
$concrete_tag_config = $concrete_operand->elements[$tag];
$wildcard_attribute_restriction = $wildcard_operand->elements[$tag][$wildcard_attribute_name];
$regex = self::getRegExForWildCardAttributeName($wildcard_attribute_name);
foreach ($concrete_tag_config as $html_tag_attribute_name => $html_tag_attribute_restrictions) {
if ($html_tag_attribute_restrictions === $wildcard_attribute_restriction && preg_match($regex, $html_tag_attribute_name) === 1) {
$tag_config = $tag_config === FALSE ? [] : $tag_config;
$tag_config[$html_tag_attribute_name] = $html_tag_attribute_restrictions;
}
}
$intersection[$tag] = $tag_config;
}
}
return new self($intersection);
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.