handler_filter_options.inc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <?php
  2. /**
  3. * Views filter handler class for handling fields with a limited set of possible
  4. * values.
  5. *
  6. * Definition items:
  7. * - options: An array of possible values for this field.
  8. */
  9. class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter {
  10. protected $value_form_type = 'checkboxes';
  11. /**
  12. * Provide a list of options for the operator form.
  13. */
  14. public function operator_options() {
  15. return array(
  16. '=' => t('Is one of'),
  17. '<>' => t('Is not one of'),
  18. 'empty' => t('Is empty'),
  19. 'not empty' => t('Is not empty'),
  20. );
  21. }
  22. /**
  23. * Set "reduce" option to FALSE by default.
  24. */
  25. public function expose_options() {
  26. parent::expose_options();
  27. $this->options['expose']['reduce'] = FALSE;
  28. }
  29. /**
  30. * Add the "reduce" option to the exposed form.
  31. */
  32. public function expose_form(&$form, &$form_state) {
  33. parent::expose_form($form, $form_state);
  34. $form['expose']['reduce'] = array(
  35. '#type' => 'checkbox',
  36. '#title' => t('Limit list to selected items'),
  37. '#description' => t('If checked, the only items presented to the user will be the ones selected here.'),
  38. '#default_value' => !empty($this->options['expose']['reduce']),
  39. );
  40. }
  41. /**
  42. * Define "reduce" option.
  43. */
  44. public function option_definition() {
  45. $options = parent::option_definition();
  46. $options['expose']['contains']['reduce'] = array('default' => FALSE);
  47. return $options;
  48. }
  49. /**
  50. * Reduce the options according to the selection.
  51. */
  52. protected function reduce_value_options() {
  53. $options = array();
  54. foreach ($this->definition['options'] as $id => $option) {
  55. if (isset($this->options['value'][$id])) {
  56. $options[$id] = $option;
  57. }
  58. }
  59. return $options;
  60. }
  61. /**
  62. * Save set checkboxes.
  63. */
  64. public function value_submit($form, &$form_state) {
  65. // Drupal's FAPI system automatically puts '0' in for any checkbox that
  66. // was not set, and the key to the checkbox if it is set.
  67. // Unfortunately, this means that if the key to that checkbox is 0,
  68. // we are unable to tell if that checkbox was set or not.
  69. // Luckily, the '#value' on the checkboxes form actually contains
  70. // *only* a list of checkboxes that were set, and we can use that
  71. // instead.
  72. $form_state['values']['options']['value'] = $form['value']['#value'];
  73. }
  74. /**
  75. * Provide a form for setting options.
  76. */
  77. public function value_form(&$form, &$form_state) {
  78. $options = array();
  79. if (!empty($this->options['expose']['reduce']) && !empty($form_state['exposed'])) {
  80. $options += $this->reduce_value_options($form_state);
  81. }
  82. else {
  83. $options += $this->definition['options'];
  84. }
  85. $form['value'] = array(
  86. '#type' => $this->value_form_type,
  87. '#title' => empty($form_state['exposed']) ? t('Value') : '',
  88. '#options' => $options,
  89. '#multiple' => TRUE,
  90. '#size' => min(4, count($this->definition['options'])),
  91. '#default_value' => isset($this->value) ? $this->value : array(),
  92. );
  93. // Hide the value box if operator is 'empty' or 'not empty'.
  94. // Radios share the same selector so we have to add some dummy selector.
  95. // #states replace #dependency (http://drupal.org/node/1595022).
  96. $form['value']['#states']['visible'] = array(
  97. ':input[name="options[operator]"],dummy-empty' => array('!value' => 'empty'),
  98. ':input[name="options[operator]"],dummy-not-empty' => array('!value' => 'not empty'),
  99. );
  100. }
  101. /**
  102. * Provides a summary of this filter's value for the admin UI.
  103. */
  104. public function admin_summary() {
  105. if (!empty($this->options['exposed'])) {
  106. return t('exposed');
  107. }
  108. if ($this->operator === 'empty') {
  109. return t('is empty');
  110. }
  111. if ($this->operator === 'not empty') {
  112. return t('is not empty');
  113. }
  114. if (!is_array($this->value)) {
  115. return;
  116. }
  117. $operator_options = $this->operator_options();
  118. $operator = $operator_options[$this->operator];
  119. $values = '';
  120. // Remove every element which is not known.
  121. foreach ($this->value as $i => $value) {
  122. if (!isset($this->definition['options'][$value])) {
  123. unset($this->value[$i]);
  124. }
  125. }
  126. // Choose different kind of ouput for 0, a single and multiple values.
  127. if (count($this->value) == 0) {
  128. return $this->operator == '=' ? t('none') : t('any');
  129. }
  130. elseif (count($this->value) == 1) {
  131. // If there is only a single value, use just the plain operator, = or <>.
  132. $operator = check_plain($this->operator);
  133. $values = check_plain($this->definition['options'][reset($this->value)]);
  134. }
  135. else {
  136. foreach ($this->value as $value) {
  137. if ($values !== '') {
  138. $values .= ', ';
  139. }
  140. if (drupal_strlen($values) > 20) {
  141. $values .= '…';
  142. break;
  143. }
  144. $values .= check_plain($this->definition['options'][$value]);
  145. }
  146. }
  147. return $operator . (($values !== '') ? ' ' . $values : '');
  148. }
  149. /**
  150. * Add this filter to the query.
  151. */
  152. public function query() {
  153. if ($this->operator === 'empty') {
  154. $this->query->condition($this->real_field, NULL, '=', $this->options['group']);
  155. }
  156. elseif ($this->operator === 'not empty') {
  157. $this->query->condition($this->real_field, NULL, '<>', $this->options['group']);
  158. }
  159. else {
  160. while (is_array($this->value) && count($this->value) == 1) {
  161. $this->value = reset($this->value);
  162. }
  163. if (is_scalar($this->value) && $this->value !== '') {
  164. $this->query->condition($this->real_field, $this->value, $this->operator, $this->options['group']);
  165. }
  166. elseif ($this->value) {
  167. if ($this->operator == '=') {
  168. $filter = $this->query->createFilter('OR');
  169. // $filter will be NULL if there were errors in the query.
  170. if ($filter) {
  171. foreach ($this->value as $v) {
  172. $filter->condition($this->real_field, $v, '=');
  173. }
  174. $this->query->filter($filter, $this->options['group']);
  175. }
  176. }
  177. else {
  178. foreach ($this->value as $v) {
  179. $this->query->condition($this->real_field, $v, $this->operator, $this->options['group']);
  180. }
  181. }
  182. }
  183. }
  184. }
  185. }