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