handler_filter_numeric.inc 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. /**
  3. * @file
  4. * Contains SearchApiViewsHandlerFilterNumeric.
  5. */
  6. /**
  7. * Views filter handler class for handling numeric and "string" fields.
  8. */
  9. class SearchApiViewsHandlerFilterNumeric extends SearchApiViewsHandlerFilter {
  10. /**
  11. * {@inheritdoc}
  12. */
  13. public function init(&$view, &$options) {
  14. parent::init($view, $options);
  15. $this->normalizeValue();
  16. }
  17. /**
  18. * {@inheritdoc}
  19. */
  20. public function option_definition() {
  21. $options = parent::option_definition();
  22. $options['value'] = array(
  23. 'contains' => array(
  24. 'value' => array('default' => ''),
  25. 'min' => array('default' => ''),
  26. 'max' => array('default' => ''),
  27. ),
  28. );
  29. return $options;
  30. }
  31. /**
  32. * {@inheritdoc}
  33. */
  34. public function operator_options() {
  35. $operators = parent::operator_options();
  36. $index = search_api_index_load(substr($this->table, 17));
  37. $server = NULL;
  38. try {
  39. if ($index) {
  40. $server = $index->server();
  41. }
  42. }
  43. catch (SearchApiException $e) {
  44. // Ignore.
  45. }
  46. if ($server && $server->supportsFeature('search_api_between')) {
  47. $operators += array(
  48. 'between' => t('Is between'),
  49. 'not between' => t('Is not between'),
  50. );
  51. }
  52. return $operators;
  53. }
  54. /**
  55. * Provides a form for setting the filter value.
  56. *
  57. * Heavily borrowed from views_handler_filter_numeric.
  58. *
  59. * @see views_handler_filter_numeric::value_form()
  60. */
  61. public function value_form(&$form, &$form_state) {
  62. $form['value']['#tree'] = TRUE;
  63. $single_field_operators = $this->operator_options();
  64. unset(
  65. $single_field_operators['empty'],
  66. $single_field_operators['not empty'],
  67. $single_field_operators['between'],
  68. $single_field_operators['not between']
  69. );
  70. $between_operators = array('between', 'not between');
  71. // We have to make some choices when creating this as an exposed
  72. // filter form. For example, if the operator is locked and thus
  73. // not rendered, we can't render dependencies; instead we only
  74. // render the form items we need.
  75. $which = 'all';
  76. $source = NULL;
  77. if (!empty($form['operator'])) {
  78. $source = ($form['operator']['#type'] == 'radios') ? 'radio:options[operator]' : 'edit-options-operator';
  79. }
  80. $identifier = NULL;
  81. if (!empty($form_state['exposed'])) {
  82. $identifier = $this->options['expose']['identifier'];
  83. if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) {
  84. // Exposed and locked.
  85. $which = in_array($this->operator, $between_operators) ? 'minmax' : 'value';
  86. }
  87. else {
  88. $source = 'edit-' . drupal_html_id($this->options['expose']['operator_id']);
  89. }
  90. }
  91. // Hide the value box if the operator is 'empty' or 'not empty'.
  92. // Radios share the same selector so we have to add some dummy selector.
  93. if ($which == 'all') {
  94. $form['value']['value'] = array(
  95. '#type' => 'textfield',
  96. '#title' => empty($form_state['exposed']) ? t('Value') : '',
  97. '#size' => 30,
  98. '#default_value' => $this->value['value'],
  99. '#dependency' => array($source => array_keys($single_field_operators)),
  100. );
  101. if ($identifier && !isset($form_state['input'][$identifier]['value'])) {
  102. $form_state['input'][$identifier]['value'] = $this->value['value'];
  103. }
  104. }
  105. elseif ($which == 'value') {
  106. // When exposed we drop the value-value and just do value if
  107. // the operator is locked.
  108. $form['value'] = array(
  109. '#type' => 'textfield',
  110. '#title' => empty($form_state['exposed']) ? t('Value') : '',
  111. '#size' => 30,
  112. '#default_value' => isset($this->value['value']) ? $this->value['value'] : '',
  113. );
  114. if ($identifier && !isset($form_state['input'][$identifier])) {
  115. $form_state['input'][$identifier] = isset($this->value['value']) ? $this->value['value'] : '';
  116. }
  117. }
  118. if ($which == 'all' || $which == 'minmax') {
  119. $form['value']['min'] = array(
  120. '#type' => 'textfield',
  121. '#title' => empty($form_state['exposed']) ? t('Min') : '',
  122. '#size' => 30,
  123. '#default_value' => $this->value['min'],
  124. );
  125. $form['value']['max'] = array(
  126. '#type' => 'textfield',
  127. '#title' => empty($form_state['exposed']) ? t('And max') : t('And'),
  128. '#size' => 30,
  129. '#default_value' => $this->value['max'],
  130. );
  131. if ($which == 'all') {
  132. $form['value']['min']['#dependency'] = array($source => $between_operators);
  133. $form['value']['max']['#dependency'] = array($source => $between_operators);
  134. }
  135. if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['min'])) {
  136. $form_state['input'][$identifier]['min'] = $this->value['min'];
  137. }
  138. if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['max'])) {
  139. $form_state['input'][$identifier]['max'] = $this->value['max'];
  140. }
  141. if (!isset($form['value']['value'])) {
  142. // Ensure there is something in the 'value'.
  143. $form['value']['value'] = array(
  144. '#type' => 'value',
  145. '#value' => NULL,
  146. );
  147. }
  148. }
  149. }
  150. /**
  151. * {@inheritdoc}
  152. */
  153. public function admin_summary() {
  154. if (!empty($this->options['exposed'])) {
  155. return t('exposed');
  156. }
  157. if ($this->operator === 'empty') {
  158. return t('is empty');
  159. }
  160. if ($this->operator === 'not empty') {
  161. return t('is not empty');
  162. }
  163. if (in_array($this->operator, array('between', 'not between'), TRUE)) {
  164. // This is of course wrong for translation purposes, but copied from
  165. // views_handler_filter_numeric::admin_summary() so probably still better
  166. // to re-use this than to do it correctly.
  167. $operator = $this->operator === 'between' ? t('between') : t('not between');
  168. $vars = array(
  169. '@min' => (string) $this->value['min'],
  170. '@max' => (string) $this->value['max'],
  171. );
  172. return $operator . ' ' . t('@min and @max', $vars);
  173. }
  174. return check_plain((string) $this->operator) . ' ' . check_plain((string) $this->value['value']);
  175. }
  176. /**
  177. * {@inheritdoc}
  178. */
  179. public function query() {
  180. $this->normalizeValue();
  181. if (in_array($this->operator, array('between', 'not between'), TRUE)) {
  182. $min = $this->value['min'];
  183. $max = $this->value['max'];
  184. if ($min !== '' && $max !== '') {
  185. $this->query->condition($this->real_field, array($min, $max), strtoupper($this->operator), $this->options['group']);
  186. }
  187. elseif ($min !== '') {
  188. $operator = $this->operator === 'between' ? '>=' : '<';
  189. $this->query->condition($this->real_field, $min, $operator, $this->options['group']);
  190. }
  191. elseif ($max !== '') {
  192. $operator = $this->operator === 'between' ? '<=' : '>';
  193. $this->query->condition($this->real_field, $min, $operator, $this->options['group']);
  194. }
  195. }
  196. else {
  197. // The parent handler doesn't expect our value structure, just pass the
  198. // scalar value instead.
  199. $this->value = $this->value['value'];
  200. parent::query();
  201. }
  202. }
  203. /**
  204. * Sets $this->value to an array of options as defined by the filter.
  205. *
  206. * @see SearchApiViewsHandlerFilterNumeric::option_definition()
  207. */
  208. protected function normalizeValue() {
  209. $value = $this->value;
  210. if (is_array($value) && isset($value[0])) {
  211. $value = $value[0];
  212. }
  213. if (!is_array($value)) {
  214. $value = array('value' => $value);
  215. }
  216. $this->value = array(
  217. 'value' => isset($value['value']) ? $value['value'] : '',
  218. 'min' => isset($value['min']) ? $value['min'] : '',
  219. 'max' => isset($value['max']) ? $value['max'] : '',
  220. );
  221. }
  222. }