Verified Commit 3682bd29 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3278636 by nod_, Wim Leers, mrinalini9, bnjmnm:...

Issue #3278636 by nod_, Wim Leers, mrinalini9, bnjmnm: HTMLRestrictions::fromString() bug: multiple occurrences of same tag results in only last one being respected

(cherry picked from commit f7ef8451)
parent fe19730b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -629,7 +629,8 @@ media_media:
    class: Drupal\ckeditor5\Plugin\CKEditor5Plugin\Media
    elements:
      - <drupal-media>
      - <drupal-media data-entity-type data-entity-uuid alt data-view-mode>
      - <drupal-media data-entity-type data-entity-uuid alt>
      - <drupal-media data-view-mode>
    conditions:
      filter: media_embed

+3 −6
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\ckeditor5\Plugin\CKEditor5PluginDefinition;
use Drupal\ckeditor5\HTMLRestrictions;

/**
 * CKEditor 5 Media plugin.
@@ -194,14 +193,12 @@ public function getDynamicPluginConfig(array $static_plugin_config, EditorInterf
   * {@inheritdoc}
   */
  public function getElementsSubset(): array {
    $all_elements = $this->getPluginDefinition()->getElements();
    $subset = HTMLRestrictions::fromString(implode($all_elements));
    $subset = $this->getPluginDefinition()->getElements();
    $view_mode_override_enabled = $this->getConfiguration()['allow_view_mode_override'];
    if (!$view_mode_override_enabled) {
      $subset = $subset->diff(HTMLRestrictions::fromString('<drupal-media data-view-mode>'));
      $subset = array_diff($subset, ['<drupal-media data-view-mode>']);
    }
    // @todo Simplify in https://www.drupal.org/project/drupal/issues/3278636, that will allow removing all uses of HTMLRestrictions in this class.
    return array_merge(['<drupal-media>'], $subset->toCKEditor5ElementsArray());
    return $subset;
  }

  /**
+36 −2
Original line number Diff line number Diff line
@@ -302,6 +302,26 @@ public function providerConvenienceConstructors(): \Generator {
      '<ol type="I A 1">',
      ['ol' => ['type' => ['I' => TRUE, 'A' => TRUE, 1 => TRUE]]],
    ];
    yield 'tag with two attributes, spread across declarations' => [
      '<a target> <a class>',
      ['a' => ['target' => TRUE, 'class' => TRUE]],
    ];
    yield 'tag with conflicting attribute config, allow one attribute and forbid all attributes' => [
      '<a target> <a>',
      ['a' => ['target' => TRUE]],
    ];
    yield 'tag with conflicting attribute config, allow one attribute and allow all attributes' => [
      '<a *> <a target>',
      ['a' => TRUE],
    ];
    yield 'tag attribute configuration spread across declarations' => [
      '<a target="_blank"> <a target="_self"> <a target="_*">',
      ['a' => ['target' => ['_blank' => TRUE, '_self' => TRUE, '_*' => TRUE]]],
    ];
    yield 'tag attribute configuration spread across declarations, allow all attributes values' => [
      '<a target> <a target="_blank"> <a target="_self"> <a target="_*">',
      ['a' => ['target' => TRUE]],
    ];

    // Multiple tag cases.
    yield 'two tags' => [
@@ -309,8 +329,8 @@ public function providerConvenienceConstructors(): \Generator {
      ['a' => FALSE, 'p' => FALSE],
    ];
    yield 'two tags (reverse order)' => [
      '<a> <p>',
      ['a' => FALSE, 'p' => FALSE],
      '<p> <a>',
      ['p' => FALSE, 'a' => FALSE],
    ];

    // Wildcard tag, attribute and attribute value.
@@ -328,6 +348,20 @@ public function providerConvenienceConstructors(): \Generator {
        ],
      ],
    ];
    yield '$text-container, with attribute values spread across declarations' => [
      '<$text-container class="text-align-left"> <$text-container class="text-align-center"> <$text-container class="text-align-right"> <$text-container class="text-align-justify">',
      [],
      [
        '$text-container' => [
          'class' => [
            'text-align-left' => TRUE,
            'text-align-center' => TRUE,
            'text-align-right' => TRUE,
            'text-align-justify' => TRUE,
          ],
        ],
      ],
    ];
    yield '$text-container + one concrete tag to resolve into' => [
      '<p> <$text-container class="text-align-left text-align-center text-align-right text-align-justify">',
      [
+24 −0
Original line number Diff line number Diff line
@@ -135,6 +135,18 @@ public function providerGetDynamicPluginConfig(): array {
              [
                'name' => 'foo2',
                'attributes' => [
                  [
                    'key' => [
                      'regexp' => [
                        'pattern' => '/^bar-.*$/',
                      ],
                    ],
                    'value' => [
                      'regexp' => [
                        'pattern' => '/^(baz)$/',
                      ],
                    ],
                  ],
                  [
                    'key' => 'bar',
                    'value' => [
@@ -148,6 +160,18 @@ public function providerGetDynamicPluginConfig(): array {
              [
                'name' => 'foo3',
                'attributes' => [
                  [
                    'key' => [
                      'regexp' => [
                        'pattern' => '/^bar-.*$/',
                      ],
                    ],
                    'value' => [
                      'regexp' => [
                        'pattern' => '/^(baz|qux-.*)$/',
                      ],
                    ],
                  ],
                  [
                    'key' => 'bar',
                    'value' => [
+22 −4
Original line number Diff line number Diff line
@@ -266,12 +266,29 @@ public function getHTMLRestrictions() {
        continue;
      }
      $tag = $node->tagName;

      // All attributes are already allowed on this tag, this is the most
      // permissive configuration, no additional processing is required.
      if (isset($restrictions['allowed'][$tag]) && $restrictions['allowed'][$tag] === TRUE) {
        continue;
      }

      if ($node->hasAttributes()) {
        // Mark the tag as allowed, assigning TRUE for each attribute name if
        // all values are allowed, or an array of specific allowed values.
        // If the tag is not yet present, prepare to add attribute restrictions.
        // Otherwise, check if a more restrictive configuration (FALSE, meaning
        // no attributes were allowed) is present: then override the existing
        // value to prepare to add attribute restrictions.
        if (!isset($restrictions['allowed'][$tag]) || $restrictions['allowed'][$tag] === FALSE) {
          $restrictions['allowed'][$tag] = [];
        }

        // Iterate over any attributes, and mark them as allowed.
        foreach ($node->attributes as $name => $attribute) {
          // Only add specific attribute values if all values are not already
          // allowed.
          if (isset($restrictions['allowed'][$tag][$name]) && $restrictions['allowed'][$tag][$name] === TRUE) {
            continue;
          }
          // Put back any trailing * on wildcard attribute name.
          $name = str_replace($star_protector, '*', $name);

@@ -302,7 +319,8 @@ public function getHTMLRestrictions() {
          }
        }
      }
      else {

      if (empty($restrictions['allowed'][$tag])) {
        // Mark the tag as allowed, but with no attributes allowed.
        $restrictions['allowed'][$tag] = FALSE;
      }