geofield_map-8.x-2.67/src/Plugin/Field/FieldFormatter/GeofieldGoogleMapFormatter.php
src/Plugin/Field/FieldFormatter/GeofieldGoogleMapFormatter.php
<?php
namespace Drupal\geofield_map\Plugin\Field\FieldFormatter;
use Drupal\geofield_map\GeofieldMapFieldTrait;
use Drupal\geofield_map\GeofieldMapFormElementsValidationTrait;
use Drupal\Component\Utility\Html;
use Drupal\Core\Url;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Utility\LinkGeneratorInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\geofield\GeoPHP\GeoPHPInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\geofield_map\Services\GoogleMapsService;
use Drupal\Core\Render\Markup;
use Drupal\geofield_map\Services\MarkerIconService;
use Drupal\Core\Utility\Token;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
/**
* Plugin implementation of the 'geofield_google_map' formatter.
*
* @FieldFormatter(
* id = "geofield_google_map",
* label = @Translation("Geofield Google Map"),
* field_types = {
* "geofield"
* }
* )
*/
class GeofieldGoogleMapFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
use GeofieldMapFieldTrait;
use GeofieldMapFormElementsValidationTrait;
/**
* Empty Map Options.
*
* @var array
*/
protected $emptyMapOptions = [
'0' => 'Empty field',
'1' => 'Custom Message',
'2' => 'Empty Map Centered at the Default Center',
];
/**
* The Default Settings.
*
* @var array
*/
protected $defaultSettings;
/**
* The config factory service.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $config;
/**
* Entity manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Entity display repository.
*
* @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
*/
protected $entityDisplayRepository;
/**
* The Link generator Service.
*
* @var \Drupal\Core\Utility\LinkGeneratorInterface
*/
protected $link;
/**
* The EntityField Manager service.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager;
/**
* The geoPhpWrapper service.
*
* @var \Drupal\geofield\GeoPHP\GeoPHPInterface
*/
protected $geoPhpWrapper;
/**
* The Renderer service property.
*
* @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
*/
protected $renderer;
/**
* The module handler to invoke the alter hook.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The token service.
*
* @var \Drupal\core\Utility\Token
*/
protected $token;
/**
* The geofieldMapGoogleMaps service.
*
* @var \Drupal\geofield_map\Services\GoogleMapsService
*/
protected $googleMapsService;
/**
* The Icon Managed File Service.
*
* @var \Drupal\geofield_map\Services\MarkerIconService
*/
protected $markerIcon;
/**
* GeofieldGoogleMapFormatter constructor.
*
* @param string $plugin_id
* The plugin_id for the formatter.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The definition of the field to which the formatter is associated.
* @param array $settings
* The formatter settings.
* @param string $label
* The formatter label display setting.
* @param string $view_mode
* The view mode.
* @param array $third_party_settings
* Any third party settings.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* A config factory for retrieving required config objects.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The Translation service.
* @param \Drupal\Core\Utility\LinkGeneratorInterface $link_generator
* The Link Generator service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* Entity type manager service.
* @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
* Entity display repository service.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
* The Entity Field Manager.
* @param \Drupal\geofield\GeoPHP\GeoPHPInterface $geophp_wrapper
* The geoPhpWrapper.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The Renderer service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\core\Utility\Token $token
* The token service.
* @param \Drupal\geofield_map\Services\GoogleMapsService $google_maps_service
* The Google Maps service.
* @param \Drupal\geofield_map\Services\MarkerIconService $marker_icon_service
* The Marker Icon Service.
*/
public function __construct(
$plugin_id,
$plugin_definition,
FieldDefinitionInterface $field_definition,
array $settings,
$label,
$view_mode,
array $third_party_settings,
ConfigFactoryInterface $config_factory,
TranslationInterface $string_translation,
LinkGeneratorInterface $link_generator,
EntityTypeManagerInterface $entity_type_manager,
EntityDisplayRepositoryInterface $entity_display_repository,
EntityFieldManagerInterface $entity_field_manager,
GeoPHPInterface $geophp_wrapper,
RendererInterface $renderer,
ModuleHandlerInterface $module_handler,
Token $token,
GoogleMapsService $google_maps_service,
MarkerIconService $marker_icon_service,
) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
$this->defaultSettings = self::getDefaultSettings();
$this->config = $config_factory;
$this->link = $link_generator;
$this->entityTypeManager = $entity_type_manager;
$this->entityDisplayRepository = $entity_display_repository;
$this->entityFieldManager = $entity_field_manager;
$this->geoPhpWrapper = $geophp_wrapper;
$this->renderer = $renderer;
$this->moduleHandler = $module_handler;
$this->token = $token;
$this->googleMapsService = $google_maps_service;
$this->markerIcon = $marker_icon_service;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['label'],
$configuration['view_mode'],
$configuration['third_party_settings'],
$container->get('config.factory'),
$container->get('string_translation'),
$container->get('link_generator'),
$container->get('entity_type.manager'),
$container->get('entity_display.repository'),
$container->get('entity_field.manager'),
$container->get('geofield.geophp'),
$container->get('renderer'),
$container->get('module_handler'),
$container->get('token'),
$container->get('geofield_map.google_maps'),
$container->get('geofield_map.marker_icon')
);
}
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return self::getDefaultSettings() + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$default_settings = self::defaultSettings();
$settings = $this->getSettings();
$elements = [];
if ($this->moduleHandler->moduleExists('token')) {
$elements['replacement_patterns'] = [
'#type' => 'details',
'#title' => 'Replacement patterns',
'#description' => $this->t('The following replacement tokens are available for the "Icon Image Path" and the "Map Geometries Options" options'),
];
$elements['replacement_patterns']['token_help'] = [
'#theme' => 'token_tree_link',
'#token_types' => [$this->fieldDefinition->getTargetEntityTypeId()],
];
}
else {
$elements['replacement_patterns']['#description'] = $this->t('The @token_link is needed to browse and use @entity_type entity token replacements.', [
'@token_link' => $this->link->generate($this->t('Token module'), Url::fromUri('https://www.drupal.org/project/token', [
'absolute' => TRUE,
'attributes' => ['target' => 'blank'],
])),
'@entity_type' => $this->fieldDefinition->getTargetEntityTypeId(),
]);
}
$elements += $this->generateGMapSettingsForm($form, $form_state, $settings, $default_settings);
$elements['#attached'] = [
'library' => [
'geofield_map/geofield_map_view_display_settings',
],
];
// Define a specific default_icon_image_mode that consider icon_image_path
// eventually set previously to its select introduction.
$init_icon_image_mode = !empty($settings['map_marker_and_infowindow']['icon_image_path']) ? 'icon_image_path' : $default_settings['map_marker_and_infowindow']['icon_image_mode'];
$default_icon_image_mode = !empty($settings['map_marker_and_infowindow']['icon_image_mode']) ? $settings['map_marker_and_infowindow']['icon_image_mode'] : $init_icon_image_mode;
$geofield_id = $this->fieldDefinition->getName();
$form_state->setTemporaryValue('geofield_id', $geofield_id);
// Get the eventual ajax user input of the icon_image_mode field.
$user_input = $form_state->getUserInput();
$user_input_icon_image_mode = $user_input['fields'][$geofield_id]['settings_edit_form']['settings']['map_marker_and_infowindow']['icon_image_mode'] ?? NULL;
$selected_icon_image_mode = $user_input_icon_image_mode ?? $default_icon_image_mode;
$elements['map_marker_and_infowindow']['icon_image_mode'] = [
'#title' => $this->t('Custom Icon definition mode'),
'#type' => 'select',
'#options' => [
'icon_file' => $this->t('Icon File'),
'icon_image_path' => $this->t('Icon Image Path'),
],
'#default_value' => $selected_icon_image_mode,
'#description' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => Markup::create('choose method between:<br><b>Icon Image Path:</b> Point the image url (absolute or relative to Drupal root folder)<br><b>Icon Image File:</b> Upload an Icon Image into Drupal application</li>'),
],
'#weight' => $elements['map_marker_and_infowindow']['icon_image_path']['#weight'] - 2,
'#ajax' => [
'callback' => [static::class, 'iconImageModeUpdate'],
'effect' => 'fade',
],
];
$file_upload_help = $this->markerIcon->getFileUploadHelp();
$fid = (integer) !empty($settings['map_marker_and_infowindow']['icon_file_wrapper']['icon_file']['fids']) ? $settings['map_marker_and_infowindow']['icon_file_wrapper']['icon_file']['fids'] : NULL;
$elements['map_marker_and_infowindow']['icon_file_wrapper'] = [
'#type' => 'container',
'label' => [
'#markup' => Markup::create($this->t('<label>Custom Icon Image File</label>')),
],
'description' => [
'#markup' => Markup::create($this->t('The chosen icon file will be used as Marker for this content @file_upload_help', [
'@file_upload_help' => $this->renderer->renderPlain($file_upload_help),
])),
],
'icon_file' => $this->markerIcon->getIconFileManagedElement($fid),
'image_style' => [
'#type' => 'select',
'#title' => $this->t('Image style'),
'#options' => $this->markerIcon->getImageStyleOptions(),
'#default_value' => $settings['map_marker_and_infowindow']['icon_file_wrapper']['image_style'] ?? 'geofield_map_default_icon_style',
'#states' => [
'visible' => [
':input[name="fields[field_geofield][settings_edit_form][settings][map_marker_and_infowindow][icon_file_wrapper][icon_file][is_svg]"]' => ['checked' => FALSE],
],
],
],
'image_style_svg' => [
'#type' => 'container',
'warning' => [
'#markup' => $this->t("Image style cannot apply to SVG Files,<br>SVG natural dimension will be applied."),
],
'#states' => [
'invisible' => [
':input[name="fields[field_geofield][settings_edit_form][settings][map_marker_and_infowindow][icon_file_wrapper][icon_file][is_svg]"]' => ['checked' => FALSE],
],
],
],
'#weight' => $elements['map_marker_and_infowindow']['icon_image_mode']['#weight'] + 1,
];
if ($selected_icon_image_mode != 'icon_file') {
$elements['map_marker_and_infowindow']['icon_file_wrapper']['#attributes']['class'] = ['hidden'];
}
if ($selected_icon_image_mode != 'icon_image_path') {
$elements['map_marker_and_infowindow']['icon_image_path']['#prefix'] = '<div id="icon-image-path" class="visually-hidden">';
$elements['map_marker_and_infowindow']['icon_image_path']['#suffix'] = '</div>';
}
return $elements + parent::settingsForm($form, $form_state);
}
/**
* Ajax callback triggered Icon Image Option Selection.
*
* @param array $form
* The build form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* Ajax response with updated form element.
*/
public static function iconImageModeUpdate(array $form, FormStateInterface $form_state) {
$response = new AjaxResponse();
$geofield_id = $form_state->getTemporaryValue('geofield_id');
// Define the data to replace, evaluating also the use case tge form is
// being updated as Layout Builder block.
$data = $form["#id"] === 'layout-builder-update-block' ? $form['settings']['formatter']['settings_wrapper']['settings']['map_marker_and_infowindow'] : $form['fields'][$geofield_id]['plugin']['settings_edit_form']['settings']['map_marker_and_infowindow'];
if (!is_null($data)) {
$response->addCommand(new ReplaceCommand(
'#map-marker-and-infowindow-wrapper',
$data,
));
}
return $response;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$default_settings = self::defaultSettings();
$settings = $this->getSettings();
// Define a specific default_icon_image_mode that consider icon_image_path
// eventually set previously to its select introduction.
$default_icon_image_mode = !empty($settings['map_marker_and_infowindow']['icon_image_path']) ? 'icon_image_path' : $default_settings['map_marker_and_infowindow']['icon_image_mode'];
$map_dimensions = [
'#markup' => $this->t('Map Dimensions: Width: @width - Height: @height', [
'@width' => $settings['map_dimensions']['width'],
'@height' => $settings['map_dimensions']['height'],
]),
];
$map_empty = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Behaviour for the Empty Map: @state', ['@state' => $this->emptyMapOptions[$settings['map_empty']['empty_behaviour']]]),
];
if ($settings['map_empty']['empty_behaviour'] === '1') {
$map_empty['message'] = [
'#markup' => $this->t('Empty Field Message: Width: @state', ['@state' => $settings['map_empty']['empty_message']]),
];
}
$map_center = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Map Default Center: @state_lat, @state_lon', [
'@state_lat' => $settings['map_center']['lat'],
'@state_lon' => $settings['map_center']['lon'],
]),
'center_force' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Force Map Center: @state', ['@state' => $settings['map_center']['center_force'] ? $this->t('Yes') : $this->t('No')]),
],
];
$map_zoom_and_pan = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => '<u>' . $this->t('Map Zoom and Pan:') . '</u>',
'zoom' => [
'initial' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Start Zoom: @state', ['@state' => $settings['map_zoom_and_pan']['zoom']['initial']]),
],
'force' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Force Start Zoom: @state', ['@state' => $settings['map_zoom_and_pan']['zoom']['force'] ? $this->t('Yes') : $this->t('No')]),
],
'min' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Min Zoom: @state', ['@state' => $settings['map_zoom_and_pan']['zoom']['min']]),
],
'max' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Max Zoom: @state', ['@state' => $settings['map_zoom_and_pan']['zoom']['max']]),
],
],
'scrollwheel' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Scrollwheel: @state', ['@state' => $settings['map_zoom_and_pan']['scrollwheel'] ? $this->t('Yes') : $this->t('No')]),
],
'draggable' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Draggable: @state', ['@state' => $settings['map_zoom_and_pan']['draggable'] ? $this->t('Yes') : $this->t('No')]),
],
'map_reset' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Map Reset Control: @state', ['@state' => !empty($settings['map_zoom_and_pan']['map_reset']) ? $this->t('Yes') : $this->t('No')]),
],
];
// Remove the unselected array keys
// from the map_type_control_options_type_ids.
$map_type_control_options_type_ids = array_filter($settings['map_controls']['map_type_control_options_type_ids'], function ($value) {
return $value !== 0;
});
$map_controls = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => '<u>' . $this->t('Map Controls:') . '</u>',
'disable_default_ui' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Disable Default UI: @state', ['@state' => $settings['map_controls']['disable_default_ui'] ? $this->t('Yes') : $this->t('No')]),
],
'map_type_id' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Default Map Type: @state', ['@state' => $settings['map_controls']['map_type_id']]),
],
];
if (!$settings['map_controls']['disable_default_ui']) {
$map_controls['zoom_control'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Zoom Control: @state', ['@state' => $settings['map_controls']['zoom_control'] ? $this->t('Yes') : $this->t('No')]),
];
$map_controls['map_type_control'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Map Type Control: @state', ['@state' => $settings['map_controls']['map_type_control'] ? $this->t('Yes') : $this->t('No')]),
];
$map_controls['map_type_control_options_type_ids'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $settings['map_controls']['map_type_control'] ? $this->t('Enabled Map Types: @state', ['@state' => implode(', ', array_keys($map_type_control_options_type_ids))]) : '',
];
$map_controls['scale_control'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Scale Control: @state', ['@state' => $settings['map_controls']['scale_control'] ? $this->t('Yes') : $this->t('No')]),
];
$map_controls['street_view_control'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Streetview Control: @state', ['@state' => $settings['map_controls']['street_view_control'] ? $this->t('Yes') : $this->t('No')]),
];
$map_controls['fullscreen_control'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Fullscreen Control: @state', ['@state' => $settings['map_controls']['fullscreen_control'] ? $this->t('Yes') : $this->t('No')]),
];
}
$icon_image_mode = !empty($settings['map_marker_and_infowindow']['icon_image_mode']) ? $settings['map_marker_and_infowindow']['icon_image_mode'] : $default_icon_image_mode;
$map_marker_and_infowindow = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => '<u>' . $this->t('Map Marker and Infowindow:') . '</u>',
'icon_image_mode' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Marker Custom Icon definition mode: @state', ['@state' => $icon_image_mode]),
'#weight' => 0,
],
'infowindow_field' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Marker Infowindow @state', ['@state' => !empty($settings['map_marker_and_infowindow']['infowindow_field']) ? 'from: ' . $settings['map_marker_and_infowindow']['infowindow_field'] : $this->t('disabled')]),
'#weight' => 2,
],
'tooltip_field' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Marker Tooltip @state', ['@state' => !empty($settings['map_marker_and_infowindow']['tooltip_field']) ? 'from: ' . $settings['map_marker_and_infowindow']['tooltip_field'] : $this->t('disabled')]),
'#weight' => 2,
],
'force_open' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Open Infowindow on Load: @state', ['@state' => !empty($settings['map_marker_and_infowindow']['force_open']) ? $this->t('Yes') : $this->t('No')]),
'#weight' => 3,
],
];
if ($icon_image_mode == 'icon_image_path') {
$map_marker_and_infowindow['icon_image_path'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Marker Icon: @state', ['@state' => !empty($settings['map_marker_and_infowindow']['icon_image_path']) ? $settings['map_marker_and_infowindow']['icon_image_path'] : $this->t('Default Google Marker')]),
'#weight' => 1,
];
}
if ($settings['map_marker_and_infowindow']['infowindow_field'] == '#rendered_entity') {
$map_marker_and_infowindow['view_mode'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('View Mode: @state', ['@state' => $settings['map_marker_and_infowindow']['view_mode']]),
];
}
if (!empty($settings['map_additional_options'])) {
$map_additional_options = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Map Additional Options:'),
'value' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $settings['map_additional_options'],
],
];
}
$map_oms = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => '<u>' . $this->t('Overlapping Markers:') . '</u>',
'map_oms_control' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Spiderfy overlapping markers: @state', ['@state' => $settings['map_oms']['map_oms_control'] ? $this->t('Yes') : $this->t('No')]),
],
];
$map_markercluster = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => '<u>' . $this->t('Marker Clustering:') . '</u>',
'markercluster_control' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Marker Cluster Enabled: @state', ['@state' => isset($settings['map_markercluster']['markercluster_control']) && $settings['map_markercluster']['markercluster_control'] ? $this->t('Yes') : $this->t('No')]),
],
];
if (!empty($settings['map_markercluster']['markercluster_additional_options'])) {
$map_markercluster['markercluster_additional_options'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Marker Cluster Additional Options:'),
'value' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $settings['map_markercluster']['markercluster_additional_options'],
],
];
}
$custom_style_map = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Custom Style Map: @state', ['@state' => $settings['custom_style_map']['custom_style_control'] ? $this->t('Yes') : $this->t('No')]),
];
if ($settings['custom_style_map']['custom_style_control']) {
$custom_style_map['custom_style_name'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Custom Style Name: @state', ['@state' => $settings['custom_style_map']['custom_style_name']]),
];
$custom_style_map['custom_style_default'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Custom Map Style as Default: @state', ['@state' => $settings['custom_style_map']['custom_style_default'] ? $this->t('Yes') : $this->t('No')]),
];
}
$map_lazy_load = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Lazy load map: @state', ['@state' => $settings['map_lazy_load']['lazy_load'] ? $this->t('Yes') : $this->t('No')]),
];
$summary = [
'map_google_api_key' => $this->setMapGoogleApiKeyElement(),
'map_dimensions' => $map_dimensions,
'map_empty' => $map_empty,
'map_center' => $map_center,
'map_zoom_and_pan' => $map_zoom_and_pan,
'map_controls' => $map_controls,
'map_marker_and_infowindow' => $map_marker_and_infowindow,
'map_additional_options' => $map_additional_options ?? NULL,
'map_oms' => $map_oms,
'map_markercluster' => $map_markercluster,
'custom_style_map' => $custom_style_map,
'map_lazy_load' => $map_lazy_load,
];
// Attach Geofield Map Library.
$summary['library'] = [
'#attached' => [
'library' => [
'geofield_map/geofield_map_general',
],
],
];
return $summary;
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
// This avoids the infinite loop by stopping the display
// of any map embedded in an infowindow.
$view_in_progress = &drupal_static(__FUNCTION__);
if ($view_in_progress) {
return [];
}
$view_in_progress = TRUE;
/** @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();
$field = $items->getFieldDefinition();
$map_settings = $this->getSettings();
// Performs some preprocess on the maps settings before sending to js.
$this->preProcessMapSettings($map_settings);
$js_settings = [
'mapid' => Html::getUniqueId("geofield_map_{$entity_type}_{$bundle}_{$entity_id}_{$field->getName()}"),
'map_settings' => $map_settings,
'data' => [],
];
// Get and set the Geofield cardinality.
$js_settings['map_settings']['geofield_cardinality'] = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality();
// Get token context.
$tokens = [
'field' => $items,
$this->fieldDefinition->getTargetEntityTypeId() => $items->getEntity(),
];
$description = [];
$description_field = $map_settings['map_marker_and_infowindow']['infowindow_field'] ?? NULL;
/** @var \Drupal\Core\Field\FieldItemList $description_field_entity */
$description_field_entity = $entity->$description_field;
// Render the entity with the selected view mode.
if (isset($description_field) && $description_field === '#rendered_entity' && is_object($entity)) {
$build = $this->entityTypeManager->getViewBuilder($entity_type)->view($entity, $map_settings['map_marker_and_infowindow']['view_mode']);
$description[] = $this->renderer->renderPlain($build);
}
// Normal rendering via fields.
elseif (isset($description_field)) {
if ($map_settings['map_marker_and_infowindow']['infowindow_field'] === 'title') {
$description[] = $entity->label();
}
elseif (isset($entity->$description_field)) {
$description_field_cardinality = $description_field_entity->getFieldDefinition()->getFieldStorageDefinition()->getCardinality();
foreach ($description_field_entity->getValue() as $value) {
$description[] = $value['value'] ?? '';
if ($description_field_cardinality == 1 || !$map_settings['map_marker_and_infowindow']['multivalue_split']) {
break;
}
}
}
}
// Define a Tooltip for the Feature.
$tooltip = isset($map_settings['map_marker_and_infowindow']['tooltip_field']) && $map_settings['map_marker_and_infowindow']['tooltip_field'] == 'title' ? $entity->label() : '';
$features = [];
foreach ($items as $delta => $item) {
// Generate GeoJsonData Feature.
$info_window_description = $description[$delta] ?? (!empty($description) ? $description[0] : NULL);
$feature = $this->getGeoJsonData($item, $entity->id(), $info_window_description, $tooltip);
// Generate the weight feature property
// (falls back to natural result ordering).
$feature['weight'] = !empty($map_settings['weight']) ? intval(str_replace(["
\n",
"\r",
], "", $this->token->replace($map_settings['weight'], $tokens))) : $delta;
// Add Custom Icon, if set.
if (isset($map_settings['map_marker_and_infowindow']['icon_image_mode'])
&& $map_settings['map_marker_and_infowindow']['icon_image_mode'] === 'icon_file') {
$image_style = 'none';
$fid = NULL;
if (isset($map_settings['map_marker_and_infowindow']['icon_file_wrapper']['image_style'])) {
$image_style = $map_settings['map_marker_and_infowindow']['icon_file_wrapper']['image_style'];
}
if ((integer) !empty($map_settings['map_marker_and_infowindow']['icon_file_wrapper']['icon_file']['fids'])) {
$fid = $map_settings['map_marker_and_infowindow']['icon_file_wrapper']['icon_file']['fids'];
}
if (isset($feature['geometry']) && $feature['geometry']->type === 'Point') {
$feature['properties']['icon'] = $this->markerIcon->getFileManagedUrl($fid, $image_style);
// Flag the data with theming, for later rendering logic.
$feature['properties']['theming'] = TRUE;
}
}
elseif (isset($map_settings['map_marker_and_infowindow']['icon_image_mode'])
&& $map_settings['map_marker_and_infowindow']['icon_image_mode'] === 'icon_image_path') {
if (isset($feature['geometry']) && $feature['geometry']->type === 'Point') {
$feature['properties']['icon'] = !empty($map_settings['map_marker_and_infowindow']['icon_image_path']) ? $this->token->replace($map_settings['map_marker_and_infowindow']['icon_image_path'], $tokens) : '';
// Flag the data with theming, for later rendering logic.
$feature['properties']['theming'] = TRUE;
}
}
// Associate dynamic path properties (token based) to the feature,
// in case of not point.
if (isset($feature['geometry']) && $feature['geometry']->type !== 'Point') {
$feature['properties']['path_options'] = !empty($map_settings['map_geometries_options']) ? str_replace([
"\n",
"\r",
], "", $this->token->replace($map_settings['map_geometries_options'], $tokens)) : '';
}
// Allow modules to adjust the feature/marker.
$this->moduleHandler->alter('geofield_map_formatter_feature', $feature, $item, $entity);
$features[] = $feature;
}
// Order the data features based on the 'weight' element.
uasort($features, [
'Drupal\Component\Utility\SortArray',
'sortByWeightElement',
]);
if (empty($features) && $map_settings['map_empty']['empty_behaviour'] !== '2') {
$view_in_progress = FALSE;
return [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $map_settings['map_empty']['empty_behaviour'] === '1' ? $map_settings['map_empty']['empty_message'] : '',
'#attributes' => [
'class' => ['empty-geofield'],
],
];
}
else {
$js_settings['data'] = [
'features' => $features,
];
}
// Allow other modules to add/alter the map js settings.
$this->moduleHandler->alter('geofield_map_googlemap_formatter', $js_settings, $items);
$element = [geofield_map_googlemap_render($js_settings)];
// Part of infinite loop stopping strategy.
$view_in_progress = FALSE;
return $element;
}
}
