You are here

public function FilterFormat::getHtmlRestrictions in Zircon Profile 8.0

Same name and namespace in other branches
  1. 8 core/modules/filter/src/Entity/FilterFormat.php \Drupal\filter\Entity\FilterFormat::getHtmlRestrictions()

Retrieve all HTML restrictions (tags and attributes) for the text format.

Note that restrictions applied to the "*" tag (the wildcard tag, i.e. all tags) are treated just like any other HTML tag. That means that any restrictions applied to it are not automatically applied to all other tags. It is up to the caller to handle this in whatever way it sees fit; this way no information granularity is lost.

Return value

array|FALSE A structured array as returned by FilterInterface::getHTMLRestrictions(), but with the intersection of all filters in this text format. Will either indicate blacklisting of tags or whitelisting of tags. In the latter case, it's possible that restrictions on attributes are also stored. FALSE means there are no HTML restrictions.

Overrides FilterFormatInterface::getHtmlRestrictions

File

core/modules/filter/src/Entity/FilterFormat.php, line 275
Contains \Drupal\filter\Entity\FilterFormat.

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();

      // The first filter with HTML restrictions provides the initial set.
      if (!isset($restrictions)) {
        return $new_restrictions;
      }
      else {

        // Track the union of forbidden (blacklisted) 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 (whitelisted) tags.
        if (isset($restrictions['allowed'])) {
          $intersection = $restrictions['allowed'];
          foreach ($intersection as $tag => $attributes) {

            // If the current tag is not whitelisted 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 whitelisted 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;
              }
              else {
                if (!is_array($current_attributes) && $current_attributes == TRUE && ($new_attributes == FALSE || is_array($new_attributes))) {
                  $intersection[$tag] = $new_attributes;
                }
                else {
                  if (is_array($current_attributes) && $new_attributes == FALSE) {
                    $intersection[$tag] = $new_attributes;
                  }
                  else {
                    if (is_array($current_attributes) && $new_attributes == TRUE) {
                      continue;
                    }
                    else {
                      if ($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 a (intersected) whitelist and a (unioned)
    // blacklist, then remove any tags from the whitelist that also exist in the
    // blacklist. Now the whitelist alone expresses all tag-level restrictions,
    // and we can delete the blacklist.
    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 only
    // whitelisting filters were used, 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'] = array();
      }
    }
    return $restrictions;
  }
}