Skip to content
Snippets Groups Projects
Commit 099d151f authored by Ben Mullins's avatar Ben Mullins
Browse files

Issue #3231336 by Wim Leers, lauriii: Simplify HtmlRestrictions and...

Issue #3231336 by Wim Leers, lauriii: Simplify HtmlRestrictions and FundamentalCompatibilityConstraintValidator now that "forbidden tags" are deprecated
parent 5459c5fe
Branches
Tags
28 merge requests!8394[warning] array_flip(): Can only flip STRING and INTEGER values, when saving a non-revisionable custom content entity,!7780issue 3443822: fix for 'No route found for the specified format html. Supported formats: json, xml.',!7416Simplify the HTML of field.html.twig,!5013Issue #3071143: Table Render Array Example Is Incorrect,!4848Issue #1566662: Update module should send notifications on Thursdays,!4792Issue #2230689: Remove redundant "Italic" style,!4220Issue #3368223: Link field > Access to internal links is not checked on display.,!3884Issue #3356842,!3870Issue #3087868,!3812Draft: Issue #3339373 by alexpott, andypost, mondrake:...,!3686Issue #3219967 against 9.5.x,!3683Issue #2939397: Clearing AliasManager cache with root path raises warning,!3543Issue #3344259: Allow ajax dialog to have focus configurable,!3356Issue #3209129: Scrolling problems when adding a block via layout builder,!2921Issue #1383696: Allow a custom HTML element to be selected for a grouping field,!2920Issue #3260175: Saving media entity without an owner crashes,!2857Issue #3314541: Remove unnecessary fill from SVG icon for the "Media Library" CKEditor 5 button — enabling dark mode support in contrib,!2841Resolve #3296811 "Resourceresponsetrait needs a",!2803Issue #3041402: Add option absolute url in formatter URL to image,!2280Issue #3280415: Metapackage Generator Breaks Under Composer --no-dev,!2205Quote all names in the regions section.,!2050Issue #3272969: Remove UnqiueField constraint.,!1956Issue #3268872: hook_views_invalidate_cache not called when a view is deleted,!1893Issue #3217260: Add a way to make media captions not editable in CKEditor,!1459Issue #3087632: menu_name max length is too long,!878Issue #3221534: throw an exception when IDs passed to loadMultiple() are badly formed,!866Issue #2845319: The highlighting of the 'Home' menu-link does not respect query strings and fragment identifiers,!204Issue #3040556: It is not possible to react to an entity being duplicated
......@@ -38,9 +38,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 {
......@@ -308,7 +305,6 @@ public static function fromTextFormat(FilterFormatInterface $text_format): HTMLR
* @return \Drupal\ckeditor5\HTMLRestrictions
*/
private static function unrestricted(): self {
// @todo Refine in https://www.drupal.org/project/drupal/issues/3231336, including adding support for all operations.
$restrictions = HTMLRestrictions::emptySet();
$restrictions->unrestricted = TRUE;
return $restrictions;
......@@ -337,28 +333,20 @@ private static function fromObjectWithHtmlRestrictions(object $object): HTMLRest
throw new \InvalidArgumentException();
}
if ($object->getHtmlRestrictions() === FALSE) {
// @todo Refine in https://www.drupal.org/project/drupal/issues/3231336
return self::unrestricted();
}
$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.');
if ($restrictions === FALSE || $restrictions === []) {
return self::unrestricted();
}
// When allowing all tags on an attribute, transform FilterHtml output from
// ['tag' => ['*'=> TRUE]] to ['tag' => TRUE]
foreach ($restrictions['allowed'] as $element => $attributes) {
$allowed = $restrictions['allowed'];
foreach ($allowed as $element => $attributes) {
if (is_array($attributes) && isset($attributes['*']) && $attributes['*'] === TRUE) {
$restrictions['allowed'][$element] = TRUE;
$allowed[$element] = TRUE;
}
}
$allowed = $restrictions['allowed'];
return new self($allowed);
}
......
......@@ -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.
*
......
......@@ -119,27 +119,13 @@ private function checkNoMarkupFilters(FilterFormatInterface $text_format, Fundam
* The constraint to validate.
*/
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'])) {
$html_restrictions = HTMLRestrictions::fromTextFormat($text_format);
if ($html_restrictions->isUnrestricted()) {
return;
}
if (!$fundamental->diff(HTMLRestrictions::fromTextFormat($text_format))->allowsNothing()) {
$fundamental = new HTMLRestrictions($this->pluginManager->getProvidedElements(self::FUNDAMENTAL_CKEDITOR5_PLUGINS));
if (!$fundamental->diff($html_restrictions)->allowsNothing()) {
$offending_filter = static::findHtmlRestrictorFilterNotAllowingTags($text_format, $fundamental);
$this->context->buildViolation($constraint->nonAllowedElementsMessage)
->setParameter('%filter_label', (string) $offending_filter->getLabel())
......@@ -287,47 +273,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% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment