Syndicate

Feed

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;
}
Last edited by Caroline Schnapp about 9 years ago.

Comments

Very Useful.

I'll surely use it, thanks for such a handy tip.

node_access()

Great tip. I use a similar method on nearly every site I build. The biggest difference though is that I use node_access intead of user_access.

instead of user_access('administer nodes') you could also use node_access('update', $node) and node_access('delete', $node). This will allow anyone with access to update or delete the node, to be able to see these links. It will also take into account the node access tables, in the case that you are using some sort of access control module.

Why didn't I think of that...?

Actually I prefer your solution, totally. :-)

I am gonna write something up, in the post, and give you credit. I am not even sure there are more database queries with your solution (maybe one more for querying the {node_access} table... again) but with any involved web site that has more than one contributor (so NOT for a web site like mine), it is more suitable. Anything to make contributing and editing content easier... I am all for that.

I have edited the article

I have added to it. Thank you again, Roger.

... and edited it again

To add a missing parenthesis in the code snippet. (OH... MY... GOD...)

I also added some info on node_access().

So the new section I added is here.

I am playing with Wordpress

I installed Wordpress tonight, Version 2.5.1.

I wanted to look at how Wordpress deals with taxonomy out of the box in its latest version.

There are 2 'vocabularies' in Wordpress : free tagging, and what they call 'categories', and categories can be organized into a tree, that is, a category can have one category as parent. And a category can have many sub-categories.

I looked at a few WP themes, and I thought: That's where it comes from! The 'Tags: x, y, z | Filed under: x, y, z' I see in so many blogs! It's Wordpress wording.

In a Wordpress post, unlike in Drupal, terms are not lumped together. Each vocabulary has its own function, ie: the_tags(), and the_category(). And that will my next instalment: how to put some order in terms displayed in Drupal teasers.

I downloaded this one Wordpress theme, and here is what I found: a quick edit link for the post!

A blog entry in Wordpress

The code for the post info line in the template file is:

<div class="postinfo">
  Tags: <?php the_tags(''); ?>  | 
  Filed Under <?php the_category(', '); ?>
  <?php edit_post_link('(Edit)', '', ''); ?>
</div>

In Wordpress, if the user is logged in and has permission to edit the post, the function edit_post_link() displays a link to edit the current post. Example: edit_post_link('edit', '<p>', '</p>');

one more thing...

I would also add one more thing to your code. If you put 'query' => drupal_get_destination() to each of your link definitions, after the node has been edited or deleted, the user will be redirected back to the page where they originally clicked the link.

Also, here is how you could do this in a module without having to fuss with the theme.

<?php
function mymodule_link($type, $node = NULL, $teaser = FALSE) {
 
$links = array();
  if (
$type == 'node' && $teaser) {
    if (
node_access('update', $node)) {
     
$links['node_edit'] = array(
       
'title' => t('edit'),
       
'href' => "node/$node->nid/edit",
       
'query' => drupal_get_destination(),
      );
    }
    if (
node_access('delete', $node)) {
     
$links['node_delete'] = array(
       
'title' => t('delete'),
       
'href' => "node/$node->nid/delete",
       
'query' => drupal_get_destination(),
      );
    }
  } 
  return
$links;
}
?>

p.s. It looks like your php/code filter is malfunctioning. Anytime i put a code or php tag anywhere in the post, the entire comment comes up blank.

drupal_get_destination()

Nice addition...

Full-blown like this, what started out as the need to add one quick edit link for Administrators looks like something that could be put in a module.

Because at first, here is what I had in mind. This is what I am using in my node.tpl.php template:

<?php if ($teaser && ($user == 1)): ?>
  <div class="links"><?php print l('(Edit)', 'node/' . $nid . '/edit'); ?> | <?php print l('(Delete)', 'node/' . $nid . '/delete'); ?></div>
<?php endif; ?>

Which is printing something like this:

It looks like your php/code filter is malfunctioning. Anytime i put a code or php tag anywhere in the post, the entire comment comes up blank.

Tell me about it! :-( I can't figure out what's going on here. I did not touch that input format (filtered HTML) and the module I am using is the same. It's the one used on Drupal, e.g. Codefilter.

I fixed the input format conflict

It looks like your php/code filter is malfunctioning. Anytime i put a code or php tag anywhere in the post, the entire comment comes up blank.

Fixed.

New module Admin Links

Put up a quick little module so I didn't have to do any theme hacking: http://drupal.org/project/admin_links

Thank you, Dave

:-) Awesome.

add link on the fly

I need an executable code snippet that can add on the fly a new internal link to an existing node's link area. I need to execute the code through the Rules module triggered actions. Any clue is highly appreciated. thnx:dariush

What a script.

I was able to learn much from this.

What a website you have

I was about to click 'spam' but wanted to reply to you.

The title tag of your pathetic (and broken) website's home page contains all of this:

##### ##### – Seo Master,Seo Expert. Search Engine Optimization Gossips. - Total Talking about Search Engine Optimization and WebMaster Resourses.:

Your one testimonial is funny:

##### ##### is really Expert. It was hard for me to believe unless i saw the results. He asked $1000 and he worked for 3 months for my site to bring #1 position in google. I don\'t have enough budget so i could only pay $500. I will pay the amount after i get my salary. Also, will be taking his service in future. great communication and very honest person. Most recommended!! - Vincent Hung (Singapore)

Your pathetic website:

Broken SEO website

how to add icon on each links?

this is very nice article... and it would be a lot cooler if you(could) show how to add some icon on each links... :)

thanks,

vsotto

I have done this already

and it would be a lot cooler if you(could) show how to add some icon on each links...

I am doing so right here.

This site rocks, as a person

This site rocks, as a person who's still learning php and gets headaches when reading through the drupal API, let alone applying it, i find it refreshing to see illustrations and simple, yet easy to understand explanations. Kudos and thanks!

Thank you for providing the

Thank you for providing the step by step detail for this process. You did a fantastic job of explaining the details.

Great tutorial

Thanks for this great tutorial. Until now I just created a new array for additional links in phptemplate_preprocess_node that I then displayed in the template but modifying $links is what I really wanted (but never knew how to).

Another Option based on user roles

I have been using this for customphp fields in views or for directly in tpl files. It is based on user role instead of being able to administer nodes. The reason being when you enable the administer nodes permissions and a user edits or creates a nodes, they are given additional options (like revisions, publishing, etc), which you might not want them to have control over.

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