Mixing Context and Drupal's Native Block Ordering System
I work on a lot of legacy sites that were built without the Context module, and I would say that at least once on each of these legacy sites, I turn to Context when I have a very specific problem: the visibility settings for a particular block are so complex that (in Drupal 6 at least) they can only be expressed by writing code. For instance: suppose you're using Organic Groups, and you want to show or hide a block based on whether the user is a member of that group. You can jam a ton of code into the PHP visibility settings for the block; or, if you don't hate yourself, you can let Context do it for you. Excellent.
The problem is, unless you put *all* your blocks under the control of Context, you don't have total control over the weight of Context-controlled blocks within their regions. You can control the order of blocks within a given context, of course, but there's no way to order Drupal-controlled blocks and Context-controlled blocks in a unified way. The only solution that I know of is to move all your blocks into Context.
Today, however, I cooked up an alternative solution. Here's the general idea:
1. Create a context as you normally would.
2. Don't assign any reactions to the context (or, if you do, make sure none of them involve enabling blocks).
3. Using Drupal's native block system (admin/build/block), assign your block to the region you want and order it as you wish among the other blocks.
4. Now, here is the trick: set the block's visibility to PHP code and call this function as many times as is needed:
yourtheme_context_is_active('name_of_context');
For example, if you had a context named 'group_post', and another named user_is_member_of_group
, and you wanted them both to be active, you would put this in the PHP visibility settings for the block:
return yourtheme_context_is_active('group_post') && yourtheme_context_is_active('user_is_member_of_group');
The code we put in yourtheme_context_is_active() calls a Context function and tells you whether the context is active.
What I like about this solution is that it allows you to use blocks as you normally would, but to use Context selectively, for the situations where your block visibility rules are complex enough that you don't want to write cumbersome code that could create maintenance issues. It also keeps as much code out of the database as possible.
Here's yourtheme_context_is_active():
function yourtheme_is_context_active($context) {
if (module_exists('context')) {
$active_contexts = context_active_contexts();
if ($active_contexts) {
if (array_key_exists($context, $active_contexts)) {
return TRUE;
}
}
}
return FALSE;
}
Put that in template.php and you're good to go.
Certainly could be a better way to do it out there, though, so if you know of one, feel free to let me know!
Tags: context module