geolocation-8.x-3.x-dev/modules/geolocation_search_api/src/Plugin/views/filter/GeolocationSearchApiFilterBoundary.php

modules/geolocation_search_api/src/Plugin/views/filter/GeolocationSearchApiFilterBoundary.php
<?php

namespace Drupal\geolocation_search_api\Plugin\views\filter;

use Drupal\views\Attribute\ViewsFilter;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\geolocation\BoundaryTrait;
use Drupal\geolocation\GeocoderManager;
use Drupal\views\Plugin\views\filter\FilterPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Filter handler for search keywords.
 *
 * @ingroup views_filter_handlers
 */
#[ViewsFilter(id: 'geolocation_search_api_filter_boundary')]
class GeolocationSearchApiFilterBoundary extends FilterPluginBase implements ContainerFactoryPluginInterface {

  use BoundaryTrait;

  /**
   * {@inheritdoc}
   */
  public $no_operator = TRUE;

  /**
   * Can be used for CommonMap interactive filtering.
   *
   * @var bool
   */
  public bool $isGeolocationCommonMapOption = TRUE;

  /**
   * {@inheritdoc}
   */
  protected $alwaysMultiple = TRUE;

  /**
   * {@inheritdoc}
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    protected GeocoderManager $geocoderManager,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

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

  /**
   * {@inheritdoc}
   */
  public function adminSummary(): string {
    return $this->t("Boundary filter");
  }

  /**
   * {@inheritdoc}
   */
  protected function defineOptions(): array {
    $options = parent::defineOptions();

    $options['expose']['contains']['input_by_geocoding_widget'] = ['default' => FALSE];
    $options['expose']['contains']['geocoder'] = ['default' => FALSE];
    $options['expose']['contains']['geocoder_settings'] = ['default' => FALSE];

    return $options;
  }

  /**
   * {@inheritdoc}
   *
   * @param array $form
   *   Form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   */
  public function buildExposeForm(&$form, FormStateInterface $form_state): void {

    parent::buildExposeForm($form, $form_state);
    $form['expose']['#type'] = 'container';

    $geocoder_options = [];
    foreach ($this->geocoderManager->getDefinitions() as $id => $definition) {
      if (empty($definition['frontendCapable'])) {
        continue;
      }
      $geocoder_options[$id] = $definition['name'];
    }

    if (!$geocoder_options) {
      return;
    }

    $form['expose']['input_by_geocoding_widget'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Use geocoding widget to retrieve boundary values'),
      '#default_value' => $this->options['expose']['input_by_geocoding_widget'],
    ];

    $form['expose']['geocoder'] = $this->geocoderManager->geocoderOptionsSelect($geocoder_options);
    $form['expose']['geocoder'] = array_merge($form['expose']['geocoder'], [
      '#default_value' => $this->options['expose']['geocoder'],
      '#states' => [
        'visible' => [
          'input[name="options[expose][input_by_geocoding_widget]"]' => ['checked' => TRUE],
        ],
      ],
    ]);

    $geocoder_plugin = $this->geocoderManager->getGeocoder(
      $this->options['expose']['geocoder'] ?? current(array_keys($geocoder_options)),
      $this->options['expose']['geocoder_settings'] ?: []
    );

    if (empty($geocoder_plugin)) {
      $form['expose']['geocoder_settings'] = [
        '#type' => 'html_tag',
        '#tag' => 'span',
        '#value' => t("No settings available."),
      ];
    }
    else {
      $form['expose']['geocoder_settings'] = $geocoder_plugin->getOptionsForm();
    }
    $form['expose']['geocoder_settings'] = array_merge($form['expose']['geocoder_settings'], [
      '#states' => [
        'visible' => [
          'input[name="options[expose][input_by_geocoding_widget]"]' => ['checked' => TRUE],
        ],
      ],
    ]);
  }

