Archive for the 'Drupal' Category

Flickr Galleries for Drupal

Install the Flickr module. That’s going to require a Flickr API key, so follow the instructions to set that up. You’ll need to enable the following modules: Flickr, Flickr Filter, Flickr Sets. Then enable the “Flickr linker” filter under Input Formats.

Keep in mind that only “public” photos work with this.

That’s going to let you put something like

[flickr-photoset:id=72157610617588420,size=s]

in the body of your document. When you save and view this document, you should see little thumbnails from your photoset. If you click on one, it’s going to take you to Flickr. We’ll be replacing that with Highslide.

Okay, so that’s nice but that [flickr-] stuff is a little hard to deal with. So what we’re going to do is install flickrset. This is a plug in I wrote for WYSIWYG and TinyMCE. You place it in

/sites/all/modules/wysiwyg/plugins

Then, in Drupal, go to /admin/settings/wysiwyg and edit any input formats that use TinyMCE. This is probably just “Full HTML.” Under the “Buttons and plugins” section you should see a new checkbox at the end labeled “Flickrset.” Turn that on and save it.

Now when you create a new document, you should see a new button in the body. The new button is the Flickr icon. When you click it, you get a pop up with three fields. You paste the URL of your Flickr photoset in there. You pick the size of the thumbnails you want. You pick the size of the “full size” pictures that you want. You click add. It’s going to build that [flickr-] crap for you.

You’ll see there’s a new thing in there, and that’s “class=showsizen.” This is the parameter for the “full size” picture. This isn’t going to work, out of the box. You’re going to need to hack the Flickr module. *gasp* So open

/sites/all/modules/flickr/flickr.module

and find the theme_flickr_photoset function. Change

$output .= theme('flickr_photo', $photo, $size);

to

$output .= theme('flickr_photo', $photo, $size, NULL, $attribs);

This is important because we’re passing the attributes to the theme function. The attributes contain, among other things, the class parameter we set earlier.

The module will let you pick a number of photos to appear in photosets. That’s nice if all your photosets are going to use the same number of photos, but if you want each gallery to display a different number of photos, you’ll need to add some functionality. Here’s how to do that.

In modules/flickr/filter/flickr_filter.module find flickr_filter_callback_photoset()

// change this line
return theme('flickr_filter_photoset', $photoset, $photoset['owner'], $config['size'], $attribs);
// to this
return theme('flickr_filter_photoset', $photoset, $photoset['owner'], $config, $attribs);

In modules/flickr/sets/flickr_set.module replace flickr_set_load() with

function flickr_set_load($sid, $num = 0, $page = 1) {
  // TODO: Not sure why this called for /flickr and does not show for admin role
 
  if ($num == 0) $num = variable_get('flickr_photos_per_page', 20);
 
  if (is_numeric($sid)) {	
    return flickr_request('flickr.photosets.getPhotos',
    array(
      'photoset_id' => $sid,
      'page' => $page,
      'per_page' => $num,
    )
    );
  }
}

In modules/flickr/flickr.module find theme_flickr_photoset()

