function FilterFormat::getHtmlRestrictions

Same name and namespace in other branches
  1. 8.9.x core/modules/filter/src/Entity/FilterFormat.php \Drupal\filter\Entity\FilterFormat::getHtmlRestrictions()
  2. 10 core/modules/filter/src/Entity/FilterFormat.php \Drupal\filter\Entity\FilterFormat::getHtmlRestrictions()
  3. 11.x core/modules/filter/src/Entity/FilterFormat.php \Drupal\filter\Entity\FilterFormat::getHtmlRestrictions()

Overrides FilterFormatInterface::getHtmlRestrictions

File

core/modules/filter/src/Entity/FilterFormat.php, line 278

Class

FilterFormat
Represents a text format.

Namespace

Drupal\filter\Entity

Code

public function getHtmlRestrictions() {
    // Ignore filters that are disabled or don't have HTML restrictions.
    $filters = array_filter($this->filters()
        ->getAll(), function ($filter) {
        if (!$filter->status) {
            return FALSE;
        }
        if ($filter->getType() === FilterInterface::TYPE_HTML_RESTRICTOR && $filter->getHTMLRestrictions() !== FALSE) {
            return TRUE;
        }
        return FALSE;
    });
    if (empty($filters)) {
        return FALSE;
    }
    else {
        // From the set of remaining filters (they were filtered by array_filter()
        // above), collect the list of tags and attributes that are allowed by all
        // filters, i.e. the intersection of all allowed tags and attributes.
        $restrictions = array_reduce($filters, function ($restrictions, $filter) {
            $new_restrictions = $filter->getHTMLRestrictions();
            if (isset($new_restrictions['forbidden_tags'])) {
                @trigger_error('forbidden_tags for FilterInterface::getHTMLRestrictions() is deprecated in drupal:9.4.0 and is removed from drupal:10.0.0', E_USER_DEPRECATED);
            }
            // The first filter with HTML restrictions provides the initial set.
            if (!isset($restrictions)) {
                return $new_restrictions;
            }
            else {
                // Track the union of forbidden tags.
                if (isset($new_restrictions['forbidden_tags'])) {
                    if (!isset($restrictions['forbidden_tags'])) {
                        $restrictions['forbidden_tags'] = $new_restrictions['forbidden_tags'];
                    }
                    else {
                        $restrictions['forbidden_tags'] = array_unique(array_merge($restrictions['forbidden_tags'], $new_restrictions['forbidden_tags']));
                    }
                }
                // Track the intersection of allowed tags.
                if (isset($restrictions['allowed'])) {
                    $intersection = $restrictions['allowed'];
                    foreach ($intersection as $tag => $attributes) {
                        // If the current tag is not allowed by the new filter, then it's
                        // outside of the intersection.
                        if (!array_key_exists($tag, $new_restrictions['allowed'])) {
                            // The exception is the asterisk (which applies to all tags): it
                            // does not need to be allowed by every filter in order to be
                            // used; not every filter needs attribute restrictions on all tags.
                            if ($tag === '*') {
                                continue;
                            }
                            unset($intersection[$tag]);
                        }
                        else {
                            $current_attributes = $intersection[$tag];
                            $new_attributes = $new_restrictions['allowed'][$tag];
                            // The current intersection does not allow any attributes, never
                            // allow.
                            if (!is_array($current_attributes) && $current_attributes == FALSE) {
                                continue;
                            }
                            elseif (!is_array($current_attributes) && $current_attributes == TRUE && ($new_attributes == FALSE || is_array($new_attributes))) {
                                $intersection[$tag] = $new_attributes;
                            }
                            elseif (is_array($current_attributes) && $new_attributes == FALSE) {
                                $intersection[$tag] = $new_attributes;
                            }
                            elseif (is_array($current_attributes) && $new_attributes == TRUE) {
                                continue;
                            }
                            elseif ($current_attributes == $new_attributes) {
                                continue;
                            }
                            else {
                                $intersection[$tag] = array_intersect_key($intersection[$tag], $new_attributes);
                                foreach (array_keys($intersection[$tag]) as $attribute_value) {
                                    $intersection[$tag][$attribute_value] = $intersection[$tag][$attribute_value] && $new_attributes[$attribute_value];
                                }
                            }
                        }
                    }
                    $restrictions['allowed'] = $intersection;
                }
                return $restrictions;
            }
        }, NULL);
        // Simplification: if we have both allowed (intersected) and forbidden
        // (unioned) tags, then remove any allowed tags that are also forbidden.
        // Once complete, the list of allowed tags expresses all tag-level
        // restrictions, and the list of forbidden tags can be removed.
        if (isset($restrictions['allowed']) && isset($restrictions['forbidden_tags'])) {
            foreach ($restrictions['forbidden_tags'] as $tag) {
                if (isset($restrictions['allowed'][$tag])) {
                    unset($restrictions['allowed'][$tag]);
                }
            }
            unset($restrictions['forbidden_tags']);
        }
        // Simplification: if the only remaining allowed tag is the asterisk
        // (which contains attribute restrictions that apply to all tags), and
        // there are no forbidden tags, then effectively nothing is allowed.
        if (isset($restrictions['allowed'])) {
            if (count($restrictions['allowed']) === 1 && array_key_exists('*', $restrictions['allowed']) && !isset($restrictions['forbidden_tags'])) {
                $restrictions['allowed'] = [];
            }
        }
        return $restrictions;
    }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.