Taxonomy_term_count_nodes gives stupid results when child terms have same nodes

By Benjamin Melançon
on 27 Dec
2 comments

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

As used in a contributed module, place_taxonomy, to list people (profiles) and actions (another content type) in each country:

Before:

Country/Region	People	Actions
Argentina	34	6
BENIN	        2		

After:

Country/Region	People	Actions
Argentina	8	1
BENIN   	1			
Posted by Benjamin Melançon on Thu, 2007-12-27 19:14
Since I always have to look

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

Posted by Benjamin Melançon on Fri, 2007-12-28 17:18
Post new comment
The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote> <h1> <h2> <h3> <h4> <h5> <h6> <small> <pre> <strike> <sub> <sup> <kbd> <s>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.