Unverified Commit b077d55c authored by lauriii's avatar lauriii
Browse files

Issue #3278394 by Wim Leers, bnjmnm: HTMLRestrictions' diff operation bug:...

Issue #3278394 by Wim Leers, bnjmnm: HTMLRestrictions' diff operation bug: diff(<tag attr="A B">, <tag attr>) should return an empty result

(cherry picked from commit ce0ec61f)
parent 9cc4bbec
......@@ -477,7 +477,8 @@ function ($value, string $tag) use ($other) {
return FALSE;
}
// Both objects have lists of allowed attributes: keep the DiffArray
// result.
// 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;
......@@ -485,17 +486,22 @@ function ($value, string $tag) use ($other) {
ARRAY_FILTER_USE_BOTH
);
// Special case: wildcard attributes, and the ability to define restrictions
// for all concrete attributes matching them using:
// - prefix wildcard, f.e. `data-*`, to match `data-foo`, `data-bar`, etc.
// - infix wildcard, f.e. `*-entity-*`
// - suffix wildcard, f.e. `foo-*`
// 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 wildcard attribute postprocessing is needed.
if (!(isset($other->elements[$tag]) && is_array($other->elements[$tag]))) {
// 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);
......@@ -509,14 +515,23 @@ function ($value, string $tag) use ($other) {
unset($tag_config[$html_tag_attribute_name]);
}
}
}
if ($tag_config !== []) {
$diff_elements[$tag] = $tag_config;
}
else {
unset($diff_elements[$tag]);
// 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);
......@@ -631,9 +646,9 @@ public function doIntersect(HTMLRestrictions $other): HTMLRestrictions {
// Special case: wildcard attributes, and the ability to define restrictions
// for all concrete attributes matching them using:
// - prefix wildcard, f.e. `data-*`, to match `data-foo`, `data-bar`, etc.
// - prefix wildcard, f.e. `*-foo`
// - infix wildcard, f.e. `*-entity-*`
// - suffix wildcard, f.e. `foo-*`
// - 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.
......@@ -789,9 +804,9 @@ public function merge(HTMLRestrictions $other): HTMLRestrictions {
// Special case: wildcard attributes, and the ability to define restrictions
// for all concrete attributes matching them using:
// - prefix wildcard, f.e. `data-*`, to match `data-foo`, `data-bar`, etc.
// - prefix wildcard, f.e. `*-foo`
// - infix wildcard, f.e. `*-entity-*`
// - suffix wildcard, f.e. `foo-*`
// - suffix wildcard, f.e. `data-*`, to match `data-foo`, `data-bar`, etc.
foreach ($union as $tag => $tag_config) {
// If there are no per-attribute restrictions for this tag, then no
// wildcard attribute postprocessing is needed.
......
......@@ -902,7 +902,7 @@ public function providerOperands(): \Generator {
yield 'attribute restrictions are different: <a hreflang=*> vs <a hreflang="en"> — vice versa' => [
'a' => new HTMLRestrictions(['a' => ['hreflang' => ['en' => TRUE]]]),
'b' => new HTMLRestrictions(['a' => ['hreflang' => TRUE]]),
'diff' => 'a',
'diff' => HTMLRestrictions::emptySet(),
'intersection' => 'a',
'union' => 'b',
];
......@@ -1196,7 +1196,7 @@ public function providerOperands(): \Generator {
yield 'global attribute tag + global attribute tag: overlap in attributes, different attribute value restrictions' => [
'a' => new HTMLRestrictions(['*' => ['foo' => TRUE, 'bar' => FALSE, 'dir' => ['ltr' => TRUE, 'rtl' => TRUE]]]),
'b' => new HTMLRestrictions(['*' => ['bar' => TRUE, 'dir' => TRUE, 'foo' => FALSE]]),
'diff' => 'a',
'diff' => new HTMLRestrictions(['*' => ['foo' => TRUE, 'bar' => FALSE]]),
'intersection' => new HTMLRestrictions(['*' => ['bar' => FALSE, 'dir' => ['ltr' => TRUE, 'rtl' => TRUE], 'foo' => FALSE]]),
'union' => new HTMLRestrictions(['*' => ['foo' => TRUE, 'bar' => TRUE, 'dir' => TRUE]]),
];
......
......@@ -200,15 +200,15 @@ public function providerCandidates(): \Generator {
// Because `<foo bar="a">` allowed.
'a' => [
TRUE => [
'test_attr_values' => 1002,
'test_tags_and_attr_values' => 2002102,
'test_attr_values' => 0,
'test_tags_and_attr_values' => 2001100,
],
],
// Because `<foo bar="b">` allowed.
'b' => [
TRUE => [
'test_attr_values' => 1002,
'test_tags_and_attr_values' => 2002102,
'test_attr_values' => 0,
'test_tags_and_attr_values' => 2001100,
],
],
],
......@@ -216,9 +216,9 @@ public function providerCandidates(): \Generator {
'-attributes-none-' => [
'test_all_attrs' => 100000,
'test_attrs' => 1100,
'test_attr_values' => 1002,
'test_attr_values' => 0,
'test_tags_and_attrs' => 2001100,
'test_tags_and_attr_values' => 2002102,
'test_tags_and_attr_values' => 2001100,
],
],
],
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment