You are here

public function BgImageFormatter::viewElements in Background Images Formatter 8

Same name and namespace in other branches
  1. 8.3 src/Plugin/Field/FieldFormatter/BgImageFormatter.php \Drupal\bg_image_formatter\Plugin\Field\FieldFormatter\BgImageFormatter::viewElements()
  2. 8.2 src/Plugin/Field/FieldFormatter/BgImageFormatter.php \Drupal\bg_image_formatter\Plugin\Field\FieldFormatter\BgImageFormatter::viewElements()

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 ImageFormatter::viewElements

1 method overrides BgImageFormatter::viewElements()
ResponsiveBgImageFormatter::viewElements in modules/responsive_bg_image_formatter/src/Plugin/Field/FieldFormatter/ResponsiveBgImageFormatter.php
Builds a renderable array for a field value.

File

src/Plugin/Field/FieldFormatter/BgImageFormatter.php, line 515

Class

BgImageFormatter
Class BgImageFormatter.

Namespace

Drupal\bg_image_formatter\Plugin\Field\FieldFormatter

Code

public function viewElements(FieldItemListInterface $items, $langcode) {
  $elements = [];
  $settings = $this
    ->getSettings();
  $css_settings = $settings['css_settings'];

  // Replace views tokens.
  $selector = $css_settings['bg_image_selector'];
  $token_start = mb_strpos($selector, '{{');
  if ($token_start !== FALSE) {
    $token_length = mb_strpos($selector, '}}') - mb_strpos($selector, '{{') + 2;
    $token = mb_substr($selector, mb_strpos($selector, '{{'), $token_length);
    $cleaned_token = trim(str_replace([
      '{{',
      '}}',
    ], '', $token));
    $entity = $items
      ->getEntity();
    if ($entity->{$cleaned_token} && $entity->{$cleaned_token}->value) {
      $selector = str_replace($token, $entity->{$cleaned_token}->value, $selector);
      $css_settings['bg_image_selector'] = $selector;
    }
  }
  $image_style = $settings['image_style'] ? $settings['image_style'] : NULL;
  $path_format = $css_settings['bg_image_path_format'];
  $selectors = explode(\PHP_EOL, trim($css_settings['bg_image_selector']));
  $colors = explode(\PHP_EOL, trim($css_settings['bg_image_color']));

  // Filter out empty selectors.
  $selectors = array_map(static function ($value) {
    return trim($value, ',');
  }, $selectors);

  // Filter out empty colors.
  $colors = array_filter(array_map('trim', $colors));
  $files = $this
    ->getEntitiesToView($items, $langcode);

  // Early opt-out if the field is empty.
  if (empty($files)) {
    return $elements;
  }

  // Prepare token data in bg image css selector.
  $token_data = [
    'user' => Drupal::currentUser(),
    $items
      ->getEntity()
      ->getEntityTypeId() => $items
      ->getEntity(),
  ];
  foreach ($selectors as &$selector) {
    $selector = Drupal::token()
      ->replace($selector, $token_data);
  }

  // Need an empty element so views renderer will see something to render.
  $elements[0] = [];
  foreach ($files as $delta => $file) {
    $css_settings['bg_image_selector'] = $selectors[$delta % \count($selectors)];
    if ($colors) {
      $css_settings['bg_image_color'] = $colors[$delta % \count($colors)];
    }
    if ($image_style) {
      $style = $this->imageStyleStorage
        ->load($image_style);
      $file_url = $style
        ->buildUrl($file
        ->getFileUri());
    }
    else {
      $file_url = file_create_url($file
        ->getFileUri());
    }
    $image_url = $path_format === 'absolute' ? $file_url : file_url_transform_relative($file_url);
    $css = $this
      ->getBackgroundImageCss($image_url, $css_settings);

    // Define unique key to prevent collisions when displaying multiple
    // background images on the same page.
    $html_head_key = 'bg_image_formatter_css__s' . sha1(implode('__', [
      $items
        ->getEntity()
        ->uuid(),
      $items
        ->getName(),
      $settings['image_style'],
      $delta,
    ]));
    $style_element = [
      '#type' => 'html_tag',
      '#tag' => 'style',
      '#attributes' => [
        'media' => $css['media'],
      ],
      '#value' => Markup::create($css['style']),
    ];
    if ($this
      ->isAjax() || $this->request
      ->isXmlHttpRequest()) {
      $elements['#attached']['drupalSettings']['bg_image_formatter_css'][$html_head_key] = $this->renderer
        ->renderPlain($style_element);
    }
    else {
      $elements['#attached']['html_head'][] = [
        $style_element,
        $html_head_key,
      ];
    }
  }
  return $elements;
}