/core/modules/views/src/Plugin/views/filter/Date.php

https://gitlab.com/geeta7/drupal · PHP · 191 lines · 125 code · 30 blank · 36 comment · 51 complexity · afee139a69af7f184b7663030b5ddfb9 MD5 · raw file

  1. <?php
  2. /**
  3. * @file
  4. * Contains \Drupal\views\Plugin\views\filter\Date.
  5. */
  6. namespace Drupal\views\Plugin\views\filter;
  7. use Drupal\Core\Form\FormStateInterface;
  8. /**
  9. * Filter to handle dates stored as a timestamp.
  10. *
  11. * @ingroup views_filter_handlers
  12. *
  13. * @ViewsFilter("date")
  14. */
  15. class Date extends NumericFilter {
  16. protected function defineOptions() {
  17. $options = parent::defineOptions();
  18. // value is already set up properly, we're just adding our new field to it.
  19. $options['value']['contains']['type']['default'] = 'date';
  20. return $options;
  21. }
  22. /**
  23. * Add a type selector to the value form
  24. */
  25. protected function valueForm(&$form, FormStateInterface $form_state) {
  26. if (!$form_state->get('exposed')) {
  27. $form['value']['type'] = array(
  28. '#type' => 'radios',
  29. '#title' => $this->t('Value type'),
  30. '#options' => array(
  31. 'date' => $this->t('A date in any machine readable format. CCYY-MM-DD HH:MM:SS is preferred.'),
  32. 'offset' => $this->t('An offset from the current time such as "@example1" or "@example2"', array('@example1' => '+1 day', '@example2' => '-2 hours -30 minutes')),
  33. ),
  34. '#default_value' => !empty($this->value['type']) ? $this->value['type'] : 'date',
  35. );
  36. }
  37. parent::valueForm($form, $form_state);
  38. }
  39. public function validateOptionsForm(&$form, FormStateInterface $form_state) {
  40. parent::validateOptionsForm($form, $form_state);
  41. if (!empty($this->options['exposed']) && $form_state->isValueEmpty(array('options', 'expose', 'required'))) {
  42. // Who cares what the value is if it's exposed and non-required.
  43. return;
  44. }
  45. $this->validateValidTime($form['value'], $form_state, $form_state->getValue(array('options', 'operator')), $form_state->getValue(array('options', 'value')));
  46. }
  47. public function validateExposed(&$form, FormStateInterface $form_state) {
  48. if (empty($this->options['exposed'])) {
  49. return;
  50. }
  51. if (empty($this->options['expose']['required'])) {
  52. // Who cares what the value is if it's exposed and non-required.
  53. return;
  54. }
  55. $value = &$form_state->getValue($this->options['expose']['identifier']);
  56. if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id'])) {
  57. $operator = &$form_state->getValue($this->options['expose']['operator_id']);
  58. }
  59. else {
  60. $operator = $this->operator;
  61. }
  62. $this->validateValidTime($this->options['expose']['identifier'], $form_state, $operator, $value);
  63. }
  64. /**
  65. * Validate that the time values convert to something usable.
  66. */
  67. public function validateValidTime(&$form, FormStateInterface $form_state, $operator, $value) {
  68. $operators = $this->operators();
  69. if ($operators[$operator]['values'] == 1) {
  70. $convert = strtotime($value['value']);
  71. if (!empty($form['value']) && ($convert == -1 || $convert === FALSE)) {
  72. $form_state->setError($form['value'], $this->t('Invalid date format.'));
  73. }
  74. }
  75. elseif ($operators[$operator]['values'] == 2) {
  76. $min = strtotime($value['min']);
  77. if ($min == -1 || $min === FALSE) {
  78. $form_state->setError($form['min'], $this->t('Invalid date format.'));
  79. }
  80. $max = strtotime($value['max']);
  81. if ($max == -1 || $max === FALSE) {
  82. $form_state->setError($form['max'], $this->t('Invalid date format.'));
  83. }
  84. }
  85. }
  86. /**
  87. * Validate the build group options form.
  88. */
  89. protected function buildGroupValidate($form, FormStateInterface $form_state) {
  90. // Special case to validate grouped date filters, this is because the
  91. // $group['value'] array contains the type of filter (date or offset)
  92. // and therefore the number of items the comparison has to be done
  93. // against 'one' instead of 'zero'.
  94. foreach ($form_state->getValue(array('options', 'group_info', 'group_items')) as $id => $group) {
  95. if (empty($group['remove'])) {
  96. // Check if the title is defined but value wasn't defined.
  97. if (!empty($group['title'])) {
  98. if ((!is_array($group['value']) && empty($group['value'])) || (is_array($group['value']) && count(array_filter($group['value'])) == 1)) {
  99. $form_state->setError($form['group_info']['group_items'][$id]['value'], $this->t('The value is required if title for this item is defined.'));
  100. }
  101. }
  102. // Check if the value is defined but title wasn't defined.
  103. if ((!is_array($group['value']) && !empty($group['value'])) || (is_array($group['value']) && count(array_filter($group['value'])) > 1)) {
  104. if (empty($group['title'])) {
  105. $form_state->setError($form['group_info']['group_items'][$id]['title'], $this->t('The title is required if value for this item is defined.'));
  106. }
  107. }
  108. }
  109. }
  110. }
  111. public function acceptExposedInput($input) {
  112. if (empty($this->options['exposed'])) {
  113. return TRUE;
  114. }
  115. // Store this because it will get overwritten.
  116. $type = $this->value['type'];
  117. $rc = parent::acceptExposedInput($input);
  118. // Don't filter if value(s) are empty.
  119. $operators = $this->operators();
  120. if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id'])) {
  121. $operator = $input[$this->options['expose']['operator_id']];
  122. }
  123. else {
  124. $operator = $this->operator;
  125. }
  126. if ($operators[$operator]['values'] == 1) {
  127. if ($this->value['value'] == '') {
  128. return FALSE;
  129. }
  130. }
  131. else {
  132. if ($this->value['min'] == '' || $this->value['max'] == '') {
  133. return FALSE;
  134. }
  135. }
  136. // restore what got overwritten by the parent.
  137. $this->value['type'] = $type;
  138. return $rc;
  139. }
  140. protected function opBetween($field) {
  141. $a = intval(strtotime($this->value['min'], 0));
  142. $b = intval(strtotime($this->value['max'], 0));
  143. if ($this->value['type'] == 'offset') {
  144. $a = '***CURRENT_TIME***' . sprintf('%+d', $a); // keep sign
  145. $b = '***CURRENT_TIME***' . sprintf('%+d', $b); // keep sign
  146. }
  147. // This is safe because we are manually scrubbing the values.
  148. // It is necessary to do it this way because $a and $b are formulas when using an offset.
  149. $operator = strtoupper($this->operator);
  150. $this->query->addWhereExpression($this->options['group'], "$field $operator $a AND $b");
  151. }
  152. protected function opSimple($field) {
  153. $value = intval(strtotime($this->value['value'], 0));
  154. if (!empty($this->value['type']) && $this->value['type'] == 'offset') {
  155. $value = '***CURRENT_TIME***' . sprintf('%+d', $value); // keep sign
  156. }
  157. // This is safe because we are manually scrubbing the value.
  158. // It is necessary to do it this way because $value is a formula when using an offset.
  159. $this->query->addWhereExpression($this->options['group'], "$field $this->operator $value");
  160. }
  161. }