How to make Contextual Links work for you!

One central component in creating a website is the user interface. If you make an effort to create a user-friendly interface, both you and the customer will benefit - They will be happy with the usability and you will receive less support tickets. Back when I was actively developing for Drupal 6, I soon saw the need for a more fine-grained editing system than the tabs. The reason is simply that tabs only cover the page node and nothing else. This means that any other nodes that are represented will be untouchable on that page. When I work on user interfaces I always aim for as few clicks as possible for every task. Unaware of the Contextual Links (1.x) module, I created a similar module of my own to achieve fewer clicks to edit any area on the page, which made tabs obsolete while in "view" mode. Great success.

Now in Drupal 7, Contextual Links is part of core and it works really, really well everywhere that the links actually appear. But of course they don't appear everywhere I would want them to out of the box, that would have been too easy ;) So, here's what I did in order to remedy the situation.

1. Every menu block should have a contextual link for editing the actual menu, not just the block. I exclusively use Superfish for menus so what I want is for every Superfish block to have such a contextual link. Here's the code, grabbed from http://bleen.net/blog/easier-way-add-contextual-links-drupal-7 and modified:

//Implements hook_contextual_links_view_alter()
function MYMODULE_contextual_links_view_alter(&$element, &$items) {
  if(isset($element['#element']['#block'])) {
    if($element['#element']['#block']->module=='superfish') {
      $menu_name = variable_get('superfish_menu_'.$element['#element']['#block']->delta, '');
      if($menu_name) {
        $menu_name = explode(':', $menu_name);
        $menu_name = $menu_name[0];
        if(user_access('administer menu')) {
          $element['#links']['menu'] = array(
            'title' => t('Edit menu'),
            'href' => url("admin/structure/menu/manage/$menu_name", array('absolute' => TRUE, 'query' => array('destination' => current_path()))),
          );
        }
      }
    }
  }
}

Now perhaps you're thinking, can't you just use Custom Contextual Links for that? Well, you can for unique blocks but you can't create this kind of automatic "edit menu" link for all superfish blocks. I like to automate as much as possible, that way you don't need to remember all the little things when you're building a site for a customer.

2. I want contextual links to appear on my panel node, not just inside each pane but also for the main node! I found a solution for this problem at http://drupal.org/node/951088 :

//Implements theme_node_view_alter()
function MYTHEME_node_view_alter(&$build) {
  $node = $build['#node'];
  if (!empty($node->nid)) {
    $build['#contextual_links']['node'] = array('node', array($node->nid));
  }
}

3. Finally, I want to add more links, such as "translate", to all nodes so that I can make tabs obsolete for "view" mode, just as I did back in Drupal 6. This is where Custom Contextual Links really shines. I simply added a link through the interface with the url "node/[node:nid]/translate", selected the link type "Node" and then "All nodes". Voilà! Problem solved.

These three ways of customizing Contextual Links are a good way of starting out and should cover most situations.