Hacking contextual links in Drupal 7

This blog post is more than 9 years old, so the content may be out of date.

Drupal 7 comes with some cool new tools like contextual links

Contextual links are added to blocks using hook_block_view or hook_block_view_alter:

$block = array(
  'subject' => t('Blog Archive'),
  'content' => array(
    'show_all_link' => l(t('All blog posts'), 'blog'),
    'archive' => $archive,
    '#theme' => 'wordpress_blog_archive',
    '#cache' => DRUPAL_CACHE_PER_PAGE,
    '#contextual_links' => array(
      'wordpress_blog' => array('node/add', array()),

The #contextual_links property is an array where each key is the name of the module which is implementing the contextual links:

    '#contextual_links' => array(
      'wordpress_blog' => ... // Links from the wordpress_blog module
      'node' => ...           // Links from the node module
      'menu' => ...           // Links from the menu module

Each module provides an array of 2 values which combine to form a path. For example:

  • node/23
    '#contextual_links' => array(
      'xxx' => array('node', array(23)),
  • admin/content
    '#contextual_links' => array(
      'xxx' => array('admin/content', array()),
  • Paths which are implemented in hook_menu using %param - e.g. node/%node - should pass 'node' as the first array value, and the specific node id in the second.

The context-links are found by searching the menu system for those links which are child links of the path supplied, and are configured to be context items.

As an example /node/%node has the following children:

  • node/%node/view (default local task) with no 'context' defined
  • node/%node/edit with context: MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE
  • node/%node/revisions with context: MENU_CONTEXT_PAGE
  • node/%node/report-as-spam with context: MENU_CONTEXT_INLINE

If node/23 is provided, the links for 'edit' and 'report-as-spam' will be returned.

Adding links which aren't child menu items

The Wordpress Blog module is a prime example: it provides a 'Blog Archive' block, and adding a contextual link to 'Create Wordpress Blog Post' is a great usability enhancement.

The problem is that node/add/wordpress_blog is a normal menu item - it's not a child task of anything. So we need to hack the menu to make this available to contextual links:

function wordpress_blog_menu_alter(&$menu) {
  $menu['node/add/wordpress-blog']['_tab'] = TRUE;
  $menu['node/add/wordpress-blog']['tab_parent'] = 'node/add';
  $menu['node/add/wordpress-blog']['context'] = MENU_CONTEXT_INLINE;

Now when you pass the context of node/add in the contextual-links, node/add/wordpress-blog is found as an in-context child of node/add.

Caution! This may break the menu system :-)
I haven't had a chance to test the side-effects of this hack - if anyone can explain why this is bad, comments are welcome!


Hey, I just hopped over to your web-site via StumbleUpon. Not somthing I would generally read, but I liked your thoughts none the less. Thanks for creating some thing worth reading.

There's a module that helps with this

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <apache>, <bash>, <c>, <cpp>, <drupal5>, <drupal6>, <java>, <javascript>, <php>, <python>, <ruby>. The supported tag styles are: <foo>, [foo]. PHP source code can also be enclosed in <?php ... ?> or <% ... %>.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.