term_reference_tree.module.orig 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. $select = db_select('taxonomy_term_data', 'd');
  130. $select->join('taxonomy_term_hierarchy', 'h', 'd.tid = h.tid');
  131. $result = $select->fields('d', array('tid', 'vid', 'name'))
  132. ->condition('d.vid', $vid, '=')
  133. ->condition('h.parent', $tid, '=')
  134. ->orderBy('weight')
  135. ->orderBy('name')
  136. ->orderBy('tid')
  137. ->execute();
  138. $terms = array();
  139. while($term = $result->fetchAssoc()) {
  140. $terms[$term['tid']] = (object) $term;
  141. }
  142. return $terms;
  143. }
  144. function _term_reference_tree_children_selected($terms, $default) {
  145. foreach($terms->children as $term) {
  146. if(isset($default[$term->tid]) || $term->children_selected) {
  147. return true;
  148. }
  149. }
  150. return false;
  151. }
  152. function _term_reference_tree_get_parent($tid) {
  153. $q = db_query_range("select h.parent from {taxonomy_term_hierarchy} h where h.tid = :tid", 0, 1, array(':tid' => $tid));
  154. $t = 0;
  155. foreach($q as $term) {
  156. $t = $term->parent;
  157. }
  158. return $t;
  159. }
  160. /**
  161. * Recursively go through the option tree and return a flat array of
  162. * options
  163. */
  164. function _term_reference_tree_flatten($element, &$form_state) {
  165. $output = array();
  166. $children = element_children($element);
  167. foreach($children as $c) {
  168. $child = $element[$c];
  169. // dsm($child, '$child');
  170. if (array_key_exists('#type', $child) && ($child['#type'] == 'radio' || $child['#type'] == 'checkbox')) {
  171. $output[] = $child;
  172. }
  173. else {
  174. $output = array_merge($output, _term_reference_tree_flatten($child, $form_state));
  175. }
  176. }
  177. return $output;
  178. }
  179. /**
  180. * Return an array of options.
  181. *
  182. * This function converts a list of taxonomy terms to a key/value list of options.
  183. *
  184. * @param $terms
  185. * An array of taxonomy term IDs.
  186. * @param $allowed
  187. * An array containing the terms allowed by the filter view
  188. * @param $filter
  189. * A string defining the view to filter by (only used to detect whether view
  190. * filtering is enabled
  191. *
  192. * @return
  193. * A key/value array of taxonomy terms (name => id)
  194. */
  195. function _term_reference_tree_get_options(&$terms, &$allowed, $filter) {
  196. $options = array();
  197. if (is_array($terms) && count($terms) > 0) {
  198. foreach($terms as $term) {
  199. if (!$filter || (is_array($allowed) && $allowed[$term->tid])) {
  200. $options[$term->tid] = entity_label('taxonomy_term', $term);
  201. $options += _term_reference_tree_get_options($term->children, $allowed, $filter);
  202. }
  203. }
  204. }
  205. return $options;
  206. }