views_handler_filter_term_node_tid.inc

  1. 3.x modules/taxonomy/views_handler_filter_term_node_tid.inc
  2. 2.x modules/taxonomy/views_handler_filter_term_node_tid.inc

Definition of views_handler_filter_term_node_tid.

File

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