Last active
June 28, 2018 12:19
-
-
Save gaelg/30947b310403bf13459eb85227897eaf to your computer and use it in GitHub Desktop.
Geofield proximity filter https://www.drupal.org/project/geofield/issues/2654360
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\mymodule\Plugin\views\filter; | |
use Drupal\Core\Form\FormStateInterface; | |
use Drupal\geofield\Plugin\views\filter\GeofieldProximity; | |
/** | |
* @ingroup views_filter_handlers | |
* | |
* @ViewsFilter("geofield_proximity_geocoder") | |
*/ | |
class GeofieldProximityGeocoder extends GeofieldProximity { | |
protected function defineOptions() { | |
$options = parent::defineOptions(); | |
$options['value']['contains']['address']['default'] = ''; | |
return $options; | |
} | |
protected function valueForm(&$form, FormStateInterface $form_state) { | |
parent::valueForm($form, $form_state); | |
$exposed = $form_state->get('exposed'); | |
$user_input = $form_state->getUserInput(); | |
// Ensure we get a compound value element. | |
if (!isset($form['value']['value'])) { | |
$distance_element = $form['value']; | |
$form['value'] = ['#tree' => TRUE]; | |
$form['value']['value'] = $distance_element; | |
} | |
$form['value']['address'] = [ | |
'#type' => 'textfield', | |
'#title' => $this->t('of...'), | |
'#size' => 30, | |
'#default_value' => $this->value['address'], | |
]; | |
if ($exposed) { | |
$form['value']['value']['#title'] = $this->t('Within...'); | |
$form['value']['value']['#suffix'] = geofield_radius_options()[$this->options['units']]; | |
$identifier = $this->options['expose']['identifier']; | |
// Ensure we get a compound input. | |
if (!is_array($user_input[$identifier])) { | |
$user_input[$identifier] = ['value' => $user_input[$identifier]]; | |
} | |
if (!isset($user_input[$identifier]['address'])) { | |
$user_input[$identifier]['address'] = $this->value['address']; | |
$form_state->setUserInput($user_input); | |
} | |
} | |
} | |
public function query() { | |
$this->ensureMyTable(); | |
if (!empty($this->value['address'])) { | |
$lat_alias = $this->realField . '_lat'; | |
$lon_alias = $this->realField . '_lon'; | |
/** @var \Drupal\mymodule\Plugin\GeofieldProximity\GeofieldProximityGeocoder $source_plugin */ | |
$source_plugin = $this->proximityManager->createInstance($this->options['source'], $this->options['source_configuration']); | |
if ($source_plugin->computeOrigin($this->value['address'])) { | |
$source_plugin->setViewHandler($this); | |
$source_plugin->setUnits($this->options['units']); | |
$info = $this->operators(); | |
$haversine_options = $source_plugin->getHaversineOptions(); | |
$haversine_options['destination_latitude'] = $this->tableAlias . '.' . $lat_alias; | |
$haversine_options['destination_longitude'] = $this->tableAlias . '.' . $lon_alias; | |
$this->{$info[$this->operator]['method']}($haversine_options); | |
} | |
else { | |
drupal_set_message(t('Unrecognized address'), 'error'); | |
} | |
} | |
} | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\mymodule\Plugin\GeofieldProximity; | |
use Drupal\Component\Utility\NestedArray; | |
use Drupal\Core\Form\FormStateInterface; | |
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; | |
use Drupal\geocoder\GeocoderInterface; | |
use Drupal\geocoder\ProviderPluginManager; | |
use Drupal\geofield\Plugin\GeofieldProximityBase; | |
use Symfony\Component\DependencyInjection\ContainerInterface; | |
/** | |
* Defines 'Geofield geocoded origin' plugin. | |
* | |
* @package Drupal\geofield\Plugin | |
* | |
* @GeofieldProximity( | |
* id = "geofield_geocoder", | |
* label = @Translation("Geofield geocoded origin"), | |
* admin_label = @Translation("Geofield geocoded origin"), | |
* ) | |
*/ | |
class GeofieldProximityGeocoder extends GeofieldProximityBase implements ContainerFactoryPluginInterface { | |
protected $geocoderPluginOptions; | |
protected $geocoder; | |
protected $providerPluginManager; | |
protected $origin; | |
/** | |
* {@inheritdoc} | |
*/ | |
public function __construct(array $configuration, $plugin_id, $plugin_definition, | |
GeocoderInterface $geocoder, | |
array $geocoder_plugin_options, | |
ProviderPluginManager $provider_plugin_manager) { | |
parent::__construct($configuration, $plugin_id, $plugin_definition); | |
$this->geocoder = $geocoder; | |
$this->geocoderPluginOptions = $geocoder_plugin_options; | |
$this->providerPluginManager = $provider_plugin_manager; | |
} | |
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { | |
return new static( | |
$configuration, | |
$plugin_id, | |
$plugin_definition, | |
$container->get('geocoder'), | |
$container->get('config.factory') | |
->get('geocoder.settings') | |
->get('plugins_options'), | |
$container->get('plugin.manager.geocoder.provider') | |
); | |
} | |
/** | |
* {@inheritdoc} | |
* @see \Drupal\geocoder_field\Plugin\Field\GeocodeFormatterBase | |
*/ | |
public function buildOptionsForm(array &$element, FormStateInterface $form_state, array $options_parents) { | |
$element['#attached']['library'] = [ | |
'geocoder_field/general', | |
]; | |
// Get the enabled/selected plugins. | |
$enabled_plugins = []; | |
$plugins = isset($this->configuration['plugins']) ? $this->configuration['plugins'] : []; | |
foreach ($plugins as $plugin_id => $plugin) { | |
if (isset($plugin['checked']) && $plugin['checked']) { | |
$enabled_plugins[] = $plugin_id; | |
} | |
} | |
// Generates the Draggable Table of Selectable Geocoder Plugins. | |
$element['plugins'] = $this->providerPluginManager->providersPluginsTableList($enabled_plugins); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function validateOptionsForm(array &$form, FormStateInterface $form_state, array $options_parents) { | |
$values = $form_state->getValues(); | |
$values = NestedArray::getValue($values, array_merge(['options'], $options_parents)); | |
$plugins = array_filter($values['plugins'], function ($value) { | |
return isset($value['checked']) && TRUE == $value['checked']; | |
}); | |
if (empty($plugins)) { | |
$form_state->setError($form, t('The selected Geocode operation needs at least one plugin.')); | |
} | |
} | |
public function computeOrigin(string $address) { | |
if ($results = $this->geocoder->geocode($address, array_keys($this->getEnabledProviderPlugins()), $this->geocoderPluginOptions)) { | |
$this->origin = [ | |
'lat' => $results->first()->getLatitude(), | |
'lon' => $results->first()->getLongitude(), | |
]; | |
return TRUE; | |
} | |
return FALSE; | |
} | |
/** | |
* Get the list of enabled Provider plugins. | |
* | |
* @see \Drupal\geocoder_field\Plugin\Field\GeocodeFormatterBase | |
* @return array | |
* Provider plugin IDs and their properties (id, name, arguments...). | |
*/ | |
protected function getEnabledProviderPlugins() { | |
$geocoder_plugins = $this->providerPluginManager->getPlugins(); | |
$plugins_settings = $this->configuration['plugins']; | |
// Filter out unchecked plugins. | |
$provider_plugin_ids = array_filter($plugins_settings, function ($plugin) { | |
return isset($plugin['checked']) && $plugin['checked'] == TRUE; | |
}); | |
$provider_plugin_ids = array_combine(array_keys($provider_plugin_ids), array_keys($provider_plugin_ids)); | |
foreach ($geocoder_plugins as $plugin) { | |
if (isset($provider_plugin_ids[$plugin['id']])) { | |
$provider_plugin_ids[$plugin['id']] = $plugin; | |
} | |
} | |
return $provider_plugin_ids; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getOrigin() { | |
return $this->origin; | |
} | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
views.filter_value.geofield_proximity_geocoder: | |
type: views.field.numeric | |
label: 'Geofield Proximity Field (geocoder)'</code> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Implements hook_field_views_data_alter(). | |
* | |
* @see geofield_field_views_data() | |
*/ | |
function mymodule_field_views_data_alter(array &$data, \Drupal\field\FieldStorageConfigInterface $field_storage) { | |
// Add the geocode proximity filter to the fields having the default proximity | |
// filter. | |
foreach ($data as $table_name => $table_data) { | |
foreach ($table_data as $field) { | |
if (isset($field['filter']) && $field['filter']['id'] == 'geofield_proximity') { | |
$field_name = $field['filter']['real field']; | |
$data[$table_name][$field_name . '_proximity_geocoder_filter'] = [ | |
'group' => $field['group'], | |
'title' => $field['title'] . ' ' . t('(to a geocoded address)'), | |
'help' => $field['help'], | |
'filter' => [ | |
'id' => 'geofield_proximity_geocoder', | |
'real field' => $field_name, | |
], | |
]; | |
} | |
} | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment