Taxonomy_term_count_nodes gives stupid results when child terms have same nodes
Description
The Drupal core function in taxonomy.module, taxonomy_term_count_nodes, has no check in it to remove duplicate nodes, which can happen in situations where a nodde belongs to both a child and a parent. In my opinion there should be a different function taxonomy_term_and_children_count_nodes or a flag in the function to say if nodes belonging to children terms should be counted at all, and if they are, there should be proper checking to remove duplicates.
Here's the Drupal taxonomy.module original, and follows will be my hack with a flag, which doesn't do what I request above yet but does give the option to opt out of counting nodes belonging to children terms:
<?php
/**
* Count the number of published nodes classified by a term.
*
* @param $tid
* The term's ID
*
* @param $type
* 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.
* Results are statically cached.
*/
function taxonomy_term_count_nodes($tid, $type = 0) {
static $count;
if (!isset($count[$type])) {
// $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.nid = n.nid WHERE n.status = 1 GROUP BY t.tid'));
}
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.nid = n.nid WHERE n.status = 1 AND n.type = '%s' GROUP BY t.tid"), $type);
}
while ($term = db_fetch_object($result)) {
$count[$type][$term->tid] = $term->c;
}
}
foreach (_taxonomy_term_children($tid) as $c) {
$children_count += taxonomy_term_count_nodes($c, $type);
}
return $count[$type][$tid] + $children_count;
}
?>And the Agaric opt-out of counting child term nodes version:
<?php
/**
* Count the number of published nodes classified by a term.
*
* @param $tid
* The term's ID
*
* @param $type
* The $node->type. If given, taxonomy_term_count_nodes only counts
* nodes of $type that are classified with the term $tid.
*
* @param $children
* Optional flag to indicate whether to count the nodes of child terms.
* TRUE or FALSE, defaults to TRUE.
*
* @return int
* An integer representing a number of nodes.
* Results are statically cached.
*/
function taxonomy_term_count_nodes($tid, $type = 0, $children = TRUE) {
static $count;
if (!isset($count[$children][$type][$tid])) {
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.nid = n.nid WHERE n.status = 1 GROUP BY t.tid'));
}
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.nid = n.nid WHERE n.status = 1 AND n.type = '%s' GROUP BY t.tid"), $type);
}
while ($term = db_fetch_object($result)) {
$count[$children][$type][$term->tid] = $term->c;
}
}
if ($children) {
foreach (_taxonomy_term_children($tid) as $c) {
$children_count += taxonomy_term_count_nodes($c, $type);
}
return $count[$children][$type][$tid] + $children_count;
}
else { // best practice to use else or not? unnecessary with return above
return $count[$children][$type][$tid]
}
}
?>While doing this I think I found a bug in the static caching: it checks if $count[$type] is set, when the query that runs if it is not set, and what is ultimately returnedd, is ddependent not just on the node type but the term tid.

As used in a contributed module, place_taxonomy, to list people (profiles) and actions (another content type) in each country:
Before:
After:
Since I always have to look it up, here's how to apply the patch:
cd /var/www/agaricroot/sudo wget http://agaricdesign.com/sites/agaricdesign.com/files/taxonomy_term_count... patch -p0 < taxonomy_term_count_nodes_children_0.patch