views_handler_filter_numeric.inc 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. <?php
  2. /**
  3. * @file
  4. * Definition of views_handler_filter_numeric.
  5. */
  6. /**
  7. * Simple filter to handle greater than/less than filters
  8. *
  9. * @ingroup views_filter_handlers
  10. */
  11. class views_handler_filter_numeric extends views_handler_filter {
  12. /**
  13. * Exposed filter options.
  14. */
  15. public $always_multiple = TRUE;
  16. /**
  17. * {@inheritdoc}
  18. */
  19. public function option_definition() {
  20. $options = parent::option_definition();
  21. $options['value'] = array(
  22. 'contains' => array(
  23. 'min' => array('default' => ''),
  24. 'max' => array('default' => ''),
  25. 'value' => array('default' => ''),
  26. ),
  27. );
  28. return $options;
  29. }
  30. /**
  31. * {@inheritdoc}
  32. */
  33. public function operators() {
  34. $operators = array(
  35. '<' => array(
  36. 'title' => t('Is less than'),
  37. 'method' => 'op_simple',
  38. 'short' => t('<'),
  39. 'values' => 1,
  40. ),
  41. '<=' => array(
  42. 'title' => t('Is less than or equal to'),
  43. 'method' => 'op_simple',
  44. 'short' => t('<='),
  45. 'values' => 1,
  46. ),
  47. '=' => array(
  48. 'title' => t('Is equal to'),
  49. 'method' => 'op_simple',
  50. 'short' => t('='),
  51. 'values' => 1,
  52. ),
  53. '!=' => array(
  54. 'title' => t('Is not equal to'),
  55. 'method' => 'op_simple',
  56. 'short' => t('!='),
  57. 'values' => 1,
  58. ),
  59. '>=' => array(
  60. 'title' => t('Is greater than or equal to'),
  61. 'method' => 'op_simple',
  62. 'short' => t('>='),
  63. 'values' => 1,
  64. ),
  65. '>' => array(
  66. 'title' => t('Is greater than'),
  67. 'method' => 'op_simple',
  68. 'short' => t('>'),
  69. 'values' => 1,
  70. ),
  71. 'between' => array(
  72. 'title' => t('Is between'),
  73. 'method' => 'op_between',
  74. 'short' => t('between'),
  75. 'values' => 2,
  76. ),
  77. 'not between' => array(
  78. 'title' => t('Is not between'),
  79. 'method' => 'op_between',
  80. 'short' => t('not between'),
  81. 'values' => 2,
  82. ),
  83. );
  84. // if the definition allows for the empty operator, add it.
  85. if (!empty($this->definition['allow empty'])) {
  86. $operators += array(
  87. 'empty' => array(
  88. 'title' => t('Is empty (NULL)'),
  89. 'method' => 'op_empty',
  90. 'short' => t('empty'),
  91. 'values' => 0,
  92. ),
  93. 'not empty' => array(
  94. 'title' => t('Is not empty (NOT NULL)'),
  95. 'method' => 'op_empty',
  96. 'short' => t('not empty'),
  97. 'values' => 0,
  98. ),
  99. );
  100. }
  101. // Add regexp support for MySQL.
  102. if (Database::getConnection()->databaseType() == 'mysql') {
  103. $operators += array(
  104. 'regular_expression' => array(
  105. 'title' => t('Regular expression'),
  106. 'short' => t('regex'),
  107. 'method' => 'op_regex',
  108. 'values' => 1,
  109. ),
  110. );
  111. }
  112. return $operators;
  113. }
  114. /**
  115. * Provide a list of all the numeric operators
  116. */
  117. public function operator_options($which = 'title') {
  118. $options = array();
  119. foreach ($this->operators() as $id => $info) {
  120. $options[$id] = $info[$which];
  121. }
  122. return $options;
  123. }
  124. /**
  125. * {@inheritdoc}
  126. */
  127. public function operator_values($values = 1) {
  128. $options = array();
  129. foreach ($this->operators() as $id => $info) {
  130. if ($info['values'] == $values) {
  131. $options[] = $id;
  132. }
  133. }
  134. return $options;
  135. }
  136. /**
  137. * Provide a simple textfield for equality
  138. */
  139. public function value_form(&$form, &$form_state) {
  140. $form['value']['#tree'] = TRUE;
  141. // We have to make some choices when creating this as an exposed
  142. // filter form. For example, if the operator is locked and thus
  143. // not rendered, we can't render dependencies; instead we only
  144. // render the form items we need.
  145. $which = 'all';
  146. if (!empty($form['operator'])) {
  147. $source = ($form['operator']['#type'] == 'radios') ? 'radio:options[operator]' : 'edit-options-operator';
  148. }
  149. if (!empty($form_state['exposed'])) {
  150. $identifier = $this->options['expose']['identifier'];
  151. if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) {
  152. // exposed and locked.
  153. $which = in_array($this->operator, $this->operator_values(2)) ? 'minmax' : 'value';
  154. }
  155. else {
  156. $source = 'edit-' . drupal_html_id($this->options['expose']['operator_id']);
  157. }
  158. }
  159. if ($which == 'all') {
  160. $form['value']['value'] = array(
  161. '#type' => 'textfield',
  162. '#title' => empty($form_state['exposed']) ? t('Value') : '',
  163. '#size' => 30,
  164. '#default_value' => $this->value['value'],
  165. '#dependency' => array($source => $this->operator_values(1)),
  166. );
  167. if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['value'])) {
  168. $form_state['input'][$identifier]['value'] = $this->value['value'];
  169. }
  170. }
  171. elseif ($which == 'value') {
  172. // When exposed we drop the value-value and just do value if
  173. // the operator is locked.
  174. $form['value'] = array(
  175. '#type' => 'textfield',
  176. '#title' => empty($form_state['exposed']) ? t('Value') : '',
  177. '#size' => 30,
  178. '#default_value' => $this->value['value'],
  179. );
  180. if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier])) {
  181. $form_state['input'][$identifier] = $this->value['value'];
  182. }
  183. }
  184. if ($which == 'all' || $which == 'minmax') {
  185. $form['value']['min'] = array(
  186. '#type' => 'textfield',
  187. '#title' => empty($form_state['exposed']) ? t('Min') : '',
  188. '#size' => 30,
  189. '#default_value' => $this->value['min'],
  190. );
  191. $form['value']['max'] = array(
  192. '#type' => 'textfield',
  193. '#title' => empty($form_state['exposed']) ? t('And max') : t('And'),
  194. '#size' => 30,
  195. '#default_value' => $this->value['max'],
  196. );
  197. if ($which == 'all') {
  198. $dependency = array(
  199. '#dependency' => array($source => $this->operator_values(2)),
  200. );
  201. $form['value']['min'] += $dependency;
  202. $form['value']['max'] += $dependency;
  203. }
  204. if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['min'])) {
  205. $form_state['input'][$identifier]['min'] = $this->value['min'];
  206. }
  207. if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['max'])) {
  208. $form_state['input'][$identifier]['max'] = $this->value['max'];
  209. }
  210. if (!isset($form['value'])) {
  211. // Ensure there is something in the 'value'.
  212. $form['value'] = array(
  213. '#type' => 'value',
  214. '#value' => NULL
  215. );
  216. }
  217. }
  218. }
  219. /**
  220. * {@inheritdoc}
  221. */
  222. public function query() {
  223. $this->ensure_my_table();
  224. $field = "$this->table_alias.$this->real_field";
  225. $info = $this->operators();
  226. if (!empty($info[$this->operator]['method'])) {
  227. $this->{$info[$this->operator]['method']}($field);
  228. }
  229. }
  230. /**
  231. * {@inheritdoc}
  232. */
  233. public function op_between($field) {
  234. if ($this->operator == 'between') {
  235. $this->query->add_where($this->options['group'], $field, array($this->value['min'], $this->value['max']), 'BETWEEN');
  236. }
  237. else {
  238. $this->query->add_where($this->options['group'], db_or()->condition($field, $this->value['min'], '<=')->condition($field, $this->value['max'], '>='));
  239. }
  240. }
  241. /**
  242. * {@inheritdoc}
  243. */
  244. public function op_simple($field) {
  245. $this->query->add_where($this->options['group'], $field, $this->value['value'], $this->operator);
  246. }
  247. /**
  248. * {@inheritdoc}
  249. */
  250. public function op_empty($field) {
  251. if ($this->operator == 'empty') {
  252. $operator = "IS NULL";
  253. }
  254. else {
  255. $operator = "IS NOT NULL";
  256. }
  257. $this->query->add_where($this->options['group'], $field, NULL, $operator);
  258. }
  259. /**
  260. * {@inheritdoc}
  261. */
  262. public function op_regex($field) {
  263. $this->query->add_where($this->options['group'], $field, $this->value['value'], 'RLIKE');
  264. }
  265. /**
  266. * {@inheritdoc}
  267. */
  268. public function admin_summary() {
  269. if ($this->is_a_group()) {
  270. return t('grouped');
  271. }
  272. if (!empty($this->options['exposed'])) {
  273. return t('exposed');
  274. }
  275. $options = $this->operator_options('short');
  276. $output = check_plain($options[$this->operator]);
  277. if (in_array($this->operator, $this->operator_values(2))) {
  278. $output .= ' ' . t('@min and @max', array('@min' => $this->value['min'], '@max' => $this->value['max']));
  279. }
  280. elseif (in_array($this->operator, $this->operator_values(1))) {
  281. $output .= ' ' . check_plain($this->value['value']);
  282. }
  283. return $output;
  284. }
  285. /**
  286. * Do some minor translation of the exposed input.
  287. */
  288. public function accept_exposed_input($input) {
  289. if (empty($this->options['exposed'])) {
  290. return TRUE;
  291. }
  292. // Rewrite the input value so that it's in the correct format so that the
  293. // parent gets the right data.
  294. if (!empty($this->options['expose']['identifier'])) {
  295. $value = &$input[$this->options['expose']['identifier']];
  296. if (!is_array($value)) {
  297. $value = array(
  298. 'value' => $value,
  299. );
  300. }
  301. }
  302. $rc = parent::accept_exposed_input($input);
  303. if (empty($this->options['expose']['required'])) {
  304. // We have to do some of our own checking for non-required filters.
  305. $info = $this->operators();
  306. if (!empty($info[$this->operator]['values'])) {
  307. switch ($info[$this->operator]['values']) {
  308. case 1:
  309. if ($value['value'] === '') {
  310. return FALSE;
  311. }
  312. break;
  313. case 2:
  314. if ($value['min'] === '' && $value['max'] === '') {
  315. return FALSE;
  316. }
  317. break;
  318. }
  319. }
  320. }
  321. return $rc;
  322. }
  323. }