You are here

class LeafletDefaultFormatter 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
  2. 2.0.x src/Plugin/Field/FieldFormatter/LeafletDefaultFormatter.php \Drupal\leaflet\Plugin\Field\FieldFormatter\LeafletDefaultFormatter

Plugin implementation of the 'leaflet_default' formatter.

Plugin annotation


@FieldFormatter(
  id = "leaflet_formatter_default",
  label = @Translation("Leaflet Map"),
  field_types = {
    "geofield"
  }
)

Hierarchy

Expanded class hierarchy of LeafletDefaultFormatter

File

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

Namespace

Drupal\leaflet\Plugin\Field\FieldFormatter
View source
class LeafletDefaultFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
  use LeafletSettingsElementsTrait;

  /**
   * The Default Settings.
   *
   * @var array
   */
  protected $defaultSettings;

  /**
   * Leaflet service.
   *
   * @var \Drupal\Leaflet\LeafletService
   */
  protected $leafletService;

  /**
   * The EntityField Manager service.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * The token service.
   *
   * @var \Drupal\core\Utility\Token
   */
  protected $token;

  /**
   * The renderer service.
   *
   * @var \Drupal\core\Render\Renderer
   */
  protected $renderer;

  /**
   * The module handler to invoke the alter hook.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * The Link generator Service.
   *
   * @var \Drupal\Core\Utility\LinkGeneratorInterface
   */
  protected $link;

  /**
   * LeafletDefaultFormatter 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 settings.
   * @param \Drupal\Leaflet\LeafletService $leaflet_service
   *   The Leaflet service.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
   *   The Entity Field Manager.
   * @param \Drupal\core\Utility\Token $token
   *   The token service.
   * @param \Drupal\core\Render\Renderer $renderer
   *   The renderer service.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler.
   * @param \Drupal\Core\Utility\LinkGeneratorInterface $link_generator
   *   The Link Generator service.
   */
  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;
  }

  /**
   * {@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('leaflet.service'), $container
      ->get('entity_field.manager'), $container
      ->get('token'), $container
      ->get('renderer'), $container
      ->get('module_handler'), $container
      ->get('link_generator'));
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return self::getDefaultSettings() + parent::defaultSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $settings = $this
      ->getSettings();
    $form['#tree'] = TRUE;

    // Get the Cardinality set for the Formatter Field.
    $field_cardinality = $this->fieldDefinition
      ->getFieldStorageDefinition()
      ->getCardinality();
    $elements = parent::settingsForm($form, $form_state);
    $field_name = $this->fieldDefinition
      ->getName();
    if ($this->moduleHandler
      ->moduleExists('token')) {
      $elements['replacement_patterns'] = [
        '#type' => 'details',
        '#title' => 'Replacement patterns',
        '#description' => $this
          ->t('The following replacement tokens are available for the "Popup Content and the Icon 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(t('Token module'), Url::fromUri('https://www.drupal.org/project/token', [
          'absolute' => TRUE,
          'attributes' => [
            'target' => 'blank',
          ],
        ])),
        '@entity_type' => $this->fieldDefinition
          ->getTargetEntityTypeId(),
      ]);
    }
    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,
          ],
        ],
      ],
    ];

    // Generate the Leaflet Map General Settings.
    $this
      ->generateMapGeneralSettings($elements, $settings);

    // Generate the Leaflet Map Reset Control.
    $this
      ->setResetMapControl($elements, $settings);

    // Generate the Leaflet Map Position Form Element.
    $map_position_options = $settings['map_position'];
    $elements['map_position'] = $this
      ->generateMapPositionElement($map_position_options);

    // Generate Icon form element.
    $icon_options = $settings['icon'];
    $elements['icon'] = $this
      ->generateIconFormElement($icon_options, $form);

    // Set Map Marker Cluster Element.
    $this
      ->setMapMarkerclusterElement($elements, $settings);

    // Set Map Geometries Options Element.
    $this
      ->setMapPathOptionsElement($elements, $settings);

    // Set Map Geocoder Control Element, if the Geocoder Module exists,
    // otherwise output a tip on Geocoder Module Integration.
    $this
      ->setGeocoderMapControl($elements, $settings);
    return $elements;
  }

  /**
   * {@inheritdoc}
   */
  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;
  }

  /**
   * {@inheritdoc}
   *
   * This function is called from parent::view().
   */
  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;
  }

  /**
   * Sets possibly existing previous settings for the Zoom Form Element.
   */
  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);
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormatterBase::$fieldDefinition protected property The field definition.
FormatterBase::$label protected property The label display setting.
FormatterBase::$settings protected property The formatter settings. Overrides PluginSettingsBase::$settings
FormatterBase::$viewMode protected property The view mode.
FormatterBase::getFieldSetting protected function Returns the value of a field setting.
FormatterBase::getFieldSettings protected function Returns the array of field settings.
FormatterBase::isApplicable public static function Returns if the formatter can be used for the provided field. Overrides FormatterInterface::isApplicable 14
FormatterBase::prepareView public function Allows formatters to load information for field values being displayed. Overrides FormatterInterface::prepareView 2
FormatterBase::view public function Builds a renderable array for a fully themed field. Overrides FormatterInterface::view 1
LeafletDefaultFormatter::$defaultSettings protected property The Default Settings.
LeafletDefaultFormatter::$entityFieldManager protected property The EntityField Manager service.
LeafletDefaultFormatter::$leafletService protected property Leaflet service.
LeafletDefaultFormatter::$link protected property The Link generator Service.
LeafletDefaultFormatter::$moduleHandler protected property The module handler to invoke the alter hook.
LeafletDefaultFormatter::$renderer protected property The renderer service.
LeafletDefaultFormatter::$token protected property The token service.
LeafletDefaultFormatter::create public static function Creates an instance of the plugin. Overrides FormatterBase::create
LeafletDefaultFormatter::defaultSettings public static function Defines the default settings for this plugin. Overrides PluginSettingsBase::defaultSettings
LeafletDefaultFormatter::setExistingZoomSettings private function Sets possibly existing previous settings for the Zoom Form Element.
LeafletDefaultFormatter::settingsForm public function Returns a form to configure settings for the formatter. Overrides FormatterBase::settingsForm
LeafletDefaultFormatter::settingsSummary public function Returns a short summary for the current formatter settings. Overrides FormatterBase::settingsSummary
LeafletDefaultFormatter::viewElements public function This function is called from parent::view(). Overrides FormatterInterface::viewElements
LeafletDefaultFormatter::__construct public function LeafletDefaultFormatter constructor. Overrides FormatterBase::__construct
LeafletSettingsElementsTrait::$controlPositionsOptions protected property Leaflet Controls Positions Options.
LeafletSettingsElementsTrait::$leafletCircleRadiusFieldTypesOptions protected property Leaflet Circle Radius Marker Field Types Options.
LeafletSettingsElementsTrait::generateIconFormElement protected function Generate the Leaflet Icon Form Element.
LeafletSettingsElementsTrait::generateMapGeneralSettings protected function Generate the Leaflet Map General Settings.
LeafletSettingsElementsTrait::generateMapPositionElement protected function Generate the Leaflet Map Position Form Element.
LeafletSettingsElementsTrait::getDefaultSettings public static function Get the Default Settings.
LeafletSettingsElementsTrait::jsonValidate public static function Form element json format validation handler.
LeafletSettingsElementsTrait::maxZoomLevelValidate public static function Form element validation handler for the Map Max Zoom level.
LeafletSettingsElementsTrait::setAdditionalMapOptions protected function Set Map additional map Settings.
LeafletSettingsElementsTrait::setGeocoderMapControl protected function Set Map Geocoder Control Element.
LeafletSettingsElementsTrait::setMapMarkerclusterElement protected function Set Map MarkerCluster Element.
LeafletSettingsElementsTrait::setMapPathOptionsElement protected function Set Map Geometries Options Element.
LeafletSettingsElementsTrait::setResetMapControl protected function Set Map MarkerCluster Element.
LeafletSettingsElementsTrait::validateGeocoderProviders public static function Validates the Geocoder Providers element.
LeafletSettingsElementsTrait::zoomLevelValidate public static function Form element validation handler for a Map Zoom level.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
PluginSettingsBase::$defaultSettingsMerged protected property Whether default settings have been merged into the current $settings.
PluginSettingsBase::$thirdPartySettings protected property The plugin settings injected by third party modules.
PluginSettingsBase::calculateDependencies public function Calculates dependencies for the configured plugin. Overrides DependentPluginInterface::calculateDependencies 6
PluginSettingsBase::getSetting public function Returns the value of a setting, or its default value if absent. Overrides PluginSettingsInterface::getSetting
PluginSettingsBase::getSettings public function Returns the array of settings, including defaults for missing settings. Overrides PluginSettingsInterface::getSettings
PluginSettingsBase::getThirdPartyProviders public function Gets the list of third parties that store information. Overrides ThirdPartySettingsInterface::getThirdPartyProviders
PluginSettingsBase::getThirdPartySetting public function Gets the value of a third-party setting. Overrides ThirdPartySettingsInterface::getThirdPartySetting
PluginSettingsBase::getThirdPartySettings public function Gets all third-party settings of a given module. Overrides ThirdPartySettingsInterface::getThirdPartySettings
PluginSettingsBase::mergeDefaults protected function Merges default settings values into $settings.
PluginSettingsBase::onDependencyRemoval public function Informs the plugin that some configuration it depends on will be deleted. Overrides PluginSettingsInterface::onDependencyRemoval 3
PluginSettingsBase::setSetting public function Sets the value of a setting for the plugin. Overrides PluginSettingsInterface::setSetting
PluginSettingsBase::setSettings public function Sets the settings for the plugin. Overrides PluginSettingsInterface::setSettings
PluginSettingsBase::setThirdPartySetting public function Sets the value of a third-party setting. Overrides ThirdPartySettingsInterface::setThirdPartySetting
PluginSettingsBase::unsetThirdPartySetting public function Unsets a third-party setting. Overrides ThirdPartySettingsInterface::unsetThirdPartySetting
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.