You are here

public function LeafletDefaultFormatter::viewElements in Leaflet 8

Same name and namespace in other branches
  1. 2.1.x src/Plugin/Field/FieldFormatter/LeafletDefaultFormatter.php \Drupal\leaflet\Plugin\Field\FieldFormatter\LeafletDefaultFormatter::viewElements()
  2. 2.0.x src/Plugin/Field/FieldFormatter/LeafletDefaultFormatter.php \Drupal\leaflet\Plugin\Field\FieldFormatter\LeafletDefaultFormatter::viewElements()

This function is called from parent::view().

Overrides FormatterInterface::viewElements

File

src/Plugin/Field/FieldFormatter/LeafletDefaultFormatter.php, line 290

Class

LeafletDefaultFormatter
Plugin implementation of the 'leaflet_default' formatter.

Namespace

Drupal\leaflet\Plugin\Field\FieldFormatter

Code

public function viewElements(FieldItemListInterface $items, $langcode) {

  /* @var \Drupal\Core\Entity\EntityInterface $entity */
  $entity = $items
    ->getEntity();

  // Take the entity translation, if existing.

  /* @var \Drupal\Core\TypedData\TranslatableInterface $entity */
  if ($entity
    ->hasTranslation($langcode)) {
    $entity = $entity
      ->getTranslation($langcode);
  }
  $entity_type = $entity
    ->getEntityTypeId();
  $bundle = $entity
    ->bundle();
  $entity_id = $entity
    ->id();

  /* @var \Drupal\Core\Field\FieldDefinitionInterface $field */
  $field = $items
    ->getFieldDefinition();

  // Sets/consider possibly existing previous Zoom settings.
  $this
    ->setExistingZoomSettings();
  $settings = $this
    ->getSettings();

  // Performs some preprocess on the leaflet map settings.
  $this->leafletService
    ->preProcessMapSettings($settings);

  // Always render the map, even if we do not have any data.
  $map = leaflet_map_get_info($settings['leaflet_map']);

  // Add a specific map id.
  $map['id'] = Html::getUniqueId("leaflet_map_{$entity_type}_{$bundle}_{$entity_id}_{$field->getName()}");

  // Get and set the Geofield cardinality.
  $map['geofield_cardinality'] = $this->fieldDefinition
    ->getFieldStorageDefinition()
    ->getCardinality();

  // Set Map additional map Settings.
  $this
    ->setAdditionalMapOptions($map, $settings);

  // Get token context.
  $token_context = [
    'field' => $items,
    $this->fieldDefinition
      ->getTargetEntityTypeId() => $items
      ->getEntity(),
  ];
  $results = [];
  $features = [];
  foreach ($items as $delta => $item) {
    $points = $this->leafletService
      ->leafletProcessGeofield($item->value);
    $feature = $points[0];
    $feature['entity_id'] = $entity_id;

    // Eventually set the popup content.
    if ($settings['popup']) {

      // Construct the renderable array for popup title / text. As we later
      // convert that to plain text, losing attachments and cacheability, save
      // them to $results.
      $build = [];
      if ($this
        ->getSetting('popup_content')) {
        $bubbleable_metadata = new BubbleableMetadata();
        $popup_content = $this->token
          ->replace($this
          ->getSetting('popup_content'), $token_context, [
          'clear' => TRUE,
        ], $bubbleable_metadata);
        $build[] = [
          '#markup' => $popup_content,
        ];
        $bubbleable_metadata
          ->applyTo($results);
      }

      // We need a string for using it inside the popup. Save attachments and
      // cacheability to $results.
      $render_context = new RenderContext();
      $rendered = $this->renderer
        ->executeInRenderContext($render_context, function () use (&$build) {
        return $this->renderer
          ->render($build, TRUE);
      });
      $feature['popup'] = !empty($rendered) ? $rendered : $entity
        ->label();
      if (!$render_context
        ->isEmpty()) {
        $render_context
          ->update($results);
      }
    }

    // Add/merge eventual map icon definition from hook_leaflet_map_info.
    if (!empty($map['icon'])) {
      $settings['icon'] = $settings['icon'] ?: [];

      // Remove empty icon options so thxat they might be replaced by the
      // ones set by the hook_leaflet_map_info.
      foreach ($settings['icon'] as $k => $icon_option) {
        if (empty($icon_option) || is_array($icon_option) && $this->leafletService
          ->multipleEmpty($icon_option)) {
          unset($settings['icon'][$k]);
        }
      }
      $settings['icon'] = array_replace($map['icon'], $settings['icon']);
    }
    $icon_type = isset($settings['icon']['iconType']) ? $settings['icon']['iconType'] : 'marker';

    // Eventually set the custom Marker icon (DivIcon, Icon Url or
    // Circle Marker).
    if ($feature['type'] === 'point' && isset($settings['icon'])) {
      $feature['icon'] = $settings['icon'];
      switch ($icon_type) {
        case 'html':
          $feature['icon']['html'] = $this->token
            ->replace($settings['icon']['html'], $token_context);
          $feature['icon']['html_class'] = isset($settings['icon']['html_class']) ? $settings['icon']['html_class'] : '';
          break;
        case 'circle_marker':
          $feature['icon']['options'] = $this->token
            ->replace($settings['icon']['circle_marker_options'], $token_context);
          break;
        default:
          if (!empty($settings['icon']['iconUrl'])) {
            $feature['icon']['iconUrl'] = !empty($settings['icon']['iconUrl']) > 0 ? $this->token
              ->replace($settings['icon']['iconUrl'], $token_context) : '';
            if (!empty($settings['icon']['shadowUrl'])) {
              $feature['icon']['shadowUrl'] = !empty($settings['icon']['shadowUrl']) > 0 ? $this->token
                ->replace($settings['icon']['shadowUrl'], $token_context) : '';
            }
          }
          break;
      }
    }

    // Associate dynamic path properties (token based) to the feature,
    // in case of not point.
    if ($feature['type'] !== 'point') {
      $feature['path'] = str_replace([
        "\n",
        "\r",
      ], "", $this->token
        ->replace($settings['path'], $token_context));
    }
    $features[] = $feature;
  }
  $js_settings = [
    'map' => $map,
    'features' => $features,
  ];

  // Allow other modules to add/alter the map js settings.
  $this->moduleHandler
    ->alter('leaflet_default_map_formatter', $js_settings, $items);
  $map_height = !empty($settings['height']) ? $settings['height'] . $settings['height_unit'] : '';
  if (!empty($settings['multiple_map'])) {
    foreach ($js_settings['features'] as $k => $feature) {
      $map = $js_settings['map'];
      $map['id'] = $map['id'] . "-{$k}";
      $results[] = $this->leafletService
        ->leafletRenderMap($map, [
        $feature,
      ], $map_height);
    }
  }
  elseif (!empty($js_settings['features']) || empty($settings['hide_empty_map'])) {
    $results[] = $this->leafletService
      ->leafletRenderMap($js_settings['map'], $js_settings['features'], $map_height);
  }
  return $results;
}