geolocation-8.x-3.x-dev/src/MapProviderBase.php

src/MapProviderBase.php
<?php

namespace Drupal\geolocation;

use Drupal\Component\Utility\SortArray;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Render\BubbleableMetadata;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provide Map Provider Base class.
 *
 * @package Drupal\geolocation
 */
abstract class MapProviderBase extends PluginBase implements MapProviderInterface, ContainerFactoryPluginInterface {

  /**
   * JS Scripts to load.
   *
   * @var string[]
   */
  protected array $scripts = [];

  /**
   * CSS Stylesheets to load.
   *
   * @var string[]
   */
  protected array $stylesheets = [];

  /**
   * {@inheritdoc}
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    protected MapFeatureManager $mapFeatureManager,
    protected ModuleHandlerInterface $moduleHandler,
    protected FileSystemInterface $fileSystem,
    protected DataLayerProviderManager $dataLayerProviderManager,
    protected TileLayerProviderManager $tileLayerProviderManager,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);

    $class_name = (new \ReflectionClass($this))->getShortName();

    $module_path = $this->moduleHandler->getModule($this->getPluginDefinition()['provider'])->getPath();

    if (file_exists($this->fileSystem->realpath($module_path) . '/css/MapProvider/' . $class_name . '.css')) {
      $this->stylesheets[] = base_path() . $module_path . '/css/MapProvider/' . $class_name . '.css';
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): MapProviderInterface {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('plugin.manager.geolocation.mapfeature'),
      $container->get('module_handler'),
      $container->get('file_system'),
      $container->get('plugin.manager.geolocation.datalayerprovider'),
      $container->get('plugin.manager.geolocation.tilelayerprovider'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public static function getDefaultSettings(): array {
    return [
      'conditional_initialization' => 'no',
      'conditional_description' => t('Clicking this button will embed a map.'),
      'conditional_label' => t('Show map'),
      'conditional_viewport_threshold' => 0.8,
      'map_features' => [],
      'data_layers' => [
        'geolocation_default_layer:default' => [
          'enabled' => TRUE,
        ],
      ],
      'tile_layers' => [],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getSettings(array $settings): array {
    $default_settings = $this->getDefaultSettings();
    $settings = array_replace_recursive($default_settings, $settings);

    foreach ($settings as $key => $setting) {
      if (!isset($default_settings[$key])) {
        unset($settings[$key]);
      }
    }

    foreach ($this->mapFeatureManager->getMapFeaturesByMapType($this->getPluginId()) as $feature_id => $feature_definition) {
      if (!empty($settings['map_features'][$feature_id]['enabled'])) {
        $feature = $this->mapFeatureManager->getMapFeature($feature_id);
        if ($feature) {
          if (empty($settings['map_features'][$feature_id]['settings'])) {
            $settings['map_features'][$feature_id]['settings'] = $feature->getSettings([], $this);
          }
          else {
            $settings['map_features'][$feature_id]['settings'] = $feature->getSettings($settings['map_features'][$feature_id]['settings'], $this);
          }
        }
        else {
          unset($settings['map_features'][$feature_id]);
        }
      }
    }

    return $settings;
  }

  /**
   * {@inheritdoc}
   */
  public function getSettingsSummary(array $settings): array {
    $summary = [
      $this->t('Map provider: %map_provider', ['%map_provider' => $this->getPluginDefinition()['name']]),
    ];
    foreach ($this->mapFeatureManager->getMapFeaturesByMapType($this->getPluginId()) as $feature_id => $feature_definition) {
      if (!empty($settings['map_features'][$feature_id]['enabled'])) {
        $feature = $this->mapFeatureManager->getMapFeature($feature_id);
        if ($feature) {
          if (!empty($settings['map_features'][$feature_id]['settings'])) {
            $feature_settings = $settings['map_features'][$feature_id]['settings'];
          }
          else {
            $feature_settings = $feature->getSettings([], $this);
          }
          $summary = array_merge(
            $summary,
            $feature->getSettingsSummary($feature_settings, $this)
          );
        }
      }
    }

    return $summary;
  }

