You are here

function _hs_taxonomy_hierarchical_select_get_tree in Hierarchical Select 7.3

Same name and namespace in other branches
  1. 5.3 modules/hs_taxonomy.module \_hs_taxonomy_hierarchical_select_get_tree()
  2. 6.3 modules/hs_taxonomy.module \_hs_taxonomy_hierarchical_select_get_tree()

Drupal core's taxonomy_get_tree() doesn't allow us to reset the cached trees, which obviously causes problems when you create new items between two calls to it.

6 calls to _hs_taxonomy_hierarchical_select_get_tree()
hs_taxonomy_hierarchical_select_children in modules/hs_taxonomy.module
Implementation of hook_hierarchical_select_children().
hs_taxonomy_hierarchical_select_create_item in modules/hs_taxonomy.module
Implements hook_hierarchical_select_create_item().
hs_taxonomy_hierarchical_select_root_level in modules/hs_taxonomy.module
Implementation of hook_hierarchical_select_root_level().
hs_taxonomy_term_count_nodes in modules/hs_taxonomy.module
Drupal core's taxonomy_term_count_nodes() is buggy. See http://drupal.org/node/144969#comment-843000.
_hs_taxonomy_hierarchical_select_get_depth in modules/hs_taxonomy.module
Get the depth of a vocabulary's tree.

... See full list

File

modules/hs_taxonomy.module, line 1111
Implementation of the Hierarchical Select API for the Taxonomy module.

Code

function _hs_taxonomy_hierarchical_select_get_tree($vid, $parent = 0, $depth = -1, $max_depth = NULL, $reset = FALSE) {
  static $children, $parents, $terms;
  if ($reset) {
    $children = $parents = $terms = array();
  }
  $tree = array();
  if (!is_array($parent)) {
    $parent = array(
      $parent,
    );
  }
  $max_depth = is_null($max_depth) ? 99999999 : $max_depth;
  $depth++;

  // We cache trees, so it's not CPU-intensive to call get_tree() on a term
  // and its children, too.
  if ($max_depth <= $depth) {
    return $tree;
  }

  // Prepare queue for the "IN ( .. )" part of query.
  $queue = array();
  foreach ($parent as $single_parent) {

    // Queue branch for processing if it's not cached yet.
    if (!isset($children[$vid][$single_parent])) {
      $queue[] = $single_parent;

      // Use an empty array to distinguish between a stub (without children)
      // term and a branch that is not loaded yet.
      $children[$vid][$single_parent] = array();
    }
  }
  if (!empty($queue)) {
    $query = db_select('taxonomy_term_data', 't');
    $query
      ->join('taxonomy_term_hierarchy', 'h', 'h.tid = t.tid');
    $result = $query
      ->addTag('translatable')
      ->addTag('term_access')
      ->addTag('hs_taxonomy_tree')
      ->fields('t')
      ->fields('h', array(
      'parent',
    ))
      ->condition('t.vid', $vid)
      ->condition('parent', array_merge(array(
      $vid,
    ), $queue), 'IN')
      ->orderBy('t.weight')
      ->orderBy('t.name')
      ->execute();
    foreach ($result as $term) {
      $children[$vid][$term->parent][] = $term->tid;
      $parents[$vid][$term->tid][] = $term->parent;
      $terms[$vid][$term->tid] = $term;
    }
  }

  // Provide support for Title module. If Title module is enabled and this
  // vocabulary uses translated term names we want output those terms with their
  // translated version. Therefore a full taxonomy term entity load is required,
  // similar to taxonomy_get_tree().
  if (!empty($terms) && module_exists('title')) {
    $vocabulary = taxonomy_vocabulary_load($vid);
    if (title_field_replacement_enabled('taxonomy_term', $vocabulary->machine_name, 'name')) {
      $term_entities = taxonomy_term_load_multiple(array_keys($terms[$vid]));
    }
  }
  $next_parent = array();
  foreach ($parent as $single_parent) {
    foreach ($children[$vid][$single_parent] as $child) {
      $term = isset($term_entities[$child]) ? $term_entities[$child] : $terms[$vid][$child];
      $term = clone $term;
      $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;

      // Need more steps ?
      if ($max_depth > $depth + 1) {

        // Queue children for the next step down the tree. Do not process
        // children which we already know as stub ones.
        if (!isset($children[$vid][$child]) || !empty($children[$vid][$child])) {
          $next_parent[] = $child;
        }
      }
    }
  }
  if (!empty($next_parent)) {

    // Process multiple children together i.e. next level.
    $tree = array_merge($tree, _hs_taxonomy_hierarchical_select_get_tree($vid, $next_parent, $depth, $max_depth));
  }
  return isset($tree) ? $tree : array();
}