SthlmConnection
DrupalCamp Sthlm Workshop II: Features
Today I'm giving two workshops at DrupalCamp Stockholm. One is about the Context module and the other about the Features module. This article serves as documentation for the second workshop on the hot topic of Features.
There is a lot of buzz around Features in the Drupal community at the moment. They're the next big thing: Everybody wants one, but they are still a little hard to come by.
So, what is a feature? The one sentence definition on the module page says it well:
A feature is a collection of Drupal entities which taken together satisfy a certain use-case.
In this workshop, we will explore the Features module using a couple of hands on examples. But first, let's talk about the concepts behind it in more detail.
A collection of exported building blocksA feature is some generic functionality that can be reused on different websites and that consists of exportable Drupal building-blocks, for example Content types, Views, ImageCache presets and Context. A feature could be a blog, an image gallery or a more complex structure of exportable building-blocks. By "exportable building-block", we mean something that can be exported to code and hence can live outside the scope of a database.
The beauty of features is that it is reusable and it keeps track of its own status; a feature knows which modules it is dependent on and whether it has been modified since it was installed. And since features are in essence modules on their own, you can easily add to or tweak a feature's functionality to suit your own needs. Some extra goodies is that features work well with Drush and that they can easily be shared with other Drupalers with the help of feature servers, more on that further down.
Anatomy of a feature
Again, a feature is in essence a module, with some specific twists. The actual .module file is more or less empty. Instead, much of a feature's structure is defined in its .info file, using a couple of Features specific keywords that define its components. The actual data, such as the settings of a view or a content type, is stored in separate files, as seen above.
Your first featureAnother way of approaching Features is to take an existing ad-hoc "feature" on a Drupal site and create a proper feature out of it, using Feature's Create feature page. It's surprisingly easy!
First, we need to set up a testing site. If you followed the previous workshop you already have everything you need. If not, you can fetch the downloadable file archive here. Once you have it downloaded and unpacked, you'll find an SQL dump named features_starting_point.

Now, go to Administer -> Site building -> Features -> Create feature. You'll see a form like the one above. We will create an image gallery feature, so fill in the name and description as shown above. You can leave Version empty, and the Update URL too. (The latter is used for when you use a Feature server to publish your features.)

Next, take a look at the Add components section. The drop down menu on the left contains all the basic types of entities that you can include in your feature. (In the image above, the menu has been repeated in order to save some screen space.) The image gallery uses one node type, one context, one view and three imagecache presets. In the screenshot above I have only selected one imagecache preset, and no views. You can see in the table to the right that Features caches them anyway, since the node type and context already depend on them. You'll also see that Features also has figured out that the image gallery requires the modules context, features, imagecache, imagefield and views. They then depend on other modules like ImageAPI, but that's handled by Drupal core's module system.
Finally, click on the Download feature button. A file named image_gallery.tar.gz will get downloaded. When you unpack it you'll find a folder containing the same files as in the screen shot above. If you want, take some time to look around in these files and see if the code makes any sense to you.
Deploying a featureNow, let's move on! It's time to move the image_gallery folder into the Drupal installation so we can take it for a spin. Put it in the sites/default/modules/ directory and then go back to Administer -> Site building -> Features. Like magic, your feature has already found its way into the list of installed features.

Because this feature consists of components that are already defined on this site (view, context etc.) it's currently not possible to effectively switch this feature on and off. It will be impossible to switch off, because the components exist independently of the feature. We need to delete all those components in order to see how this feature behaves in real life. Go through and delete the following items:
- The gallery view.
- The gallery context.
- The Imagecache presets large, mini_thumbnail, and thumbnail.
Don't delete the Image content type. If you do, all existing images will disappear.
Your image gallery page should be gone now though. Go back to the Features page and activate the Image gallery feature. If everything works according to plan, your image gallery should be fully restored. If you want you can try disabling and enabling the image gallery again! It's amazing to see how a complete section of the site can be just switched on and off like that!
Now, for homework you can create a second feature of the News section on the test site. Just repeat the steps from Your first feature onwards.
Keeping track of local changes to installed featues
Again, features builds upon standard Drupal components like views and CCK fields. What about if you change one of the components that belongs to a feature? Features comes prepared for such overridden components. If you go to the gallery view and for example change the title of one of the displays, you will see that the Features page will show the Image gallery features as overridden. If you have the Diff module available (which the test install has) you can click on the overridden link and see a summary of what parts of the feature has been changed, expressed as a diff on the exported component code. If you decide you want to go back to the original version, you can click the Revert tab. Here you will be offered the choice of reverting just the components you want.
Third party featuresNow, one of the great benefits of Features is that they're easy to share. Let's say we want to make a user blog feature on our site, and instead of building it from scratch, we will use the Blog feature that comes with the Spaces module. This description will be kind of brief, so you may have to explore some of the details on your own.
Begin by activating the Spaces blog features. Before we can make proper use of the feature, we need to activate the Spaces user module to give us a user oriented space for this feature. (The Spaces module is out of scope for this workshop, but it provides a convenient way to use Features, so we'll use it here.)
Once the appropriate modules are available, you can go to Administer -> Site building -> Spaces and create a space preset for user spaces. Make sure the Spaces blog feature is active by default.
Now go to your user's (admin's) user page. Right now there is no convenient link to that page, so go to the path /user. You should see a Features tab, which allows you to decide which features are available in this space. Make sure the blog feature is activated and then go back to your user page. There is now a "View recent blog entries" link, which takes you to your personal blog page. Try adding a blog post and see how everything behaves.
This is just a quick example of how you can use Features and Spaces to activate your own or third-party features on your site. A more elaborate example is the Open Atrium project, which is a complete project information system built with Features, Spaces and Context among other things. I recommend downloading Open Atrium to get a real feel for these modules' potential.
Feature serversFeature servers are a method of publishing and distributing features to many client sites. Updates that are made on the server are distributed automatically to the client sites. Feature servers can form a decentralized structure where many servers are used to provide features to single web sites. One benefit of this is that it's possible to focus on narrower use cases than is the case with modules published on drupal.org, as they need to be as generic as possible in order to serve as many audiences as possible. Another is the possibility to distribute features to a closed group of sites.
Discussion: Features' futuresThere are a lot of expectations on Features and Feature servers in the community. If you extend these ideas you can picture a future where modules on drupal.org are used strictly as general, flexible building blocks, and modules that are more related to specific use cases or problem domains move to a Features based distributed model, with a network of feature servers maintained by many different people and organizations.
Please share your thoughts in the comments!
More informationDrupalCamp Sthlm Workshop I: Context
Today I'm giving two workshops at DrupalCamp Stockholm. One is about the Context module and the other about the Features module. This article serves as documentation for the workshop on Context, a real cornerstone kind of module in Drupal.
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 briefLet'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 blocksTo 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_generate
3) 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 structureWe 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 wayWithout 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 ContextThese 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.
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.
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 upThe 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.
Attachments: