Unverified Commit ce0ec61f authored by Lauri Timmanee's avatar Lauri Timmanee
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
parent b091beee
Loading
Loading
Loading
Loading
+32 −17
Original line number Diff line number Diff line
@@ -468,7 +468,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;
@@ -476,17 +477,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);
@@ -500,7 +506,17 @@ function ($value, string $tag) use ($other) {
            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;
      }
@@ -508,7 +524,6 @@ function ($value, string $tag) use ($other) {
        unset($diff_elements[$tag]);
      }
    }
    }

    return new self($diff_elements);
  }
@@ -622,9 +637,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.
@@ -780,9 +795,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.
+2 −2
Original line number Diff line number Diff line
@@ -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]]),
    ];
+6 −6
Original line number Diff line number Diff line
@@ -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,
          ],
        ],
      ],