You are here

public function GeneralEmailFormatter::viewElements in Formatter Suite 8

Builds a renderable array for a field value.

Parameters

\Drupal\Core\Field\FieldItemListInterface $items: The field values to be rendered.

string $langcode: The language that should be used to render the field.

Return value

array A renderable array for $items, as an array of child elements keyed by consecutive numeric indexes starting from 0.

Overrides FormatterInterface::viewElements

File

src/Plugin/Field/FieldFormatter/GeneralEmailFormatter.php, line 359

Class

GeneralEmailFormatter
Formats an email address.

Namespace

Drupal\formatter_suite\Plugin\Field\FieldFormatter

Code

public function viewElements(FieldItemListInterface $items, $langcode) {
  if ($items
    ->isEmpty() === TRUE) {
    return [];
  }

  // Prepare custom classes, if any.
  $classes = $this
    ->getSetting('classes');
  if (empty($classes) === TRUE) {
    $classes = [];
  }
  else {

    // Security: Class names are entered by an administrator.
    // They may not include anything but CSS-compatible words, and
    // certainly no HTML.
    //
    // Here, the class text is stripped of HTML tags as a start.
    // A regex tosses unacceptable characters in a CSS class name.
    $classes = strip_tags($classes);
    $classes = mb_ereg_replace('[^_a-zA-Z0-9- ]', '', $classes);
    if ($classes === FALSE) {
      $classes = [];
    }
    $classes = explode(' ', $classes);
  }
  $elements = [];
  foreach ($items as $delta => $item) {

    //
    // Get the link title.
    // -------------------
    // Use custom text, text from the link, or the URL. If custom text
    // is selected, but there isn't any, fall through to text from the
    // link. If there is none of that, fall through to the URL.
    switch ($this
      ->getSetting('emailStyle')) {
      case 'custommailto':

        // Security: Custom text is entered by an administrator.
        // It may legitimately include HTML entities and minor HTML, but
        // it should not include dangerous HTML.
        //
        // Because it may include HTML, we cannot pass it directly as
        // the '#title' on a link, which will escape the HTML.
        //
        // We therefore use an Xss admin filter to remove any egreggious
        // HTML (such as scripts and styles), and then FormattableMarkup()
        // to mark the resulting text as safe.
        $title = Xss::filterAdmin($this
          ->getSetting('linkText'));
        if (empty($title) === FALSE) {
          $title = new FormattableMarkup($title, []);
          $elements[$delta] = [
            '#type' => 'link',
            '#title' => $title,
            '#url' => Url::fromUri('mailto:' . $item->value),
            '#attributes' => [
              'class' => $classes,
            ],
          ];
          break;
        }

      // Fall-through and use the email address as the title text.
      case 'mailto':

        // Security: The email address in the field is entered by a user.
        // It needs to be a properly-formed address, and it certainly
        // should not include HTML.
        //
        // Url::fromUri() will check that the URL is well-formed and
        // throw an exception if it is not. We catch that and note the
        // problem in the rendered output.
        //
        // Including the email address in the '#title' field insures
        // that it will have any embedded HTML escaped.
        try {
          $url = Url::fromUri('mailto:' . $item->value);
          $elements[$delta] = [
            '#type' => 'link',
            '#title' => $item->value,
            '#url' => $url,
            '#attributes' => [
              'class' => $classes,
            ],
          ];
        } catch (\Exception $e) {

          // The URL with the email address is malformed.
          $title = $this
            ->t('Malformed email address: "@address"', [
            '@address' => $item->value,
          ]);
          $elements[$delta] = [
            '#type' => 'html_tag',
            '#tag' => 'span',
            '#value' => $title,
            '#attributes' => [
              'class' => $classes,
            ],
          ];
        }
        break;
      case 'plain':

        // Security: The email address in the field is entered by a user.
        // It needs to be a properly-formed address, and it certainly
        // should not include HTML.
        //
        // Including the email address in the '#title' field insures
        // that it will have any embedded HTML escaped.
        foreach ($items as $delta => $item) {
          $elements[$delta] = [
            '#type' => 'html_tag',
            '#tag' => 'span',
            '#value' => $item->value,
            '#attributes' => [
              'class' => $classes,
            ],
          ];
        }
        break;
    }
  }
  if (empty($elements) === TRUE) {
    return [];
  }

  //
  // Add multi-value field processing.
  // ---------------------------------
  // If the field has multiple values, redirect to a theme and pass
  // the list style and separator.
  $isMultiple = $this->fieldDefinition
    ->getFieldStorageDefinition()
    ->isMultiple();
  if ($isMultiple === TRUE) {

    // Replace the 'field' theme with one that supports lists.
    $elements['#theme'] = 'formatter_suite_field_list';

    // Set the list style.
    $elements['#list_style'] = $this
      ->getSetting('listStyle');

    // Set the list separator.
    //
    // Security: The list separator is entered by an administrator.
    // It may legitimately include HTML entities and minor HTML, but
    // it should not include dangerous HTML.
    //
    // Because it may include HTML, we cannot pass it as-is and let a TWIG
    // template use {{ }}, which will process the text and corrupt any
    // entered HTML or HTML entities.
    //
    // We therefore use an Xss admin filter to remove any egreggious HTML
    // (such as scripts and styles), and then FormattableMarkup() to mark the
    // resulting text as safe.
    $listSeparator = Xss::filterAdmin($this
      ->getSetting('listSeparator'));
    $elements['#list_separator'] = new FormattableMarkup($listSeparator, []);
  }
  return $elements;
}