Drupal views create exposed filter programmatically

Let's assume there is a requirement where we need to filter node content for a given year. We can achieve this by creating a views exposed filter that will filter node content for the selected year.

In this post, I am using the module named "custom_views_filter" for demonstration purposes.

We will create a custom_views_filter.module file and add the below code.

/**
 * Implements hook_views_data_alter().
 */
function custom_views_filter_views_data_alter(array &$data) {
  $data['node']['year_filter'] = [
    'title' => t('Year'),
    'filter' => [
      'title' => t('Year'),
      'help' => t('Provides a custom filter for nodes to search yearly.'),
      'id' => 'year_views_filter',
    ],
  ];
}

This will register the filter with the views plugin. Now create the views plugin filter.

Create a folder called Plugin/view/filter under the src folder and add a file named ContentYearViewsFilter.php, then add the below code:

namespace Drupal\custom_views_filter\Plugin\views\filter;

use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\filter\InOperator;
use Drupal\views\ViewExecutable;

/**
 * Filter content yearly.
 *
 * @ingroup views_filter_handlers
 *
 * @ViewsFilter("year_views_filter")
 */
class ContentYearViewsFilter extends InOperator {

  /**
   * The current display.
   *
   * @var string
   *   The current display of the view.
   */
  protected $currentDisplay;

  /**
   * {@inheritdoc}
   */
  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
    parent::init($view, $display, $options);
    $this->valueTitle = t('Year');
    $this->definition['options callback'] = [$this, 'generateOptions'];
    $this->currentDisplay = $view->current_display;
  }

  /**
   * Helper function to generates options.
   *
   * @return array
   *   An array of options.
   */
  public function generateOptions(): array {
    $keys = range(date("Y"), date("Y") - 5);
    $values = range(date("Y"), date("Y") - 5);
    return array_combine($keys, $values);
  }

  /**
   * Helper function to builds the query.
   */
  public function query() {
    if (!empty($this->value)) {
      // Start date like 2021-01-01.
      $start_date_timestamp = DrupalDateTime::createFromArray([
        'year' => $this->value[0],
        'month' => 1,
        'day' => 1,
      ])->getTimestamp();
      // End date like 2021-12-31.
      $start_end_timestamp = DrupalDateTime::createFromArray([
        'year' => $this->value[0],
        'month' => 12,
        'day' => 31,
      ])->getTimestamp();
      $this->query->addWhere('AND', 'node_field_data.created', $this->value, '>=');
      $this->query->addWhere('AND', 'node_field_data.created', $start_end_timestamp, '<=');
    }
  }
}

 

0/5