  /**
   * {@inheritdoc}
   *
   * @param array $form
   *   Form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   */
  public function buildExposedForm(&$form, FormStateInterface $form_state): void {
    parent::buildExposedForm($form, $form_state);

    $identifier = $this->options['expose']['identifier'];
    if (empty($form[$identifier . '_wrapper'][$identifier])) {
      return;
    }
    $form[$identifier . '_wrapper']['#tree'] = FALSE;
    $form[$identifier . '_wrapper'][$identifier]['#tree'] = TRUE;

    if (
      !$this->options['expose']['input_by_geocoding_widget']
      || empty($this->options['expose']['geocoder'])
    ) {
      return;
    }

    $geocoder_plugin = $this->geocoderManager->getGeocoder(
      $this->options['expose']['geocoder'],
      $this->options['expose']['geocoder_settings'] ?: []
    );

    if (empty($geocoder_plugin)) {
      return;
    }

    $form[$identifier . '_wrapper'][$identifier]['lat_north_east']['#type'] = 'hidden';
    $form[$identifier . '_wrapper'][$identifier]['lng_north_east']['#type'] = 'hidden';
    $form[$identifier . '_wrapper'][$identifier]['lat_south_west']['#type'] = 'hidden';
    $form[$identifier . '_wrapper'][$identifier]['lng_south_west']['#type'] = 'hidden';

    $geocoder_plugin->alterRenderArray($form[$identifier . '_wrapper'][$identifier], $identifier);

    $form = BubbleableMetadata::mergeAttachments($form, [
      '#attached' => [
        'library' => [
          'geolocation/geolocation.views.filter.geocoder',
        ],
        'drupalSettings' => [
          'geolocation' => [
            'geocoder' => [
              'viewsFilterGeocoder' => [
                $identifier => [
                  'settings' => $geocoder_plugin->getSettings(),
                ],
              ],
            ],
          ],
        ],
      ],
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function acceptExposedInput($input): bool {
    if (!parent::acceptExposedInput($input)) {
      return FALSE;
    }

    if ($this->isBoundarySet($this->value)) {
      return TRUE;
    }

    $identifier = $this->options['expose']['identifier'];
    if (
      empty($input[$identifier]['geolocation_geocoder_address'])
      || empty($this->options['expose']['input_by_geocoding_widget'])
      || empty($this->options['expose']['geocoder'])
    ) {
      return FALSE;
    }

    $geocoder_plugin = $this->geocoderManager->getGeocoder(
      $this->options['expose']['geocoder'],
      $this->options['expose']['geocoder_settings']
    );

    if (empty($geocoder_plugin)) {
      return FALSE;
    }

    $location_data = $geocoder_plugin->geocode($input[$this->options['expose']['identifier']]['geolocation_geocoder_address']);

    // Location geocoded server-side. Add to input for later processing.
    if (!empty($location_data['boundary'])) {
      $this->value = array_replace($input[$identifier], $location_data['boundary']);
      return TRUE;
    }

    return FALSE;
  }

  /**
   * {@inheritdoc}
   *
   * @param array $form
   *   Form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   */
  protected function valueForm(&$form, FormStateInterface $form_state): void {
    parent::valueForm($form, $form_state);

    $form['value']['#type'] = 'container';
    $form['value']['#tree'] = TRUE;

    $value_element = &$form['value'];

    // Add the Latitude and Longitude elements.
    $value_element += [
      'lat_north_east' => [
        '#type' => 'textfield',
        '#title' => $this->t('North East Boundary - Latitude'),
        '#default_value' => !empty($this->value['lat_north_east']) ? $this->value['lat_north_east'] : '',
        '#size' => 30,
        '#weight' => 10,
      ],
      'lng_north_east' => [
        '#type' => 'textfield',
        '#title' => $this->t('North East Boundary - Longitude'),
        '#default_value' => !empty($this->value['lng_north_east']) ? $this->value['lng_north_east'] : '',
        '#size' => 30,
        '#weight' => 20,
      ],
      'lat_south_west' => [
        '#type' => 'textfield',
        '#title' => $this->t('South West Boundary - Latitude'),
        '#default_value' => !empty($this->value['lat_south_west']) ? $this->value['lat_south_west'] : '',
        '#size' => 30,
        '#weight' => 30,
      ],
      'lng_south_west' => [
        '#type' => 'textfield',
        '#title' => $this->t('South West Boundary - Longitude'),
        '#default_value' => !empty($this->value['lng_south_west']) ? $this->value['lng_south_west'] : '',
        '#size' => 30,
        '#weight' => 40,
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function query(): void {
    if (empty($this->value)) {
      return;
    }

    // Get the field alias.
    $lat_north_east = $this->value['lat_north_east'];
    $lng_north_east = $this->value['lng_north_east'];
    $lat_south_west = $this->value['lat_south_west'];
    $lng_south_west = $this->value['lng_south_west'];

    if (
      !is_numeric($lat_north_east)
      || !is_numeric($lng_north_east)
      || !is_numeric($lat_south_west)
      || !is_numeric($lng_south_west)
    ) {
      return;
    }

    /** @var \Drupal\search_api\Query\Query $query */
    $query = $this->query;

    $location_options = [
      [
        'field' => $this->realField,
        'geom' => "[$lat_south_west,$lng_south_west TO $lat_north_east,$lng_north_east]",
      ],
    ];
    $query->setOption('search_api_rpt', $location_options);
  }

  /**
   * Determine if boundary is set.
   *
   * @param mixed $values
   *   Value array.
   *
   * @return bool
   *   Boundary set or not.
   */
  private function isBoundarySet(mixed $values): bool {
    if (!is_array($values)) {
      return FALSE;
    }

    if (
      isset($values['lat_north_east'])
      && is_numeric($values['lat_north_east'])
      && isset($values['lng_north_east'])
      && is_numeric($values['lng_north_east'])
      && isset($values['lat_south_west'])
      && is_numeric($values['lat_south_west'])
      && isset($values['lng_south_west'])
      && is_numeric($values['lng_south_west'])
    ) {
      return TRUE;
    }

    return FALSE;
  }

}

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

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