You are here

public function CommonMap::render in Geolocation Field 8

Same name and namespace in other branches
  1. 8.3 src/Plugin/views/style/CommonMap.php \Drupal\geolocation\Plugin\views\style\CommonMap::render()

Render the display in this style.

Overrides StylePluginBase::render

File

src/Plugin/views/style/CommonMap.php, line 87

Class

CommonMap
Allow to display several field items on a common map.

Namespace

Drupal\geolocation\Plugin\views\style

Code

public function render() {
  if (!empty($this->options['geolocation_field'])) {
    $geo_field = $this->options['geolocation_field'];
  }
  else {
    \Drupal::logger('geolocation')
      ->error("The geolocation common map views style was called without a geolocation field defined in the views style settings.");
    return [];
  }
  if (!empty($this->options['title_field']) && $this->options['title_field'] != 'none') {
    $title_field = $this->options['title_field'];
  }
  if (!empty($this->options['icon_field']) && $this->options['icon_field'] != 'none') {
    $icon_field = $this->options['icon_field'];
  }
  if (!empty($this->options['marker_scroll_to_result']) && !empty($this->options['id_field']) && $this->options['id_field'] != 'none') {
    $id_field = $this->options['id_field'];
  }
  $map_id = $this->view->dom_id;
  $build = [
    '#theme' => $this->view
      ->buildThemeFunctions('geolocation_common_map_display'),
    '#view' => $this->view,
    '#id' => $map_id,
    '#attached' => [
      'library' => [
        'geolocation/geolocation.commonmap',
      ],
      'drupalSettings' => [
        'geolocation' => [
          'commonMap' => [
            $map_id => [
              'settings' => $this
                ->getGoogleMapsSettings($this->options),
            ],
          ],
          'google_map_url' => $this
            ->getGoogleMapsApiUrl(),
        ],
      ],
    ],
  ];

  // Add cache dependency for the view.
  $renderer = $this
    ->getRenderer();
  $renderer
    ->addCacheableDependency($build, $this->view->storage);
  if (!empty($this->options['show_raw_locations'])) {
    $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['showRawLocations'] = TRUE;
  }

  /*
   * Context popup content.
   */
  if (!empty($this->options['context_popup_content'])) {
    $context_popup_content = \Drupal::token()
      ->replace($this->options['context_popup_content']);
    $context_popup_content = PlainTextOutput::renderFromHtml($context_popup_content);
    $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['contextPopupContent'] = [];
    $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['contextPopupContent']['enable'] = TRUE;
    $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['contextPopupContent']['content'] = $context_popup_content;
  }

  /*
   * Marker clusterer.
   */
  if (!empty($this->options['marker_clusterer'])) {
    $build['#attached']['library'][] = 'geolocation/geolocation.markerclusterer';
    $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['markerClusterer'] = [];
    $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['markerClusterer']['enable'] = TRUE;
    $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['markerClusterer']['imagePath'] = $this->options['marker_clusterer_image_path'];
    if (!empty($this->options['marker_clusterer_styles'])) {
      $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['markerClusterer']['styles'] = json_decode($this->options['marker_clusterer_styles']);
    }
  }

  /*
   * Dynamic map handling.
   */
  if (!empty($this->options['dynamic_map']['enabled'])) {
    if (!empty($this->options['dynamic_map']['update_target']) && $this->view->displayHandlers
      ->has($this->options['dynamic_map']['update_target'])) {
      $update_view_display_id = $this->options['dynamic_map']['update_target'];
    }
    else {
      $update_view_display_id = $this->view->current_display;
    }
    $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['dynamic_map'] = [
      'enable' => TRUE,
      'hide_form' => $this->options['dynamic_map']['hide_form'],
      'views_refresh_delay' => $this->options['dynamic_map']['views_refresh_delay'],
      'update_view_id' => $this->view
        ->id(),
      'update_view_display_id' => $update_view_display_id,
    ];
    if (substr($this->options['dynamic_map']['update_handler'], 0, strlen('boundary_filter_')) === 'boundary_filter_') {
      $filter_id = substr($this->options['dynamic_map']['update_handler'], strlen('boundary_filter_'));
      $filters = $this->displayHandler
        ->getOption('filters');
      $filter_options = $filters[$filter_id];
      $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['dynamic_map'] += [
        'boundary_filter' => TRUE,
        'parameter_identifier' => $filter_options['expose']['identifier'],
      ];
    }
  }
  $this
    ->renderFields($this->view->result);

  /*
   * Add locations to output.
   */
  foreach ($this->view->result as $row_number => $row) {
    if (!empty($title_field)) {
      if (!empty($this->rendered_fields[$row_number][$title_field])) {
        $title_build = $this->rendered_fields[$row_number][$title_field];
      }
      elseif (!empty($this->view->field[$title_field])) {
        $title_build = $this->view->field[$title_field]
          ->render($row);
      }
    }
    if ($this->view->field[$geo_field] instanceof GeolocationField) {

      /** @var \Drupal\geolocation\Plugin\views\field\GeolocationField $geolocation_field */
      $geolocation_field = $this->view->field[$geo_field];
      $entity = $geolocation_field
        ->getEntity($row);
      if (isset($entity->{$geolocation_field->definition['field_name']})) {

        /** @var \Drupal\Core\Field\FieldItemListInterface $field_item_list */
        $geo_items = $entity->{$geolocation_field->definition['field_name']};
      }
      else {
        $geo_items = [];
      }
    }
    else {
      return $build;
    }
    if (!empty($id_field)) {
      $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['markerScrollToResult'] = TRUE;

      /** @var \Drupal\views\Plugin\views\field\Field $id_field_handler */
      $id_field_handler = $this->view->field[$id_field];
      if (!empty($id_field_handler)) {
        $location_id = $id_field_handler
          ->getValue($row);
      }
    }
    $icon_url = NULL;
    if (!empty($icon_field)) {

      /** @var \Drupal\views\Plugin\views\field\Field $icon_field_handler */
      $icon_field_handler = $this->view->field[$icon_field];
      if (!empty($icon_field_handler)) {
        $image_items = $icon_field_handler
          ->getItems($row);
        if (!empty($image_items[0]['rendered']['#item']->entity)) {
          $file_uri = $image_items[0]['rendered']['#item']->entity
            ->getFileUri();
          $style = NULL;
          if (!empty($image_items[0]['rendered']['#image_style'])) {

            /** @var \Drupal\image\Entity\ImageStyle $style */
            $style = ImageStyle::load($image_items[0]['rendered']['#image_style']);
          }
          if (!empty($style)) {
            $icon_url = file_url_transform_relative($style
              ->buildUrl($file_uri));
          }
          else {
            $icon_url = file_url_transform_relative(file_create_url($file_uri));
          }
        }
      }
    }

    /** @var \Drupal\geolocation\Plugin\Field\FieldType\GeolocationItem $item */
    foreach ($geo_items as $delta => $item) {
      $position = [
        'lat' => $item
          ->get('lat')
          ->getValue(),
        'lng' => $item
          ->get('lng')
          ->getValue(),
      ];
      $location = [
        '#theme' => 'geolocation_common_map_location',
        '#content' => $this->view->rowPlugin
          ->render($row),
        '#title' => empty($title_build) ? '' : $title_build,
        '#position' => $position,
      ];
      if (!empty($icon_url)) {
        $location['#icon'] = $icon_url;
      }
      else {
        if (!empty($this->options['google_map_settings']['marker_icon_path']) && !empty($this->rowTokens[$row_number])) {
          $icon_token_uri = $this
            ->viewsTokenReplace($this->options['google_map_settings']['marker_icon_path'], $this->rowTokens[$row_number]);
          $icon_token_url = file_create_url(trim($icon_token_uri));
          if ($icon_token_url) {
            $location['#icon'] = $icon_token_url;
          }
          else {
            try {
              $icon_token_url = Url::fromUri($icon_token_uri);
              if ($icon_token_url) {
                $location['#icon'] = $icon_token_url
                  ->setAbsolute(TRUE)
                  ->toString();
              }
            } catch (\Exception $e) {

              // User entered mal-formed URL, but that doesn't matter.
              // We hereby skip it anyway.
            }
          }
        }
      }
      if (!empty($location_id)) {
        $location['#location_id'] = $location_id;
      }
      if ($this->options['marker_row_number']) {
        $location['#marker_label'] = (int) $row_number + 1;
      }
      $build['#locations'][] = $location;
    }
  }
  $centre = NULL;
  $fitbounds = FALSE;

  // Maps will not load without any centre defined.
  if (!is_array($this->options['centre'])) {
    return $build;
  }

  /*
   * Centre handling.
   */
  foreach ($this->options['centre'] as $id => $option) {

    // Ignore if not enabled.
    if (empty($option['enable'])) {
      continue;
    }

    // Break if fitBounds is enabled, as it will supersede any other option.
    if ($fitbounds) {
      break;
    }
    elseif (isset($centre['lat']) && isset($centre['lng'])) {
      break;
    }
    elseif (isset($centre['lat_north_east']) && isset($centre['lng_north_east']) && isset($centre['lat_south_west']) && isset($centre['lng_south_west'])) {
      break;
    }
    switch ($id) {
      case 'fixed_value':
        $centre = [
          'lat' => (double) $option['settings']['latitude'],
          'lng' => (double) $option['settings']['longitude'],
        ];
        break;
      case 'first_row':
        if (!empty($build['#locations'][0]['#position'])) {
          $centre = $build['#locations'][0]['#position'];
        }
        break;
      case 'fit_bounds':

        // fitBounds will only work when at least one result is available.
        if (!empty($build['#locations'][0]['#position'])) {
          $fitbounds = TRUE;
        }
        break;
      case 'client_location':
        $build['#clientlocation'] = TRUE;
        $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['client_location'] = [
          'enable' => TRUE,
        ];
        if ($option['settings']['update_map']) {
          $build['#attached']['drupalSettings']['geolocation']['commonMap'][$map_id]['client_location']['update_map'] = TRUE;
        }
        break;

      /*
       * Handle the dynamic options.
       */
      default:
        if (preg_match('/proximity_filter_*/', $id)) {
          $filter_id = substr($id, 17);

          /** @var \Drupal\geolocation\Plugin\views\filter\ProximityFilter $handler */
          $handler = $this->displayHandler
            ->getHandler('filter', $filter_id);
          if (isset($handler->value['lat']) && isset($handler->value['lng'])) {
            $centre = [
              'lat' => (double) $handler
                ->getLatitudeValue(),
              'lng' => (double) $handler
                ->getLongitudeValue(),
            ];
          }
          break;
        }
        elseif (preg_match('/boundary_filter_*/', $id)) {
          $filter_id = substr($id, 16);

          /** @var \Drupal\geolocation\Plugin\views\filter\ProximityFilter $handler */
          $handler = $this->displayHandler
            ->getHandler('filter', $filter_id);
          if (isset($handler->value['lat_north_east']) && $handler->value['lat_north_east'] !== "" && isset($handler->value['lng_north_east']) && $handler->value['lng_north_east'] !== "" && isset($handler->value['lat_south_west']) && $handler->value['lat_south_west'] !== "" && isset($handler->value['lng_south_west']) && $handler->value['lng_south_west'] !== "") {
            $centre = [
              'lat_north_east' => (double) $handler->value['lat_north_east'],
              'lng_north_east' => (double) $handler->value['lng_north_east'],
              'lat_south_west' => (double) $handler->value['lat_south_west'],
              'lng_south_west' => (double) $handler->value['lng_south_west'],
            ];
          }
          break;
        }
    }
  }
  if (!empty($centre)) {
    $build['#centre'] = $centre ?: [
      'lat' => 0,
      'lng' => 0,
    ];
  }
  $build['#fitbounds'] = $fitbounds;
  return $build;
}