Author image
Senior Mind

Extending the drupal context module to allow conditional contexts based on taxonomy terms

We are loving the Drupal context module here at ComputerMinds, it puts a lovely user friendly formal front end onto creating context's for your site, something we had previously been doing with various snippets of code. If you haven't come accross the context module before then I fully recommend you have a look at this post http://www.developmentseed.org/blog/2008/apr/09/context-ui which explains all ...

Taxonomy based context

The one key element that seems to be missing from context is the ability to set the context based on taxonomy, but no fear - the context module is super easy to extend and this just gives us an excuse to have a play

The first thing we do is tell the context module that we have a new context condition, based on the taxonomy term. We borrow a sneaky bit of code from the taxonomy module to render all the taxonomy terms in a pretty array.

function context_taxonomy_context_conditions() {
  $items = array();

  if (module_exists('taxonomy')) {
    $taxonomy = module_invoke('taxonomy', 'form_all', 1);

    $items['taxonomy'] = array(
      '#title' => t('Taxonomy'),
      '#description' => t('Set this context when displaying a node within this taxonomy term.'),
      '#options' => $taxonomy,
      '#type' => 'select',
      '#multiple' => true,
    );
  }

  return $items;
}

Now we just need to tell the context module which taxonomy term we are currently viewing, we can do that using a normal nodeapi implementation, just calling the context_set_by_condition with the appropriate condition name, and the appropriate value, and the context module will look after the rest - brilliant.

/**
* Implementation of hook_nodeapi().
*/
function context_taxonomy_nodeapi(&$node, $op, $teaser, $page) {
  if ($op == 'view' && $page && arg(0) == 'node') {
    // Implementation of context for nodequeue.
    if (module_exists('taxonomy')) {
      foreach($node->taxonomy as $term){
        context_set_by_condition('taxonomy', $term->tid);
      }
    }
  }
}

This should really be submitted as a patch to the context_contrib module, and I will look at doing that fairly soon - but for now it should serve as a nice little intro to create your own context conditions

Comments

I want to set the active menu trail in the primary navigation based upon the root term under which a node's taxonomy terms reside.

Awesome!! I can't wait to try it out. Thank you so much for posting.
Cheers,
Kelly

Cross posted your code into the appropriate Context issue que.

http://drupal.org/node/343110#comment-1764030

Josh

It works well on my site.

This is now in the release of context module proper.

Awesome, great tutorial . Thanks for sharing

where is the function context_set_by_condition() defined? i'm having trouble understanding how this actually works..

context_set_by_condition() is defined in the context module, and it will set a context based on the conditions you supply to it.

any idea which file? i've searched through everything and have found 10 places where it's either called or mentioned (all of them in context.core.inc), but can't find the function definition itself.

in you example it looks like the function is being called for every term in the node, and i'm curious what happens at the other end -- i.e. how does the module decide which term actually causes the context to be set.

the reason i'm asking is because the module's active-menu-trail way of setting context doesn't seem to work at all but i've hit a dead end trying to figure out why.

nevermind, found it... my text editor was ignoring context.module for some reason

It is GREAT, without this feature the Context module was unusable for me...Thanks !

This should REALLY be part of the context module.

I extended this module a bit to set the context based upon a taxonomy term's "lineage" within a taxonomy hierarchy. Interestingly, this version provides the same result if your term is a "root level" term, but also checks to see if the term is a child in a given taxonomy hierarchy tree.

My use case is that I'm currently working with a site that uses the NAT module (not my choice, but hey) to build out deep, hierarchical content structures. I want to set the active menu trail in the primary navigation based upon the root term under which a node's taxonomy terms reside. So, I grab the node's terms, and then look up their parents in the hierarchy. If I find a root-level term that's set to trigger a context, bam.

/**
* Implementation of hook_context_conditions().
*/
function context_taxonomy_tree_context_conditions() {
$items = array();

if (module_exists('taxonomy')) {
$taxonomy = module_invoke('taxonomy', 'form_all', 1);

$items['taxonomy'] = array(
'#title' => t('Taxonomy'),
'#description' => t('Set this context when displaying a node within this taxonomy term tree or hierarchy.'),
'#options' => $taxonomy,
'#type' => 'select',
'#multiple' => true,
);
}


return $items;
}


/**
* Implementation of hook_nodeapi().
*/
function context_taxonomy_tree_nodeapi(&$node, $op, $teaser, $page) {
if ($op == 'view' && $page && arg(0) == 'node') {
// Implementation of context for nodequeue.
if (module_exists('taxonomy')) {
foreach($node->taxonomy as $term){ // Look up the current node's taxonomy terms.
  // Look up the term's lineage in the taxonomy hierarchy.
  // Implementation of taxonomy_get_parents_all($tid) - returns an array of all ancestors of a given term ID, root term is last.
$lineage = taxonomy_get_parents_all($term->tid);
$root_term = end($lineage);
context_set_by_condition('taxonomy', $root_term->tid);
}
}
}
}
Comments on this article are now closed, if you want to give us feeback you can use our contact form instead.