Passing variables between different Drupal hooks using context API

Drupal’s nature of using hooks to allow functionality to be overridden by contributed modules makes it difficult to make data available between different hook implementations during the request process, especially if they are overridden. Simply put, we need to have certain values available system-wide once they are set.

For instance, Views block display defines an RSS link, but once the page template in the theme is reached that information is long gone. If we needed to have the RSS be the current page’s feed link, then we would require a complex (and sometimes risky) implementation.

Drupal’s nature of using hooks to allow functionality to be overridden by contributed modules makes it difficult to make data available between different hook implementations during the request process, especially if they are overridden. Simply put, we need to have certain values available system-wide once they are set.

For instance, Views block display defines an RSS link, but once the page template in the theme is reached that information is long gone. If we needed to have the RSS be the current page’s feed link, then we would require a complex (and sometimes risky) implementation. But the Context API offers a set of functions that makes life really easy in these situations: context_set, context_isset, and context_get.

First, figure out what information you need, from where, and very importantly, through what hook, if any, can you reach that variable. For example in a View, an attached feed url+icon can be obtained by using hook_views_pre_render.

It is important to determine if the value is already available or not. Then determine where the information is available, and if there is a hook to access that variable. In my case, I needed that information in the page template, or for that matter, the hook_page_preprocess function, because by the time the process reaches this stage the view will be long gone.

In your theme template.php file, your custom module, or feature, define a hook function at the moment your variable is available. For instance:

<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #007700">function </span><span style="color: #0000BB">mytheme_views_pre_render</span><span style="color: #007700">(&</span><span style="color: #0000BB">$vars</span><span style="color: #007700">) {<br>  switch (</span><span style="color: #0000BB">$vars</span><span style="color: #007700">-></span><span style="color: #0000BB">name</span><span style="color: #007700">){<br>    case </span><span style="color: #DD0000">'my_view'</span><span style="color: #007700">:<br>      if (isset(</span><span style="color: #0000BB">$vars</span><span style="color: #007700">-></span><span style="color: #0000BB">feed_icon</span><span style="color: #007700">) && !empty(</span><span style="color: #0000BB">$vars</span><span style="color: #007700">-></span><span style="color: #0000BB">feed_icon</span><span style="color: #007700">)){<br>      </span><span style="color: #0000BB">context_set</span><span style="color: #007700">(</span><span style="color: #DD0000">'mytheme_page_feed'</span><span style="color: #007700">, </span><span style="color: #DD0000">'page_feed_icon'</span><span style="color: #007700">, </span><span style="color: #0000BB">$vars</span><span style="color: #007700">-></span><span style="color: #0000BB">feed_icon</span><span style="color: #007700">);<br>    }<br>    break;<br>  }<br>}<br></span><span style="color: #0000BB">?></span></span>

The variable must be now set in the context you want, so we can to use it as needed. For instance, create a hook (if it doesn’t exist) or just add the extra code to an existing one. For example:

<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #007700">function </span><span style="color: #0000BB">mytheme_preprocess_page</span><span style="color: #007700">(&</span><span style="color: #0000BB">$variables</span><span style="color: #007700">) {<br>  if (</span><span style="color: #0000BB">context_isset</span><span style="color: #007700">(</span><span style="color: #DD0000">'mytheme_page_feed'</span><span style="color: #007700">, </span><span style="color: #DD0000">'page_feed_icon'</span><span style="color: #007700">)){<br>    </span><span style="color: #0000BB">$variables</span><span style="color: #007700">[</span><span style="color: #DD0000">'page_feed_icon'</span><span style="color: #007700">] = </span><span style="color: #0000BB">context_get</span><span style="color: #007700">(</span><span style="color: #DD0000">'mytheme_page_feed'</span><span style="color: #007700">, </span><span style="color: #DD0000">'page_feed_icon'</span><span style="color: #007700">));<br>  }<br>::<br>::<br>}<br></span><span style="color: #0000BB">?></span></span>

Now you can use the variable $page_feed_icon in your template page.
Notice the use of the hooks, and make sure they are used in the proper sequence. Also, the use of the functions: context_set, context_isset, and context_get, which:

See API.txt in the context module
Context provides a centralized set of API functions for setting and retrieving a static cache:
// Set a static cache value at [my_namspace|my_namspace][mykey]<br>context_set('my_namespace', 'mykey', $value);<br><br>// Retrieve a static cache value at [my_namespace|my_namespace][mykey]<br>context_get('my_namespace', 'mykey'); // $value<br><br>// Boolean for whether there is a value at [my_namespace|my_namespace][mykey]<br>context_isset('my_namespace', 'mykey'); // TRUE<br>
These are used internally by context, but may also be used by other modules. Don’t use the namespace `context` unless you want to affect things that context is up to.

An obvious but never overrated advantage is that you will have code that is more clean, less prone to errors, and less repetitive.

Felix Silberstein