geolocation-8.x-3.x-dev/src/Plugin/views/argument/ProximityArgument.php

src/Plugin/views/argument/ProximityArgument.php
<?php

namespace Drupal\geolocation\Plugin\views\argument;

use Drupal\views\Attribute\ViewsArgument;
use Drupal\Core\Form\FormStateInterface;
use Drupal\geolocation\ProximityTrait;
use Drupal\views\Plugin\views\argument\Formula;
use Drupal\views\Plugin\views\query\Sql;

/**
 * Argument handler for geolocation proximity.
 *
 * Argument format should be in the following format:
 * "37.7749295,-122.41941550000001<=5mi" (defaults to km).
 *
 * @ingroup views_argument_handlers
 */
#[ViewsArgument(id: 'geolocation_argument_proximity')]
class ProximityArgument extends Formula {

  use ProximityTrait;
  /**
   * Distance.
   *
   * @var float
   */
  protected float $distance = 0;

  /**
   * {@inheritdoc}
   *
   * @param array $form
   *   Form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state): void {
    parent::buildOptionsForm($form, $form_state);
    $form['description']['#markup'] .= $this->t('<br/> Proximity format should be in the following format: <strong>"37.7749295,-122.41941550000001<=5mi"</strong> (defaults to km).');
  }

  /**
   * Get the formula for this argument.
   */
  public function getFormula(): ?string {
    // Parse argument for reference location.
    $values = $this->getParsedReferenceLocation();
    // Make sure we have enough information to start with.
    if (
      !empty($values)
      && isset($values['lat'])
      && isset($values['lng'])
      && isset($values['distance'])
    ) {
      $distance = self::convertDistance((float) $values['distance'], $values['unit']);

      // Build a formula for the where clause.
      $formula = self::getProximityQueryFragment($this->tableAlias, $this->realField, $values['lat'], $values['lng']);
      // Set the operator and value for the query.
      $this->operator = $values['operator'] ?? '<';
      $this->distance = $distance;

      return !empty($formula) ? str_replace('***table***', $this->tableAlias, $formula) : NULL;
    }

    return NULL;
  }

  /**
   * {@inheritdoc}
   *
   * @param int|string|false $group_by
   *   Group by.
   */
  public function query($group_by = FALSE): void {
    $this->ensureMyTable();
    // Now that our table is secure, get our formula.
    $placeholder = $this->placeholder();
    $formula = $this->getFormula();
    if (!$formula) {
      return;
    }
    $formula .= ' ' . $this->operator . ' ' . $placeholder;
    $placeholders = [
      $placeholder => $this->distance,
    ];

    // The addWhere function is only available for SQL queries.
    if ($this->query instanceof Sql) {
      // @phpstan-ignore-next-line
      $this->query->addWhere(0, $formula, $placeholders, 'formula');
    }
  }

  /**
   * Processes the passed argument into an array of relevant geolocation data.
   */
  public function getParsedReferenceLocation(): ?array {
    // Cache the vales so this only gets processed once.
    static $values;

    if (!isset($values)) {
      // Get the value.
      $value = $this->getValue();

      // Set static values to empty array and return early if no argument.
      if (empty($value)) {
        $values = [];
        return NULL;
      }
      // Process argument values into an array.
      preg_match('/^([0-9\-.]+),+([0-9\-.]+)([<>=]+)([0-9.]+)(.*$)/', $this->getValue(), $values);

      // Validate latitude is set and in range.
      if (!(isset($values[1]) && $values[1] >= -90 && $values[1] <= 90)) {
        return NULL;
      }

      // Validate longitude is set and in range.
      if (!(isset($values[2]) && $values[2] >= -180 && $values[2] <= 180)) {
        return NULL;
      }

      // Validate operator is in a list of permitted values.
      if (!(isset($values[3])
        && in_array($values[3], ['<>', '=', '>=', '<=', '>', '<']))) {
        return NULL;
      }

      // Validate distance is positive and non-zero.
      if (!(isset($values[4]) && $values[4] > 0)) {
        return NULL;
      }

      $values = [
        'lat' => floatval($values[1]),
        'lng' => floatval($values[2]),
        'operator' => $values[3],
        'distance' => floatval($values[4]),
        'unit' => $values[5] ?? 'km',
      ];
    }
    return $values;
  }

}

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

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