taxonomy.views.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. <?php
  2. /**
  3. * @file
  4. * Provide views data and handlers for taxonomy.module.
  5. *
  6. * @ingroup views_module_handlers
  7. */
  8. /**
  9. * Implements hook_views_data().
  10. */
  11. function taxonomy_views_data() {
  12. $data = array();
  13. // ----------------------------------------------------------------------
  14. // taxonomy_vocabulary table
  15. $data['vocabulary']['moved to'] = 'taxonomy_vocabulary';
  16. $data['taxonomy_vocabulary']['table']['group'] = t('Taxonomy vocabulary');
  17. $data['taxonomy_vocabulary']['table']['join'] = array(
  18. // vocabulary links to taxonomy_term_data directly via vid.
  19. 'taxonomy_term_data' => array(
  20. 'left_field' => 'vid',
  21. 'field' => 'vid',
  22. ),
  23. );
  24. // Provide a "default relationship" to keep older views from choking.
  25. $data['taxonomy_vocabulary']['table']['default_relationship'] = array(
  26. 'node' => array(
  27. 'table' => 'node',
  28. 'field' => 'term_node_tid',
  29. ),
  30. );
  31. // vocabulary name
  32. $data['taxonomy_vocabulary']['name'] = array(
  33. 'title' => t('Name'), // The item it appears as on the UI,
  34. 'field' => array(
  35. 'help' => t('Name of the vocabulary a term is a member of. This will be the vocabulary that whichever term the "Taxonomy: Term" field is; and can similarly cause duplicates.'),
  36. 'handler' => 'views_handler_field',
  37. 'click sortable' => TRUE,
  38. ),
  39. 'sort' => array(
  40. 'handler' => 'views_handler_sort',
  41. 'help' => t('The taxonomy vocabulary name'),
  42. ),
  43. );
  44. $data['taxonomy_vocabulary']['machine_name'] = array(
  45. 'title' => t('Machine name'), // The item it appears as on the UI,
  46. 'field' => array(
  47. 'help' => t('Machine-Name of the vocabulary a term is a member of. This will be the vocabulary that whichever term the "Taxonomy: Term" field is; and can similarly cause duplicates.'),
  48. 'handler' => 'views_handler_field',
  49. 'click sortable' => TRUE,
  50. ),
  51. 'filter' => array(
  52. 'help' => t('Filter the results of "Taxonomy: Term" to a particular vocabulary.'),
  53. 'handler' => 'views_handler_filter_vocabulary_machine_name',
  54. ),
  55. 'argument' => array(
  56. 'help' => t('Filter the results of "Taxonomy: Term" to a particular vocabulary.'),
  57. 'handler' => 'views_handler_argument_vocabulary_machine_name',
  58. ),
  59. );
  60. $data['taxonomy_vocabulary']['vid'] = array(
  61. 'title' => t('Vocabulary ID'), // The item it appears as on the UI,
  62. 'help' => t('The taxonomy vocabulary ID'),
  63. 'field' => array(
  64. 'handler' => 'views_handler_field_numeric',
  65. 'click sortable' => TRUE,
  66. ),
  67. 'argument' => array(
  68. 'handler' => 'views_handler_argument_vocabulary_vid',
  69. 'name field' => 'name',
  70. ),
  71. 'sort' => array(
  72. 'handler' => 'views_handler_sort',
  73. ),
  74. );
  75. $data['taxonomy_vocabulary']['description'] = array(
  76. 'title' => t('Description'), // The item it appears as on the UI,
  77. 'help' => t('The taxonomy vocabulary description'),
  78. 'field' => array(
  79. 'handler' => 'views_handler_field',
  80. ),
  81. );
  82. $data['taxonomy_vocabulary']['weight'] = array(
  83. 'title' => t('Weight'),
  84. 'help' => t('The taxonomy vocabulary weight'),
  85. 'field' => array(
  86. 'handler' => 'views_handler_field_numeric',
  87. 'click sortable' => TRUE,
  88. ),
  89. 'argument' => array(
  90. 'handler' => 'views_handler_argument_numeric',
  91. 'name field' => 'weight',
  92. ),
  93. 'sort' => array(
  94. 'handler' => 'views_handler_sort',
  95. ),
  96. 'filter' => array(
  97. 'handler' => 'views_handler_filter_numeric',
  98. ),
  99. );
  100. // ----------------------------------------------------------------------
  101. // taxonomy_term_data table
  102. $data['term_data']['moved to'] = 'taxonomy_term_data';
  103. $data['taxonomy_term_data']['table']['group'] = t('Taxonomy term');
  104. $data['taxonomy_term_data']['table']['base'] = array(
  105. 'field' => 'tid',
  106. 'title' => t('Term'),
  107. 'help' => t('Taxonomy terms are attached to nodes.'),
  108. 'access query tag' => 'term_access',
  109. );
  110. $data['taxonomy_term_data']['table']['entity type'] = 'taxonomy_term';
  111. // The term data table
  112. $data['taxonomy_term_data']['table']['join'] = array(
  113. 'taxonomy_vocabulary' => array(
  114. 'field' => 'vid',
  115. 'left_field' => 'vid',
  116. ),
  117. // This is provided for many_to_one argument
  118. 'taxonomy_index' => array(
  119. 'field' => 'tid',
  120. 'left_field' => 'tid',
  121. ),
  122. );
  123. // Provide a "default relationship" to keep older views from choking.
  124. $data['taxonomy_term_data']['table']['default_relationship'] = array(
  125. 'node' => array(
  126. 'table' => 'node',
  127. 'field' => 'term_node_tid',
  128. ),
  129. );
  130. // tid field
  131. $data['taxonomy_term_data']['tid'] = array(
  132. 'title' => t('Term ID'),
  133. 'help' => t('The tid of a taxonomy term.'),
  134. 'field' => array(
  135. 'handler' => 'views_handler_field_numeric',
  136. 'click sortable' => TRUE,
  137. ),
  138. 'sort' => array(
  139. 'handler' => 'views_handler_sort',
  140. ),
  141. 'argument' => array(
  142. 'handler' => 'views_handler_argument_taxonomy',
  143. 'name field' => 'name',
  144. 'zero is null' => TRUE,
  145. ),
  146. 'filter' => array(
  147. 'title' => t('Term'),
  148. 'help' => t('Taxonomy term chosen from autocomplete or select widget.'),
  149. 'handler' => 'views_handler_filter_term_node_tid',
  150. 'hierarchy table' => 'taxonomy_term_hierarchy',
  151. 'numeric' => TRUE,
  152. ),
  153. );
  154. // raw tid field
  155. $data['taxonomy_term_data']['tid_raw'] = array(
  156. 'title' => t('Term ID'),
  157. 'help' => t('The tid of a taxonomy term.'),
  158. 'real field' => 'tid',
  159. 'filter' => array(
  160. 'handler' => 'views_handler_filter_numeric',
  161. 'allow empty' => TRUE,
  162. ),
  163. );
  164. $data['taxonomy_term_data']['tid_representative'] = array(
  165. 'relationship' => array(
  166. 'title' => t('Representative node'),
  167. 'label' => t('Representative node'),
  168. 'help' => t('Obtains a single representative node for each term, according to a chosen sort criterion.'),
  169. 'handler' => 'views_handler_relationship_groupwise_max',
  170. 'relationship field' => 'tid',
  171. 'outer field' => 'taxonomy_term_data.tid',
  172. 'argument table' => 'taxonomy_term_data',
  173. 'argument field' => 'tid',
  174. 'base' => 'node',
  175. 'field' => 'nid',
  176. ),
  177. );
  178. // Term name field
  179. $data['taxonomy_term_data']['name'] = array(
  180. 'title' => t('Name'),
  181. 'help' => t('The taxonomy term name.'),
  182. 'field' => array(
  183. 'handler' => 'views_handler_field_taxonomy',
  184. 'click sortable' => TRUE,
  185. ),
  186. 'sort' => array(
  187. 'handler' => 'views_handler_sort',
  188. ),
  189. 'filter' => array(
  190. 'handler' => 'views_handler_filter_string',
  191. 'help' => t('Taxonomy term name.'),
  192. ),
  193. 'argument' => array(
  194. 'handler' => 'views_handler_argument_string',
  195. 'help' => t('Taxonomy term name.'),
  196. 'many to one' => TRUE,
  197. 'empty field name' => t('Uncategorized'),
  198. ),
  199. );
  200. // taxonomy weight
  201. $data['taxonomy_term_data']['weight'] = array(
  202. 'title' => t('Weight'),
  203. 'help' => t('The term weight field'),
  204. 'field' => array(
  205. 'handler' => 'views_handler_field_numeric',
  206. 'click sortable' => TRUE,
  207. ),
  208. 'sort' => array(
  209. 'handler' => 'views_handler_sort',
  210. ),
  211. 'filter' => array(
  212. 'handler' => 'views_handler_filter_numeric',
  213. ),
  214. 'argument' => array(
  215. 'handler' => 'views_handler_argument_numeric',
  216. ),
  217. );
  218. // Term description
  219. $data['taxonomy_term_data']['description'] = array(
  220. 'title' => t('Term description'),
  221. 'help' => t('The description associated with a taxonomy term.'),
  222. 'field' => array(
  223. 'handler' => 'views_handler_field_markup',
  224. 'format' => array('field' => 'format'),
  225. ),
  226. 'filter' => array(
  227. 'handler' => 'views_handler_filter_string',
  228. ),
  229. );
  230. // Term vocabulary
  231. $data['taxonomy_term_data']['vid'] = array(
  232. 'title' => t('Vocabulary'),
  233. 'help' => t('Filter the results of "Taxonomy: Term" to a particular vocabulary.'),
  234. 'filter' => array(
  235. 'handler' => 'views_handler_filter_vocabulary_vid',
  236. ),
  237. );
  238. // Link to edit the term
  239. $data['taxonomy_term_data']['edit_term'] = array(
  240. 'field' => array(
  241. 'title' => t('Term edit link'),
  242. 'help' => t('Provide a simple link to edit the term.'),
  243. 'handler' => 'views_handler_field_term_link_edit',
  244. ),
  245. );
  246. // ----------------------------------------------------------------------
  247. // taxonomy_index table
  248. $data['term_node']['moved to'] = 'taxonomy_index';
  249. $data['taxonomy_index']['table']['group'] = t('Taxonomy term');
  250. $data['taxonomy_index']['table']['join'] = array(
  251. 'taxonomy_term_data' => array(
  252. // links directly to taxonomy_term_data via tid
  253. 'left_field' => 'tid',
  254. 'field' => 'tid',
  255. ),
  256. 'node' => array(
  257. // links directly to node via nid
  258. 'left_field' => 'nid',
  259. 'field' => 'nid',
  260. ),
  261. 'taxonomy_term_hierarchy' => array(
  262. 'left_field' => 'tid',
  263. 'field' => 'tid',
  264. ),
  265. );
  266. $data['taxonomy_index']['nid'] = array(
  267. 'title' => t('Content with term'),
  268. 'help' => t('Relate all content tagged with a term.'),
  269. 'relationship' => array(
  270. 'handler' => 'views_handler_relationship',
  271. 'base' => 'node',
  272. 'base field' => 'nid',
  273. 'label' => t('node'),
  274. 'skip base' => 'node',
  275. ),
  276. );
  277. // @todo This stuff needs to move to a node field since
  278. // really it's all about nodes.
  279. // tid field
  280. $data['taxonomy_index']['tid'] = array(
  281. 'group' => t('Content'),
  282. 'title' => t('Has taxonomy term ID'),
  283. 'help' => t('Display content if it has the selected taxonomy terms.'),
  284. 'argument' => array(
  285. 'handler' => 'views_handler_argument_term_node_tid',
  286. 'name table' => 'taxonomy_term_data',
  287. 'name field' => 'name',
  288. 'empty field name' => t('Uncategorized'),
  289. 'numeric' => TRUE,
  290. 'skip base' => 'taxonomy_term_data',
  291. ),
  292. 'filter' => array(
  293. 'title' => t('Has taxonomy term'),
  294. 'handler' => 'views_handler_filter_term_node_tid',
  295. 'hierarchy table' => 'taxonomy_term_hierarchy',
  296. 'numeric' => TRUE,
  297. 'skip base' => 'taxonomy_term_data',
  298. 'allow empty' => TRUE,
  299. ),
  300. );
  301. // ----------------------------------------------------------------------
  302. // term_hierarchy table
  303. $data['taxonomy_term_hierarchy']['table']['group'] = t('Taxonomy term');
  304. $data['term_hierarchy']['moved to'] = 'taxonomy_term_hierarchy';
  305. $data['taxonomy_term_hierarchy']['table']['join'] = array(
  306. 'taxonomy_term_hierarchy' => array(
  307. // links to self through left.parent = right.tid (going down in depth)
  308. 'left_field' => 'tid',
  309. 'field' => 'parent',
  310. ),
  311. 'taxonomy_term_data' => array(
  312. // links directly to taxonomy_term_data via tid
  313. 'left_field' => 'tid',
  314. 'field' => 'tid',
  315. ),
  316. );
  317. // Provide a "default relationship" to keep older views from choking.
  318. $data['taxonomy_term_hierarchy']['table']['default_relationship'] = array(
  319. 'node' => array(
  320. 'table' => 'node',
  321. 'field' => 'term_node_tid',
  322. ),
  323. );
  324. $data['taxonomy_term_hierarchy']['parent'] = array(
  325. 'title' => t('Parent term'),
  326. 'help' => t('The parent term of the term. This can produce duplicate entries if you are using a vocabulary that allows multiple parents.'),
  327. 'relationship' => array(
  328. 'base' => 'taxonomy_term_data',
  329. 'field' => 'parent',
  330. 'label' => t('Parent'),
  331. ),
  332. 'filter' => array(
  333. 'help' => t('Filter the results of "Taxonomy: Term" by the parent pid.'),
  334. 'handler' => 'views_handler_filter_numeric',
  335. ),
  336. 'argument' => array(
  337. 'help' => t('The parent term of the term.'),
  338. 'handler' => 'views_handler_argument_taxonomy',
  339. ),
  340. );
  341. return $data;
  342. }
  343. /**
  344. * Implements hook_views_data_alter().
  345. */
  346. function taxonomy_views_data_alter(&$data) {
  347. $data['node']['term_node_tid'] = array(
  348. 'title' => t('Taxonomy terms on node'),
  349. 'help' => t('Relate nodes to taxonomy terms, specifiying which vocabulary or vocabularies to use. This relationship will cause duplicated records if there are multiple terms.'),
  350. 'relationship' => array(
  351. 'handler' => 'views_handler_relationship_node_term_data',
  352. 'label' => t('term'),
  353. 'base' => 'taxonomy_term_data',
  354. ),
  355. 'field' => array(
  356. 'title' => t('All taxonomy terms'),
  357. 'help' => t('Display all taxonomy terms associated with a node from specified vocabularies.'),
  358. 'handler' => 'views_handler_field_term_node_tid',
  359. 'no group by' => TRUE,
  360. ),
  361. );
  362. $data['node']['term_node_tid_depth'] = array(
  363. 'help' => t('Display content if it has the selected taxonomy terms, or children of the selected terms. Due to additional complexity, this has fewer options than the versions without depth.'),
  364. 'real field' => 'nid',
  365. 'argument' => array(
  366. 'title' => t('Has taxonomy term ID (with depth)'),
  367. 'handler' => 'views_handler_argument_term_node_tid_depth',
  368. 'accept depth modifier' => TRUE,
  369. ),
  370. 'filter' => array(
  371. 'title' => t('Has taxonomy terms (with depth)'),
  372. 'handler' => 'views_handler_filter_term_node_tid_depth',
  373. ),
  374. );
  375. $data['node']['term_node_tid_depth_join'] = array(
  376. 'help' => t('Display content if it has the selected taxonomy terms, or children of the selected terms. Due to additional complexity, this has fewer options than the versions without depth.'),
  377. 'real field' => 'nid',
  378. 'argument' => array(
  379. 'title' => t('Has taxonomy term ID with depth (using joins)'),
  380. 'handler' => 'views_handler_argument_term_node_tid_depth_join',
  381. 'accept depth modifier' => TRUE,
  382. ),
  383. 'filter' => array(
  384. 'title' => t('Has taxonomy terms with depth (using joins)'),
  385. 'handler' => 'views_handler_filter_term_node_tid_depth_join',
  386. ),
  387. );
  388. $data['node']['term_node_tid_depth_modifier'] = array(
  389. 'title' => t('Has taxonomy term ID depth modifier'),
  390. 'help' => t('Allows the "depth" for Taxonomy: Term ID (with depth) to be modified via an additional contextual filter value.'),
  391. 'argument' => array(
  392. 'handler' => 'views_handler_argument_term_node_tid_depth_modifier',
  393. ),
  394. );
  395. }
  396. /**
  397. * Implements hook_field_views_data().
  398. *
  399. * Views integration for taxonomy_term_reference fields. Adds a term relationship to the default
  400. * field data.
  401. *
  402. * @see field_views_field_default_views_data()
  403. */
  404. function taxonomy_field_views_data($field) {
  405. $data = field_views_field_default_views_data($field);
  406. foreach ($data as $table_name => $table_data) {
  407. foreach ($table_data as $field_name => $field_data) {
  408. if (isset($field_data['filter']) && $field_name != 'delta') {
  409. $data[$table_name][$field_name]['filter']['handler'] = 'views_handler_filter_term_node_tid';
  410. $data[$table_name][$field_name]['filter']['vocabulary'] = $field['settings']['allowed_values'][0]['vocabulary'];
  411. }
  412. }
  413. // Add the relationship only on the tid field.
  414. $data[$table_name][$field['field_name'] . '_tid']['relationship'] = array(
  415. 'handler' => 'views_handler_relationship',
  416. 'base' => 'taxonomy_term_data',
  417. 'base field' => 'tid',
  418. 'label' => t('term from !field_name', array('!field_name' => $field['field_name'])),
  419. );
  420. }
  421. return $data;
  422. }
  423. /**
  424. * Implements hook_field_views_data_views_data_alter().
  425. *
  426. * Views integration to provide reverse relationships on term references.
  427. */
  428. function taxonomy_field_views_data_views_data_alter(&$data, $field) {
  429. foreach ($field['bundles'] as $entity_type => $bundles) {
  430. $entity_info = entity_get_info($entity_type);
  431. $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type;
  432. list($label, $all_labels) = field_views_field_label($field['field_name']);
  433. $entity = $entity_info['label'];
  434. if ($entity == t('Node')) {
  435. $entity = t('Content');
  436. }
  437. $data['taxonomy_term_data'][$pseudo_field_name]['relationship'] = array(
  438. 'title' => t('@entity using @field', array('@entity' => $entity, '@field' => $label)),
  439. 'help' => t('Relate each @entity with a @field set to the term.', array('@entity' => $entity, '@field' => $label)),
  440. 'handler' => 'views_handler_relationship_entity_reverse',
  441. 'field_name' => $field['field_name'],
  442. 'field table' => _field_sql_storage_tablename($field),
  443. 'field field' => $field['field_name'] . '_tid',
  444. 'base' => $entity_info['base table'],
  445. 'base field' => $entity_info['entity keys']['id'],
  446. 'label' => t('!field_name', array('!field_name' => $field['field_name'])),
  447. 'join_extra' => array(
  448. 0 => array(
  449. 'field' => 'entity_type',
  450. 'value' => $entity_type,
  451. ),
  452. 1 => array(
  453. 'field' => 'deleted',
  454. 'value' => 0,
  455. 'numeric' => TRUE,
  456. ),
  457. ),
  458. );
  459. }
  460. }
  461. /**
  462. * Implements hook_views_plugins().
  463. */
  464. function taxonomy_views_plugins() {
  465. return array(
  466. 'module' => 'views', // This just tells our themes are elsewhere.
  467. 'argument validator' => array(
  468. 'taxonomy_term' => array(
  469. 'title' => t('Taxonomy term'),
  470. 'handler' => 'views_plugin_argument_validate_taxonomy_term',
  471. 'path' => drupal_get_path('module', 'views') . '/modules/taxonomy', // not necessary for most modules
  472. ),
  473. ),
  474. 'argument default' => array(
  475. 'taxonomy_tid' => array(
  476. 'title' => t('Taxonomy term ID from URL'),
  477. 'handler' => 'views_plugin_argument_default_taxonomy_tid',
  478. 'path' => drupal_get_path('module', 'views') . '/modules/taxonomy',
  479. 'parent' => 'fixed',
  480. ),
  481. ),
  482. );
  483. }
  484. /**
  485. * Helper function to set a breadcrumb for taxonomy.
  486. */
  487. function views_taxonomy_set_breadcrumb(&$breadcrumb, &$argument) {
  488. if (empty($argument->options['set_breadcrumb'])) {
  489. return;
  490. }
  491. $args = $argument->view->args;
  492. $parents = taxonomy_get_parents_all($argument->argument);
  493. foreach (array_reverse($parents) as $parent) {
  494. // Unfortunately parents includes the current argument. Skip.
  495. if ($parent->tid == $argument->argument) {
  496. continue;
  497. }
  498. if (!empty($argument->options['use_taxonomy_term_path'])) {
  499. $path = taxonomy_term_uri($parent);
  500. $path = $path['path'];
  501. }
  502. else {
  503. $args[$argument->position] = $parent->tid;
  504. $path = $argument->view->get_url($args);
  505. }
  506. $breadcrumb[$path] = check_plain($parent->name);
  507. }
  508. }