? 103528.explain.color.disabled.patch
? 104047.node.preview.pwolanin.patch
? 108579.user.not.found.patch
? 109765.make.D6.E_ALL.compliant.patch
? 144969.taxonomy_term_count_nodes.patch
? 51153.block.empty.title.patch
? 82764.node.not.found.patch
? 84490.admin.created.users.patch
? files
? includes/.common.inc.swp
? sites/1.am.103583-head
? sites/1.am.head-drupal
? sites/1.am.masquilier.org
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.355
diff -u -p -r1.355 taxonomy.module
--- modules/taxonomy/taxonomy.module	14 May 2007 13:43:37 -0000	1.355
+++ modules/taxonomy/taxonomy.module	20 May 2007 12:44:42 -0000
@@ -1059,30 +1059,84 @@ function taxonomy_get_synonym_root($syno
  *   The $node->type. If given, taxonomy_term_count_nodes only counts
  *   nodes of $type that are classified with the term $tid.
  *
- * @return int
- *   An integer representing a number of nodes.
+ * @param $save_to_db
+ *   This function is recursive, and we don't need to save the result in the DB at each iteration.
+ *   $save_to_db is set to FALSE at each nested call, so that the actual saving to DB can happen only
+ *   when the function exits the last time.
+ *
+ * @return $array
+ *   where: 
+ *     $array['count_own'] being the number of nodes within the term proper.
+ *     $array['count_children'] being the number of nodes in children terms, not counting those which are already counted in the parent term.
+ *     $array['own_nodes'] array of nid's within this $tid.
+ *     $array['children_nodes'] array of all the descendent nid's from children terms, not including those already set as one's own.
+ *
  *   Results are statically cached.
+ * Also, in order to improve performance accross requests, we cache the serialized array on database, in {cache_page} (this table is flushed each time a node or a taxonomy item is added/updated/deleted).
  */
-function taxonomy_term_count_nodes($tid, $type = 0) {
-  static $count;
+function taxonomy_term_count_nodes($tid, $type = 0, $save_to_db = TRUE) {
+  static $count = array();
+  $modified = FALSE; // We keep track of modification of $count, to check whether we need to save it to DB.
 
+  if (empty($count)) {
+    $count = cache_get('taxonomy_term_count_nodes', 'cache_page');
+    $count = unserialize($count->data);
+  }
+  
   if (!isset($count[$type])) {
+    $modified = TRUE;
+    $count[$type] = array();
+    // In the queries below, we cannot use 'SELECT t.tid, COUNT(n.nid) AS c FROM ...'
+    // because a node may be assigned more than one term and be counted more than once. 
+    // We therefore take note of the nid's and count the number of items in the $count array, 
+    // making sure there is no duplicate.
+
     // $type == 0 always evaluates TRUE if $type is a string
     if (is_numeric($type)) {
-      $result = db_query(db_rewrite_sql('SELECT t.tid, COUNT(n.nid) AS c FROM {term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.status = 1 GROUP BY t.tid'));
+      $result = db_query(db_rewrite_sql('SELECT t.tid, n.nid FROM {term_node} t JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 '));
     }
     else {
-      $result = db_query(db_rewrite_sql("SELECT t.tid, COUNT(n.nid) AS c FROM {term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.status = 1 AND n.type = '%s' GROUP BY t.tid"), $type);
+      $result = db_query(db_rewrite_sql("SELECT t.tid, n.nid FROM {term_node} t JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 AND n.type = '%s'"), $type);
     }
-    while ($term = db_fetch_object($result)) {
-      $count[$type][$term->tid] = $term->c;
+    while ($item = db_fetch_object($result)) {
+      if (!isset($count[$type][$item->tid])) {
+        $count[$type][$item->tid] = array('own_nodes' => array());
+      }
+      $count[$type][$item->tid]['own_nodes'][$item->nid] = 1;  
     }
   }
 
-  foreach (_taxonomy_term_children($tid) as $c) {
-    $children_count += taxonomy_term_count_nodes($c, $type);
+  if (!isset($count[$type][$tid]['count_own'])) {
+    $modified = TRUE;
+    $count[$type][$tid]['count_own'] = count($count[$type][$tid]['own_nodes']);
+    $count[$type][$tid]['count_children'] = 0;
+    $count[$type][$tid]['children_nodes'] = array();
+    foreach (_taxonomy_term_children($tid) as $c) {
+      $children = directory_taxonomy_term_count_nodes($c, $type, FALSE); // FALSE: we do not need to save $count in the db at this iteration.
+      // Add the children's own nodes:
+      foreach ($children['own_nodes'] AS $child_nid => $n) {
+        if (!isset($count[$type][$tid]['own_nodes'][$child_nid])) { // make sure the nid is not already counted for the parent.
+          $count[$type][$tid]['children_nodes'][$child_nid] = 1;
+        }
+      }
+      // Add the nodes of the children's children.
+      foreach ($children['children_nodes'] AS $child_nid => $n) {
+        if (!isset($count[$type][$tid]['own_nodes'][$child_nid])) { // make sure the nid is not already counted for the parent.
+          $count[$type][$tid]['children_nodes'][$child_nid] = 1;
+        }
+      }
+    }
+    $count[$type][$tid]['count_children'] = count($count[$type][$tid]['children_nodes']);
   }
-  return $count[$type][$tid] + $children_count;
+
+  if ($modified && $save_to_db) {
+    $cache = serialize($count);
+    // the cached data will be used for at least one hour before being flushed.
+    
+    cache_set('taxonomy_term_count_nodes', 'cache_page', $cache, time() + 60 * 60);
+  }
+
+  return $count[$type][$tid];
 }
 
 /**
