term_reference_tree.module 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <?php
  2. module_load_include('inc', 'term_reference_tree', 'term_reference_tree.field');
  3. module_load_include('inc', 'term_reference_tree', 'term_reference_tree.widget');
  4. /**
  5. * Implements hook_element_info().
  6. */
  7. function term_reference_tree_element_info() {
  8. $types = array(
  9. 'checkbox_tree' => array(
  10. '#input' => TRUE,
  11. '#process' => array('term_reference_tree_process_checkbox_tree'),
  12. '#theme' => array('checkbox_tree'),
  13. '#pre_render' => array('form_pre_render_conditional_form_element'),
  14. ),
  15. 'checkbox_tree_level' => array(
  16. '#input' => FALSE,
  17. '#theme' => array('checkbox_tree_level'),
  18. '#pre_render' => array('form_pre_render_conditional_form_element'),
  19. ),
  20. 'checkbox_tree_item' => array(
  21. '#input' => FALSE,
  22. '#theme' => array('checkbox_tree_item'),
  23. '#pre_render' => array('form_pre_render_conditional_form_element'),
  24. ),
  25. 'checkbox_tree_label' => array(
  26. '#input' => FALSE,
  27. '#theme' => array('checkbox_tree_label'),
  28. '#pre_render' => array('form_pre_render_conditional_form_element'),
  29. ),
  30. 'checkbox_tree_track_list' => array(
  31. '#input' => FALSE,
  32. '#theme' => array('checkbox_tree_track_list'),
  33. '#pre_render' => array('form_pre_render_conditional_form_element'),
  34. ),
  35. );
  36. return $types;
  37. }
  38. /**
  39. * Implements hook_theme().
  40. */
  41. function term_reference_tree_theme() {
  42. return array(
  43. 'checkbox_tree' => array(
  44. 'render element' => 'element',
  45. ),
  46. 'checkbox_tree_level' => array(
  47. 'render element' => 'element',
  48. ),
  49. 'checkbox_tree_item' => array(
  50. 'render element' => 'element',
  51. ),
  52. 'checkbox_tree_label' => array(
  53. 'render element' => 'element',
  54. ),
  55. 'checkbox_tree_track_list' => array(
  56. 'render element' => 'element',
  57. ),
  58. 'term_tree_list' => array(
  59. 'render element' => 'element',
  60. ),
  61. );
  62. }
  63. /**
  64. * This function returns a taxonomy term hierarchy in a nested array.
  65. *
  66. * @param $tid
  67. * The ID of the root term.
  68. * @param $vid
  69. * The vocabulary ID to restrict the child search.
  70. *
  71. * @return
  72. * A nested array of the term's child objects.
  73. */
  74. function _term_reference_tree_get_term_hierarchy($tid, $vid, &$allowed, $filter, $label, $default = array()) {
  75. $terms = _term_reference_tree_get_children($tid, $vid, $default);
  76. $result = array();
  77. if ($filter != '') {
  78. foreach ($allowed as $k => $v) {
  79. if (array_key_exists($k, $terms)) {
  80. $term =& $terms[$k];
  81. $children = _term_reference_tree_get_term_hierarchy($term->tid, $vid, $allowed, $filter, $label, $default);
  82. if (is_array($children)) {
  83. $term->children = $children;
  84. $term->children_selected = _term_reference_tree_children_selected($term, $default);
  85. }
  86. else {
  87. $term->children_selected = FALSE;
  88. }
  89. $term->TEST = $label;
  90. array_push($result, $term);
  91. }
  92. }
  93. }
  94. else {
  95. foreach ($terms as &$term) {
  96. if ($filter == '' || array_key_exists($term->tid, $allowed)) {
  97. $children = _term_reference_tree_get_term_hierarchy($term->tid, $vid, $allowed, $filter, $label, $default);
  98. if (is_array($children)) {
  99. $term->children = $children;
  100. $term->children_selected = _term_reference_tree_children_selected($term, $default);
  101. }
  102. else {
  103. $term->children_selected = FALSE;
  104. }
  105. $term->TEST = $label;
  106. array_push($result, $term);
  107. }
  108. }
  109. }
  110. return $result;
  111. }
  112. /**
  113. * This function is like taxonomy_get_children, except it doesn't load the entire term.
  114. *
  115. * @param $tid
  116. * The ID of the term whose children you want to get.
  117. * @param $vid
  118. * The vocabulary ID.
  119. *
  120. * @return
  121. * An array of taxonomy terms, each in the form array('tid' => $tid, 'name' => $name)
  122. */
  123. function _term_reference_tree_get_children($tid, $vid) {
  124. // DO NOT LOAD TAXONOMY TERMS HERE
  125. // Taxonomy terms take a lot of time and memory to load, and this can be
  126. // very bad on large vocabularies. Instead, we load the term as necessary
  127. // in cases where it's needed (such as using tokens or when the locale
  128. // module is enabled).
  129. $query = db_select('taxonomy_term_data', 't');
  130. $query->join('taxonomy_term_hierarchy', 'h', 't.tid = h.tid');
  131. $query->join('taxonomy_vocabulary', 'v', 'v.vid = t.vid');
  132. $query->fields('t', array('tid', 'name'));
  133. $query->addField('v', 'machine_name', 'vocabulary_machine_name');
  134. $query->condition('t.vid', $vid);
  135. $query->condition('h.parent', $tid);
  136. $query->addTag('term_access');
  137. $query->addTag('translatable');
  138. $query->orderBy('t.weight');
  139. $query->orderBy('t.name');
  140. $results = $query->execute();
  141. $terms = array();
  142. while ($term = $results->fetchObject()) {
  143. $terms[$term->tid] = $term;
  144. }
  145. return $terms;
  146. }
  147. function _term_reference_tree_children_selected($terms, $default) {
  148. foreach ($terms->children as $term) {
  149. if (isset($default[$term->tid]) || $term->children_selected) {
  150. return TRUE;
  151. }
  152. }
  153. return FALSE;
  154. }
  155. function _term_reference_tree_get_parent($tid) {
  156. $q = db_query_range("SELECT h.parent FROM {taxonomy_term_hierarchy} h WHERE h.tid = :tid", 0, 1, array(':tid' => $tid));
  157. $t = 0;
  158. foreach ($q as $term) {
  159. $t = $term->parent;
  160. }
  161. return $t;
  162. }
  163. /**
  164. * Recursively go through the option tree and return a flat array of
  165. * options
  166. */
  167. function _term_reference_tree_flatten($element, &$form_state) {
  168. $output = array();
  169. $children = element_children($element);
  170. foreach ($children as $c) {
  171. $child = $element[$c];
  172. if (array_key_exists('#type', $child) && ($child['#type'] == 'radio' || $child['#type'] == 'checkbox')) {
  173. $output[] = $child;
  174. }
  175. else {
  176. $output = array_merge($output, _term_reference_tree_flatten($child, $form_state));
  177. }
  178. }
  179. return $output;
  180. }
  181. /**
  182. * Return an array of options.
  183. *
  184. * This function converts a list of taxonomy terms to a key/value list of options.
  185. *
  186. * @param $terms
  187. * An array of taxonomy term IDs.
  188. * @param $allowed
  189. * An array containing the terms allowed by the filter view
  190. * @param $filter
  191. * A string defining the view to filter by (only used to detect whether view
  192. * filtering is enabled
  193. *
  194. * @return
  195. * A key/value array of taxonomy terms (name => id)
  196. */
  197. function _term_reference_tree_get_options(&$terms, &$allowed, $filter) {
  198. $options = array();
  199. if (is_array($terms) && count($terms) > 0) {
  200. foreach ($terms as $term) {
  201. if (!$filter || (is_array($allowed) && $allowed[$term->tid])) {
  202. $options[$term->tid] = entity_label('taxonomy_term', $term);
  203. $options += _term_reference_tree_get_options($term->children, $allowed, $filter);
  204. }
  205. }
  206. }
  207. return $options;
  208. }