October 2010

Context Everywhere

We have frequently used the Context module by Development Seed in our projects in the past year.  We started using Context because it allowed us to ditch the default Drupal block page and its 20-line path exceptions.  With its admin module integration, even non-technical users can place blocks on context.

We continue to use Context because of its powerful API -- our collective imagination is the only limit when creating custom conditions and reactions.

 

Context Overview

"Context allows you to manage contextual conditions and reactions for different portions of your site." (From the Context module page).

Conditions describe the circumstances under which context should be active. Reactions are what happens when the context is active. A common example is showing blocks on a page when a certain content type is being viewed.

This example has the following setup:

Conditions

First you set a condition based on the content type (labeled "Node Type" here).  Beyond Node Type, there are other condition types. One of the more common condition types is path; setting a path condition allows you to activate the context on a certain URL, much like when using the block admin page.

Reactions

For reactions, we set blocks and menu.  When setting the block reaction, you select which blocks to use from the list in the right column, and assign them to their regions in the middle column.  For the menu reaction, you would select which menu link will be assigned the active class to appear selected.

Now when you visit the an article node, the Sidebar content Index and Popular and commented content blocks will display in the right sidebar.

Like many others, we did this basic setup of path-based and content type-based contexts, and this solved 90% of our needs. While this approach worked great for simpler sites, it's not very flexible for more complex sites.

 

Contexts in Complexity

 

When working with more complex sites requiring blocks specialized to specific pages, we found ourselves creating path-based contexts. This, however, quickly became just as cumbersome to manage as the block admin page. We found that path-based contexts were mostly being used for page-based nodes; to address this, we decided to try using hook_nodeapi to create context per page node.

While this was a fun development exercise, it resulted in even more contexts then the path-based method. The main flaw in all of these designs was the need to place the default blocks on each of the contexts individually; this raised questions as to whether we should abandon contexts and go back to using the block admin page.

Fortunately, around this time the ability to base a condition upon other contexts was added to the Context module. This allowed us to introduce the concept of default contexts.

Default Context

 

As the name implies, default contexts are a set of reactions to use when no other context is active. Taking it further, using a standardize naming convention lets you have context interactivity based on your context names. To explain how these work, let's take a deeper look at the context-based conditions.

The first step is to decide on a naming convention. While we don't have a standard we use all of the time, I've found that using the region name in the context works well. The basic format is <region>-<name>-<extra>. 

  • Region: The region the context controls. Separating the context per regions is a key piece to our Context design.
  • Name: This is a description of the context.
  • Extra: This is optional. We standardized on a few statements:  "default", "override". Default is the default context for the region. Override replaces all context for that region. If this is left blank, then it's active the same time as the default.

 

We always have a sitewide Context. This is used for blocks like primary menu, headers, footers and ads. Another standard context is for the admin pages. We remove the blocks for end users and place status type blocks in the admin context.

When using a sidewide context, we set the Core Block System setting to "Disabled" at admin/build/context/settings.  Now only context will place blocks.  The option states there a performance gain by not having to pull the Drupal blocks.  Preformance is also increased by Context not having to figure out where to put the blocks in relation to the context blocks.

 

Most site designs have consistent blocks across most of the site. We place these blocks in the default context. In our example below, we want to have certain blocks only appear on the blog nodes but we also want to display the default blocks.

Here is how we accomplish this. Say we have a region called "left". This is the region for the left sidebar.  The example below breaks out the contexts and their conditions for overriding and adding onto the defaults.

 

Sitewide Context

  • Name: sitewide_context
  • Sitewide Context: Always Active

Default Context for Left Sidebar

  • Name: left-sidebar-default
  • Context: ~left-*-override

Context for Admin Pages for left Sidebar

  • Name: left-admin-override
  • Path: admin*
    • node/*/edit

Blog Content Type Left Sidebar Context

  • Name: left-blog
  • Node Type: Blog

 

This was just a very simple example, but it is a start to show you how to design your contexts to keep control.  If you would like to learn about writing a custom plugin for context, please read my prior post "The Joy of Extending Context."

If you are interested in learning more about context design, join my session at Drupal Camp Indy on Oct 23 in Indianapolis, IN.

Have you been using Context, or looking for this kind of solution, for your projects? Tell us about it below!

Comments

Great post. Thank you for sharing. I was wondering how I could better manage the complexity with the Context module. -Bookmarked

nice post, one of the clearest explanations I've seen. Especially nice that it goes beyond the most basic configuration!

very, very helpful thanks for clarifying all this!

This approach worked well for me with general sections of the site, rather than regions.

Thanks!

I was looking for a dynamic context, one that would allow me to add block to one particular node. No luck. Even Spaces hates me, could not implement this following approach too :( http://www.leveltendesign.com/answer/adding-customize-dashboard-magic-yo...

@Anonymous,

Try using the path condition to node/[nid] where nid it he nid on the node. If you need a context for every node of a certain ctype, check out http://bitbucket.org/treehouseagency/node_context. Be be very careful as it will create tons of contexts and can be come uncontrollable very quickly.

Thanks mate. I was about to write exactly same code under same module name. :) As long as nodeapi removes context after node is deleted I am fine with many contexts (groped under same tag). Also I was thinking about feature to NOT creating context (or disabling it) for node. Anyways, I will take a look at code and maybe contribute something. Its best solutions ONLY for small-corporate-20-something-pages sites, its very possible to do this with Spaces and Spaces Node, but its just not stable enough and little dark territory for me.

Yes, I think I can contribute as I need this for current project. I would add possibility to create and delete context automatically with node api, use tips from this post for context naming rules, move settings on content type form and add some more small tweaks.

New code works well. Is anyone else interested?

hi,

I am using drual 6.19 and 6.2. I install context module with required other module.s But it doesn't show block at places which I mention in reaction section of context.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <hr> <blockquote> <h3> <h4> <h5> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <pre>, <c>, <cpp>, <drupal5>, <drupal6>, <java>, <javascript>, <php>, <python>, <ruby>. The supported tag styles are: <foo>, [foo].

More information about formatting options

By submitting this form, you accept the Mollom privacy policy.
Stay Informed

Sign up now for the Treehouse Newsletter.