From 163cca42f0d572f080ba7d31407053587f60f0f0 Mon Sep 17 00:00:00 2001
From: Silvio <s1lv10@uol.com.br>
Date: Fri, 16 Oct 2009 11:03:22 -0300
Subject: First version with working functions

---
 taxonomy_node_tree.module | 202 +++++++++++++++++++++++++++++++++-------------
 1 file changed, 148 insertions(+), 54 deletions(-)

diff --git a/taxonomy_node_tree.module b/taxonomy_node_tree.module
index 40d71dc..088c02a 100644
--- a/taxonomy_node_tree.module
+++ b/taxonomy_node_tree.module
@@ -2,12 +2,14 @@
 // $Id$
 
 /**
- * Drawer logic.
+ * Return the parent terms of a given vocabulary.
+ *
+ * This function takes a vocabulary id and returns a
+ * list of it's parent terms.
  */
-function theme_taxonomy_node_tree($menu_name, $mlid) {
+function taxonomy_node_tree_parents($vid) {
   // Get all terms from a given vocabulary
-  $vocabulary = variable_get('taxonomy_node_tree', '1');
-  $terms      = taxonomy_node_tree_taxonomy_get_tree($vocabulary);
+  $terms = taxonomy_node_tree_taxonomy_get_tree($vid);
 
   foreach ($terms as $term) {
     // Just show parent terms
@@ -16,24 +18,45 @@ function theme_taxonomy_node_tree($menu_name, $mlid) {
     }
   }
 
-  // Build the drawer
-  $output = taxonomy_node_tree_build($menu);
-  return $output;
+  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(),
+        ),
+      );
 }
 
 /**
- * Drawer rendering.
+ * Render the parent items of a menu.
  *
  * @ingroup themeable
  */
-function taxonomy_node_tree_build($menu) {
+function theme_taxonomy_node_tree_menu_parents($menu, $class = 'menu', $id = NULL, $base = NULL) {
+
+  if ($id != NULL) {
+    $id = ' id="'. $id .'"';
+  }
 
-  $output  = '<ul id="drw_tabs">';
-  $output .= implode((array) module_invoke_all('taxonomy_node_tree_build'));
+  $output  = '<ul class="'. $class .'"'.  $id .'>';
+  $output .= implode((array) module_invoke_all('taxonomy_node_tree_menu_parents'));
 
   foreach ($menu as $item) {
     $link['title'] = $item->name;
-    $link['href']  = 'taxonomy_node_tree/' . $item->tid;
+    $link['href']  = $base . $item->tid;
     $output       .= theme('taxonomy_node_tree_link', $link);
   }
 
@@ -45,37 +68,36 @@ function taxonomy_node_tree_build($menu) {
 }
 
 /**
- * Menu callback.
+ * Link theme function.
+ *
+ * @ingroup themeable
  */
-function taxonomy_render_tree($tid = 0, $vid) {
-  // First render all nodes whose parent is $term
-  if ($tid != 0) {
-
-    $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);
-    }
+function theme_taxonomy_node_tree_link($link) {
+  if (empty($link['localized_options'])) {
+    $link['localized_options'] = array();
   }
 
-  // Render other child nodes
-
-  $terms  = taxonomy_node_tree_taxonomy_get_tree($vid, $tid);
-  foreach ($terms as $term) { 
-    $filter[] = $term->tid;
-  }
+  $link['attributes']['rel'] = 'drw';
 
-  // TODO: continue from here
-  $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"';
+  $output  = '<li class="drw_li">';
+  $output .= l($link['title'], $link['href'], array('attributes' => array('rel' => 'drw')));
+  $output .= '</li>';
 
-  $result = db_query(db_rewrite_sql($query), implode(',', $filter));
+  return $output;
+}
 
-  while ($node = db_fetch_object($result)) {
+/**
+ * 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) {
@@ -85,19 +107,105 @@ function taxonomy_render_tree($tid = 0, $vid) {
       $tree[$term->tid] = $term;
     }
   }
+  return $tree;
+}
 
-  // add children relationship just for terms present in the 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;
+}
 
-  // build menu with hierarchy
+/**
+ * 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_build_tree($tree, $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 .= '<ul id="drw_item" class="hidden">';
   foreach ($tree as $term) {
@@ -112,20 +220,6 @@ function taxonomy_render_tree($tid = 0, $vid) {
   exit();
 }
 
-function taxonomy_node_tree_build_tree(&$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_build_tree($tree, $tree[$child]);
-      }
-    }
-    $tree[$term->parents[0]]->below[] = drupal_clone($term);
-    unset($tree[$term->tid]);
-  }
-}
-
 /**
  * Recursively build the menu.
  *
-- 
cgit v1.2.3