Skip to main content

Mixing Context and Drupal's Native Block Ordering System

File under

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:

    <?php 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 niot_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!

drupal 7 context native blocks

hi venutip,

great idea - i was thinking about something like this but would not be able to write code.
unfortunately i am using drupal 7 and your solution did not work for me.

will you upgrade your code to d7?

thx
 karl

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • You can use Markdown syntax to format and style the text. Also see Markdown Extra for tables, footnotes, and more.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <img> <code> <ul> <ol> <li> <dl> <dt> <dd> <pre> <h1> <h2> <h3> <h4> <h5> <h6>
  • Lines and paragraphs break automatically.
  • Adds typographic refinements.

More information about formatting options