Hi,

I have a taxonomy with a number of articles under each term and I'd like to alter the behavior of taxonomy term pages (/taxonomy/term/%term_id).

I have overridden hook_taxonomy_term_view_alter in my module, hoping to get access to the array of nodes that is printed on the term page.

/** 
* override hook_taxonomy_term_view_alter 
*/
function mymodule_taxonomy_term_view_alter(&$build){
    Logger::log("viewing taxonomy term");
}

However, no log message shows up when I view a taxonomy term page. Any idea why this method isn't firing? Thanks.

Comments

nevets’s picture

In what way do you want to alter the page displayed? I ask because there are several approaches, both views and panels for example are capable of overriding the path but may not appropriate based on your need.

rubenski’s picture

Hi Nevets,

I'd like to select nodes from (a configurable number of) subcategories when on a term page. I don't want to rely on other modules like views.

basically what I need to do in my method is...

- find out what term page I am on
- find out if there are subterms present in the vocabulary under this term
- get nodes from the database for these subterms
- add nodes found to the array for display

nevets’s picture

Views would be a good choice since it already can handle depth (so can the default path but not without an extra argument).

rubenski’s picture

I'm afraid I don't understand what you mean, Nevets, and I don't want to rely on views at this time.

I am at the point where I can create and maintain a menu that is based on a taxonomy (like the taxonomy_menu module) and now I want to allow the user to configure the number of sublevels to show on a taxonomy term page (taxonomy/term/$term_id).

I was expecting that hook_taxonomy_term_view_alter(&$build) would enable me to hook into the proces that creates the array of nodes that are displayed on a term page, but it doesn't fire when I'm on a term page.

Is there any way to hook into the process that generates the node list for a term page?

rubenski’s picture

I don't know when hook_taxonomy_term_view_alter runs, so I've abandoned that..

Right now I am using hook_page_alter to get the extra nodes I need on the taxonomy term page. Here's the code.

function mymodule_page_alter(&$page){
    $pathParts = explode("/", current_path());
    // If we're on a term page...
    if(count($pathParts) == 3 && $pathParts[0] == "taxonomy" && $pathParts[1] = "term" && 
        is_numeric($pathParts[2])){
         
        // Load the current term   
        $termId = $pathParts[2];
        $term = taxonomy_term_load($termId);
        // Get its children
        $children = taxonomy_get_children($term->tid, $term->vid);
        $extraNodeIds = array(); 
        // For each child term get the associated node ids
        foreach($children as $childTerm){
            $extraNodeIds = array_merge($extraNodeIds, taxonomy_select_nodes($childTerm->tid));
        }  
        // Fetch extra nodes for display
        $nodes = node_load_multiple($extraNodeIds);
        
        // Yargh... how do I add the extra nodes to the $page?
    }
}

All I need now is to add the extra nodes I have in $nodes to the $page, but how? The $page array is structured in a way I didn't expect. The actual nodes are nested pretty deeply like this. The nodes in the $page array start at [n], for example [15], and the nodes I have in my $nodes array are objects that start at "[#object] => stdClass Object". How to bridge this gap? There must be a more elegant way to do this..

   [content] => Array
        (
            [system_main] => Array
                (
                    [nodes] => Array
                        (
                            [15] => Array
                                (
                                    [body] => Array
                                        (
                                            [#theme] => field
                                            [#weight] => 0
                                            [#title] => Body
                                            [#access] => 1
                                            [#label_display] => hidden
                                            [#view_mode] => teaser
                                            [#language] => und
                                            [#field_name] => body
                                            [#field_type] => text_with_summary
                                            [#field_translatable] => 1
                                            [#entity_type] => node
                                            [#bundle] => article
                                            [#object] => stdClass Object
                                                (
                                                    [vid] => 15
                                                    [uid] => 1
                                                    [title] => Programmeren 2 article
                                                    [log] => 
ransom’s picture

http://drupal.org/project/devel

It will help you drill down what exactly you want to override and how, grate for theming and module development.

http://drupal.org/node/190815

I'm guessing taxonomy-term.tpl.php means it's a new template file you can drop into your theme directory like most other tpl.php files.

Hope it helps.

rubenski’s picture

I solved this by using the hook_query_alter.

I am taking the number of sublevels I want to show nodes from from the config I built myself. Then, with that value I am overriding the query that is used by drupal to fetch nodes on a term page.

function mymodule_query_alter(QueryAlterableInterface $query){
    $pathParts = explode("/", current_path());
    // If we're on a term page and we're querying for nodes..
    if(count($pathParts) == 3 && 
        $pathParts[0] == "taxonomy" && 
        $pathParts[1] = "term" && 
        is_numeric($pathParts[2])){    
        
        // Get the tables from the query 
        $tables =& $query->getTables();
        
        // Isolate the node table
        if(isset($tables['base'])){
            if($tables['base']['table'] == 'node'){
                
                // Get the where clause
                $where =& $query->conditions();
                
                // Get the current term id
                $termId = $pathParts[2];
                
                // Create Dao
                $sectionDao = new SectionDao();  
                
                // Load the term association and the term itself. 
                // TODO: this could be done faster in one custom query...
                $association = $sectionDao->findTermLinkAssociationByTid($termId);
                $menuLink = menu_link_load($association['mlid']);
                
                // Determinte the min and max depth for child terms 
                $minDepth = 0;
                $maxDepth = 0;
                
                if($association['child_levels'] == 0){ 
                    // No further action is needed when no extra child levels are wanted: return
                    return;
                }else{   
                    // The minimal depth is the terms right under the current term               
                    $minDepth = $menuLink['depth'] + 1;
                    // The maximum depth is supplied by the user in the admin 
                    $maxDepth = $menuLink['depth'] + $association['child_levels'];
                }
                
                $childTermKeys = array();
                // Fetch the child terms under the current term/link, untill the max depth
                $extraMenuItems =
                    $sectionDao->findChildItems($association['mlid'], $minDepth, $maxDepth);

                $extraNodeIds = array(); 
                // Select the extra nodes
                // TODO:  This loop is a potential performance problem with large vocabs
                foreach($extraMenuItems as $extraMenuItem){
                    $extraNodeIds = array_merge($extraNodeIds, taxonomy_select_nodes($extraMenuItem->tid));    
                }

                // Add the extra node ids the where clause of the query
                $where[0]['value'] = array_merge($where[0]['value'], $extraNodeIds);
               
            }    
        }
    }     
}

Works like a charm. The user can select the number of sublevels he wants to display nodes from on a term page and the query is dynamically altered to include nodes from those sublevels.

Next step is to set conditional child levels like "when term page has less than 5 nodes, fetch 5 most recent nodes from subterm pages", etc.