You are here

public function FileDownloadLink::viewElements in File Download Link 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/FileDownloadLink.php, line 237

Class

FileDownloadLink
Plugin implementation of the 'file_download_link' formatter.

Namespace

Drupal\file_download_link\Plugin\Field\FieldFormatter

Code

public function viewElements(FieldItemListInterface $items, $langcode) {
  $elements = [];
  foreach ($this
    ->getEntitiesToView($items, $langcode) as $delta => $file) {

    // Options for the link, like classes.
    $mime_type_explosion = explode("/", $file
      ->getMimeType());
    $file_type = reset($mime_type_explosion);
    $file_extension = end($mime_type_explosion);
    $options = [
      'attributes' => [
        'class' => [
          'file-download',
          'file-download-' . $file_type,
          'file-download-' . $file_extension,
        ],
      ],
    ];
    if ($this
      ->getSetting('new_tab')) {
      $options['attributes']['target'] = '_blank';
    }
    if ($this
      ->getSetting('force_download')) {
      $options['attributes']['download'] = TRUE;
    }
    if ($this
      ->getSetting('link_title')) {
      $options['attributes']['title'] = $this
        ->getSetting('link_title');
    }

    // Make the render array.
    $elements[$delta] = [
      '#type' => 'link',
      '#title' => $this
        ->getSetting('link_text'),
      '#url' => Url::fromUri(file_create_url($file
        ->getFileUri())),
      '#options' => $options,
      '#cache' => [
        'tags' => $file
          ->getCacheTags(),
      ],
    ];

    // Deal with tokens for the text, title, and classes.
    if ($this->moduleHandler
      ->moduleExists('token')) {
      $data = [];
      $data[$this->tokenEntityMapper
        ->getTokenTypeForEntityType($file
        ->getEntityTypeId())] = $file;
      $entity = $items
        ->getEntity();
      $field = $this->fieldDefinition
        ->getName();
      $entity_token_type = $this->tokenEntityMapper
        ->getTokenTypeForEntityType($entity
        ->getEntityTypeId());
      $data[$entity_token_type] = $entity;
      $bubbleable_metadata = new BubbleableMetadata();

      // Link Text.
      if ($this
        ->getSetting('link_text')) {
        $text = $this
          ->getSetting('link_text');
        $text = $this
          ->addDeltaToTokens($text, $delta, $entity_token_type, $field);
        $text = $this->token
          ->replace($text, $data, [
          'langcode' => $langcode,
          'clear' => TRUE,
        ], $bubbleable_metadata);

        // Token encodes & and ' e.g. as & and '.
        $text = Html::decodeEntities($text);
        $elements[$delta]['#title'] = $text;
      }

      // Link title (attribute).
      if ($this
        ->getSetting('link_title')) {
        $title = $this
          ->getSetting('link_title');
        $title = $this
          ->addDeltaToTokens($title, $delta, $entity_token_type, $field);
        $title = $this->token
          ->replace($title, $data, [
          'langcode' => $langcode,
          'clear' => TRUE,
        ], $bubbleable_metadata);
        $title = Html::decodeEntities($title);
        if ($title) {
          $elements[$delta]['#options']['attributes']['title'] = $title;
        }
        else {
          unset($elements[$delta]['#options']['attributes']['title']);
        }
      }

      // Custom classes.
      if ($this
        ->getSetting('custom_classes')) {
        $custom_classes = $this
          ->getSetting('custom_classes');
        $custom_classes = $this
          ->addDeltaToTokens($custom_classes, $delta, $entity_token_type, $field);
        $custom_classes = $this->token
          ->replace($custom_classes, $data, [
          'langcode' => $langcode,
          'clear' => TRUE,
        ], $bubbleable_metadata);
        $custom_classes = Html::decodeEntities($custom_classes);

        // Custom classes are added to render array later.
      }

      // Next line is important. See https://www.drupal.org/node/2528662.
      $bubbleable_metadata
        ->applyTo($elements[$delta]);
    }

    // An empty title is replaced by filename.
    // Put this after token stuff to guard against cleared tokens.
    if (empty($elements[$delta]['#title'])) {
      $elements[$delta]['#title'] = $file
        ->getFilename();
    }

    // Custom classes are added now.
    if ($this
      ->getSetting('custom_classes')) {
      if (!isset($custom_classes)) {

        // $custom_classes is set if tokens have been replaced.
        $custom_classes = $this
          ->getSetting('custom_classes');
      }
      if (!empty($custom_classes)) {
        $classes = explode(" ", $custom_classes);
        foreach ($classes as $class) {
          $elements[$delta]['#options']['attributes']['class'][] = Html::cleanCssIdentifier($class);
        }
      }
    }
  }
  return $elements;
}