tid) == array()) {
$menu[] = $term;
}
}
return $menu;
}
/**
* Implementation of hook_theme();
*
* @TODO: update
*/
function taxonomy_node_tree_theme() {
return array(
'taxonomy_node_tree_menu_parents' => array(
'arguments' => array(
'menu' => NULL,
'parent' => NULL,
),
),
'taxonomy_node_tree_link' => array(
'arguments' => array(),
),
);
}
/**
* Render the parent items of a menu.
*
* @ingroup themeable
*/
function theme_taxonomy_node_tree_menu_parents($menu, $class = 'menu', $id = NULL, $base = NULL) {
if ($id != NULL) {
$id = ' id="'. $id .'"';
}
$output = '
';
$output .= implode((array) module_invoke_all('taxonomy_node_tree_menu_parents'));
foreach ($menu as $item) {
$link['title'] = $item->name;
$link['href'] = $base . $item->tid;
$output .= theme('taxonomy_node_tree_link', $link);
}
$output .= '
';
$output .= '';
$output .= '
';
return $output;
}
/**
* Link theme function.
*
* @ingroup themeable
*/
function theme_taxonomy_node_tree_link($link) {
if (empty($link['localized_options'])) {
$link['localized_options'] = array();
}
$link['attributes']['rel'] = 'drw';
$output = '';
$output .= l($link['title'], $link['href'], array('attributes' => array('rel' => 'drw')));
$output .= '';
return $output;
}
/**
* 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;
}
/**
* Menu callback.
*
* @TODO: revamp
*/
function taxonomy_node_tree($tid = 0, $vid = 1, $type = NULL) {
if ($type) {
// TODO: validate $type before sql query
$type = ' AND node.type = "'. $type .'"';
}
// Select nodes and terms
if ($tid != 0) {
// First render all nodes whose parent is $term
$output = '';
$nodes = taxonomy_select_nodes(array($tid));
while ($node = db_fetch_object($nodes)) {
$link['title'] = $node->title;
$link['href'] = 'node/' . $node->nid;
$output .= theme('taxonomy_node_tree_link', $link);
}
// Render other child nodes
$terms = taxonomy_node_tree_taxonomy_get_tree($vid, $tid);
foreach ($terms as $term) {
$filter[] = $term->tid;
}
$query = 'SELECT node.nid, node.title, term_node.tid FROM {node} LEFT JOIN
{term_node} ON term_node.nid = node.nid WHERE term_node.tid IN (%s)
AND node.status = "1"';
$query .= $type;
$result = db_query(db_rewrite_sql($query), implode(',', $filter));
}
else {
$query = 'SELECT node.nid, node.title, term_node.tid FROM {node} LEFT JOIN
{term_node} ON term_node.nid = node.nid WHERE term_node.tid IN
(SELECT tid FROM {term_data} WHERE vid = "%d" AND node.status = "1")';
$query .= $type;
$result = db_query(db_rewrite_sql($query));
}
$tree = taxonomy_node_tree_build($result, $terms);
// format output
$output .= '';
foreach ($tree as $term) {
$output .= taxonomy_node_tree_menu_build($term);
}
$output .= '
';
// Display output
echo($output);
// We need to exit here to avoid themeable output
exit();
}
/**
* Recursively build the menu.
*
* @ingroup themeable
*/
function taxonomy_node_tree_menu_build($term) {
global $taxonomy_node_tree_id;
if ($taxonomy_node_tree_id == null) {
$taxonomy_node_tree_id = 0;
}
$taxonomy_node_tree_id++;
if (isset($term->tid)) {
$output .= '';
$output .= $term->name;
if (isset($term->below)) {
$output .= '';
foreach($term->below as $child) {
$output .= taxonomy_node_tree_menu_build($child);
}
$output .= '
';
} else if (isset($term->nodes)) {
$output .= '';
foreach ($term->nodes as $node) {
$output .= '- ';
$output .= '' . $node->title . '';
}
$output .= '
';
$output .= '';
}
$output .= '';
}
return $output;
}
/**
* 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;
}