From 91b4eed7d7d380edfd567bd4439168d32b389955 Mon Sep 17 00:00:00 2001 From: s j <sj@1729.be> Date: Sun, 14 Nov 2021 08:06:20 +0100 Subject: [PATCH] add date period filter --- .../views_date_period.filter.schema.yml | 10 ++ src/Plugin/views/filter/DatePeriodFilter.php | 150 ++++++++++++++++++ views_date_period.views.inc | 58 +++++++ 3 files changed, 218 insertions(+) create mode 100644 config/schema/views_date_period.filter.schema.yml create mode 100644 src/Plugin/views/filter/DatePeriodFilter.php create mode 100644 views_date_period.views.inc diff --git a/config/schema/views_date_period.filter.schema.yml b/config/schema/views_date_period.filter.schema.yml new file mode 100644 index 0000000..5e044d1 --- /dev/null +++ b/config/schema/views_date_period.filter.schema.yml @@ -0,0 +1,10 @@ +views.filter_value.views_date_period_filter: + type: mapping + label: 'Date Period' + mapping: + period: + type: string + label: 'Period' + year: + type: string + label: 'Year' diff --git a/src/Plugin/views/filter/DatePeriodFilter.php b/src/Plugin/views/filter/DatePeriodFilter.php new file mode 100644 index 0000000..9b57674 --- /dev/null +++ b/src/Plugin/views/filter/DatePeriodFilter.php @@ -0,0 +1,150 @@ +<?php + +namespace Drupal\views_date_period\Plugin\views\filter; + +use Drupal\Core\Datetime\DateHelper; +use Drupal\Core\Form\FormStateInterface; +use Drupal\views\Plugin\views\display\DisplayPluginBase; +use Drupal\views\Plugin\views\filter\Equality; +use Drupal\views\ViewExecutable; + +/** + * Filters a date field by (predefined) period. + * + * @ingroup views_filter_handlers + * + * @ViewsFilter("views_date_period_filter") + */ +class DatePeriodFilter extends Equality { + + /** + * {@inheritdoc} + */ + public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { + parent::init($view, $display, $options); + $this->valueTitle = t('Period'); + } + + /** + * {@inheritdoc} + */ + protected function defineOptions() { + $options = parent::defineOptions(); + $options['periods']['default'] = [ + 'quarter' => 1, + 'month' => 1, + 'halfyear' => 1, + ]; + return $options; + } + + /** + * {@inheritdoc} + */ + public function buildOptionsForm(&$form, FormStateInterface $form_state) { + parent::buildOptionsForm($form, $form_state); + + $form['periods'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Periods'), + '#default_value' => $this->options['periods'], + '#weight' => -90, + '#options' => [ + 'quarter' => $this->t("Quarter"), + 'halfyear' => $this->t("Halfyear"), + 'month' => $this->t("Month"), + ], + ]; + } + + /** + * Display the filter on the administrative summary. + */ + public function adminSummary() { + return $this->operator . ' ' . $this->value['year'] . '-' . $this->value['period']; + } + + /** + * Override the query. + */ + public function query() { + if (!empty($this->value['year'])) { + $this->ensureMyTable(); + + $year = $this->value['year']; + if (!$year) { + $year = date('Y'); + } + + if (empty($this->value['period'])) { + $start = date("Y-m-d", strtotime("{$year}-1-1")); + $end = date("Y-m-d", strtotime("{$year}-12-1 last day of this month")); + } + elseif (substr($this->value['period'], 0, 1) === 'Q') { + $quarter = substr($this->value['period'], 1, 1); + $month = 1 + 3 * ($quarter - 1); + $start = date("Y-m-d", strtotime("{$year}-{$month}-1")); + $month = 3 * $quarter; + $end = date("Y-m-d", strtotime("{$year}-{$month}-1 last day of this month")); + } + else { + $start = date("Y-m-d", strtotime("{$year}-{$this->value['period']}-1")); + $end = date("Y-m-d", strtotime("{$year}-{$this->value['period']}-1 last day of this month")); + } + + $this->query->addWhereExpression( + 0, + "$this->tableAlias.$this->realField BETWEEN '{$start}' and '{$end}'", + [] + ); + } + } + + /** + * Skip validation if no options have been chosen. + */ + public function validate() { + if (!empty($this->value)) { + parent::validate(); + } + } + + /** + * {@inheritdoc} + */ + protected function valueForm(&$form, FormStateInterface $form_state) { + parent::valueForm($form, $form_state); + + $form['value']['#tree'] = TRUE; + $form['value']['#type'] = 'fieldgroup'; + + $months = DateHelper::monthNamesAbbr(TRUE); + $options = [ + (string) $this->t("Quarter") => [ + 'Q1' => 'Q1', + 'Q2' => 'Q2', + 'Q3' => 'Q3', + 'Q4' => 'Q4', + ], + (string) $this->t("Halfyear") => [ + 'H1' => 'H1', + 'H2' => 'H2', + ], + (string) $this->t("Month") => $months, + ]; + $form['value']['period'] = [ + '#type' => 'select', + '#options' => $options, + '#empty_value' => '_none', + ]; + $form['value']['year'] = [ + '#type' => 'textfield', + '#size' => 4, + '#maxlength' => 4, + '#placeholder' => $this->t("Year"), + ]; + + return $form; + } + +} diff --git a/views_date_period.views.inc b/views_date_period.views.inc new file mode 100644 index 0000000..691c322 --- /dev/null +++ b/views_date_period.views.inc @@ -0,0 +1,58 @@ +<?php + +/** + * @file + * Provides views handlers for views_date_period. + */ + +use Drupal\Core\Entity\ContentEntityTypeInterface; + +/** + * Implements hook_views_data_alter(). + */ +function views_date_period_views_data_alter(array &$data) { + + // Get all entity types to next handling. + $entity_types = \Drupal::entityTypeManager()->getDefinitions(); + // Entity field manager. + /** @var \Drupal\Core\Entity\EntityFieldManager $entity_field_manager */ + $entity_field_manager = \Drupal::service('entity_field.manager'); + + // Process all entity types. + foreach ($entity_types as $entity_type_id => $entity_type) { + // We need to process only content entity types. + if ($entity_type instanceof ContentEntityTypeInterface) { + // Base fields what we need to process. + $base_field_definitions = $entity_field_manager->getBaseFieldDefinitions( + $entity_type_id); + /* $timestamp_field_types = ['timestamp', 'created', 'changed']; */ + $timestamp_field_types = ['datetime']; + + foreach ($base_field_definitions as $base_field_id => $base_field_definition) { + if (in_array($base_field_definition->getType(), $timestamp_field_types)) { + // The table name where the data stored for specific entity. + $table_name = $entity_type->getDataTable() ?: $entity_type->getBaseTable(); + // Field label for next manipulations. + $base_field_label = (string) $base_field_definition->getLabel(); + + // Add period fileter. + $data[$table_name][$base_field_id . '_date_period'] = [ + 'title' => t('@label period', ['@label' => $base_field_label]), + 'help' => t('@label period filter.', ['@label' => $base_field_label]), + /* + 'argument' => [ + 'field' => $base_field_id, + 'id' => 'views_dates_date_generic', + ], + */ + 'filter' => [ + 'field' => $base_field_id, + 'id' => 'views_date_period_filter', + ], + ]; + } + } + } + } + +} -- GitLab