Ordering blocks across multiple contexts while using Context module in Drupal 6

The Context module is great and does a lot of things. Web Omlette has a good summary of using the Context module for block administration.

One issue with the Context module comes when you have multiple contexts adding different blocks to the same page. An example being:

Context A places blocks 1 and 2 in the left sidebar.
Context B places blocks 3 and 4 in the left sidebar.

Although you can order the blocks in each individual context, you can't easily order them (you can apparently do so if you use the inline context UI rather than the admin one) when combining contexts.

If page X matches both context A and context B it can be a bit of a mess in terms of the order of the blocks. You are most likely going to end up with A1, B3, A2, B4 but this isn't guaranteed.

Solution - Move to code

The easiest way of managing this that I have found is to export the contexts to code and manage the weights of the blocks through the code.

You will need to either set up a new custom module or add the following code to an existing module:

<?php
function MY_MODULE_NAME_ctools_plugin_api($module$api) {
  if (
$module == "context" && $api == "context") {
    return array(
"version" => 3);
  }
}
?>

Then create a new file in your module directory called MY_MODULE_NAME.context.inc. Replacing MY_MODULE_NAME with the name of your module.

In your new include file, create the following function:

<?php
function MY_MODULE_NAME_context_default_contexts() {
  
$export = array();

  return $export;
}
?>

Then you would set up each individual context how you want within the Context UI then export. You will get code similar to the following:

$context = new stdClass;
$context->disabled = FALSE; /* Edit this to true to make a default context disabled initially */
$context->api_version = 3;
$context->name = 'b_research_nav';
$context->description = '';
$context->tag = 'b';
$context->conditions = array(
  'node' => array(
    'values' => array(
      'research' => 'research',
      'research_success' => 'research_success',
    ),
    'options' => array(
      'node_form' => '0',
    ),
  ),
);
$context->reactions = array(
  'block' => array(
    'blocks' => array(
      'menu_block-1' => array(
        'module' => 'menu_block',
        'delta' => 1,
        'region' => 'left',
        'weight' => 0,
      ),
      'block-15' => array(
        'module' => 'block',
        'delta' => 15,
        'region' => 'left',
        'weight' => 1,
      ),
    ),
  ),
);
$context->condition_mode = 0;

// Translatables
// Included for use with string extractors like potx.
t('b');

This can then be added within your function above followed by:

<?php
$export
[$context->name] = $context;
?>

Reload the Context UI admin page and you will see the option to 'Revert' your context. If you get this then you have set it up correctly.

Your final include file would look something like the below:

<?php
function MY_MODULE_NAME_context_default_contexts() {
  
$export = array();
  
$context = new stdClass;
  
$context->disabled FALSE/* Edit this to true to make a default context disabled initially */
  
$context->api_version 3;
  
$context->name 'b_research_nav';
  
$context->description '';
  
$context->tag 'b';
  
$context->conditions = array(
    
'node' => array(
      
'values' => array(
        
'research' => 'research',
        
'research_success' => 'research_success',
      ),
      
'options' => array(
        
'node_form' => '0',
      ),
    ),
  );
  
$context->reactions = array(
    
'block' => array(
      
'blocks' => array(
        
'menu_block-1' => array(
          
'module' => 'menu_block',
          
'delta' => 1,
          
'region' => 'left',
          
'weight' => 0,
        ),
        
'block-15' => array(
          
'module' => 'block',
          
'delta' => 15,
          
'region' => 'left',
          
'weight' => 1,
        ),
      ),
    ),
  );
  
$context->condition_mode 0;

  // Translatables
  // Included for use with string extractors like potx.
  
t('b');
  
$export[$context->name] = $context;

  $context = new stdClass;
  
$context->disabled FALSE/* Edit this to true to make a default context disabled initially */
  
$context->api_version 3;
  
$context->name 'a_research_nav';
  
$context->description '';
  
$context->tag 'a';
  
$context->conditions = array(
    
'node' => array(
      
'values' => array(
        
'research' => 'research',
        
'research_success' => 'research_success',
      ),
      
'options' => array(
        
'node_form' => '0',
      ),
    ),
  );
  
$context->reactions = array(
    
'block' => array(
      
'blocks' => array(
        
'menu_block-2' => array(
          
'module' => 'menu_block',
          
'delta' => 1,
          
'region' => 'left',
          
'weight' => 0,
        ),
        
'block-13' => array(
          
'module' => 'block',
          
'delta' => 13,
          
'region' => 'left',
          
'weight' => 1,
        ),
      ),
    ),
  );
  
$context->condition_mode 0;

  // Translatables
  // Included for use with string extractors like potx.
  
t('a');
  
$export[$context->name] = $context;
  return 
$export;
}
?>

The above code adds two contexts. If you look at the code you will see that the conditions match so 4 blocks should be added to the left sidebar. The issue is that the blocks have the following weights set:

  • Menu block 1- 0
  • Menu block 2 - 0
  • Block 13 - 1
  • Block 15 - 1

Now within the code you can change the weights of these to order them how you like.

But as soon as they are overridden in the Context UI admin page the weights will be reset, so any further changes in the UI will need to be exported to the code again and then you will need to change the weighting while also reverting to the code version in the UI.

Unfortunately due to the complexities involved there is never likely to be an interface which is able to handle this properly.