Commit 35b8d4f5 authored by catch's avatar catch
Browse files

Issue #3272516 by Wim Leers, yogeshmpawar, bnjmnm, catch: Deprecate...

Issue #3272516 by Wim Leers, yogeshmpawar, bnjmnm, catch: Deprecate FilterInterface::getHTMLRestrictions()' forbidden_tags functionality
parent 13645eaf
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -37,9 +37,6 @@
 *
 * @see ::WILDCARD_ELEMENT_METHODS
 *
 * NOTE: Currently only supports the 'allowed' portion.
 * @todo Add support for "forbidden" tags in https://www.drupal.org/project/drupal/issues/3231336
 *
 * @internal
 */
final class HTMLRestrictions {
@@ -341,12 +338,6 @@ private static function fromObjectWithHtmlRestrictions(object $object): HTMLRest
    }

    $restrictions = $object->getHTMLRestrictions();
    if (!isset($restrictions['allowed'])) {
      // @todo Handle HTML restrictor filters that only set forbidden_tags
      //   https://www.drupal.org/project/ckeditor5/issues/3231336.
      throw new \DomainException('text formats with only filters that forbid tags rather than allowing tags are not yet supported.');
    }

    $allowed = $restrictions['allowed'];

    return new self($allowed);
+0 −7
Original line number Diff line number Diff line
@@ -25,13 +25,6 @@ class FundamentalCompatibilityConstraint extends Constraint {
   */
  public $noMarkupFiltersMessage = 'CKEditor 5 only works with HTML-based text formats. The "%filter_label" (%filter_plugin_id) filter implies this text format is not HTML anymore.';

  /**
   * The violation message when fundamental HTML elements are forbidden.
   *
   * @var string
   */
  public $forbiddenElementsMessage = 'CKEditor 5 needs at least the <p> and <br> tags to be allowed to be able to function. They are forbidden by the "%filter_label" (%filter_plugin_id) filter.';

  /**
   * The violation message when fundamental HTML elements are not allowed.
   *
+0 −56
Original line number Diff line number Diff line
@@ -114,22 +114,7 @@ private function checkNoMarkupFilters(FilterFormatInterface $text_format, Fundam
   */
  private function checkHtmlRestrictionsAreCompatible(FilterFormatInterface $text_format, FundamentalCompatibilityConstraint $constraint): void {
    $fundamental = new HTMLRestrictions($this->pluginManager->getProvidedElements(self::FUNDAMENTAL_CKEDITOR5_PLUGINS));

    // @todo Remove in favor of HTMLRestrictions::diff() in https://www.drupal.org/project/drupal/issues/3231336
    $html_restrictions = $text_format->getHtmlRestrictions();
    $minimum_tags = array_keys($fundamental->getAllowedElements());
    $forbidden_minimum_tags = isset($html_restrictions['forbidden_tags'])
      ? array_diff($minimum_tags, $html_restrictions['forbidden_tags'])
      : [];
    if (!empty($forbidden_minimum_tags)) {
      $offending_filter = static::findHtmlRestrictorFilterForbiddingTags($text_format, $minimum_tags);
      $this->context->buildViolation($constraint->forbiddenElementsMessage)
        ->setParameter('%filter_label', (string) $offending_filter->getLabel())
        ->setParameter('%filter_plugin_id', $offending_filter->getPluginId())
        ->addViolation();
    }

    // @todo Remove early return in https://www.drupal.org/project/drupal/issues/3231336
    if (!isset($html_restrictions['allowed'])) {
      return;
    }
@@ -212,47 +197,6 @@ private static function getFiltersInFormatOfType(FilterFormatInterface $text_for
    }
  }

  /**
   * Analyzes a text format to find the filter not allowing required tags.
   *
   * @param \Drupal\filter\FilterFormatInterface $text_format
   *   A text format whose filters to check for compatibility.
   * @param string[] $required_tags
   *   A list of HTML tags that are required.
   *
   * @return \Drupal\filter\Plugin\FilterInterface
   *   The filter plugin instance not allowing the required tags.
   *
   * @throws \InvalidArgumentException
   */
  private static function findHtmlRestrictorFilterForbiddingTags(FilterFormatInterface $text_format, array $required_tags): FilterInterface {
    // Get HTML restrictor filters that actually restrict HTML.
    $filters = static::getFiltersInFormatOfType(
      $text_format,
      FilterInterface::TYPE_HTML_RESTRICTOR,
      function (FilterInterface $filter) {
        return $filter->getHTMLRestrictions() !== FALSE;
      }
    );

    foreach ($filters as $filter) {
      $restrictions = $filter->getHTMLRestrictions();

      // @todo Fix
      //   \Drupal\filter_test\Plugin\Filter\FilterTestRestrictTagsAndAttributes::getHTMLRestrictions(),
      //   whose computed value for forbidden_tags does not comply with the API
      //   https://www.drupal.org/project/drupal/issues/3231331.
      if (array_keys($restrictions['forbidden_tags']) != range(0, count($restrictions['forbidden_tags']))) {
        $restrictions['forbidden_tags'] = array_keys($restrictions['forbidden_tags']);
      }
      if (isset($restrictions['forbidden_tags']) && !empty(array_intersect($required_tags, $restrictions['forbidden_tags']))) {
        return $filter;
      }
    }

    throw new \InvalidArgumentException('This text format does not have a "tags forbidden" restriction that includes the required tags.');
  }

  /**
   * Analyzes a text format to find the filter not allowing required tags.
   *
+0 −27
Original line number Diff line number Diff line
@@ -462,33 +462,6 @@ public function providerPair(): array {
      ],
      'violations' => [],
    ];
    $data['INVALID: forbidden tags'] = [
      'settings' => [
        'toolbar' => [
          'items' => [],
        ],
        'plugins' => [],
      ],
      'image_upload' => [
        'status' => FALSE,
      ],
      'filters' => [
        'filter_test_restrict_tags_and_attributes' => [
          'id' => 'filter_test_restrict_tags_and_attributes',
          'provider' => 'filter_test',
          'status' => TRUE,
          'weight' => 0,
          'settings' => [
            'restrictions' => [
              'forbidden_tags' => ['p' => FALSE],
            ],
          ],
        ],
      ],
      'violations' => [
        '' => 'CKEditor 5 needs at least the &lt;p&gt; and &lt;br&gt; tags to be allowed to be able to function. They are forbidden by the "<em class="placeholder">Tag and attribute restricting filter</em>" (<em class="placeholder">filter_test_restrict_tags_and_attributes</em>) filter.',
      ],
    ];
    $restricted_html_format_filters = Yaml::parseFile(__DIR__ . '/../../../../../profiles/standard/config/install/filter.format.restricted_html.yml')['filters'];
    $data['INVALID: the default restricted_html text format'] = [
      'settings' => [
+3 −37
Original line number Diff line number Diff line
@@ -42,9 +42,9 @@ public static function filterXss($html, FilterFormatInterface $format, FilterFor
    // <embed>, for example? Then we would strip that tag, even though it is
    // allowed, thereby causing data loss!
    // Therefore, we want to be smarter still. We want to take into account
    // which HTML tags are allowed and forbidden by the text format we're
    // filtering for, and if we're switching from another text format, we want
    // to take that format's allowed and forbidden tags into account as well.
    // which HTML tags are allowed by the text format we're filtering for, and
    // if we're switching from another text format, we want to take that
    // format's allowed tags into account as well.
    // In other words: we only expect markup allowed in both the original and
    // the new format to continue to exist.
    $format_restrictions = $format->getHtmlRestrictions();
@@ -52,17 +52,6 @@ public static function filterXss($html, FilterFormatInterface $format, FilterFor
      $original_format_restrictions = $original_format->getHtmlRestrictions();
    }

    // Any tags that are explicitly blacklisted by the text format must be
    // appended to the list of default dangerous tags: if they're explicitly
    // forbidden, then we must respect that configuration.
    // When switching from another text format, we must use the union of
    // forbidden tags: if either text format is more restrictive, then the
    // safety expectations of *both* text formats apply.
    $forbidden_tags = self::getForbiddenTags($format_restrictions);
    if ($original_format !== NULL) {
      $forbidden_tags = array_merge($forbidden_tags, self::getForbiddenTags($original_format_restrictions));
    }

    // Any tags that are explicitly whitelisted by the text format must be
    // removed from the list of default dangerous tags: if they're explicitly
    // allowed, then we must respect that configuration.
@@ -78,9 +67,6 @@ public static function filterXss($html, FilterFormatInterface $format, FilterFor
    // formats.
    $blacklisted_tags = array_diff($dangerous_tags, $allowed_tags);

    // Also blacklist tags that are explicitly forbidden in either text format.
    $blacklisted_tags = array_merge($blacklisted_tags, $forbidden_tags);

    $output = static::filter($html, $blacklisted_tags);

    // Since data-attributes can contain encoded HTML markup that could be
@@ -140,26 +126,6 @@ protected static function getAllowedTags($restrictions) {
    return $allowed_tags;
  }

  /**
   * Get all forbidden tags from a restrictions data structure.
   *
   * @param array|false $restrictions
   *   Restrictions as returned by FilterInterface::getHTMLRestrictions().
   *
   * @return array
   *   An array of forbidden HTML tags.
   *
   * @see \Drupal\filter\Plugin\Filter\FilterInterface::getHTMLRestrictions()
   */
  protected static function getForbiddenTags($restrictions) {
    if ($restrictions === FALSE || !isset($restrictions['forbidden_tags'])) {
      return [];
    }
    else {
      return $restrictions['forbidden_tags'];
    }
  }

  /**
   * {@inheritdoc}
   */
Loading