View source
<?php
namespace Drupal\leaflet\Plugin\Field\FieldFormatter;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Render\RenderContext;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Leaflet\LeafletService;
use Drupal\leaflet\LeafletSettingsElementsTrait;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Utility\Token;
use Drupal\core\Render\Renderer;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Utility\LinkGeneratorInterface;
class LeafletDefaultFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
use LeafletSettingsElementsTrait;
protected $defaultSettings;
protected $leafletService;
protected $entityFieldManager;
protected $token;
protected $renderer;
protected $moduleHandler;
protected $link;
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, LeafletService $leaflet_service, EntityFieldManagerInterface $entity_field_manager, Token $token, Renderer $renderer, ModuleHandlerInterface $module_handler, LinkGeneratorInterface $link_generator) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
$this->defaultSettings = self::getDefaultSettings();
$this->leafletService = $leaflet_service;
$this->entityFieldManager = $entity_field_manager;
$this->token = $token;
$this->renderer = $renderer;
$this->moduleHandler = $module_handler;
$this->link = $link_generator;
}
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('leaflet.service'), $container
->get('entity_field.manager'), $container
->get('token'), $container
->get('renderer'), $container
->get('module_handler'), $container
->get('link_generator'));
}
public static function defaultSettings() {
return self::getDefaultSettings() + parent::defaultSettings();
}
public function settingsForm(array $form, FormStateInterface $form_state) {
$settings = $this
->getSettings();
$form['#tree'] = TRUE;
$field_cardinality = $this->fieldDefinition
->getFieldStorageDefinition()
->getCardinality();
$elements = parent::settingsForm($form, $form_state);
$field_name = $this->fieldDefinition
->getName();
$this
->setReplacementPatternsElement($elements);
if ($field_cardinality !== 1) {
$elements['multiple_map'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Multiple Maps'),
'#description' => $this
->t('Check this option if you want to render a single Map for every single Geo Point.'),
'#default_value' => $settings['multiple_map'],
'#return_value' => 1,
];
}
else {
$elements['multiple_map'] = [
'#type' => 'hidden',
'#value' => 0,
];
}
$elements['popup'] = [
'#title' => $this
->t('Popup Infowindow'),
'#description' => $this
->t('Show a Popup Infowindow on Marker click, with custom content.'),
'#type' => 'checkbox',
'#default_value' => $settings['popup'],
];
$elements['popup_content'] = [
'#type' => 'textarea',
'#title' => $this
->t('Popup content'),
'#description' => $this
->t('Define the custom content for the Pop Infowindow. If empty the Content Title will be output.<br>See "REPLACEMENT PATTERNS" above for available replacements.'),
'#default_value' => $settings['popup_content'],
'#states' => [
'visible' => [
'input[name="fields[' . $field_name . '][settings_edit_form][settings][popup]"]' => [
'checked' => TRUE,
],
],
],
];
$this
->generateMapGeneralSettings($elements, $settings);
$this
->setResetMapControl($elements, $settings);
$map_position_options = $settings['map_position'];
$elements['map_position'] = $this
->generateMapPositionElement($map_position_options);
$elements['weight'] = $this
->generateWeightElement($settings['weight']);
$icon_options = $settings['icon'];
$elements['icon'] = $this
->generateIconFormElement($icon_options);
$this
->setMapMarkerclusterElement($elements, $settings);
$this
->setMapPathOptionsElement($elements, $settings);
$this
->setGeocoderMapControl($elements, $settings);
return $elements;
}
public function settingsSummary() {
$summary = [];
$summary[] = $this
->t('Leaflet Map: @map', [
'@map' => $this
->getSetting('leaflet_map'),
]);
$summary[] = $this
->t('Map height: @height @height_unit', [
'@height' => $this
->getSetting('height'),
'@height_unit' => $this
->getSetting('height_unit'),
]);
$summary[] = $this
->t('Popup Infowindow: @popup', [
'@popup' => $this
->getSetting('popup') ? $this
->t('Yes') : $this
->t('No'),
]);
if ($this
->getSetting('popup') && $this
->getSetting('popup_content')) {
$summary[] = $this
->t('Popup content: @popup_content', [
'@popup_content' => $this
->getSetting('popup_content'),
]);
}
return $summary;
}
public function viewElements(FieldItemListInterface $items, $langcode) {
$entity = $items
->getEntity();
if ($entity
->hasTranslation($langcode)) {
$entity = $entity
->getTranslation($langcode);
}
$entity_type = $entity
->getEntityTypeId();
$bundle = $entity
->bundle();
$entity_id = $entity
->id();
$field = $items
->getFieldDefinition();
$this
->setExistingZoomSettings();
$settings = $this
->getSettings();
$map = leaflet_map_get_info($settings['leaflet_map']);
$map['id'] = Html::getUniqueId("leaflet_map_{$entity_type}_{$bundle}_{$entity_id}_{$field->getName()}");
$map['geofield_cardinality'] = $this->fieldDefinition
->getFieldStorageDefinition()
->getCardinality();
$this
->setAdditionalMapOptions($map, $settings);
$tokens = [
'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;
$feature['weight'] = !empty($settings['weight']) ? intval(str_replace([
"\n",
"\r",
], "", $this->token
->replace($settings['weight'], $tokens))) : $delta;
if ($settings['popup']) {
$build = [];
if ($this
->getSetting('popup_content')) {
$bubbleable_metadata = new BubbleableMetadata();
$popup_content = $this->token
->replace($this
->getSetting('popup_content'), $tokens, [
'clear' => TRUE,
], $bubbleable_metadata);
$build[] = [
'#markup' => $popup_content,
];
$bubbleable_metadata
->applyTo($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);
}
}
if (!empty($map['icon'])) {
$settings['icon'] = $settings['icon'] ?: [];
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';
if ($feature['type'] === 'point' && isset($settings['icon'])) {
$feature['icon'] = $settings['icon'];
if (!empty($settings["icon"]["iconSize"]["x"])) {
$feature['icon']["iconSize"]["x"] = $this->token
->replace($settings["icon"]["iconSize"]["x"], $tokens);
}
if (!empty($settings["icon"]["iconSize"]["y"])) {
$feature['icon']["iconSize"]["y"] = $this->token
->replace($settings["icon"]["iconSize"]["y"], $tokens);
}
if (!empty($settings["icon"]["shadowSize"]["x"])) {
$feature['icon']["shadowSize"]["x"] = $this->token
->replace($settings["icon"]["shadowSize"]["x"], $tokens);
}
if (!empty($settings["icon"]["shadowSize"]["y"])) {
$feature['icon']["shadowSize"]["y"] = $this->token
->replace($settings["icon"]["shadowSize"]["y"], $tokens);
}
switch ($icon_type) {
case 'html':
$feature['icon']['html'] = $this->token
->replace($settings['icon']['html'], $tokens);
$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'], $tokens);
break;
default:
if (!empty($settings['icon']['iconUrl'])) {
$feature['icon']['iconUrl'] = str_replace([
"\n",
"\r",
], "", $this->token
->replace($settings['icon']['iconUrl'], $tokens));
if (!empty($feature['icon']['iconUrl'])) {
$feature['icon']['iconUrl'] = $this->leafletService
->pathToAbsolute($feature['icon']['iconUrl']);
}
}
if (!empty($settings['icon']['shadowUrl'])) {
$feature['icon']['shadowUrl'] = str_replace([
"\n",
"\r",
], "", $this->token
->replace($settings['icon']['shadowUrl'], $tokens));
if (!empty($feature['icon']['shadowUrl'])) {
$feature['icon']['shadowUrl'] = $this->leafletService
->pathToAbsolute($feature['icon']['shadowUrl']);
}
}
$this->leafletService
->setFeatureIconSizesIfEmptyOrInvalid($feature);
break;
}
}
if ($feature['type'] !== 'point') {
$feature['path'] = str_replace([
"\n",
"\r",
], "", $this->token
->replace($settings['path'], $tokens));
}
$feature['className'] = !empty($settings['className']) ? str_replace([
"\n",
"\r",
], "", $this->token
->replace($settings['className'], $tokens)) : '';
$this->moduleHandler
->alter('leaflet_formatter_feature', $feature, $item, $entity);
$features[] = $feature;
}
uasort($features, [
'Drupal\\Component\\Utility\\SortArray',
'sortByWeightElement',
]);
$js_settings = [
'map' => $map,
'features' => $features,
];
$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;
}
private function setExistingZoomSettings() {
$settings = $this
->getSettings();
if (isset($settings['zoom'])) {
$settings['map_position']['zoom'] = (int) $settings['zoom'];
$settings['map_position']['minZoom'] = (int) $settings['minZoom'];
$settings['map_position']['maxZoom'] = (int) $settings['maxZoom'];
$this
->setSettings($settings);
}
}
}