  /**
   * {@inheritdoc}
   */
  public function getSettingsForm(array $settings, array $parents = [], array $context = []): array {
    $states_prefix_parents = $parents;
    $states_prefix = array_shift($states_prefix_parents) . '[' . implode('][', $states_prefix_parents) . ']';

    $form = [
      '#type' => 'details',
      '#open' => TRUE,
      '#title' => $this->t('%map_provider Settings', ['%map_provider' => $this->pluginDefinition['name']]),
      '#description' => $this->t('Additional map settings provided by %map_provider', ['%map_provider' => $this->pluginDefinition['name']]),
      '#tree' => TRUE,
      '#parents' => $parents,
    ];

    $form['conditional_initialization'] = [
      '#type' => 'select',
      '#options' => [
        'no' => $this->t('No'),
        'button' => $this->t('Yes, show button'),
        'viewport' => $this->t('Yes, when visible in the viewport'),
        'programmatically' => $this->t('Yes, on custom code'),
      ],
      '#default_value' => $settings['conditional_initialization'],
      '#title' => $this->t('Conditional initialization'),
      '#description' => $this->t('Delay map initialization on specific conditions. This is required for GDPR / DSGVO / CMP compliance! <br /> Call `Drupal.geolocation.maps.initializeDelayed();` to trigger.'),
    ];

    $form['conditional_description'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Conditional Description'),
      '#default_value' => $settings['conditional_description'],
      '#size' => 60,
      '#states' => [
        'visible' => [
          ':input[name="' . $states_prefix . '[conditional_initialization]"]' => ['value' => 'button'],
        ],
      ],
    ];

    $form['conditional_label'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Conditional Button Label'),
      '#default_value' => $settings['conditional_label'],
      '#size' => 60,
      '#states' => [
        'visible' => [
          ':input[name="' . $states_prefix . '[conditional_initialization]"]' => ['value' => 'button'],
        ],
      ],
    ];

    $form['conditional_viewport_threshold'] = [
      '#type' => 'number',
      '#title' => $this->t('Threshold'),
      '#description' => $this->t('Percentage of the map on screen to initialize the map. 1.0 = 100% on screen, 0.1 = 10% on screen.'),
      '#default_value' => $settings['conditional_viewport_threshold'],
      '#min' => 0.1,
      '#max' => 1,
      '#step' => 0.1,
      '#states' => [
        'visible' => [
          'select[name="' . $states_prefix . '[conditional_initialization]"]' => ['value' => 'viewport'],
        ],
      ],
    ];

    if ($this->mapFeatureManager->getMapFeaturesByMapType($this->getPluginId())) {
      $form['map_features'] = [
        '#type' => 'details',
        '#title' => $this->t('Map Features'),
        '#weight' => 2,
        'form' => $this->mapFeatureManager->getOptionsForm($settings['map_features'], array_merge($parents, ['map_features']), $this),
      ];
    }

    $form['data_layers'] = [
      '#type' => 'details',
      '#title' => $this->t('Data Layers & Features'),
      '#weight' => 3,
      'form' => $this->dataLayerProviderManager->getOptionsForm(
        $settings['data_layers'] ?? [],
        array_merge($parents, ['data_layers']),
        $this,
        $context
      ),
    ];

    $form['tile_layers'] = [
      '#type' => 'details',
      '#title' => $this->t('Additional Tile Layers'),
      '#weight' => 4,
      'form' => $this->tileLayerProviderManager->getOptionsForm(
        $settings['tile_layers'] ?? [],
          array_merge($parents, ['tile_layers']),
        $this,
        $context
      ),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function alterRenderArray(array $render_array, array $map_settings, array $context = []): array {

    $map_settings['import_path'] = $this->getJavascriptModulePath();
    $map_settings['scripts'] = $this->scripts;
    $map_settings['stylesheets'] = $this->stylesheets;

    if (!empty($map_settings['map_features'])) {
      uasort($map_settings['map_features'], [SortArray::class, 'sortByWeightElement']);

      foreach ($map_settings['map_features'] as $feature_id => $feature_settings) {
        if (!empty($feature_settings['enabled'])) {
          $feature = $this->mapFeatureManager->getMapFeature($feature_id);
          if ($feature) {
            if (empty($feature_settings['settings'])) {
              $feature_settings['settings'] = [];
            }
            $render_array = $feature->alterMap($render_array, $feature->getSettings($feature_settings['settings']), $context, $this);
          }
        }
      }

      unset($map_settings['map_features']);
    }

    $render_array = $this->dataLayerProviderManager->alterMap($render_array, $map_settings['data_layers'], $context);
    unset($map_settings['data_layers']);

    $render_array = $this->tileLayerProviderManager->alterMap($render_array, $map_settings['tile_layers'], $context);
    unset($map_settings['tile_layers']);

    $render_array['#attached'] = BubbleableMetadata::mergeAttachments(
      $render_array['#attached'] ?? [],
      [
        'drupalSettings' => [
          'geolocation' => [
            'maps' => [
              $render_array['#id'] => &$map_settings,
            ],
          ],
        ],
      ]
    );

    return $render_array;
  }

  /**
   * {@inheritdoc}
   */
  public static function getControlPositions(): array {
    return [];
  }

  /**
   * Get the path to load JS module.
   *
   * @return string|null
   *   JS Module path.
   */
  public function getJavascriptModulePath() : ?string {
    $class_name = (new \ReflectionClass($this))->getShortName();

    $module_path = $this->moduleHandler->getModule($this->getPluginDefinition()['provider'])->getPath();

    if (!file_exists($this->fileSystem->realpath($module_path) . '/js/MapProvider/' . $class_name . '.js')) {
      return NULL;
    }

    return base_path() . $module_path . '/js/MapProvider/' . $class_name . '.js';
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc