Hello,

I just noticed that parent terms in hierarchical taxonomy are shown as having 0 nodes.

While it is true that they may not have direct nodes, but the nodes for their children terms should be rolled up.

Comments

archard’s picture

I thought about putting this in originally, but decided to see if there was any interest before I went through with implementing it. I'll put it an admin page in the next version that allows you to toggle the term count for parents between 0 and whatever the sum of all the child terms are.

giorgio79’s picture

Much appreciated archard, looking forward to it. Let me know if you need any assistance.

mrgoltra’s picture

I was going crazy why parent terms are always 0. I spent the whole weekend trying to figure this out.

Me too, looking forward.

Thank you

archard’s picture

I worked on it quite a bit last week but didn't finish. I'll be pretty busy for the next 2 or 3 days, but hopefully I'll finish it by this weekend.

Flying Drupalist’s picture

Thanks! Subscribe. :)

archard’s picture

Status: Active » Needs review
StatusFileSize
new1.68 KB
new6.88 KB

I need patch testers. I think it works properly but I just don't have time to test it thoroughly.

You need to apply the patch and also put term_node_count.admin_.inc_.txt in the module's root directory and rename it term_node_count.admin.inc

Sorry im a patch noob.

artscoop’s picture

Hi, I've just tested your patch (that I couldn't apply due to errors, whatever. I had to apply it by hand), and it works.
But it doesn't work fine with many taxonomy terms ( It times out after 5 minutes, for about 1000 terms )

I've changed some code (taken from Taxonomy_VTN), and it processes 1000 terms in about 15 seconds, So it is at least 20 times faster.
Here is the function you should replace :

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;
}  
archard’s picture

Thanks artscoop.

I assume the crash happened on the install. I was afraid that might happen and was part of the reason I chose not to include this originally. Without considering child terms you can easily get that counts all in one query (with a couple sub-queries). I'll consider a few possibilities for how to deal with this. I think the use of static caching should solve it. The reason I don't use it now is because if multiple nodes are updated in on operation, like on the node operations page or the devel generate items page, then the node counts will get cached on the first node and not update for the rest. To deal with this I think I'll put a flag inside my count function that will skip the static caching only for certain cases. I should be able to keep the caching in for the install phase.

Marko B’s picture

Can u post patched file(s) here so i could test it, patch doesnt work for me. Thanx

artscoop’s picture

Hi deepM, you have to apply the patch by hand.
Open the file in a text editor.
You will have to find the lines marked with a "-" in the module and replace them with the next lines marked with a "+" (for example)
You may also have to add lines. These will be marked with a "+" and be preceded by some code in the original module.

ManyNancy’s picture

Is this patch working? Could this be committed?

alcoder’s picture

StatusFileSize
new12.28 KB

I think this patch is working. I am attaching the whole patched module. The function term_node_count_count_nodes() is replaced by the function written by artscoop. It would be good if the maintainer would create a new release for this project.

ryan88’s picture

Thank you for your post. This is just what I needed.

dicreat’s picture

Thank you for this patch!

fasdalf@fasdalf.ru’s picture

Following does not work:
1- replace files
2- change setting
3- edit node

but this appears to be working:
1- replace files
2- change setting
3- rebuild node counts
4- save settings page again (why?)
5- edit node

Is that normal?

Also if i remove child term child count decreases, but parent count does not.

P.S. I'm using hierarhical select now.
P.P.S. Without HS thing behave the same.

fasdalf@fasdalf.ru’s picture

I modified 3 functions to make this module work properly with and without "inherit" setting.

function term_node_count_update($tids_to_update) {
  // 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)) {
      $parents = array();
      foreach ($tids_to_update as $tid) {
//////// LOOK HERE
        // Get all parents tids for nested hierarhy
        foreach (taxonomy_get_parents_all($tid) as $parent) {
          $parents[$parent->tid] = $parent->tid;
        }
      }
      $tids_to_update = array_unique($tids_to_update + $parents);
    }
    //print_r($tids_to_update);
    $sql = 'UPDATE {term_node_count} SET node_count = %d WHERE tid = %d';
    //$counts = term_node_count_count_nodes2($tids_to_update);
    foreach ($tids_to_update as $tid) {
      $count = term_node_count_count_nodes($tid);
      db_query($sql, $count, $tid);
    }
  }
}

