Blog

Previous/Next Node in Drupal 7

Sometimes it is usefull ot provide previous/next links from the node you are reading. Customers love it, people love it and it is more compact than a "Latest News" list from views.

There is somecode laying around the net for doing this sort of thing but most of it is for Drupal 6 or isn't very well written.

I adapted some of the snippets I found on the net to create the following:

  1. function THEME_prevnext($nid, $ntype) {
  2. $prev = db_query("SELECT nid, title FROM {node} WHERE nid < :nid AND type = :ntype AND status = 1 ORDER BY nid DESC LIMIT 1", array(':nid' => $nid, ':ntype' => $ntype));
  3. $next = db_query("SELECT nid, title FROM {node} WHERE nid > :nid AND type = :ntype AND status = 1 ORDER BY nid ASC LIMIT 1", array(':nid' => $nid, ':ntype' => $ntype));
  4.  
  5. $prev_link = FALSE;
  6. $next_link = FALSE;
  7.  
  8. foreach ($prev as $prev_node) {
  9. $prev_alias = drupal_lookup_path('alias', 'node' . $prev_node->nid);
  10. if($prev_alias) {
  11. $prev_link = "<a href='/" . $prev_alias . "' title='previous'>" .$prev_node->title. "</a>";
  12. }
  13. else {
  14. $prev_link = "<a href='/node/" . $prev_node->nid . "' title='previous'>" .$prev_node->title. "</a>";
  15. }
  16. }
  17.  
  18. foreach ($next as $next_node) {
  19. $next_alias = drupal_lookup_path('alias', 'node/' . $next_node->nid);
  20. if($next_alias) {
  21. $next_link = '<a href="/' . $next_alias . '" title="next">' .$next_node->title. '</a>';
  22. }
  23. else {
  24. $next_link = "<a href='/node/" . $next_node->nid . "' title='next'>" . $next_node->title . "</a>";
  25. }
  26. }
  27.  
  28. $output = '<ul id="prevnext_nodes">';
  29. if($prev_link) $output .= '<li>' . t('Previous article: ') . $prev_link .'</li>';
  30. if($next_link) $output .= '<li>' . t('Next article: ') . $next_link .'</li>';
  31. $output .= '</ul>';
  32.  
  33. return $output;
  34. }

The above code is placed inside the template.php file and it does several checks in order to work on sites that have or don't have aliases for their nodes.
It also works correctly when the user is in the first or last node of the site, something that could happen easily especially in small blogs.

It accepts two arguments, the node-id and the node-type. So the links it generates are for the specific node-type the user is currently viewing. This of course can be easily adapted to anything you want.

I print the links by using this command in node.tpl.php
echo(dialogoi_fusion_prevnext($node->nid, $node->type));
Print render also works, but I'm not really sure whether it is the correct way of doing this:
print render(dialogoi_fusion_prevnext($node->nid, $node->type));

Evolution of my pointing devices!

Over the years many mice have been in my hands. Computer mice that is! I've paid for only four (4) of them, all the rest were accompanying the varius computers I've bought in my life and I they are now in the hands of my friends. The latest one arrived this morning to me and it is an Evoluent VM4R. It is hands down the most amazing in design. It looks more futuristic than my previous mouse, the Sidewinder X5, which is one hell of a mouse!

Every mouse I buy is chosen according to it's size, except my first one where I was younger and my palm was much smaller than now, and it's design. It has to be a nice mouse, after all it sits on my desk all the time! Plus I really love the effect it has on people when they see it. The Sidewinder X5 was a winner in this area but I believe that the Evoluent will astonish people even more. After all it looks like it came from Star Wars!

The photos show my mice in chronological order. I've been happy with all of them and I wouldn't change my X5 with the Evoluent if it was a bit more comfortable (=larger for my palm to rest). I must admit, the Evoluent seems to be the next-generation of mice. It is designed to allow all five of your fingers to work and at the same time it is bulky enough to allow them to rest.

