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 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:
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.
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.
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*
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!