Hacking contextual links in Drupal 7
This blog post is more than 2 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!


Comments
Alex Ollivier (not verified)
July 19, 2011 - 5:17pm
Permalink
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.
cruzeazy (not verified)
November 6, 2011 - 7:08am
Permalink
There's a module that helps with this
http://drupal.org/project/ccl
Add new comment