Submitted by Nik on
This snippet of code gives a brief example of how to rewrite components of the $links variable to make them prettier :) Specifically, here I’m overwriting the link generated by the Forward module. You can see the result below: the little envelope icon labelled “Email”. Normally, this would just say “Forward this page”, which is a bit… well, it could be better. Obviously, it’s nice to be able to change these things to taste.
There are two ways to achieve this result: using theme code in template.php, or inside of a helper module. First, I’ll discuss the module approach.
The helper module method is what I had originally used. It’s a little neater, in that you code it once and forget about it, and it doesn’t clutter up template.php’s _phptemplate_variables function, which can easily become bloated with code.
In the module, I’ve added a function to implement Drupal’s hook_link_alter() function. Here’s the code to do it:
<?php
function mymodule_link_alter(&$node, &$links) {
foreach ($links as $module => $link) { // iterate over the $links array
//drupal_set_message(print_r($links)); // uncomment to display your $links array
// check if this element is the forward module's link
if ($module == 'forward_links') {
$title = t('Email this page to a friend'); // change the title to suit
$path = path_to_theme() . '/images/email.png'; // make an image path
// now update the links array
// set the title to some html of the image and choice of link text
$links[$module]['title'] = theme('image', $path, $title, $title) . ' Email';
// let's set some attributes on the link
$links[$module]['attributes'] = array(
'title' => $title,
'class' => 'forward-page',
'rel' => 'nofollow',
);
// this must be set, so that l() interprets the image tag correctly
$links[$module]['html'] = TRUE;
}
}
}
?>
Ok so really, this ought to be done in the theme layer. Like I said, it’s perhaps not as compact and neat, but here’s the code. It’s mostly the same, but note a couple of additions and changes: firstly, we are not changing $links
– this is a pre-rendered string by the time it gets to the template.php. We need to get to the original goodies! Hence, we use $vars['node']->links[module-name][field-name]
.
Secondly, note that because we have now altered the value of one of the original links’ values, does not mean that the node’s $links
is correct. This is the bit that caught me out! We must now regenerate the $links
variable using the theme_links()
function, as per the last line of code below. This mimics what phptemplate.engine does in core.
<?php
function _phptemplate_variables($hook, $vars = array()) {
switch ($hook) {
case 'node':
foreach ($vars['node']->links as $module => $link) {
if ($module == 'forward_links') {
$title = t('Email this page to a friend');
$path = path_to_theme() . '/images/email.png';
$vars['node']->links[$module]['title'] =
theme('image', $path, $title, $title) . ' Email';
$vars['node']->links[$module]['attributes'] =
array('title' => $title, 'class' => 'forward-page', 'rel' => 'nofollow');
$vars['node']->links[$module]['html'] = TRUE;
}
}
$vars['links'] = theme('links', $vars['node']->links,
array('class' => 'links inline'));
break;
}
}
?>
You can achieve this effect for anything that’s in the $links
array. On this page (below), you can see the link I’ve described here, another for print-friendly pages and also a themed comment link.
Comments
Drupal Theme Garden replied on Permalink
Nice piece of code.
And, yes, you're right, template.php is better place.
Nik replied on Permalink
I’ve updated the article to include theming the links in the theme layer (natch). There was a little trick I missed which is why I hadn’t got it working until now.
lgm replied on Permalink
Great idea!
Another example is adding the following in node.tpl.php
This example replaces the words “Printer-friendly version” with “printer.png”
Nik replied on Permalink
Well… you could do that, but there’s a number of reasons why not to. Firstly, by using a snippet like the one above in the template.php, you are providing a solution to all your node types. Secondly, in the example above, you’re not using standard Drupal functions such as l() and t(), which you really ought to for reasons of coding standards, availability for translation and server security.
Just so you know…
Joao replied on Permalink
As the print module maintainer, I would like to point out that there's better solutions in the case of the print module than either of the above. You can theme the $links link of the print module to your heart's content using the theme_print_format_link() function.
See more about that in #4 of http://drupal.org/node/190173.
Nik replied on Permalink
Thanks for the tip, Joao – the technique I used above is really only meant as an indicator of a generic solution. A lot of modules, including forward (aobve) and taxonomy (core), do not have such theme functions. As such, this technique is probably the next most favourable.
Good news that the print module is becoming more configurable and accessible though!
krunar replied on Permalink
hi,
is it possible to do this without making a module? somewhere in phptemplate for example.
Nik replied on Permalink
It certainly is – I haven’t had enough free time to juggle the example above into theme-based code (that works for me…!) yet though.
The
$links
variable is available from within _phptemplate_variables, so you can alter this in template.php in thecase: 'node'
bit of that. If you read this article that last bit will be clearer, if you don’t already know what I mean.So, the code below should work in a similar fashion, although I’ve had mixed luck – it had otherwise been my intention to publish the full code for that method also.
feelexit replied on Permalink
hi, I want to theme $links in comments
in _phptemplate_variables function, I add following code
case 'comment':
print_r($vars['comment']->links);
break;
nothing shows up, probably theres no such variable called $vars['comment']->links.
can you please show me how theme it in comment. I got stuck here for 2 days.
thank you so much for ur help.
vsotto replied on Permalink
does this work in drupal 6?
Nik replied on Permalink
I don’t think there’s any issue with using this for D6, but you might want to check the function parameters on whichever one you use, to make sure they’re the same.
Anonymous replied on Permalink
For D6 you should probably use YOURTHEME_preprocess_node instead of _phptemplate_variables though.
Anonymous replied on Permalink
Thanks for this article, it worked for me
Mould Maker replied on Permalink
It is easy to do it for my website, but I found that if I use _preprocess_node(&$vars, $hook) then I can not get the node ID in the function.
Add new comment