Quick edit and delete links for the Administrator

You want to add quick edit links to the teaser view of your nodes — one link to edit the node, and another to delete it, and you want these links to be shown only to users with the 'administer nodes' permission. Alternatively, you may want these links to be viewed only by the user with uid (user ID) 1.

First Solution

  1. Edit node.tpl.php to add an unordered list of 2 links, contained within a div with a class name (e.g. 'quick-edit-links') and...

  2. style these links in your theme's style.css file.

Say you would like anyone who's logged-in and who has 'administer nodes' permission to see these two additional links below the teaser of every node: Edit [content-type-name] and Delete [content-type-name], like so:

Quick edit links by themselves

Let's get to it.

In your theme folder, your file node.tpl.php may look like this before the edit (I am only providing a snippet of the template here):

<?php if ($links): ?>
  <div class="links"><?php print $links; ?></div>
<?php endif; ?>

Below the above code, you will add your new 'quick edit' links like so:

<?php if ($teaser && user_access('administer nodes')): ?>
  <?php $content_type_name = node_get_types('name', $node); ?>
  <?php $quick_links['quick-edit'] = array('title' => 'Edit ' . $content_type_name, 'href' => 'node/' . $nid . '/edit'); ?>
  <?php $quick_links['quick-delete'] = array('title' => 'Delete ' . $content_type_name, 'href' => 'node/' . $nid . '/delete'); ?>
  <div class="links quick-edit-links">
    <?php print theme('links', $quick_links, array('class' => 'links inline')); ?>
  </div>
<?php endif; ?>

In the above snippet, you build a new array of links, $quick_links, and you theme that array with the function theme('links', ...).

You may prefer to write the markup yourself, using the Drupal function l(), like so:

<?php if ($teaser && user_access('administer nodes')): ?>
<?php $content_type_name = node_get_types('name', $node); ?>
  <div class="links quick-edit-links">
    <ul class="links inline">
      <li class="first quick-edit"><?php print l('Edit ' . $content_type_name, 'node/' . $nid . '/edit'); ?></li>
      <li class="last quick-delete"><?php print l('Delete ' . $content_type_name, 'node/' . $nid . '/delete'); ?></li>
    </ul>
  </div>
<?php endif; ?>

Second Solution

In template.php, using a preprocess function, add 2 new links to $node->links and re-theme (like a re-rince) $node->links to overwrite the existing $links variable. And... style as needed.

Let me show you what I mean. You may want to add the quick edit links next to the other node links, like so:

Quick edit links with other links.

To achieve this, in your theme's template.php file, you will add a prepocess function for your node template. Open your theme template.php file in a text editor, and add the following code:

<?php
/**
* Override or insert PHPTemplate variables into the node template.
*/
function phptemplate_preprocess_node(&$vars) {
 
// If we are in teaser view and have administer nodes permission
 
if ($vars['teaser'] && user_access('administer nodes')) {
   
// get the human-readable name for the content type of the node
   
$content_type_name = node_get_types('name', $vars['node']);
   
// making a back-up of the old node links...
   
$links = $vars['node']->links;
   
// and adding the quick edit link
   
$links['quick-edit'] = array(
     
'title' => 'Edit ' . $content_type_name,
     
'href' => 'node/' . $vars['nid'] . '/edit',
    );
   
// and then adding the quick delete link
   
$links['quick-delete'] = array(
     
'title' => 'Delete ' . $content_type_name,
     
'href' => 'node/' . $vars['nid'] . '/delete',
    );
   
// overwriting the $links variable with our new links THEMED
   
$vars['links'] = theme('links', $links, array('class' => 'links inline'));
  }
}
?>

Here's what you've done:

Modifying the $links variable.

The first solution will work in Drupal 5 as well. Both solutions work only for PHPTemplate-powered themes. With the first solution, it's easy to place the additional links anywhere in the node view.

If you want your quick edit links to be viewed only by the all-mighty Administrator, in your file node.tpl.php, you will replace this code...

&& user_access('administer nodes')

... with that one:

&& ($user->uid == 1)

The variable $user is part of what's called in themespeak the default baseline variables. The baseline variables are available to all template files, as they are generated by the preprocess function template_preprocess(). No need to refer to the oft-used global $user in your template file (although that will work fine as well). Just use the baseline variable $user (it's less code). However, in the preprocess function defined above, to make use of the baseline variable $user, you'll need to write $var['user'].

&& ($var['user']->uid == 1)

You can find more information on preprocess functions (new to Drupal 6) in this other article. Preprocess functions are used to pass additional variables to template files, or to modify the variables already passed to them. In our second solution, we modified the variable $links, which is a themed representation of the node links.


A little variation

Showing these links to people with 'administer nodes' permission is quite restrictive: chances are only a handful of people — maybe one person — have access to the Administration section for content.

You may have a web site with many contributors. Some will have 'edit' permission to some or all of the site content, with or without a right to 'delete'. When the situation is relatively complex, and you do want quick edit links whenever possible, you can rely on the Drupal's function node_access($op, $node, $account = NULL) as Roger López points out in this comment. The preprocess function rewritten with the use of node_access() becomes:

<?php
/**
* Override or insert PHPTemplate variables into the node template.
*/
function phptemplate_preprocess_node(&$vars) {
 
// If we're in teaser view and have right to update(edit) the node
 
if ($vars['teaser'] && node_access('update', $vars['node'])) {
   
// get the human-readable name for the content type of the node
   
$content_type_name = node_get_types('name', $vars['node']);
   
// making a back-up of the old node links...
   
$links = $vars['node']->links;
   
// and adding the quick edit link
   
$links['quick-edit'] = array(
     
'title' => 'Edit ' . $content_type_name,
     
'href' => 'node/' . $vars['nid'] . '/edit',
    );
   
// and then adding the quick delete link
    // if we have the right to delete the node
   
if (node_access('delete', $vars['node'])) {
     
$links['quick-delete'] = array(
       
'title' => 'Delete ' . $content_type_name,
       
'href' => 'node/' . $vars['nid'] . '/delete',
      );
    }
   
// overwriting the $links variable with our new links THEMED
   
$vars['links'] = theme('links', $links, array('class' => 'links inline'));
  }
}
?>

The function node_access($op, $node, $account = NULL) determines whether the current user (OR the user with the specified $account) has the right to perform a given operation on a specified node. If he has the right to perform the operation, the function returns TRUE, if not it returns FALSE. The operations, given by the flag $op, are 'view', 'update' (to edit the node), and 'delete'.

Take note of this: if the node was last saved with an input format not permitted to the user (e.g. say it has been edited by the Administrator who saved it in the 'PHP code' input format), the user won't be able to edit his node anymore — for obvious security reasons. In the node_access() function, you'll find this:

// If the node is in a restricted format, disallow editing.
if ($op == 'update' && !filter_access($node->format)) {
  return FALSE;
}