Index: modules/taxonomy/taxonomy.module =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v retrieving revision 1.450 diff -u -p -r1.450 taxonomy.module --- modules/taxonomy/taxonomy.module 19 Dec 2008 15:34:27 -0000 1.450 +++ modules/taxonomy/taxonomy.module 23 Dec 2008 15:38:44 -0000 @@ -808,6 +808,9 @@ function taxonomy_get_children($tid, $vi * @param $max_depth * The number of levels of the tree to return. Leave NULL to return all levels. * + * @param $reset + * Whether to reset the static cache. + * * @param $depth * Internal use only. * @@ -816,9 +819,13 @@ function taxonomy_get_children($tid, $vi * to have "depth" and "parents" attributes in addition to its normal ones. * Results are statically cached. */ -function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $depth = -1) { +function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $reset = FALSE, $depth = -1) { static $children, $parents, $terms; + if ($reset) { + $children = $parents = $terms = array(); + } + $depth++; // We cache trees, so it's not CPU-intensive to call get_tree() on a term @@ -847,7 +854,7 @@ function taxonomy_get_tree($vid, $parent $tree[] = $term; if (!empty($children[$vid][$child])) { - $tree = array_merge($tree, taxonomy_get_tree($vid, $child, $max_depth, $depth)); + $tree = array_merge($tree, taxonomy_get_tree($vid, $child, $max_depth, FALSE, $depth)); } } } @@ -910,51 +917,32 @@ function taxonomy_get_synonym_root($syno * 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 {taxonomy_term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.status = 1 GROUP BY t.tid')); - } - else { - $result = db_query(db_rewrite_sql("SELECT t.tid, COUNT(n.nid) AS c FROM {taxonomy_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); - } - $count[$type] = array(); - while ($term = db_fetch_object($result)) { - $count[$type][$term->tid] = $term->c; - } - } - $children_count = 0; - foreach (_taxonomy_term_children($tid) as $c) { - $children_count += taxonomy_term_count_nodes($c, $type); +function taxonomy_term_count_nodes($tid, $type = 0, $reset = FALSE) { + static $count = array(); + if ($reset) { + $count = array(); } - return $children_count + (isset($count[$type][$tid]) ? $count[$type][$tid] : 0); -} -/** - * Helper for taxonomy_term_count_nodes(). Used to find out - * which terms are children of a parent term. - * - * @param $tid - * The parent term's ID - * - * @return array - * An array of term IDs representing the children of $tid. - * Results are statically cached. - * - */ -function _taxonomy_term_children($tid) { - static $children; + $term = taxonomy_term_load($tid); + $tree = taxonomy_get_tree($term->vid, $tid, NULL, $reset); + $tids = array($tid); + foreach ($tree as $descendent) { + $tids[] = $descendent->tid; + } - if (!isset($children)) { - $result = db_query('SELECT tid, parent FROM {taxonomy_term_hierarchy}'); - while ($term = db_fetch_object($result)) { - $children[$term->parent][] = $term->tid; + if (!isset($count[$type][$tid])) { + $query = db_select('taxonomy_term_node', 't'); + $query->addExpression('COUNT(DISTINCT(n.nid))', 'nid_count'); + $query->join('node', 'n', 't.vid = n.vid'); + $query->condition('t.tid', $tids, 'IN'); + $query->condition('n.status', 1); + if (!is_numeric($type)) { + $query->condition('n.type', $type); } + $query->addTag('term_access'); + $count[$type][$tid] = $query->execute()->fetchField(); } - return isset($children[$tid]) ? $children[$tid] : array(); + return $count[$type][$tid]; } /** Index: modules/taxonomy/taxonomy.test =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.test,v retrieving revision 1.18 diff -u -p -r1.18 taxonomy.test --- modules/taxonomy/taxonomy.test 19 Dec 2008 15:34:27 -0000 1.18 +++ modules/taxonomy/taxonomy.test 23 Dec 2008 15:38:45 -0000 @@ -237,6 +237,75 @@ function getInfo() { } /** + * Unit tests for taxonomy term functions. + */ +class TaxonomyTermUnitTest extends TaxonomyWebTestCase { + + function getInfo() { + return array( + 'name' => t('Taxonomy term unit tests'), + 'description' => t('Unit tests for taxonomy term functions.'), + 'group' => t('Taxonomy'), + ); + } + + /** + * Tests for taxonomy_term_count_nodes(). + */ + function testTaxonomyTermCountNodes() { + // Create a vocabulary with three terms. + $vocabulary = $this->createVocabulary(); + $term1 = $this->createTerm($vocabulary->vid); + $term2 = $this->createTerm($vocabulary->vid); + $term3 = $this->createTerm($vocabulary->vid); + + // Attach term1 to a node. + $node1 = $this->drupalCreateNode(array('type' => 'page')); + $node1->taxonomy = array($term1->tid); + node_save($node1); + $this->assertEqual(taxonomy_term_count_nodes($term1->tid), 1, t('Term has one valid node association.')); + + // Attach term2 to a node. + $node2 = $this->drupalCreateNode(array('type' => 'article')); + $node2->taxonomy = array($term2->tid); + node_save($node2); + $this->assertEqual(taxonomy_term_count_nodes($term2->tid), 1, t('Term has one valid node association.')); + + // Confirm that term3 is not associated with any nodes. + //$this->assertEqual(taxonomy_term_count_nodes($term3->tid), 0, t('Term is not associated with any nodes')); + + // Set term3 as the parent of term1. + $term1->parent = array($term3->tid); + taxonomy_term_save($term1); + + // Confirm that the term hierarchy is altered correctly. + $children = taxonomy_get_children($term3->tid); + $this->assertTrue(isset($children[$term1->tid]), t('Term 3 saved as parent of term 1')); + $this->assertEqual(count(taxonomy_get_tree($term3->vid, $term3->tid, NULL, TRUE)), 1, t('Term 3 has one child term')); + + // Confirm that term3's parental relationship with term1 leads to a + // node assocation being counted. + $this->assertEqual(taxonomy_term_count_nodes($term3->tid, 0, TRUE), 1, t('Term has one valid node association due to child term.')); + + // Set term3 as the parent of term2. + $term2->parent = array($term3->tid); + taxonomy_term_save($term2); + + // term3 should now have two node associations counted. + $this->assertEqual(taxonomy_term_count_nodes($term3->tid, 0, TRUE), 2, t('Term has two valid node associations due to child terms.')); + + // Save node1 with both child taxonomy terms, this should still result + // in term3 having two node associations. + $node1->taxonomy = array($term1->tid, $term2->tid); + node_save($node1); + $this->assertEqual(taxonomy_term_count_nodes($term3->tid, 0, TRUE), 2, t('Term has two valid node associations.')); + + // Confirm that the node type argument returns a single node association. + $this->assertEqual(taxonomy_term_count_nodes($term3->tid, 'page', TRUE), 1, t("Term is associated with one node of type 'page'.")); + } +} + +/** * Tests for taxonomy term functions. */ class TaxonomyTermTestCase extends TaxonomyWebTestCase {