Problem/Motivation

Merging
  1. ✅ Merging <a hreflang> and <a hreflang="en"> works fine.
  2. ✅ Merging <ol type> and <ol type="A"> works fine.
  3. ❌ Merging <ol type> and <ol type="1"> CRASHES.

Why?

Because https://3v4l.org/fVk1K.

GHS representation

Related: HtmlRestrictions::fromString('<ol type="1">')->toGeneralHtmlSupportConfig() fails with:

assert($value === TRUE || Inspector::assertAllStrings($value)) in core/modules/ckeditor5/src/HTMLRestrictions.php:1018

because its assumptions are incorrect, again because of https://3v4l.org/fVk1K.

Steps to reproduce

See #3261599-7: Use CKEditor 5's native <ol start> support (and also support <ol reversed>).

Proposed resolution

TBD

Remaining tasks

  • Tests.
  • Fix.

User interface changes

N/A

API changes

N/A

Data model changes

N/A

Release notes snippet

N/A

Comments

Wim Leers created an issue. See original summary.

wim leers’s picture

Status: Active » Needs review
StatusFileSize
new5.1 KB
wim leers’s picture

Title: \Drupal\ckeditor5\HTMLRestrictions::merge() fails to correctly merge allowed attribute values that can be interpreted as integers » HTMLRestrictions::merge() and ::toGeneralHtmlSupportConfig() fail on allowed attribute values that can be interpreted as integers
Issue summary: View changes
StatusFileSize
new1.02 KB
new5.69 KB

Actually, it's not just that. It's also ::toGeneralHtmlSupportConfig(). Adding test coverage for that too.

The last submitted patch, 2: 3274648-2.patch, failed testing. View results

wim leers’s picture

StatusFileSize
new804 bytes
new6.45 KB

At least #3 is a trivial fix. The assertion is pointless and wrong, so we can just remove it.

The last submitted patch, 3: 3274648-3.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 5: 3274648-4.patch, failed testing. View results

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

nod_’s picture

+++ b/core/modules/ckeditor5/tests/src/Unit/HTMLRestrictionsTest.php
@@ -854,6 +883,34 @@ public function providerOperands(): \Generator {
+    yield 'attribute restrictions are different: <ol type=*> vs <ol type="A"> — vice versa' => [
+      'b' => new HTMLRestrictions(['ol' => ['type' => ['A' => TRUE]]]),
+      'a' => new HTMLRestrictions(['ol' => ['type' => TRUE]]),
+      'diff' => 'a',
+      'intersection' => 'a',
+      'union' => 'b',
+    ];
...
+    yield 'attribute restrictions are different: <ol type=*> vs <ol type="1"> — vice versa' => [
+      'b' => new HTMLRestrictions(['ol' => ['type' => ['1' => TRUE]]]),
+      'a' => new HTMLRestrictions(['ol' => ['type' => TRUE]]),
+      'diff' => 'a',
+      'intersection' => 'a',
+      'union' => 'b',
+    ];

If I look at #3278394: HTMLRestrictions' diff operation bug: diff(<tag attr="A B">, <tag attr>) should return an empty result in those cases: diff should be HTMLRestrictions::emptySet() no?

wim leers’s picture

#9: Woah … yes indeed … 😬 Great find! Sorry for misleading you there 🙈

nod_’s picture

Status: Needs work » Needs review
StatusFileSize
new6.42 KB

Messed around with RecursiveIteratorIterator and RecursiveArrayIterator to replace array_merge_recursive but couldn't make it work like I want to. Anyway the fixed tests, still failing on merge as per the PHP issue.

wim leers’s picture

Messed around with RecursiveIteratorIterator and RecursiveArrayIterator to replace array_merge_recursive but couldn't make it work like I want to.

Too bad! 😬

Status: Needs review » Needs work

The last submitted patch, 11: core-html-3274648-11.patch, failed testing. View results

nod_’s picture

Status: Needs work » Needs review
StatusFileSize
new14.62 KB
new8.33 KB

Tried to go fancy when simple was enough. Many comments talk about strangeness of array_merge_recursive() so went for comparing the values directly instead of trying to infer what were the values based on the result.

the code style is pretty different than the other methods so might need some work, left most comments as-is so they're not accurate anymore. in any case it should be green.

Status: Needs review » Needs work

The last submitted patch, 14: core-html-3274648-14.patch, failed testing. View results

nod_’s picture

somehow that all pass locally :/

wim leers’s picture

Reproduced the failure locally on 9.5.x with both PHP 7.4 and 8.0.

wim leers’s picture

$ git log --oneline -n 1
47c9c02376 (HEAD -> 9.5.x, origin/9.5.x) Issue #3274651 by Wim Leers, nod_, alexpott: Impossible to enable <ol type> or <ul type> with GHS: switch to List's successor, DocumentList
$ php --version
PHP 8.0.12 (cli) (built: Oct 21 2021 14:38:26) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.12, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.12, Copyright (c), by Zend Technologies
$ curl -O https://www.drupal.org/files/issues/2022-05-28/core-html-3274648-14.patch
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 14968  100 14968    0     0  33410      0 --:--:-- --:--:-- --:--:-- 33336
$ git apply -3v core-html-3274648-14.patch
Checking patch core/drupalci.yml...
Applied patch to 'core/drupalci.yml' cleanly.
Checking patch core/modules/ckeditor5/src/HTMLRestrictions.php...
Applied patch to 'core/modules/ckeditor5/src/HTMLRestrictions.php' cleanly.
Checking patch core/modules/ckeditor5/tests/src/Unit/HTMLRestrictionsTest.php...
Applied patch to 'core/modules/ckeditor5/tests/src/Unit/HTMLRestrictionsTest.php' cleanly.
Checking patch core/package.json...
Applied patch to 'core/package.json' cleanly.
Applied patch core/drupalci.yml cleanly.
Applied patch core/modules/ckeditor5/src/HTMLRestrictions.php cleanly.
Applied patch core/modules/ckeditor5/tests/src/Unit/HTMLRestrictionsTest.php cleanly.
Applied patch core/package.json cleanly.
$ vendor/bin/phpunit --configuration core/phpunit.xml core/modules/ckeditor5/tests/src/Unit/HTMLRestrictionsTest.php
PHPUnit 8.5.26 #StandWithUkraine

Testing Drupal\Tests\ckeditor5\Unit\HTMLRestrictionsTest
............................................................F..  63 / 159 ( 39%)
..FF........................................................... 126 / 159 ( 79%)
.................................                               159 / 159 (100%)

Time: 4.47 seconds, Memory: 10.00 MB

There were 3 failures:

1) Drupal\Tests\ckeditor5\Unit\HTMLRestrictionsTest::testRepresentations with data set "realistic" (Drupal\ckeditor5\HTMLRestrictions Object (...), array('<a href hreflang="en fr">', '<p data-* class="block">', '<br>'), '<a href hreflang="en fr"> <p ...> <br>', array(array('a', array(array('href', true), array('hreflang', array(array('/^(en|fr)$/'))))), array('p', array(array(array(array('/^data-.*$/')), true)), array(array('/^(block)$/'))), array('br')))
assert($value === TRUE || $tag === '*' && $value === FALSE) in /Users/wim.leers/Work/d8/core/modules/ckeditor5/src/HTMLRestrictions.php:1100

