default Drupal contexts like default views

I was using the brilliant context module in a project recently. The fact that it uses ctools means it has a few characteristics reminiscent of views (and panels). One of these is the import / export functionality, and the distinction between the different types of storage for the contexts you've set up - i.e.

  • normal
  • default
  • overridden

Seeing this, I was certain there must be a way of defining contexts in code in a module, similar to the way you can define default views hook_views_api() and hook_views_default_views(). However, I really struggled to find any documentation about the correct hooks and syntax to achieve this.

Of course, one way of finding out was to use the features module to package up a context and have a look at the code it produced.

It turns out this works in a very similar way to the views module (unsurprisingly given their shared heritage). I thought I'd document it here in case other people are struggling to find some clear instructions as to how to include your own default context objects in your module.

Just like with views, you need to implement an api hook, and then the actual context_default_contexts hook which returns the exported context object(s):

/**
 * Implementation of hook_ctools_plugin_api().
 */
function mymodule_ctools_plugin_api($module, $api) {
  if ($module == "context" && $api == "context") {
    return array("version" => 3); 
  }
}

and then in mymodule.context.inc something along the lines of this:

/**
 * Implementation of hook_context_default_contexts().
 */
function mymodule_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 = 'testy';
  $context->description = 'testing context';
  $context->tag = '';
  $context->conditions = array(
    'node' => array(
      'values' => array(
        'page' => 'page',
      ), 
      'options' => array(
        'node_form' => '1',
      ),
    ),
  );
  $context->reactions = array(
    'menu' => 'admin/help',
  );  
  $context->condition_mode = 0;
 
  // Translatables
  // Included for use with string extractors like potx.
  t('testing context');
 
  $export[$context->name] = $context;
  return $export;
}

Perhaps the reason I couldn't find easy documentation for this is that it's really the ctools api doing the work - I think I'll submit an issue for the context module though to suggest at least a hint is added to the README to point developers in the right direction.
[edit]I posted a documentation issue on drupal.org[/edit]

One of the posts I did find which helped was Stella Power's interesting write up on how to use ctools to create exportables in your own module.

Comments

Thank you thank you thank

Thank you thank you thank you. This is just what I needed.

Nice !!

Really useful information ! thanks a lot to share it. I was searching how to dynamically create contexts and the answer was here. I miss the hook_ctools_plugin_api declaration. Now it works like a charm.

The only thing I need is to navigate on the admin/build/context page to load all dynamic context in the system.

Thierry aka titouille