First, what is a context? The module page puts it like this:
You can think of each context as representing a "section" of your site. For each context, you can choose the conditions that trigger the context to be active and choose different aspects of Drupal that should react to this active context.
Contexts could be used to define ordinary site sections, for example the "Culture" or "Economics" section of a newspaper site, but they can also be more complex and require a number of different conditions to be met before it is triggered. The conditions could apply to virtually anything, like the active node type, the active path or the role of the current user.
There are several ways in which Drupal can react to an active context; it can set the active menu item, display or hide blocks, add css classes and so on.
You can even create your own module to define custom conditions that should activate a context, or to define custom reactions to a context.
This is all somewhat theoretical so far, but we will move on to a real world example to help explain the concepts behind Contexts.
The brief
Let's imagine we got a brief from a customer saying that they want a simple site where they can publish news and images with the following specifications.
On the entry page of the news section, the latest news items should be listed with their title and an intro text. In a sidebar there should be a list of the ten most recent news, only displaying their title as a link, and a similar list of the ten latest comments to news stories. These two lists should be displayed on all pages in the news section.
On the entry page of the image gallery section, the latest images should be displayed side by side on top with a thumbnail image and their title. Underneath there should be a grid with small thumbnails of all images. This grid should be visible on all pages in the image gallery section. All thumbnails are links to the corresponding image page.
As you would expect, each section should have its corresponding menu item which is always shown as active as long as the user is in that section. Additionally, the title of the page as well as some design features need to change depending on which section is currently visited.
Let's see if this is something that can be implemented in Drupal!
Preparing some building blocks
To save time, a starter kit for this exercise is available for download here: context_features_workshop.tgz.
The file archive contains a complete Drupal install with all the modules needed, and also a database dump ready to be imported with PHPMyAdmin or by any method you choose. The login is admin / admin .
I recommend that you use it as a starting point, but if you prefer to do things yourself, or if you just want to know how it's been set up, the following recipe describes the process.
1) Download Drupal 6 and do a standard installation.
2) Download and enable the following modules:
- Context: Context och Context UI.
- Views: Views and View UI.
- CCK: Content and Text.
- FileField.
- ImageField.
- ImageCache: ImageCache and ImageCache UI.
- ImageAPI: ImageAPI and your choice of ImageAPI GD or ImageAPI ImageMagick.
- CSS Injector – for showing off some cool tricks.
- Purl – for the next workshop!
- Spaces – for the next workshop!
- Features – for the next workshop!
- Diff – for the next workshop!
- Date: Date and DateAPI – for the next workshop!
- Administration Menu – for convenience
- Devel: Devel and Devel Generate – for generating test content
If you're using Drush, here's a handy shortcut:
drush dl context views cck filefield imagefield imagecache imageapi \
css_injector purl spaces features diff date admin_menu devel
drush enable context context_ui context_contrib views views_ui \
content text filefield imagefield imagecache imagecache_ui \
imageapi imageapi_gd css_injector purl spaces features diff date \
date_api admin_menu devel devel_generate3) Now create a couple of content types (I'm using Story and Image in this example, the latter containing an image field) and generate nodes of those types with Devel Generate.
4) Then create a couple of views (eg. News and Gallery) to go with the content types, and give them each a menu item in the Primary links. Also make one or two block displays in each view, so that you have something to play around with later.
Lots of building blocks, no structure
We now have all the basic components we need: Node types, fields, nodes, views, menu items and blocks. You might want to take a few minutes to get familiar with them.
It's time to start thinking of how to make sense of these different parts. The goal is to create two cohesive sections on the site: News and Gallery. We've already created menu items for our views, which is a first step in that direction. However, once you click to see the full version of a node in these views, the context of the menu is immediately lost. There's no way to tell that the content you're viewing belongs to any specific menu item. This is the first fundamental problem.
The other problem is the blocks that each view has defined, like lists of the most recent news items, and the miniature view of all images in the gallery. How do we tell Drupal that you want to associate them with their corresponding menu items and node types?
Structuring the components – the old way
Without going into too much detail, both of the issues above can be dealt with without the Context module. Before we start building our first contexts, we will do a quick summary of the other available options and talk about where and why they're lacking.
Let's begin with nodes and menus problem. Drupal lets you place nodes in the menu tree, so that you for instance can specify that each specific Story node is a sub-item of the News menu. However, this is exactly the kind of dumb labour that computers are meant to do for us (not the other way around), and a menu structure also doesn't scale very well once you have more than just a couple of nodes in it.
A common solution to this problem is Menu Trails which can be used to associate different node types with specific menu items. That would solve one of the problems.
But, then there's the block visibility issue. Drupal's block configuration gives you some control out of the box of when a block should be visible and not. The easiest way is to specify what URL paths you want the blocks to be visible on, which works well in some cases. For example, we would be able to tell Drupal that we want the Latest News block to be visible on the News view page, which has the path news.
But that's of no use on node pages. Each node has the same basic URL pattern (node/X) regardless of its type. A way around this is to use Pathauto to set up different path rules for different node types, and then use those paths in the block configuration. It works, but it is a somewhat fragile solution, and it's an example of giving structural meaning to something (a path alias) that is more like a decoration than a fundamental site component. (Path aliases do play an important role in a usable, search engine optimized Drupal site. They're just better suited for displaying the site structure than dictating it.)
Another way to solve this is to specify the block visibility setting with PHP code, which isn't really much better. Using this method, it's possible to detect what kind of page the user is on, inspect the current node, and change the block visibility accordingly. First of all, this is hard to even try for people without PHP experience. Second, it's very easy to make a mistake and effectively break the site with something like a missing quote. PHP code stored in the database is also a bad idea for security reasons.
Benefits of using Context
These are some of the problems that the Context module solves. It links together node types, views, menus, and blocks, all in one central location. In addition, it gives you some extra benefits. You can:
- Avoid PHP code in the settings (stored in the database).
- Put blocks in different regions depending on context.
- Export contexts as code, making version control and distribution much easier.
- Work with Sections and Features to make and distribute reusable site features.
- Have a basic framework for all your context related development needs. Context doesn't always have to be about ordinary site sections, a context could also work with things like language, browser type, client location, etc.
Your first contexts
Time for some real action finally! Go back to our example site and visit Administer -> Site building -> Context. This is the interface you use to define contexts for each section of your site. Let's start with the Image Gallery!

This is where you name your context. For now, you should leave the Namespace and Attribute fields at their default values and just fill in "gallery" in the Value field. (Namespaces are a way of letting different modules work with Contexts without interfering with each other. Attribute can be used to distinguish between different types of contexts, but that's outside the scope of this workshop.)

The first configuration section is called Conditions, and this is where you define what conditions have to be met in order for the context to get activated. There are several different types of conditions you can work with (and they can also be extended by contributed modules):
- Node pages: Choose which content types should trigger this context. In this case, Image.
- User pages: Here you can have your context get activated on the user pages of certain roles.
- Sitewide context: Use this to create a context that is always active.
- Path: Specify the URL paths you want to trigger the context. You may write
galleryhere, but it's not strictly necessary. - Menu trail: Choose which menu items should trigger the context. Choose Gallery.
- Views: Use this to associate specific views with your context. Choose the gallery view, even though there will be some overlap with the menu trail setting.

The next section is Reactions. This is where the fun part begins! These settings define what will happen when a context is active.
- Active menu: This menu item will get activated whenever this context is active.
- Theme variables: Here you can specify certain variables that can be used in your theme. The most useful option here is Section class. It provides a very robust way of creating different styling on different contexts. For instance, you can use the value
context-galleryto be able to have CSS rules likebody.context-gallery #site-name { font-size: 20px; }. - Disabled regions can be used to disable the output of whole block regions, like sidebars, headers etc.
- CSS Injector: This is an example of a third party module providing additional functionality through Context's API. CSS Injector can be used to define CSS rules that are included in the page depending on different conditions. In this case, context conditions. The downloadable installation in this article has a couple of CSS Injector rules already set up, so if you want you can try and apply those to this context. (Note that it's usually better to use your theme for this kind of thing. The body class option in the Theme Variables section is meant to help you do context specific styling in your regular css files, as shown above.)
- Context workshop examples: Yes! This is our own little example module doing its magic and showing up in the UI. (It will only be available if you downloaded the start package in the beginning of course.) It provides a setting for changing the actual site name when this context is active. The site name is usually visible in the page header and in the title bar. Write "Context Workshop Gallery" for now. The source code of this module can be found in
sites/default/modules/contextworkshop/.

The Blocks section is where you choose which blocks should be enabled in this context, and in which region they should go. Note that blocks that are already activated on the standard block administration page (Administer -> Site building -> Blocks) are "locked" in this interface. You cannot move them between regions or disable them, but you can place other blocks on top of or below them.
Check the box next to the block that is defined in the Gallery view (gallery: Block) and click Add on the Content row. This tells Context that you want this block to be visible in the Content region (below the page's main content).
Your done! Click Save and you should be redirected back to the main Contexts page where your new context will be listed.
The result

You can now go to your gallery page and take a look at the result. Beautiful, isn't it? There are a couple of things to look for:
- The Gallery menu item should be active, not only when you're on the main gallery page, but also when you click to view a single image (which is a standard node page).
- The gallery view block should be visible underneath the main gallery view. Note that it stays there also when you browse around between different images.
- The page title should now have changed to "Context Workshop Gallery".
- The page title should have a different styling, provided that you used the CSS Injector option earlier.
- If you take a look at the source code, you should find the class
context-galleryadded to thebodytag.
Homework: the News section
Now that you know your way around the Context interface, you should be able to repeat the steps above to create a new News context. You may want to put the News related blocks in a sidebar instead of in the Content region, but other than that the instructions are more or less the same.
Summing up
The brief asked for a simple site with two cohesive sections - News and Gallery. To achieve this, we started out with a half baked Drupal site made with the usual tools: Nodes, Fields, Views, Blocks and Menus. In order to keep sections together, we first considered using the standard Drupal tools, but saw that this would require at least a couple of extra modules (Pathauto and Menutrails) with corresponding settings, and that we would end up with a site structure that is somewhat hard to maintain.
Using the Context module, however, we managed to easily define specific contexts with corresponding reactions for each section, just using one extra module. The end result is a site structure that is stable, extensible, and easy to maintain.






Comments
Great introduction
It looks like you had quite a nice workshop! :)
I haven't heard of PURL before, so that's a new tool for my box. Thanks for the tips!
Great work
Excellent workshop - and my mouth waters at this module. Many thanks for setting it in context!
Post new comment