aboutsummaryrefslogtreecommitdiff
path: root/taxonomy_node_tree.module
blob: fba8a7ca30c2582b3d92b4026a5f7736b22c4e14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<?php
// $Id$

/**
 * @file
 * Taxonomy Node Tree.
 *
 * This module implements functions to build hierarchical
 * term trees including children nodes.
 */

/**
 * Return the parent terms of a given vocabulary.
 *
 * This function takes a vocabulary id and returns a
 * list of it's parent terms.
 */
function taxonomy_node_tree_parents($vid) {
  // Get all terms from a given vocabulary
  $terms = taxonomy_node_tree_taxonomy_get_tree($vid);

  foreach ($terms as $term) {
    // Just show parent terms
    if (taxonomy_get_parents($term->tid) == array()) {
      $menu[] = $term;
    }
  }

  return $menu;
}

/**
 * Setup an index of terms associated with it's children nodes.
 *
 * This function accept a list of nodes and terms and build a
 * tree with the corresponding association between terms and
 * nodes.
 *
 * @TODO: It is assumed that nodes are just associated with
 *        a single term.
 */
function taxonomy_node_tree_index($nodes, $terms) {  
  while ($node = db_fetch_object($nodes)) {
    foreach ($terms as $term) {
      // add nodes into the term
      if ($node->tid == $term->tid) {
        $term->nodes[] = $node;
      }
      // update an index of terms
      $tree[$term->tid] = $term;
    }
  }
  return $tree;
}

/**
 * Add children relationship for terms present in the tree.
 */
function taxonomy_node_tree_relation($tree) {
  foreach ($tree as $term) {
    if ($term->parents[0] != 0 && isset($tree[$term->parents[0]])) {
      $tree[$term->parents[0]]->children[] = $term->tid;
    }
  }
  return $tree;
}

/**
 * Sort terms in the tree.
 *
 * This function add terms on it's right place in the taxonomy tree.
 */
function taxonomy_node_tree_sort(&$tree, $term) {
  if ($term->parents[0] != 0 && isset($tree[$term->parents[0]])) {
    // is child
    if (isset($term->children)) {
      // is also parent, so go down one level
      foreach ($term->children as $child) {
        taxonomy_node_tree_sort($tree, $tree[$child]);
      }
    }
    $tree[$term->parents[0]]->below[] = drupal_clone($term);
    unset($tree[$term->tid]);
  }
}

/**
 * Sort a taxonomy tree to the right hierarchy.
 */
function taxonomy_node_tree_hierarchy($tree) {
  foreach ($tree as $term) {
    taxonomy_node_tree_sort($tree, $term);
  }
  return $tree;
}

function taxonomy_node_tree_build($nodes, $terms) {
  $tree = taxonomy_node_tree_index($nodes, $terms);
  $tree = taxonomy_node_tree_relation($tree);
  $tree = taxonomy_node_tree_hierarchy($tree);
  return $tree;
}

/**
 * Version of taxonomy_get_tree() without caching.
 */
function taxonomy_node_tree_taxonomy_get_tree($vid, $parent = 0, $depth = -1, $max_depth = NULL, $cache = FALSE) {
  static $children, $parents, $terms;

  $depth++;

  // We can cache trees, so it's not CPU-intensive to call get_tree() on a term
  // and its children, too.
  if (!$cache && !isset($children[$vid])) {
    $children[$vid] = array();

    $result = db_query(db_rewrite_sql('SELECT t.tid, t.*, parent FROM {term_data} t INNER JOIN {term_hierarchy} h ON t.tid = h.tid WHERE t.vid = %d ORDER BY weight, name', 't', 'tid'), $vid);
    while ($term = db_fetch_object($result)) {
      $children[$vid][$term->parent][] = $term->tid;
      $parents[$vid][$term->tid][] = $term->parent;
      $terms[$vid][$term->tid] = $term;
    }
  }

  $max_depth = (is_null($max_depth)) ? count($children[$vid]) : $max_depth;
  $tree = array();
  if ($max_depth > $depth && !empty($children[$vid][$parent])) {
    foreach ($children[$vid][$parent] as $child) {
      $term = drupal_clone($terms[$vid][$child]);
      $term->depth = $depth;
      // The "parent" attribute is not useful, as it would show one parent only.
      unset($term->parent);
      $term->parents = $parents[$vid][$child];
      $tree[] = $term;
      if (!empty($children[$vid][$child])) {
        $tree = array_merge($tree, taxonomy_get_tree($vid, $child, $depth, $max_depth));
      }
    }
  }

  return $tree;

}