date_views_filter_handler.inc 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. /**
  3. * @file
  4. * A flexible, configurable date filter.
  5. * This filter combines multiple date filters into a single filter
  6. * where all fields are controlled by the same date and can be combined
  7. * with either AND or OR.
  8. */
  9. // @codingStandardsIgnoreStart
  10. class date_views_filter_handler extends date_views_filter_handler_simple {
  11. function init(&$view, &$options) {
  12. parent::init($view, $options);
  13. if (empty($this->view->date_info)) {
  14. $this->view->date_info = new stdClass();
  15. }
  16. if (empty($this->view->date_info->date_fields)) {
  17. $this->view->date_info->date_fields = array();
  18. }
  19. $this->view->date_info->date_fields = array_merge($this->view->date_info->date_fields, $this->options['date_fields']);
  20. }
  21. // Set default values for the date filter.
  22. function option_definition() {
  23. $options = parent::option_definition();
  24. $options['date_fields'] = array('default' => array());
  25. $options['date_method'] = array('default' => 'OR');
  26. $options['date_group'] = array('default' => 'date');
  27. return $options;
  28. }
  29. function op_between($field) {
  30. $this->date_combine_conditions('op_between');
  31. }
  32. function op_simple($field) {
  33. $this->date_combine_conditions('op_simple');
  34. }
  35. function op_contains($field) {
  36. $this->date_combine_conditions('op_contains');
  37. }
  38. function op_empty($field) {
  39. $this->get_query_fields();
  40. if (empty($this->query_fields)) {
  41. return;
  42. }
  43. // Add each condition to the custom filter group.
  44. foreach ((array) $this->query_fields as $query_field) {
  45. $field = $query_field['field'];
  46. $this->date_handler = $query_field['date_handler'];
  47. // Respect relationships when determining the table alias.
  48. if ($field['table_name'] != $this->table || !empty($this->relationship)) {
  49. $this->related_table_alias = $this->query->ensure_table($field['table_name'], $this->relationship);
  50. }
  51. else {
  52. $this->related_table_alias = NULL;
  53. }
  54. $table_alias = !empty($this->related_table_alias) ? $this->related_table_alias : $field['table_name'];
  55. $field_name = $table_alias . '.' . $field['field_name'];
  56. parent::op_empty($field_name);
  57. }
  58. }
  59. /**
  60. * Combines multiple date WHERE expressions into a single WHERE expression.
  61. *
  62. * @param string $function
  63. * The function name to use to add individual conditions. Either 'op_simple'
  64. * or 'op_between'.
  65. */
  66. protected function date_combine_conditions($function) {
  67. $this->get_query_fields();
  68. if (empty($this->query_fields)) {
  69. return;
  70. }
  71. // Create a custom filter group for the conditions.
  72. $this->query->set_where_group($this->options['date_method'], $this->options['date_group']);
  73. // Add each condition to the custom filter group.
  74. foreach ((array) $this->query_fields as $query_field) {
  75. $field = $query_field['field'];
  76. $this->date_handler = $query_field['date_handler'];
  77. // Respect relationships when determining the table alias.
  78. if ($field['table_name'] != $this->table || !empty($this->relationship)) {
  79. $this->related_table_alias = $this->query->ensure_table($field['table_name'], $this->relationship);
  80. }
  81. else {
  82. $this->related_table_alias = NULL;
  83. }
  84. $table_alias = !empty($this->related_table_alias) ? $this->related_table_alias : $field['table_name'];
  85. $field_name = $table_alias . '.' . $field['field_name'];
  86. // Call the appropriate function, either 'op_between' or 'op_simple'.
  87. parent::$function($field_name);
  88. }
  89. // Gather all of the condition strings and their placeholders.
  90. $conditions = array();
  91. $placeholders = array();
  92. foreach ($this->query->where[$this->options['date_group']]['conditions'] as $condition) {
  93. $conditions[] = $condition['field'];
  94. $placeholders += $condition['value'];
  95. }
  96. // Remove the conditions from the custom filter group.
  97. unset($this->query->where[$this->options['date_group']]);
  98. // Combine all of the conditions into one string.
  99. $conditions = implode(' ' . $this->options['date_method'] . ' ', $conditions);
  100. // Add it to the filter group chosen in the Views UI.
  101. $this->query->add_where_expression($this->options['group'], $conditions, $placeholders);
  102. }
  103. function extra_options_form(&$form, &$form_state) {
  104. parent::extra_options_form($form, $form_state);
  105. $fields = date_views_fields($this->base_table);
  106. $options = array();
  107. foreach ($fields['name'] as $name => $field) {
  108. $options[$name] = $field['label'];
  109. }
  110. $form['date_fields'] = array(
  111. '#title' => t('Date field(s)'),
  112. '#type' => 'checkboxes',
  113. '#options' => $options,
  114. '#default_value' => $this->options['date_fields'],
  115. '#multiple' => FALSE,
  116. '#description' => t('Select date field(s) to filter.'),
  117. '#required' => TRUE,
  118. );
  119. $form['date_method'] = array(
  120. '#title' => t('Method'),
  121. '#type' => 'radios',
  122. '#options' => array('OR' => t('OR'), 'AND' => t('AND')),
  123. '#default_value' => $this->options['date_method'],
  124. '#description' => t('Method of handling multiple date fields in the same query. Return items that have any matching date field (date = field_1 OR field_2), or only those with matches in all selected date fields (date = field_1 AND field_2).'),
  125. );
  126. }
  127. function extra_options_validate($form, &$form_state) {
  128. $check_fields = array_filter($form_state['values']['options']['date_fields']);
  129. if (empty($check_fields)) {
  130. form_error($form['date_fields'], t('You must select at least one date field for this filter.'));
  131. }
  132. }
  133. function extra_options_submit($form, &$form_state) {
  134. $form_state['values']['options']['date_fields'] = array_filter($form_state['values']['options']['date_fields']);
  135. }
  136. // Update the summary values to provide
  137. // meaningful information for each option.
  138. function admin_summary() {
  139. if (empty($this->options['date_fields'])) {
  140. return t('Missing date fields!');
  141. }
  142. $handler = $this->date_handler;
  143. $fields = date_views_fields($this->view->base_table);
  144. if (!empty($this->options['date_fields'])) {
  145. $output = array();
  146. foreach ($this->options['date_fields'] as $field) {
  147. if (array_key_exists($field, $fields['name'])) {
  148. $output[] = $fields['name'][$field]['label'];
  149. }
  150. }
  151. }
  152. $field = implode(' ' . $this->options['date_method'] . ' ', $output);
  153. $output = "$field " . check_plain($this->operator) . ' ';
  154. $parts = $handler->date_parts();
  155. $widget_options = $this->widget_options();
  156. // If the filter is exposed, display the granularity.
  157. if ($this->options['exposed']) {
  158. return t('(@field) <strong>Exposed</strong> @widget @format', array('@field' => $field, '@format' => $parts[$handler->granularity], '@widget' => $widget_options[$this->options['form_type']]));
  159. }
  160. // If not exposed, display the value.
  161. if (in_array($this->operator, $this->operator_values(2))) {
  162. $min = check_plain(!empty($this->options['default_date']) ? $this->options['default_date'] : $this->options['value']['min']);
  163. $max = check_plain(!empty($this->options['default_to_date']) ? $this->options['default_to_date'] : $this->options['value']['max']);
  164. $output .= t('@min and @max', array('@min' => $min, '@max' => $max));
  165. }
  166. else {
  167. $output .= check_plain(!empty($this->options['default_date']) ? $this->options['default_date'] : $this->options['value']['value']);
  168. }
  169. return $output;
  170. }
  171. function get_query_fields() {
  172. $fields = date_views_fields($this->base_table);
  173. $fields = $fields['name'];
  174. $this->query_fields = array();
  175. foreach ((array) $this->options['date_fields'] as $delta => $name) {
  176. if (array_key_exists($name, $fields) && $field = $fields[$name]) {
  177. $date_handler = new date_sql_handler($field['sql_type'], date_default_timezone());
  178. $date_handler->granularity = $this->options['granularity'];
  179. $date_handler->db_timezone = date_get_timezone_db($field['tz_handling']);
  180. $date_handler->local_timezone = date_get_timezone($field['tz_handling']);
  181. $this->query_fields[] = array('field' => $field, 'date_handler' => $date_handler);
  182. }
  183. }
  184. }
  185. }
  186. // @codingStandardsIgnoreEnd