Index: term_node_count/term_node_count.admin.inc
===================================================================
--- term_node_count/term_node_count.admin.inc	(revision 0)
+++ term_node_count/term_node_count.admin.inc	(revision 0)
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * Admin settings page.
+ */
+function term_node_count_admin() {
+	$form = array();
+	
+	$form['inherit'] = array(
+		'#type' => 'radios',
+		'#title' => t("Inherit child term's node counts?"),
+		'#description' => t("If a term has children, should the child term's node counts be included in the parent term's node counts?"),
+		'#options' => array(t('No'), t('Yes')),
+		'#default_value' => variable_get('term_node_count_inherit', 0)
+	);
+	$form['rebuild'] = array(
+		'#type' => 'fieldset',
+		'#title' => t('Rebuild node counts'),
+		'#collapsed' => TRUE,
+		'#collapsible' => TRUE
+	);
+	$form['rebuild']['notice'] = array(
+		'#type' => 'item',
+		'#description' => t('If data from Term Node Count gets corrupted somehow, you can rebuild the node counts and restore them to their appropriate levels.')
+	);
+	$form['rebuild']['button'] = array(
+		'#type' => 'submit',
+		'#value' => t('Rebuild'),
+		'#submit' => array('term_node_count_rebuild')
+	);
+	$form['submit'] = array(
+		'#type' => 'submit',
+		'#value' => t('Save')
+	);
+	
+	return $form;
+}
+
+/**
+ * Function to return node counts to their appropriate levels if data is corrupted.
+ */
+function term_node_count_rebuild() {
+	include drupal_get_path('module', 'term_node_count') . '/term_node_count.install';
+	module_invoke('term_node_count', 'uninstall');
+	module_invoke('term_node_count', 'install');
+	
+	drupal_set_message(t('Term node counts have been rebuilt.'));
+}
+
+/**
+ * Submit handler for settings form.
+ */
+function term_node_count_admin_submit($form, &$form_state) {
+	$values = $form_state['values'];
+	
+	variable_set('term_node_count_inherit', $values['inherit']);
+	term_node_count_rebuild();
+	
+	drupal_set_message(t('The configuration has been saved.'));
+}
Index: term_node_count/term_node_count.module
===================================================================
--- term_node_count/term_node_count.module	(revision 2343)
+++ term_node_count/term_node_count.module	(working copy)
@@ -3,6 +3,31 @@
 // $Id: term_node_count.module,v 1.3 2009/03/05 22:43:11 archard Exp $
 
 /**
+ * Implementation of hook_menu().
+ */
+function term_node_count_menu() {
+	$items = array();
+	$items['admin/settings/term_node_count'] = array(
+		'title' => 'Term Node Count',
+		'page callback' => 'drupal_get_form',
+		'page arguments' => array('term_node_count_admin'),
+		'description' => t('Admin settings page for Term Node Count'),
+		'access arguments' => array('administer term node count'),
+		'type' => MENU_NORMAL_ITEM,
+		'file' => 'term_node_count.admin.inc'
+	);
+	
+	return $items;
+}
+
+/**
+ * Implementation of hook_perm().
+ */
+function term_node_count_perm() {
+	return array('administer term node count');
+}
+
+/**
  * Implementation of hook_taxonomy().
  */
 function term_node_count_taxonomy($op, $type, $form_values) {
@@ -13,6 +38,10 @@
 	switch ($type) {
 		case 'term':
 			switch ($op) {
+				case 'update':
+					// if the term heirarchy changes then the node count has to as well.
+					term_node_count_update(array($tid));
+					break;
 				case 'insert':
 					$sql = 'INSERT INTO {term_node_count} (tid) VALUES (%d)';
 					db_query($sql, $tid);
@@ -86,42 +115,26 @@
 	// go through each tid provided, count the number of nodes attached
 	// to it and update the term_node_count table
 	if (!empty($tids_to_update)) {
+		// determine if parent ids need updating as well
+		if (variable_get('term_node_count_inherit', 0)) {
+			$tids_list = implode($tids_to_update, ',');
+			$sql = 'SELECT parent FROM {term_hierarchy} WHERE parent != 0 AND tid IN (%s)';
+			$result = db_query($sql, $tids_list);
+			$parents = array();
+			while ($data = db_fetch_object($result)) {
+				$parents[$data->pid] = $data->pid;
+			}
+			$tids_to_update += $parents;
+		}
 		$sql = 'UPDATE {term_node_count} SET node_count = %d WHERE tid = %d';
-		$counts = term_node_count_count_nodes($tids_to_update);
-		foreach ($counts as $tid => $count) {
+		foreach ($tids_to_update as $tid) {
+			$count = term_node_count_count_nodes($tid);
 			db_query($sql, $count, $tid);
 		}
 	}
 }
 
 /**
- * Function used to count nodes. It's like taxonomy_term_count_nodes but without static caching.
- * Also I don't think child terms should be included.
- */
-function term_node_count_count_nodes($terms) {
-	if (!empty($terms)) {
-		$tids_list = implode(',', $terms);
-		$tids_list = rtrim($tids_list, ',');
-		// note that we're only bringing back published nodes
-		$sql = "SELECT tid, COUNT(tid) AS count FROM {term_node} tn INNER JOIN {node} n ON tn.vid = n.vid WHERE tid IN (%s) AND n.status = 1 GROUP BY tid";
-		$result = db_query($sql, $tids_list);
-		$counts = array();
-		while ($term = db_fetch_object($result)) {
-			$counts[$term->tid] = $term->count;
-		}
-		
-		// if the term id didn't return any results, then there are no nodes attached to it
-		foreach ($terms as $tid) {
-			if (!isset($counts[$tid])) {
-				$counts[$tid] = 0;
-			}
-		}
-	}
-	
-	return $counts;
-}
-
-/**
  * Find out which terms were previously saved so we can figure out how to update term_node_count.
  * 
  * I hate node revisions.
@@ -206,4 +219,27 @@
 	return array(
 		'api' => 2
 	);
-}
\ No newline at end of file
+}
+
+/**
+ * Counter function. This is just a copy of taxonomy_term_count_nodes with no static caching and an extra if statement.
+ */
+function term_node_count_count_nodes($tid) {
+    // For each term ID, generate an array of descendant term IDs to the right depth.
+    $descendant_tids = array();
+    $depth = NULL;
+    $term = taxonomy_get_term($tid);
+    $tree = taxonomy_get_tree($term->vid, $tid, -1, $depth);
+    $descendant_tids[] = array_merge(array($tid), array_map('_taxonomy_get_tid_from_term', $tree));
+
+    $args = call_user_func_array('array_merge', $descendant_tids);
+    $placeholders = db_placeholders($args, 'int');
+    $sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} tn ON n.vid = tn.vid WHERE tn.tid IN ('. $placeholders .') AND n.status = 1';
+    $sql_count = db_rewrite_sql($sql_count);
+    $result = db_query($sql_count, $args);
+    if ($result) {
+      return (int)db_result($result);
+    }
+
+  return 0;
+}  
Index: term_node_count/term_node_count.install
===================================================================
--- term_node_count/term_node_count.install	(revision 2343)
+++ term_node_count/term_node_count.install	(working copy)
@@ -19,6 +19,24 @@
 	// then we'll say that if there is a term id that isnt in term_count_count then it has 0 nodes
 	$sql = 'INSERT INTO {term_node_count} (tid, node_count) (SELECT tid, 0 FROM {term_data} WHERE tid NOT IN (SELECT tid FROM {term_node_count}))';
 	db_query($sql);
+	
+	// the user might want parent terms to inherit node counts from their child terms
+	if (variable_get('term_node_count_inherit', 0)) {
+		// first we find all the terms that have child terms and update each separately
+		$sql = 'SELECT parent FROM {term_hierarchy} WHERE parent != 0';
+		$result = db_query($sql);
+		$parents = array();
+		while ($data = db_fetch_object($result)) {
+			$parents[] = $data->parent;
+		}
+		
+		// now that we have all parent terms, we'll go through and sum up the child term's node counts and update the parent term
+		foreach ($parents as $pid) {
+			$count = term_node_count_count_nodes($pid);
+			$sql = 'UPDATE {term_node_count} SET node_count = %d WHERE tid = %d';
+			db_query($sql, $count, $pid);
+		}
+	}		
 }
 
 /**
