Как добавить nofollow для всех исходящих ссылок

Дубовской Александр
Team lead

Для этого достаточно добавить свой plugin для формата текста. Пример кода (файл /modules/custom/custom_output/src/Plugin/Filter) :

<?php
/**
 * @file
 * Contains \Drupal\custom_output\Plugin\Filter\FilterExternalLinks.
 */

namespace Drupal\custom_output\Plugin\Filter;

use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\filter\FilterProcessResult;
use Drupal\filter\Plugin\FilterBase;

/**
 * Provides a filter to add rel="nofollow" to external links.
 *
 * @Filter(
 *   id = "filter_external_links",
 *   title = @Translation("Add rel='nofollow' to external links"),
 *   type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_REVERSIBLE,
 *   settings = {
 *     "filter_external_links_nofollow" = TRUE,
 *     "filter_external_links_target" = TRUE,
 *   },
 *   weight = 10
 * )
 */
class FilterExternalLinks extends FilterBase {

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $form['filter_external_links_nofollow'] = array(
      '#type' => 'checkbox',
      '#title' => $this->t('Add rel="nofollow" to external links'),
      '#default_value' => $this->settings['filter_external_links_nofollow'],
    );
    $form['filter_external_links_target'] = array(
      '#type' => 'checkbox',
      '#title' => $this->t('Add target="_blank" attribute to external links'),
      '#default_value' => $this->settings['filter_external_links_target'],
    );
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function process($text, $langcode) {
    return new FilterProcessResult($this->filterLinkAttributes($text));
  }

  /**
   * Adds attributes rel="nofollow" and target="_blank" to external links.
   *
   * @param string $text
   *
   * @return string
   */
  public function filterLinkAttributes($text) {
    $html_dom = Html::load($text);
    $links = $html_dom->getElementsByTagName('a');

    foreach ($links as $link) {
      if (!$this->isExternalUrl($link->getAttribute('href'))) {
        continue;
      }
      if ($this->settings['filter_external_links_nofollow']) {
        $link->setAttribute('rel', 'nofollow');
      }
      if ($this->settings['filter_external_links_target']) {
        $link->setAttribute('target', '_blank');
      }
    }

    return trim(Html::serialize($html_dom));
  }

  /**
   * Returns TRUE if the given URI is considered internal, FALSE otherwise.
   *
   * @param type $uri
   *
   * @return boolean
   */
  public function isExternalUrl($uri) {
    $uri_domain = parse_url($uri, PHP_URL_HOST);

    try {
      $url = Url::fromUri($uri);
    }
    catch (\InvalidArgumentException $e) {
      return FALSE;
    }
    return $url->isExternal();
  }

}

 

В результате добавится такой вариант в настройках формата текста (/admin/config/content/formats):