You are here

OpenlayersMap.php in Openlayers 8.4

File

src/Plugin/views/style/OpenlayersMap.php
View source
<?php

/**
 * @file
 * Definition of Drupal\openlayers\Plugin\views\style\OpenlayersMap.
 */
namespace Drupal\openlayers\Plugin\views\style;

use Drupal\core\form\FormStateInterface;
use Drupal\views\Plugin\views\style\StylePluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\openlayers\OpenlayersService;
use Drupal\openlayers\MapSettings;
use Drupal\openlayers\OpenlayersMapOptionsTrait;

/**
 * Style plugin to render geodata on an Openlayers map.
 *
 * @ingroup views_style_plugins
 *
 * @ViewsStyle(
 *   id = "openlayers_map",
 *   title = @Translation("Openlayers map"),
 *   help = @Translation("Returns views results plotted on an Openlayers map."),
 *   theme = "openlayers-map",
 *   display_types = { "normal" }
 * )
 *
 */
class OpenlayersMap extends StylePluginBase {
  use OpenlayersMapOptionsTrait;

  /**
   * The Entity Field manager service property.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * Openlayers service.
   *
   * @var \Drupal\Openlayers\OpenlayersService
   */
  protected $openlayersService;

  /**
   * Constructs a Openlayers Map object.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityFieldManagerInterface $entity_field_manager, OpenlayersService $openlayers_service) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityFieldManager = $entity_field_manager;
    $this->openlayersService = $openlayers_service;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container
      ->get('entity_field.manager'), $container
      ->get('openlayers.service'));
  }

  /**
   * Overrides \Drupal\views\Plugin\views\style\StylePluginBase\StylePluginBase::defineOptions().
   */
  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['data_source'] = array(
      'default' => '',
    );
    $options['height'] = array(
      'default' => '400',
    );
    $options['height_unit'] = array(
      'default' => 'px',
    );
    return $options;
  }

  /**
   * Overrides \Drupal\views\Plugin\views\style\StylePluginBase\StylePluginBase::buildOptionsForm().
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);
    $options = $this->displayHandler
      ->getFieldLabels(TRUE);

    // Get a sublist of geo data fields in the view.
    $fields_geo_data = $this
      ->getAvailableDataSources();
    $form['data_source'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Geodata Source'),
      '#description' => $this
        ->t('Select the field containing geodata that you wish to use.'),
      '#options' => $fields_geo_data,
      '#default_value' => $this->options['data_source'],
      '#required' => TRUE,
      '#weight' => -10,
    ];

    // Include the Openlayers Map general options.
    $this
      ->includeGeneralOptions($form, $this->options);
  }

  /**
   * Overrides \Drupal\views\Plugin\views\style\StylePluginBase\StylePluginBase::render().
   */
  public function render() {
    $results = [];
    $features = [];
    $this
      ->renderFields($this->view->result);
    $geofield_name = $this->options['data_source'];
    $map_id = $this->options['map'];
    $map_height = $this->options['height'] . $this->options['height_unit'];

    /* @var \Drupal\views\ResultRow $result */
    foreach ($this->view->result as $id => $view_result) {

      // Ensure $geofield_values is an array, for both single value and multi-value fields
      $geofield_values = (array) $this
        ->getFieldValue($view_result->index, $geofield_name);
      foreach ($geofield_values as $geofield_value) {
        $features[] = [
          'type' => 'wkt',
          'value' => $geofield_value,
        ];
      }
    }

    //  Now prepare to display the map using the Views result
    $map_settings = new MapSettings($map_id);
    $map = $map_settings->settings;
    $map['id'] = $map_id;
    $js_settings = [
      'map' => $map,
      'features' => $features,
    ];
    $results[] = $this->openlayersService
      ->openlayersRenderMap($js_settings['map'], $js_settings['features'], $map_height);
    return $results;
  }

  /**
   * {@inheritdoc}
   */
  public function evenEmpty() {
    return TRUE;
  }

  /**
   * Get a list of fields and a sublist of geo data fields in this view.
   *
   * @return array
   *   Available data sources.
   */
  protected function getAvailableDataSources() {
    $fields_geo_data = [];

    /* @var \Drupal\views\Plugin\views\ViewsHandlerInterface $handler) */
    foreach ($this->displayHandler
      ->getHandlers('field') as $field_id => $handler) {
      $label = $handler
        ->adminLabel() ?: $field_id;
      $this->viewFields[$field_id] = $label;
      if (is_a($handler, '\\Drupal\\views\\Plugin\\views\\field\\EntityField')) {

        /* @var \Drupal\views\Plugin\views\field\EntityField $handler */
        try {
          $entity_type = $handler
            ->getEntityType();
        } catch (\Exception $e) {
          $entity_type = NULL;
        }
        $field_storage_definitions = $this->entityFieldManager
          ->getFieldStorageDefinitions($entity_type);
        $field_storage_definition = $field_storage_definitions[$handler->definition['field_name']];
        $type = $field_storage_definition
          ->getType();
        if (in_array($type, [
          'geofield',
          'geolocation',
        ])) {
          $fields_geo_data[$field_id] = $label;
        }
      }
    }
    return $fields_geo_data;
  }

}

Classes

Namesort descending Description
OpenlayersMap Style plugin to render geodata on an Openlayers map.