Hacking contextual links in Drupal 7

This blog post is more than 6 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

Pretty nice post. I just stumbled upon your blog and wished to say that
I have really enjoyed browsing your blog posts.
After all I'll be subscribing to your rss feed and I hope you write again very soon!

Hi! Do you know if they make any plugins to protect against hackers?
I'm kinda paranoid about losing everything I've worked hard on. Any recommendations?

Howdy just wanted to give you a quick heads up. The words in your article seem to be running off the screen in Ie.

I'm not sure if this is a format issue or something to do with
web browser compatibility but I figured I'd post to let you know.

The style and design look great though! Hope you get the problem solved
soon. Many thanks

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.