Skip to content

Instantly share code, notes, and snippets.

@gaelg
Last active June 28, 2018 12:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gaelg/30947b310403bf13459eb85227897eaf to your computer and use it in GitHub Desktop.
Save gaelg/30947b310403bf13459eb85227897eaf to your computer and use it in GitHub Desktop.
<?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');
}
}
}
}
?>
<?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;
}
}
?>
views.filter_value.geofield_proximity_geocoder:
type: views.field.numeric
label: 'Geofield Proximity Field (geocoder)'</code>
<?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