/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/Framework/TestResult.php:737
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/Framework/TestSuite.php:626
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/Framework/TestSuite.php:626
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:659
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/TextUI/Command.php:235
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/TextUI/Command.php:194

2) Drupal\Tests\ckeditor5\Unit\HTMLRestrictionsTest::testRepresentations with data set "<h2 id="jump-*">" (Drupal\ckeditor5\HTMLRestrictions Object (...), array('<h2 id="jump-*">'), '<h2 id="jump-*">', array(array('h2', array(array('id', array(array('/^(jump-.*)$/')))))))
assert($value === TRUE || $tag === '*' && $value === FALSE) in /Users/wim.leers/Work/d8/core/modules/ckeditor5/src/HTMLRestrictions.php:1100

/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/Framework/TestResult.php:737
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/Framework/TestSuite.php:626
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/Framework/TestSuite.php:626
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:659
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/TextUI/Command.php:235
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/TextUI/Command.php:194

3) Drupal\Tests\ckeditor5\Unit\HTMLRestrictionsTest::testRepresentations with data set "<ol type="1 A">" (Drupal\ckeditor5\HTMLRestrictions Object (...), array('<ol type="1 A">'), '<ol type="1 A">', array(array('ol', array(array('type', array(array('/^(1|A)$/')))))))
assert($value === TRUE || $tag === '*' && $value === FALSE) in /Users/wim.leers/Work/d8/core/modules/ckeditor5/src/HTMLRestrictions.php:1100

/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/Framework/TestResult.php:737
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/Framework/TestSuite.php:626
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/Framework/TestSuite.php:626
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:659
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/TextUI/Command.php:235
/Users/wim.leers/Work/d8/vendor/phpunit/phpunit/src/TextUI/Command.php:194

FAILURES!
Tests: 159, Assertions: 528, Failures: 3.

Are you sure you have zend.assertions=1 in your php.ini?

nod_’s picture

Status: Needs work » Needs review
StatusFileSize
new14.46 KB
new1.31 KB

Yep, it was the assertions config.

wim leers’s picture

Priority: Normal » Major
Status: Needs review » Needs work
Issue tags: +blocker

This now blocks #3273983: Do not assume that plugin supporting <tag attr> also supports <tag> in SourceEditingRedundantTags and upgrade path, which is major and a stable blocker.

Review

As the author of the current \Drupal\ckeditor5\HTMLRestrictions::merge() (after having adapted it from @bnjmnm's code, but sprinkled a lot of extra complexity on it): thank you, this is MUCH simpler! 🤩🙏

Even the diffstat say this pretty objectively (when you exclude the new test cases and the DrupalCI changes to restrict to CKE5 tests only):

$ git diff HEAD
 core/modules/ckeditor5/src/HTMLRestrictions.php | 144 ++++++++++++++++++++++++---------------------------------
 1 file changed, 61 insertions(+), 83 deletions(-)
  1. +++ b/core/modules/ckeditor5/src/HTMLRestrictions.php
    @@ -694,113 +694,90 @@ public function doIntersect(HTMLRestrictions $other): HTMLRestrictions {
    +  private function _merge_config_arrays(array $array1, array $array2): array {
    

    Two things:
    A) this is stateless. So let's change this to static
    B) Drupal core does not use underscore-based naming in methods.

  2. +++ b/core/modules/ckeditor5/src/HTMLRestrictions.php
    @@ -694,113 +694,90 @@ public function doIntersect(HTMLRestrictions $other): HTMLRestrictions {
    +      // There is no keys in common, simply append the arrays.
    

    s/is/are/

  3. +++ b/core/modules/ckeditor5/src/HTMLRestrictions.php
    @@ -694,113 +694,90 @@ public function doIntersect(HTMLRestrictions $other): HTMLRestrictions {
    +      // There are some keys in common that needs to be merged.
    

    s/needs/need/

  4. +++ b/core/modules/ckeditor5/src/HTMLRestrictions.php
    @@ -694,113 +694,90 @@ public function doIntersect(HTMLRestrictions $other): HTMLRestrictions {
             // If the HTML tag restrictions for only one of the two operands was a
             // boolean, then the result of array_merge_recursive() is an array
             // containing the complete contents of the non-boolean operand plus an
             // additional key-value pair with the first numeric key: 0.
    

    Comment is outdated. Needs to be rewritten.

  5. +++ b/core/modules/ckeditor5/src/HTMLRestrictions.php
    @@ -694,113 +694,90 @@ public function doIntersect(HTMLRestrictions $other): HTMLRestrictions {
               // If the boolean was FALSE (meaning: "no attributes allowed"), then
               // the other operand's values should be used in an union: this yields
               // the most permissive result.
    

    Comment is outdated. Can be deleted altogether I think 🥳

nod_’s picture

Status: Needs work » Needs review
StatusFileSize
new11.96 KB
new6.94 KB

updated docs

nod_’s picture

StatusFileSize
new11.96 KB

phpcs

wim leers’s picture

Status: Needs review » Needs work

Final review round — will RTBC next 🤓 🥳

  1. +++ b/core/modules/ckeditor5/src/HTMLRestrictions.php
    @@ -693,6 +693,67 @@ public function doIntersect(HTMLRestrictions $other): HTMLRestrictions {
    +   * Merge the configuration array according to HTMLRestrictions rules.
    ...
    +   *   The first restriction array.
    ...
    +   *   The second restriction array.
    ...
    +  private static function mergeConfigurationElements(array $array1, array $array2): array {
    

    "configuration array" vs "restriction array" vs "configuration elements"

    Let's make these consistent.

    This is referring to \Drupal\filter\Plugin\FilterInterface::getHTMLRestrictions()'s "allowed elements".

    That's why \Drupal\ckeditor5\HTMLRestrictions::$elements is described as "An array of allowed elements."

    So I propose to call this mergeAllowedElementsLevel(). Why "level"? Because it is able to recurse one time, because this processes one level: either the tags' attributes, or the attributes' attribute values.

  2. +++ b/core/modules/ckeditor5/src/HTMLRestrictions.php
    @@ -1109,7 +1074,10 @@ public function toGeneralHtmlSupportConfig(): array {
    +            // transform the "1" string into 1 the number when it is used as an
    

    s/transform/transforms/

nod_’s picture

Status: Needs work » Needs review
StatusFileSize
new11.99 KB
new2.34 KB

Thanks for the pointers on docs :)

wim leers’s picture

Status: Needs review » Reviewed & tested by the community

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 24: core-html-3274648-24.patch, failed testing. View results

nod_’s picture

Status: Needs work » Reviewed & tested by the community

  • lauriii committed 94b5d57 on 10.0.x
    Issue #3274648 by nod_, Wim Leers: HTMLRestrictions::merge() and ::...

  • lauriii committed f7d9368 on 9.5.x
    Issue #3274648 by nod_, Wim Leers: HTMLRestrictions::merge() and ::...

  • lauriii committed 15be5c7 on 9.4.x
    Issue #3274648 by nod_, Wim Leers: HTMLRestrictions::merge() and ::...

  • lauriii committed fd25d63 on 9.3.x
    Issue #3274648 by nod_, Wim Leers: HTMLRestrictions::merge() and ::...
lauriii’s picture

Version: 9.5.x-dev » 9.3.x-dev
Status: Reviewed & tested by the community » Fixed

Committed 94b5d57 and pushed to 10.0.x. Cherry-picked to 9.5.x, 9.4.x and 9.3.x because this is a non-disruptive bug fix and CKEditor 5 is experimental. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.