It takes sometime to get used to it though but this is only logical. I've been using normal mice since the age of... I can't remember, more than 20 years (and I'm not yet 30). My brain expects the mouse to have a certain shape, it will take a few days before the Evoluent starts to feel natural. I'll post more soon...

ps: I'd love it if the Evoluent logo was glowing red!

Date fields in Views with custom output for advanced theming

Let's say you want to spice up the display of dates in your Drupal Views. All blogs are displaying date-elements in it's own line and apply a different styling to it. Wordpress blogs do it after all, so why can't we?

 

There are numerous post that explain how to do this in the node display form by customizing your template.php. Trust me it is not as difficult as it sounds and you should try it. I avoided it for months but in the end it was nothing more than a few lines of easy code!

This post however will deal with Views! You know about Views right? Well views are powerfull, very powerfull. They just ask from you to spend some time with them. Views can display all information available from Drupal in fields. All these fields are customizable in many ways. Date fields are no difference. By default when you add a new date-field in your view (eg node: post-date) it will ask you how you wan't this information displayed. By choosing "Custom" in date format views allows you to enter the pattern this field will be displayed.

The configuration shown in the picture will display dates like that:

<blockquote>05/Sep 11:29</blockquote>

While this is pretty nice, because we ommited the year with only a few clicks, it is now easily themable. We want to theme time differently than day and month for our project. We need to apply a different class to it then. The easy way of doing this, without editing template.php is by passing all this information in the "custom date format" field, like that:

&lt;\d\iv \c\l\a\s\s=&quot;\d&quot;&gt;d/M&lt;/\d\iv&gt;&lt;\d\iv \c\l\a\s\s=&quot;\t&quot;&gt;H:i&lt;/\d\iv&gt;

What I've done above is that I'm displaying date and time in to different html div's and apply to different css classed (d and t, for date and time accordingly). All the backslashes ("\") are escape characters, they are placed in front of characters that we do not want views/php to interpret them as characters that will define the date-output of php (more on this here http://us.php.net/manual/en/function.date.php).

So we escape every "d" in the the word "div" because "d" also stand for "Day of the month, 2 digits with leading zeros". That's all!
The above code will output this:

<blockquote> 28/Oct
09:19</blockquote>

and the html code behind it will be:

<br />&lt;div class=&quot;d&quot;&gt;29/Dev&lt;/div&gt;&lt;div class=&quot;t&quot;&gt;20:12&lt;/div&gt;<br />&lt;div class=&quot;d&quot;&gt;29/Dec&lt;/div&gt;&lt;div class=&quot;t&quot;&gt;20:12&lt;/div&gt;

Language negotiation is one of the problems one has to solve when building a multilingual website. I've tried various methods and, although I don't usually prefer it on simple sites, the best one seems to be "domain name" negotiation.

This way every language has its own domain, whatever you choose it to be. Since I build sites in Greek and English I go with http://example.gr and http://en.example.gr for each language accordingly.

There is one problem by using this method and one drawback. The drawback is that since you use different domains you need to re-login in the site if you change language, not good but I can live with it.

The problem is that when you move data between the dev <> stage <> live environments you end having your site pointing to the wrong domain (eg stage points to en.dev.example.com).

There is a discussion about it going on here and a module that promises to solve this, but only for Drupal 7, right here.
After reading the discussion on d.o. I decided that I should somehow automate the solution people provided.

So I wrote a bash script that, after moving your database between enviroments, makes the changes needed for your site to work.
It uses Drush and drush-aliases. Subdomains and alias names must be the same for the script to work, although you could easily change it to your liking.

  1. #!/bin/bash
  2. function fix-lang (){
  3. if [ $1 ]
  4. then
  5. if [ $1 = "live" ]
  6. then
  7. drush @$1 sqlq "UPDATE drp_languages SET domain = 'http://en.example.com' WHERE language = 'en'"
  8. drush @$1 sqlq "UPDATE drp_languages SET domain = 'http://el.example.com' WHERE language = 'el'"
  9. drush @$1 cc 'all'
  10. echo "ALL DONE"
  11. elif [ $1 != "live" ]
  12. then
  13. drush @$1 sqlq "UPDATE drp_languages SET domain = 'http://en.$1.example.com' WHERE language = 'en'"
  14. drush @$1 sqlq "UPDATE drp_languages SET domain = 'http://el.$1.example.com' WHERE language = 'el'"
  15. drush @$1 cc 'all'
  16. echo "ALL DONE"
  17. fi
  18. else
  19. echo "No site specified"
  20. fi
  21. }

As you can see the domain is hardcoded inside the script. Since I use a different unix account for each of my clients this is no problem, I change the script accordingly for every site.
Hope it helps you with multilingual sites and if you've come up with a different solution I'd love to see it!

You simple paste the above code in your .bashrc or .bash_profile, adapt it to your needs and run it like this.
fix-lang dev
or whatever you name your environment! If you run fix-lang live the script will understand that you don't deal with a subdomain but with the main domain.

Translating CCK Checkboxes and Radiobuttons

Translating Drupal is easier nowdays than it was two years ago. Gábor Hojtsy has helped a lot and LDO is a really cool platform for translating Drupal.

But what happens when you need to translate things on your site? Things not available through the "Translate Interface" of i8n?
One such thing is the Allowed values list in CCK Fields. The solution is really easy and is done by using a few easy lines of PHP code.

When I was building TicketWest.gr I wanted to have an option about parking in several venues of my town. I made a CCK field with options, Yes and No and decided to display them as radiobuttons.
Yes and No weren't translatable as I found out later.

After some googling I found the answer. I populated the Allowed Values List with PHP instead of the default text. The code I used was:

  1. return array(
  2. 'no' => t('No'),
  3. 'yes' => t('Yes')
  4. );

The left side is the key, the value that will be stored in the database. The right side is the label displayed in the user interface. As you can see the label is inside the t() function which makes it translatable.
Now by using "translate interface" you could easily change Yes and No to your language, in my case it was Ναι for Yes and Όχι for No!