View source
<?php
namespace Drupal\geolocation;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class GeolocationCore implements ContainerInjectionInterface {
use StringTranslationTrait;
const EARTH_RADIUS_KM = 6371;
const EARTH_RADIUS_MILE = 3959;
protected $moduleHandler;
protected $entityManager;
protected $config;
protected $geocoderManager;
public function __construct(ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_manager, ConfigFactory $config, GeocoderManager $geocoder_manager) {
$this->moduleHandler = $module_handler;
$this->entityManager = $entity_manager;
$this->config = $config
->get('geolocation.settings');
$this->geocoderManager = $geocoder_manager;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('module_handler'), $container
->get('entity_type.manager'), $container
->get('config.factory'), $container
->get('plugin.manager.geolocation.geocoder'));
}
public function getGeocoderManager() {
return $this->geocoderManager;
}
public function getViewsFieldData(FieldStorageConfigInterface $field_storage) {
module_load_include('inc', 'views', 'views.views');
$data = views_field_default_views_data($field_storage);
$args = [
'@field_name' => $field_storage
->getName(),
];
foreach ($data as $table_name => $table_data) {
foreach ($table_data as $field_name => $field_data) {
if ($field_name != 'delta') {
if (isset($field_data['field'])) {
$data[$table_name][$field_name]['field']['id'] = 'geolocation_field';
$data[$table_name][$field_name]['field']['click sortable'] = FALSE;
}
if (isset($field_data['filter'])) {
if (substr($field_name, -4, 4) == '_lat') {
$data[$table_name][$field_name]['title'] = $this
->t('Latitude (@field_name)', $args);
continue;
}
if (substr($field_name, -4, 4) == '_lng') {
$data[$table_name][$field_name]['title'] = $this
->t('Longitude (@field_name)', $args);
continue;
}
unset($data[$table_name][$field_name]['filter']);
}
if (isset($field_data['argument'])) {
unset($data[$table_name][$field_name]['argument']);
}
if (isset($field_data['sort'])) {
unset($data[$table_name][$field_name]['sort']);
}
}
}
$field_coordinates_table_data = [];
$entity_type_id = $field_storage
->getTargetEntityTypeId();
$target_entity_type = $this->entityManager
->getDefinition($field_storage
->getTargetEntityTypeId());
if (array_key_exists($target_entity_type
->getBaseTable() . '__' . $field_storage
->getName(), $data)) {
$field_coordinates_table_data = $data[$target_entity_type
->getBaseTable() . '__' . $field_storage
->getName()][$field_storage
->getName()];
}
elseif (array_key_exists($entity_type_id . '__' . $field_storage
->getName(), $data)) {
$field_coordinates_table_data = $data[$entity_type_id . '__' . $field_storage
->getName()][$field_storage
->getName()];
}
$data[$table_name][$args['@field_name'] . '_proximity'] = [
'group' => $target_entity_type
->getLabel(),
'title' => $this
->t('Proximity (@field_name)', $args),
'title short' => isset($field_coordinates_table_data['title short']) ? $field_coordinates_table_data['title short'] . $this
->t(":proximity") : '',
'help' => isset($field_coordinates_table_data['help']) ? $field_coordinates_table_data['help'] : '',
'argument' => [
'id' => 'geolocation_argument_proximity',
'table' => $table_name,
'entity_type' => $entity_type_id,
'field_name' => $args['@field_name'] . '_proximity',
'real field' => $args['@field_name'],
'label' => $this
->t('Distance to !field_name', $args),
'empty field name' => '- No value -',
'additional fields' => [
$args['@field_name'] . '_lat',
$args['@field_name'] . '_lng',
$args['@field_name'] . '_lat_sin',
$args['@field_name'] . '_lat_cos',
$args['@field_name'] . '_lng_rad',
],
],
'filter' => [
'id' => 'geolocation_filter_proximity',
'table' => $table_name,
'entity_type' => $entity_type_id,
'field_name' => $args['@field_name'] . '_proximity',
'real field' => $args['@field_name'],
'label' => $this
->t('Distance to !field_name', $args),
'allow empty' => TRUE,
'additional fields' => [
$args['@field_name'] . '_lat',
$args['@field_name'] . '_lng',
$args['@field_name'] . '_lat_sin',
$args['@field_name'] . '_lat_cos',
$args['@field_name'] . '_lng_rad',
],
],
'field' => [
'table' => $table_name,
'id' => 'geolocation_field_proximity',
'field_name' => $args['@field_name'] . '_proximity',
'entity_type' => $entity_type_id,
'real field' => $args['@field_name'],
'float' => TRUE,
'additional fields' => [
$args['@field_name'] . '_lat',
$args['@field_name'] . '_lng',
$args['@field_name'] . '_lat_sin',
$args['@field_name'] . '_lat_cos',
$args['@field_name'] . '_lng_rad',
],
'element type' => 'div',
'is revision' => isset($table_data[$args['@field_name']]['field']['is revision']) && $table_data[$args['@field_name']]['field']['is revision'],
'click sortable' => TRUE,
],
'sort' => [
'table' => $table_name,
'id' => 'geolocation_sort_proximity',
'field_name' => $args['@field_name'] . '_proximity',
'entity_type' => $entity_type_id,
'real field' => $args['@field_name'],
],
];
$data[$table_name][$args['@field_name'] . '_boundary'] = [
'group' => $target_entity_type
->getLabel(),
'title' => $this
->t('Boundary (@field_name)', $args),
'title short' => isset($field_coordinates_table_data['title short']) ? $field_coordinates_table_data['title short'] . $this
->t(":boundary") : '',
'help' => isset($field_coordinates_table_data['help']) ? $field_coordinates_table_data['help'] : '',
'filter' => [
'id' => 'geolocation_filter_boundary',
'table' => $table_name,
'entity_type' => $entity_type_id,
'field_name' => $args['@field_name'] . '_boundary',
'real field' => $args['@field_name'],
'label' => $this
->t('Boundaries around !field_name', $args),
'allow empty' => TRUE,
'additional fields' => [
$args['@field_name'] . '_lat',
$args['@field_name'] . '_lng',
],
],
];
}
return $data;
}
public function getProximityQueryFragment($table_name, $field_id, $filter_lat, $filter_lng, $earth_radius = self::EARTH_RADIUS_KM) {
$field_latsin = "{$table_name}.{$field_id}_lat_sin";
$field_latcos = "{$table_name}.{$field_id}_lat_cos";
$field_lng = "{$table_name}.{$field_id}_lng_rad";
$filter_lat = empty($filter_lat) ? 0 : $filter_lat;
$filter_lng = empty($filter_lng) ? 0 : $filter_lng;
$filter_latcos = cos(deg2rad($filter_lat));
$filter_latsin = sin(deg2rad($filter_lat));
$filter_lng = deg2rad($filter_lng);
return "(\n ACOS(LEAST(1,\n {$filter_latcos}\n * {$field_latcos}\n * COS( {$filter_lng} - {$field_lng} )\n +\n {$filter_latsin}\n * {$field_latsin}\n )) * {$earth_radius}\n )";
}
public function getBoundaryQueryFragment($table_name, $field_id, $filter_lat_north_east, $filter_lng_north_east, $filter_lat_south_west, $filter_lng_south_west) {
$field_lat = "{$table_name}.{$field_id}_lat";
$field_lng = "{$table_name}.{$field_id}_lng";
return "({$field_lat} BETWEEN {$filter_lat_south_west} AND {$filter_lat_north_east})\n AND\n (\n ({$filter_lng_south_west} < {$filter_lng_north_east} AND {$field_lng} BETWEEN {$filter_lng_south_west} AND {$filter_lng_north_east})\n OR\n (\n {$filter_lng_south_west} > {$filter_lng_north_east} AND (\n {$field_lng} BETWEEN {$filter_lng_south_west} AND 180 OR {$field_lng} BETWEEN -180 AND {$filter_lng_north_east}\n )\n )\n )\n ";
}
public static function sexagesimalToDecimal($sexagesimal = '') {
$pattern = "/(?<degree>-?\\d{1,3})°[ ]?((?<minutes>\\d{1,2})')?[ ]?((?<seconds>(\\d{1,2}|\\d{1,2}\\.\\d+))\")?/";
preg_match($pattern, $sexagesimal, $gps_matches);
if (!empty($gps_matches)) {
$value = $gps_matches['degree'];
if (!empty($gps_matches['minutes'])) {
$value += $gps_matches['minutes'] / 60;
}
if (!empty($gps_matches['seconds'])) {
$value += $gps_matches['seconds'] / 3600;
}
}
else {
return FALSE;
}
return $value;
}
public static function decimalToSexagesimal($decimal = '') {
$decimal = (double) $decimal;
$degrees = floor($decimal);
$rest = $decimal - $degrees;
$minutes = floor($rest * 60);
$rest = $rest * 60 - $minutes;
$seconds = round($rest * 60, 4);
$value = $degrees . '°';
if (!empty($minutes)) {
$value .= ' ' . $minutes . '\'';
}
if (!empty($seconds)) {
$value .= ' ' . $seconds . '"';
}
return $value;
}
}