// change the first two lines to this
function theme_flickr_photoset($ps, $owner, $config, $attribs = NULL) {
  $size = $config['size'];
// then change this line
$photos = flickr_set_load($ps['id']);
// to this
$photos = flickr_set_load($ps['id'], $config['num']);

Okay, so now if we look at our saved document, we see all the thumbnails there. Each image should have the “showsizen” class we specified. It may be “showsizeb” if you chose that size instead- n is normal, b is large. (These are abbreviations from the Flickr module, I didn’t make them up.) It’s still not going to expand to the correct size, we haven’t gotten that far. Just make sure your images have that class when they get displayed.

The last thing is this jQuery. This is going to hijack the resulting HTML so that Highslide can handle the full sized images.

$(document).ready(function() {
  $('.flickr-photoset a').each(function() {
      // we need a slightly different version of the static image url
      var thumb_url = $(this).children('img').attr('src');
 
      var showsize = "";
      if ($(this).children('img').hasClass('showsizeb')) {
        showsize = "_b";
      }
      if ($(this).children('img').hasClass('showsizen')) {
        showsize = "";
      }
 
      var dotpos = thumb_url.indexOf('.jpg');
      thumb_url = thumb_url.substr(0, dotpos - 2) + showsize + ".jpg";
 
      // now replace the a.href with this
      $(this).attr('href', thumb_url);
 
      // and fix it up for highslide
      $(this).addClass('highslide');
 
      this.onclick = function() {  return hs.expand(this); }
  });
});

Drupal Templates By Node ID

By default, Drupal will let you define a template called node-bork.tpl.php, which is a template for all nodes of type “bork.” That’s pretty handy, but what if you want a template for a specific node id? What I want to be able to do is define a template called node-4.tpl.php, which would be the template for the node with node id 4. Here’s how.

In your template.php file, add this:

function phptemplate_preprocess_node(&$vars) {
  $vars['template_files'][] = 'node-'. $vars['nid'];
}

Content Management Strategies for Drupal

Rather than copy/paste code, I’ll share some theories.

When I started working with Drupal, the way you created/edited content was awful. I could not understand how “users” were supposed to understand how to do it. It was so confusing. Eventually I figured out a better way to do it.

Out of the box, users are given a menu that says “Create Content.” From here, they can create content items. That’s cool. If you want to edit a page, you navigate to that page and click the “edit” tab. This works for very simple sites, but nothing is ever really that simple. What we were doing was giving users administrative privileges. (Bear with me.) Then we told them, to edit a page go to Administer, Content Management, Content. On that screen, click one of the many drop downs and pick the type of content you want to edit. Then wade through the filtered list to find the “page” you want to edit. At the time it was the only way we knew to edit content.

This was terribly confusing. Even for me as a developer it seemed like a hassle. Users could not understand it, could not follow a list of instructions like that when what they wanted to do was really pretty simple. And then I started getting questions from our users who were poking around in the administrative menu and finding things they should not be finding.

So what I started doing was setting up content management views, and a menu to keep them all organized. I set up a view for the “story” content type. I label it “View/Edit News Items” and put it in the “Manage Content” menu. The view has things like title, maybe a teaser or author, updated date, a view link and an edit link. Under the link for the view in the menu, I add a “Create News Item” link that allows them to create a story from right there. I’ll repeat this group for whatever content types I need to. Some websites have a “location” content type, so I’ll build a view for that, and give them a create link. Some websites have blog entries, job opportunities, quotes. You get the idea.

This makes more sense to users. When they log in they see, clearly, how to get to the content that they want to edit. It’s organized. It’s quick. You don’t even really have to “train” people who to edit content. It’s right there.

And to give you another example… Our website has a document listing all of our clients. How does anybody edit it? Well, if you didn’t know that the list of clients was stored in a document, you wouldn’t even know what to do. But if you did, then you’d have to have administrative privileges, and you’d go to Administer, Content Management, Content, switch the content type to “Client Listing,” and edit the resulting document. With the new system, you log in, you don’t need admin privileges, you see a link in the “Manage Content” menu that clearly says “View/Edit Client Listing.” You click that and edit the document. You’re done. You’re happy.

image_import_zip For Drupal 6

I’m working on a project where we have a ton of images that we’ll need to import into image galleries in Drupal 6. There are a bunch of nice modules to do this, but they expect the end user to have the correct JRE installed, or fail to function with .htaccess authentication. We needed something simpler.

There’s a module called “image_import_zip” which allows you to upload a zip file full of images without using FTP. It extracts them, and then you can use “image_import” to turn them all into image nodes. Which sounds nice, except that “image_import_zip” is only for Drupal 5, and the people responsible tell you to go use something Flashy for Drupal 6.

So I went ahead and hacked the module to work with Drupal 6. Enjoy.

Drupal Get Image Path

I’m still learning how Drupal (6) puts things together. We have a situation where we have a page that has an image attached to it. When we view the page, we need the full path to the image that’s attached. You would think it would be pretty simple. You would expect that somewhere in the $node object is a url for the image that is attached. But that’s just not the case.

Drupal calls the page a node. It also calls the image a node. You have a table that says “this node is attached to that node” by ids. Specificially, image_attach.nid is your page, and image_attach.iid is the node id of the image. Then you have an image table, which lists the images by node id, with a size, and a file id. (Confused yet?) We use image_attach.iid and the size we’re looking for to get image.fid. And then there’s one last table, which is files, which lists by id, and has the actual filepath. We can use image.fid to get the files.filepath we want.

So I wrote a function to do all of that nonsense for me. You pass it the node id of the page which has the image attached to it, and it returns the path/to/the/attached/image/thank/you/very/much.jpg.

function lookupImagePath($nid, $thumbnail = false) {
 
	if ($thumbnail) {
		$size = 'thumbnail';
	} else {
		$size = '_original';
	}
 
	$sql  = 'SELECT f.filepath ';
	$sql .= 'FROM image_attach a, image i, files f ';
	$sql .= 'WHERE a.iid = i.nid ';
	$sql .= 'AND i.fid = f.fid ';
	$sql .= 'AND a.nid = ' . $nid . ' ';
	$sql .= 'AND i.image_size = "' . $size . '" ';
 
	$res = db_query($sql);
	$row = db_fetch_array($res);
	$filepath = $row['filepath'];
 
	return $filepath;
 
} // end lookupImagePath

Template for Node By Node ID

I’m working in Drupal 6 and we have a page template page.tpl.php, which handles most everything. It has a bunch of stuff for the header, and it handle the sidebar on the left, and the content in the middle of the page. The content in the middle of the page comes from whatever node you’re viewing, and it gets run through node.tpl.php first. This formats the node for output. Thing is, I have a particular node (with node ID 77) that I want to be formatted differently.

Drupal says you can make a new template called page-node-77.tpl.php and format the node content accordingly. But I don’t want to have two templates that display the same stuff (like the header and the sidebar on the left). All I want to do is change the node template. What I want to be able to do is make a new file called node-77.tpl.php and have that be used instead of node.tpl.php.

After much research, I find that includes/theme.inc has the function template_preprocess_node, which is where I want to put my code. At the end of this function is

$variables['template_files'][] = 'node-'. $node->type;

This allows us to define template files for nodes by type, but not by ID. So add

$variables['template_files'][] = 'node-'. $node->nid;

and you’re all set.