Now uses taxonomy API to determine all parets if necessery

function term_node_count_saved_terms($node) {
  $saveds_tids = array();
  $sql = 'SELECT tid FROM {term_node} tn INNER JOIN {node} n ON tn.vid = n.vid WHERE tn.vid = %d AND n.status = 1';
  if (!$node->revision) {
    // if there's no revisioning involved then this is a piece of cake
    $result = db_query($sql, $node->vid);
  }
  else {
    // this is a revision
    if (!$node->revision_timestamp) {
      // the user is creating a new revision
      $result = db_query($sql, $node->vid);
    }
    else {
      // the user is reverting back to an older revision
      // the problem here is that instead of telling me the most recent vid
      // drupal gives me the vid associated with whatever version we're reverting to
//////// LOOK HERE
      $old_vid = db_result(db_query('SELECT vid FROM {node} WHERE nid = %d', $node->nid));
      $result = db_query($sql, $old_vid);
    }
  }
  while ($tids = db_fetch_object($result)) {
    $saveds_tids[$tids->tid] = $tids->tid;
  }
  return $saveds_tids;
}

Pulls current revision from {node} table

function term_node_count_count_nodes($tid) {
//////// LOOK HERE
  if (variable_get('term_node_count_inherit', 0)) {
    // For each term ID, generate an array of descendant term IDs to the right depth.    $tids = array();
    $tids = array();
    $depth = NULL;
    $term = taxonomy_get_term($tid);
    $tree = taxonomy_get_tree($term->vid, $tid, -1, $depth);
    $tids[] = array_merge(array($tid), array_map('_taxonomy_get_tid_from_term', $tree));
    $args = call_user_func_array('array_merge', $tids);
  } else {
    // Count for current term only
    $args = array($tid);
  }
  $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);
  } else {
    return 0;
  }
}  

Counts children's nodes only when inherit option enabled.

marketter’s picture

Subscribed. Really looking forward to this patch getting added to the next release. Let me know if you need additional testers.

off’s picture

#12 works fine

YK85’s picture

+1 subscribing

Marko B’s picture

Why is no 12 not used in official relase?

Heihachi88’s picture

Thanks #12, it works perfectly. Dont forget about settings on page → admin/settings/term_node_count
Inherit child term's node counts?: Yes, then rebuild node counts

johan2’s picture

Hi,
I am trying to figure out why this doesn't work on my site.
I am running D6.22 and replaced "term_node_count-6.x-1.3" after it didn't work with this patch.
But the node count always gives the result 0.
I call the node count through a term-view, even turned off all filters so all nodes should be counted but still it stays 0. The terms are recognized since they show up but the query returns 0.
Anybody has an idea how this happens?
regards,
Johan

aaronbauman’s picture

Status: Needs review » Needs work
StatusFileSize
new7.55 KB

Here's a proper patch from the .zip in #12.

I haven't reviewed this at all, but invoking an uninstall/install function on a form submission is a gigantic waving blinking flashing red flag, so i'll go ahead and mark this needs work.
If I have time I'll re-work this and upload a new version on the off chance anyone still cares about this 3.5-year old feature reqeust.

dizee’s picture

I still care! :)

gielfeldt’s picture

This is issue is probably better addressed at query time:

Tree:

 tid:1 (100 nodes)
  - tid:2 (200 nodes)
  - tid:3 (50 nodes)


Acquire children tids and use:

SELECT c.count FROM (
  SELECT 1 AS a, SUM(tnc.node_count) AS COUNT 
  FROM term_node_count tnc 
  WHERE tnc.tid IN (1,2,3)
  GROUP BY a
) c;


I'm also thinking about integrating it with taxonomy edge:

SELECT c2.node_count AS node_count FROM (
  SELECT 1 AS a, SUM(c.count) AS node_count FROM (
    SELECT te.parent, SUM(tnc.node_count) AS COUNT 
    FROM term_node_count tnc 
    JOIN term_edge te ON tnc.tid = te.tid 
    WHERE te.parent IN(1)
    GROUP BY parent
  ) c
  GROUP BY a
) c2;