5c440c38e970b5149e3500456f0a9e750c5c6a1b
[project/views.git] / modules / taxonomy / views_handler_filter_term_node_tid.inc
1 <?php
2
3 /**
4 * Filter by term id
5 */
6 class views_handler_filter_term_node_tid extends views_handler_filter_many_to_one {
7 function can_group() { return FALSE; }
8
9 function has_extra_options() { return TRUE; }
10
11 function get_value_options() { /* don't overwrite the value options */ }
12
13 function option_definition() {
14 $options = parent::option_definition();
15
16 $options['type'] = array('default' => 'textfield');
17 $options['limit'] = array('default' => TRUE);
18 $options['vid'] = array('default' => 0);
19 $options['hierarchy'] = array('default' => 0);
20 $options['error_message'] = array('default' => TRUE);
21
22 return $options;
23 }
24
25 function extra_options_form(&$form, &$form_state) {
26 $vocabularies = taxonomy_get_vocabularies();
27 foreach ($vocabularies as $voc) {
28 $options[$voc->vid] = check_plain($voc->name);
29 }
30
31 if ($this->options['limit']) {
32 // We only do this when the form is displayed.
33 if ($this->options['vid'] == 0) {
34 $first_vocabulary = reset($vocabularies);
35 $this->options['vid'] = $first_vocabulary->vid;
36 }
37
38 $form['vid'] = array(
39 '#prefix' => '<div class="views-left-40">',
40 '#suffix' => '</div>',
41 '#type' => 'radios',
42 '#title' => t('Vocabulary'),
43 '#options' => $options,
44 '#description' => t('Select which vocabulary to show terms for in the regular options.'),
45 '#default_value' => $this->options['vid'],
46 );
47 }
48
49 $form['markup_start'] = array(
50 '#value' => '<div class="views-left-40">',
51 );
52
53 $form['type'] = array(
54 '#type' => 'radios',
55 '#title' => t('Selection type'),
56 '#options' => array('select' => t('Dropdown'), 'textfield' => t('Autocomplete')),
57 '#default_value' => $this->options['type'],
58 );
59
60 $form['hierarchy'] = array(
61 '#type' => 'checkbox',
62 '#title' => t('Show hierarchy in dropdown'),
63 '#default_value' => !empty($this->options['hierarchy']),
64 '#process' => array('views_process_dependency'),
65 '#dependency' => array('radio:options[type]' => array('select')),
66 );
67
68 $form['markup_end'] = array(
69 '#value' => '</div>',
70 );
71 }
72
73 function value_form(&$form, &$form_state) {
74 $vocabulary = taxonomy_vocabulary_load($this->options['vid']);
75 if (empty($vocabulary) && $this->options['limit']) {
76 $form['markup'] = array(
77 '#prefix' => '<div class="form-item">',
78 '#suffix' => '</div>',
79 '#value' => t('An invalid vocabulary is selected. Please change it in the options.'),
80 );
81 return;
82 }
83
84 if ($this->options['type'] == 'textfield') {
85 $default = '';
86 if ($this->value) {
87 $result = db_query("SELECT * FROM {term_data} td WHERE td.tid IN (" . implode(', ', $this->value) . ')');
88 while ($term = db_fetch_object($result)) {
89 if ($default) {
90 $default .= ', ';
91 }
92 $default .= $term->name;
93 }
94 }
95
96 $form['value'] = array(
97 '#title' => $this->options['limit'] ? t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name)) : t('Select terms'),
98 '#type' => 'textfield',
99 '#default_value' => $default,
100 );
101
102 if ($this->options['limit']) {
103 $form['value']['#autocomplete_path'] = 'taxonomy/autocomplete/' . $vocabulary->vid;
104 }
105 }
106 else {
107 if (!empty($this->options['hierarchy']) && $this->options['limit']) {
108 $tree = taxonomy_get_tree($vocabulary->vid);
109 $options = array();
110
111 if ($tree) {
112 foreach ($tree as $term) {
113 $choice = new stdClass();
114 $choice->option = array($term->tid => str_repeat('-', $term->depth) . $term->name);
115 $options[] = $choice;
116 }
117 }
118 }
119 else {
120 $options = array();
121 if ($this->options['limit']) {
122 $result = db_query(db_rewrite_sql("SELECT t.* FROM {term_data} t WHERE t.vid = %d ORDER BY t.weight, t.name", 't', 'tid'), $vocabulary->vid);
123 }
124 else {
125 $result = db_query(db_rewrite_sql("SELECT td.* FROM {term_data} td INNER JOIN {vocabulary} v ON td.vid = v.vid ORDER BY v.weight, v.name, td.weight, td.name", 'td', 'tid'));
126 }
127 while ($term = db_fetch_object($result)) {
128 $options[$term->tid] = $term->name;
129 }
130 }
131
132 $default_value = (array) $this->value;
133
134 if (!empty($form_state['exposed'])) {
135 $identifier = $this->options['expose']['identifier'];
136
137 if (!empty($this->options['expose']['reduce'])) {
138 $options = $this->reduce_value_options($options);
139
140 if (empty($this->options['expose']['single']) && !empty($this->options['expose']['optional'])) {
141 $default_value = array();
142 }
143 }
144
145 if (!empty($this->options['expose']['single'])) {
146 if (!empty($this->options['expose']['optional']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) {
147 $default_value = 'All';
148 }
149 else if (empty($default_value)) {
150 $keys = array_keys($options);
151 $default_value = array_shift($keys);
152 }
153 else {
154 $copy = $default_value;
155 $default_value = array_shift($copy);
156 }
157 }
158 }
159 $form['value'] = array(
160 '#type' => 'select',
161 '#title' => $this->options['limit'] ? t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name)) : t('Select terms'),
162 '#multiple' => TRUE,
163 '#options' => $options,
164 '#size' => min(9, count($options)),
165 '#default_value' => $default_value,
166 );
167
168 if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier])) {
169 $form_state['input'][$identifier] = $default_value;
170 }
171 }
172
173
174 if (empty($form_state['exposed'])) {
175 // Retain the helper option
176 $this->helper->options_form($form, $form_state);
177 }
178 }
179
180 function value_validate($form, &$form_state) {
181 // We only validate if they've chosen the text field style.
182 if ($this->options['type'] != 'textfield') {
183 return;
184 }
185
186 $values = drupal_explode_tags($form_state['values']['options']['value']);
187 $tids = $this->validate_term_strings($form['value'], $values);
188
189 if ($tids) {
190 $form_state['values']['options']['value'] = $tids;
191 }
192 }
193
194 function accept_exposed_input($input) {
195 if (empty($this->options['exposed'])) {
196 return TRUE;
197 }
198
199 // If view is an attachment and is inheriting exposed filters, then assume
200 // exposed input has already been validated
201 if (isset($this->view->is_attachment) && $this->view->display_handler->uses_exposed()) {
202 $this->validated_exposed_input = (array)$this->view->exposed_raw_input[$this->options['expose']['identifier']];
203 }
204
205 // If it's optional and there's no value don't bother filtering.
206 if ($this->options['expose']['optional'] && empty($this->validated_exposed_input)) {
207 return FALSE;
208 }
209
210 $rc = parent::accept_exposed_input($input);
211 if ($rc) {
212 // If we have previously validated input, override.
213 if (isset($this->validated_exposed_input)) {
214 $this->value = $this->validated_exposed_input;
215 }
216 }
217
218 return $rc;
219 }
220
221 function exposed_validate(&$form, &$form_state) {
222 if (empty($this->options['exposed'])) {
223 return;
224 }
225
226 $identifier = $this->options['expose']['identifier'];
227
228 // We only validate if they've chosen the text field style.
229 if ($this->options['type'] != 'textfield') {
230 if ($form_state['values'][$identifier] != 'All') {
231 $this->validated_exposed_input = (array) $form_state['values'][$identifier];
232 }
233 return;
234 }
235
236 if (empty($this->options['expose']['identifier'])) {
237 return;
238 }
239
240 $values = drupal_explode_tags($form_state['values'][$identifier]);
241
242 $tids = $this->validate_term_strings($form[$identifier], $values);
243 if ($tids) {
244 $this->validated_exposed_input = $tids;
245 }
246 }
247
248 /**
249 * Validate the user string. Since this can come from either the form
250 * or the exposed filter, this is abstracted out a bit so it can
251 * handle the multiple input sources.
252 */
253 function validate_term_strings(&$form, $values) {
254 if (empty($values)) {
255 return array();
256 }
257
258 $tids = array();
259 $placeholders = array();
260 $args = array();
261 $results = array();
262 foreach ($values as $value) {
263 $missing[strtolower($value)] = TRUE;
264 $args[] = $value;
265 $placeholders[] = "'%s'";
266 }
267
268 if (!$args) {
269 return;
270 }
271
272 // add the taxonomy vid to the argument list.
273 $args[] = $this->options['vid'];
274
275 $result = db_query("SELECT * FROM {term_data} td WHERE td.name IN (" . implode(', ', $placeholders) . ") AND td.vid = %d", $args);
276 while ($term = db_fetch_object($result)) {
277 unset($missing[strtolower($term->name)]);
278 $tids[] = $term->tid;
279 }
280
281 if ($missing && !empty($this->options['error_message'])) {
282 form_error($form, format_plural(count($missing), 'Unable to find term: @terms', 'Unable to find terms: @terms', array('@terms' => implode(', ', array_keys($missing)))));
283 }
284 elseif ($missing && empty($this->options['error_message'])) {
285 $tids = array(0);
286 }
287
288 return $tids;
289 }
290
291 function value_submit($form, &$form_state) {
292 // prevent array_filter from messing up our arrays in parent submit.
293 }
294
295 function expose_form_right(&$form, &$form_state) {
296 parent::expose_form_right($form, $form_state);
297 if ($this->options['type'] != 'select') {
298 unset($form['expose']['reduce']);
299 }
300 $form['error_message'] = array(
301 '#type' => 'checkbox',
302 '#title' => t('Display error message'),
303 '#default_value' => !empty($this->options['error_message']),
304 );
305 }
306
307 function admin_summary() {
308 // set up $this->value_options for the parent summary
309 $this->value_options = array();
310
311 if ($this->value) {
312 $result = db_query("SELECT * FROM {term_data} td WHERE td.tid IN (" . implode(', ', $this->value) . ")");
313
314 while ($term = db_fetch_object($result)) {
315 $this->value_options[$term->tid] = $term->name;
316 }
317 }
318 return parent::admin_summary();
319 }
320 }