Last active
May 24, 2023 17:08
-
-
Save msankhala/532af1b40945a88ef7933933b46868f3 to your computer and use it in GitHub Desktop.
Drupal 9 Views custom filter plugin to filter content based on users zipcode
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 | |
/** | |
* @file | |
* Contains mymodule.module. | |
*/ | |
use Drupal\Core\Routing\RouteMatchInterface; | |
/** | |
* Implements hook_help(). | |
*/ | |
function mymodule_help($route_name, RouteMatchInterface $route_match) { | |
switch ($route_name) { | |
// Main module help for the mymodule module. | |
case 'help.page.mymodule': | |
$output = ''; | |
$output .= '<h3>' . t('About') . '</h3>'; | |
$output .= '<p>' . t('This module used for custom work of personalization in the site.') . '</p>'; | |
return $output; | |
default: | |
} | |
} | |
/** | |
* Implements hook_views_data(). | |
*/ | |
function mymodule_views_data() { | |
$data = []; | |
// Register the node__field_event_location table. | |
$data['node__field_event_location'] = [ | |
'table' => [ | |
'group' => t('Personalization'), | |
'join' => [ | |
// Join with the node table. | |
'left_field' => 'entity_id', | |
'field' => 'entity_id', | |
'table' => 'node_field_data', | |
], | |
], | |
'nearest_event' => [ | |
'title' => t('Nearest Events - Personalization'), | |
'help' => t("Filter events based on the user\'s zipcode and nearest event rules."), | |
'filter' => [ | |
'field' => 'id', | |
'id' => 'mymodule_nearest_event_filter', | |
], | |
], | |
]; | |
return $data; | |
} |
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\views\Plugin\views\filter\FilterPluginBase; | |
use Drupal\Core\Form\FormStateInterface; | |
use Geocoder\Formatter\StringFormatter; | |
use Drupal\user\Entity\User; | |
/** | |
* Filter handler to display nearest events based on user's zipcode. | |
* | |
* @ingroup views_filter_handlers | |
* | |
* @ViewsFilter("mymodule_nearest_event_filter") | |
*/ | |
class NearestEventFilter extends FilterPluginBase { | |
/** | |
* {@inheritdoc} | |
*/ | |
public function adminSummary() { | |
// Show summary based on the options chosen. | |
$summary = $this->operator . ' '; | |
$options = []; | |
if ($this->options['nearest_events']['city']) { | |
$options[] = $this->t('City'); | |
} | |
if ($this->options['nearest_events']['state']) { | |
$options[] = $this->t('State'); | |
} | |
if ($this->options['nearest_events']['country']) { | |
$options[] = $this->t('Country'); | |
} | |
$summary .= implode(', ', $options); | |
return $summary; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function defineOptions() { | |
$options = parent::defineOptions(); | |
// Option 1: Checkboxes to choose which nearest event options to show. | |
$options['nearest_events']['city'] = FALSE; | |
$options['nearest_events']['state'] = FALSE; | |
$options['nearest_events']['country'] = FALSE; | |
return $options; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function buildOptionsForm(&$form, FormStateInterface $form_state) { | |
parent::buildOptionsForm($form, $form_state); | |
// Implement the checkboxes for the nearest event options. | |
$form['nearest_events'] = [ | |
'#type' => 'fieldset', | |
'#title' => $this->t('Nearest event options'), | |
'#collapsible' => TRUE, | |
'#collapsed' => FALSE, | |
]; | |
$form['nearest_events']['city'] = [ | |
'#type' => 'checkbox', | |
'#title' => $this->t('City'), | |
'#default_value' => $this->options['nearest_events']['city'], | |
]; | |
$form['nearest_events']['state'] = [ | |
'#type' => 'checkbox', | |
'#title' => $this->t('State'), | |
'#default_value' => $this->options['nearest_events']['state'], | |
]; | |
$form['nearest_events']['country'] = [ | |
'#type' => 'checkbox', | |
'#title' => $this->t('Country'), | |
'#default_value' => $this->options['nearest_events']['country'], | |
]; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function query() { | |
// Retrieve the current logged-in user's zipcode from the user entity field. | |
$user = \Drupal::currentUser(); | |
// Load the user entity. | |
$user = User::load($user->id()); | |
$zipcode = $user->get('field_zipcode')->value; | |
// If user's zipcode is empty then add condition event bundle = NOEVENT so | |
// that no events are shown and it fllback to NO RESULTS BEHAVIOR. @See NO | |
// RESULTS BEHAVIOR in the view. | |
if (empty($zipcode)) { | |
$this->addNoEventCondition(); | |
} | |
// If user's zipcode is not empty, then get the user's city, state, and | |
// country. | |
// Use the Geocoder module to get the user's city, state, and country. | |
// Replace 'googlemaps' with the appropriate Geocoder provider ID. | |
$geocoder = \Drupal::service('geocoder'); | |
/** @var Geocoder\Model\AddressCollection */ | |
$result = $geocoder->geocode($zipcode, ['googlemaps']); | |
/** @var Geocoder\Provider\GoogleMaps\Model\GoogleAddress */ | |
// If no results are found, then add condition event type = NOEVENT so | |
// that no events are shown and it fllback to NO RESULTS BEHAVIOR. @See NO | |
// RESULTS BEHAVIOR in the view. | |
if (empty($result)) { | |
$this->addNoEventCondition(); | |
} | |
// Get the user's city, state, and country. | |
$location = $result->first(); | |
$city = $location->getLocality(); | |
$formatter = new StringFormatter(); | |
$state = $formatter->format($location, '%a1'); | |
$country = $location->getCountry()->getCode(); | |
// Build the query to filter events based on the nearest event rules. | |
$this->ensureMyTable(); | |
$or_conditions = []; | |
// If the user's city is not empty, then add the city condition to the | |
// query. | |
if (!empty($city) && $this->options['nearest_events']['city']) { | |
$or_conditions[] = "$this->tableAlias.field_event_location_locality = '$city'"; | |
} | |
// If the user's state is not empty, then add the state condition to the | |
// query. | |
if (!empty($state) && $this->options['nearest_events']['state']) { | |
$or_conditions[] = "$this->tableAlias.field_event_location_administrative_area = '$state'"; | |
} | |
// If the user's country is not empty, then add the country condition to the | |
// query. | |
if (!empty($country) && $this->options['nearest_events']['country']) { | |
$or_conditions[] = "$this->tableAlias.field_event_location_country_code = '$country'"; | |
} | |
// Add the OR conditions to the query. | |
if (!empty($or_conditions)) { | |
$this->query->addWhereExpression($this->options['group'], implode(' OR ', $or_conditions)); | |
} | |
} | |
/** | |
* Add condition event bundle = NOEVENT so that no events are shown and it. | |
*/ | |
protected function addNoEventCondition() { | |
$this->ensureMyTable(); | |
$this->query->addWhere($this->options['group'], "$this->tableAlias.bundle", 'NOEVENT', '='); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment