date_views_argument_handler.inc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. /**
  3. * @file
  4. * Date API views argument handler.
  5. * This argument combines multiple date arguments into a single argument
  6. * where all fields are controlled by the same date and can be combined
  7. * with either AND or OR.
  8. */
  9. /**
  10. * Date API argument handler.
  11. */
  12. // @codingStandardsIgnoreStart
  13. class date_views_argument_handler extends date_views_argument_handler_simple {
  14. /**
  15. * Get granularity and use it to create the formula and a format
  16. * for the results.
  17. */
  18. function init(&$view, &$options) {
  19. parent::init($view, $options);
  20. if (empty($this->view->date_info)) {
  21. $this->view->date_info = new stdClass();
  22. }
  23. if (empty($this->view->date_info->date_fields)) {
  24. $this->view->date_info->date_fields = array();
  25. }
  26. $this->view->date_info->date_fields = array_merge($this->view->date_info->date_fields, $this->options['date_fields']);
  27. }
  28. /**
  29. * Default value for the date_fields option.
  30. */
  31. function option_definition() {
  32. $options = parent::option_definition();
  33. $options['date_fields'] = array('default' => array());
  34. $options['date_method'] = array('default' => 'OR');
  35. $options['date_group'] = array('default' => 'date');
  36. return $options;
  37. }
  38. /**
  39. * Add a form element to select date_fields for this argument.
  40. */
  41. function options_form(&$form, &$form_state) {
  42. parent::options_form($form, $form_state);
  43. $fields = date_views_fields($this->base_table);
  44. $options = array();
  45. foreach ($fields['name'] as $name => $field) {
  46. $options[$name] = $field['label'];
  47. }
  48. $form['date_fields'] = array(
  49. '#title' => t('Date field(s)'),
  50. '#type' => 'checkboxes',
  51. '#options' => $options,
  52. '#default_value' => $this->options['date_fields'],
  53. '#multiple' => TRUE,
  54. '#description' => t("Select one or more date fields to filter with this argument."),
  55. );
  56. $form['date_method'] = array(
  57. '#title' => t('Method'),
  58. '#type' => 'radios',
  59. '#options' => array('OR' => t('OR'), 'AND' => t('AND')),
  60. '#default_value' => $this->options['date_method'],
  61. '#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). '),
  62. );
  63. $form['date_group'] = array(
  64. '#type' => 'hidden',
  65. '#value' => $this->options['date_group'],
  66. );
  67. }
  68. function options_validate(&$form, &$form_state) {
  69. // Views will whine if we don't have something for the these values even though we removed the option for summaries.
  70. $form_state['values']['options']['summary']['format'] = 'none';
  71. $form_state['values']['options']['summary']['options']['none'] = array();
  72. // It is very important to call the parent function here:
  73. parent::options_validate($form, $form_state);
  74. if ($form_state['values']['form_id'] == 'views_ui_config_item_form') {
  75. $check_fields = array_filter($form_state['values']['options']['date_fields']);
  76. if (empty($check_fields)) {
  77. form_error($form['date_fields'], t('You must select at least one date field for this argument.'));
  78. }
  79. }
  80. }
  81. function options_submit(&$form, &$form_state) {
  82. // It is very important to call the parent function here:
  83. parent::options_submit($form, $form_state);
  84. if ($form_state['values']['form_id'] == 'views_ui_config_item_form') {
  85. $form_state['values']['options']['date_fields'] = array_filter($form_state['values']['options']['date_fields']);
  86. }
  87. }
  88. // Update the summary values to show selected granularity.
  89. function admin_summary() {
  90. $fields = date_views_fields($this->base_table);
  91. if (!empty($this->options['date_fields'])) {
  92. $output = array();
  93. foreach ($this->options['date_fields'] as $field) {
  94. if (array_key_exists($field, $fields['name'])) {
  95. $output[] = $fields['name'][$field]['label'];
  96. }
  97. }
  98. return implode('<br />' . $this->options['date_method'] . ' ', $output);
  99. }
  100. else {
  101. return parent::admin_summary();
  102. }
  103. }
  104. /**
  105. * Provide a list of default behaviors for this argument if the argument
  106. * is not present.
  107. *
  108. * Override this method to provide additional (or fewer) default behaviors.
  109. */
  110. function default_actions($which = NULL) {
  111. $defaults = parent::default_actions();
  112. // There is no easy way to do summary queries on multiple fields, so remove that option.
  113. unset($defaults['summary']);
  114. if ($which) {
  115. if (!empty($defaults[$which])) {
  116. return $defaults[$which];
  117. }
  118. }
  119. else {
  120. return $defaults;
  121. }
  122. }
  123. /**
  124. * Set up the query for this argument.
  125. *
  126. * The argument sent may be found at $this->argument.
  127. */
  128. function query($group_by = FALSE) {
  129. // @TODO Not doing anything with $group_by yet, need to figure out what has to be done.
  130. if ($this->date_forbid()) {
  131. return;
  132. }
  133. $this->get_query_fields();
  134. $this->query->set_where_group($this->options['date_method'], $this->options['date_group']);
  135. $this->granularity = $this->date_handler->arg_granularity($this->argument);
  136. $format = $this->date_handler->views_formats($this->granularity, 'sql');
  137. $this->placeholders = array();
  138. if (!empty($this->query_fields)) {
  139. // Use set_where_group() with the selected date_method
  140. // of 'AND' or 'OR' to create the where clause.
  141. foreach ($this->query_fields as $count => $query_field) {
  142. $field = $query_field['field'];
  143. $this->date_handler = $query_field['date_handler'];
  144. $this->field = $field['field_name'];
  145. $this->real_field = $field['field_name'];
  146. $this->table = $field['table_name'];
  147. $this->original_table = $field['table_name'];
  148. if ($field['table_name'] != $this->table || !empty($this->relationship)) {
  149. $this->table = $this->query->ensure_table($field['table_name'], $this->relationship);
  150. }
  151. // $this->table_alias gets set when the first field is processed if otherwise empty.
  152. // For subsequent fields, we need to be sure it is emptied again.
  153. elseif (empty($this->relationship)) {
  154. $this->table_alias = NULL;
  155. }
  156. parent::query($group_by);
  157. $this->placeholders = array_merge($this->placeholders, $this->date_handler->placeholders);
  158. }
  159. }
  160. }
  161. /**
  162. * Collect information about our fields we will need to create the right query.
  163. */
  164. function get_query_fields() {
  165. $fields = date_views_fields($this->base_table);
  166. $fields = $fields['name'];
  167. $this->query_fields = array();
  168. foreach ($this->options['date_fields'] as $delta => $name) {
  169. if (array_key_exists($name, $fields) && $field = $fields[$name]) {
  170. $date_handler = new date_sql_handler($field['sql_type'], date_default_timezone());
  171. $date_handler->granularity = $this->options['granularity'];
  172. $date_handler->db_timezone = date_get_timezone_db($field['tz_handling']);
  173. $date_handler->local_timezone = date_get_timezone($field['tz_handling']);
  174. date_views_set_timezone($date_handler, $this, $field);
  175. $this->query_fields[] = array('field' => $field, 'date_handler' => $date_handler);
  176. }
  177. }
  178. }
  179. }
  180. // @codingStandardsIgnoreEnd