Skip to content

Instantly share code, notes, and snippets.

@msankhala
Last active May 24, 2023 17:08
Show Gist options
  • Save msankhala/532af1b40945a88ef7933933b46868f3 to your computer and use it in GitHub Desktop.
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
<?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;
}
<?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