With the release of Wordpress 2.5 awhile back, they introduced the ‘gallery’ shortcode. The gallery shortcode takes all the media attachments and creates a nicely laid out gallery, thumbnails and all. The problem with it is that it doesn’t do much more then that, unless of course your theme supports it. It shows the attachment and that’s basically it. No navigation, no special listing of galleries, nada.
One of the problems I’ve found with Wordpress is that it’s somewhat difficult to really implement good galleries that stick with the theme. I’ve tried Gallery2/WPG and some others and I’ve even gone the route of trying to have a completely separate gallery or photo blog. Nothing really made me that happy. I like the theme I have currently, so I wasn’t looking forward to finding a new one or actually hacking a new theme together to support the galleries better. So last weekend I sat down and got my hands dirty.
There were a couple goals I had for this project.
- Better navigation when you were viewing a photo in the gallery
- EXIF data on the image page
- A special format for any gallery type post
- A listing of all the galleries
I first started off with what I thought was the easiest - better navigation in the galleries. When WP displays the gallery page, it looks for a couple templates, the first being image.php, then attachment.php and then some others. I went into my theme and created a image.php file. I also brought up the Default theme’s image.php to get somewhat of an idea of what I needed.
Basically, the image.php is the same as a single page, it’s just displaying different content. First I’ll post the entire image.php and then explain what I was doing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | <?php get_header(); ?> <div id="content_gallery"> <?php if (have_posts()) : while (have_posts()) : the_post(); ?> <div class="post" id="post-<?php the_ID(); ?>"> <h2><a href="<?php echo get_permalink($post->post_parent); ?>" rev="attachment"><?php echo get_the_title($post->post_parent); ?></a> </h2> <div class="gallery_entry"> <?php $parent = $post->post_parent; $attachments = array_values(get_children(array('post_parent' => $post->post_parent, 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'ID') ) ); foreach ( $attachments as $k => $attachment ) if ( $attachment->ID == $post->ID ) break; $next = $k+1; $prev = $k-1; $next_link = ""; $prev_link = ""; if ( isset($attachments[$next]) ) { $next_exists = 1; $next_link = "<a href='" . get_attachment_link( $attachments[$next]->ID ) . "'> next image >></a>"; $img_link = "<a href='" . get_attachment_link( $attachments[$next]->ID ) . "'>"; } if ( isset($attachments[$prev]) ) { $prev_exists = 1; $prev_link = "<a href='" . get_attachment_link( $attachments[$prev]->ID ) . "'> << previous image</a>"; if (!$next_exists) { $img_link = "<a href='" . get_attachment_link( $attachments[$prev]->ID ) . "'>"; } } if (!$next_exists and !$prev_exists) { $img_link = "<a href='" . get_attachment_link( $attachments[$k]->ID ) . "'>"; } $img_url = wp_get_attachment_url( $attachments[$k]->ID ); preg_match("/.*(/wp-content/uploads/S+.S+)/", $img_url, $matches); if (sizeof($matches) > 1) { $fn = "/home/phasenet/public_html" . $matches[1]; $exif_data = read_exif_data($fn); } ?> <p class="attachment"><?php echo $img_link; echo wp_get_attachment_image( $post->ID, 'medium' ); ?></a></p> <div class="caption"><?php if ( !empty($post->post_excerpt) ) the_excerpt(); ?></div> <?php the_content('<p class="serif">Read the rest of this entry »</p>'); ?> <table id='photo-details'> <tr> <th> Original Image: </th> <td> <a href="<?php echo $img_url ?>"><?php print $exif_data['COMPUTED']['Width'] . "x" . $exif_data['COMPUTED']['Height']; ?></a>, <?php echo exif_filesize($exif_data['FileSize']); ?></td> </tr> <tr> <th> Camera: </th> <td> <?php print $exif_data['Model'] ?> </td> </tr> <tr> <th> Focal Length: </th> <td> <?php if ($exif_data['FocalLength']) print exif_divide($exif_data['FocalLength']); else print "Not available" ?> </td> </tr> <tr> <th> Aperture: </th> <td> <?php print $exif_data['COMPUTED']['ApertureFNumber'] ?> </td> </tr> <tr> <th> Shutter: </th> <td> <?php if ($exif_data['ExposureTime']) print $exif_data['ExposureTime']; else print "Not available"; ?> </td> </tr> <tr> <th> ISO: </th> <td> <?php if ($exif_data['ImageInfo'][2]) print $exif_data['ImageInfo'][2]; else print "Not available"; ?> </td> </tr> </table> <div class="navigation"> <div class="alignleft"><?php echo $prev_link ?></div> <div class="alignright"><?php echo $next_link ?></div> </div> <br class="clear" /> </div> </div> <?php comments_template(); ?> <?php endwhile; else: ?> <p>Sorry, no attachments matched your criteria.</p> <?php endif; ?> </div> <?php get_footer(); ?> |
No apologies for my code syntax or style.
In any case, we can start stepping through it. As I said earlier, the image.php acts like single.php in that we’re actually getting the_post. However, one thing that we need is the parent of this post ( ie - the gallery main page ), in order to get the children so we can create the navigation links. We do this via the following:
9 10 | $parent = $post->post_parent; $attachments = array_values(get_children(array('post_parent' => $post->post_parent, 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'ID') ) ); |
Now that we have all of the children posts ( or really, the other pictures in the gallery ), we have to figure out where in that list our current page is so that we can determine who is next and who was before us. We’ll do this via a simple loop:
12 13 14 15 16 17 | foreach ( $attachments as $k => $attachment ) if ( $attachment->ID == $post->ID ) break; $next = $k+1; $prev = $k-1; |
Pretty simple. We loop until the ID in the list matches our current ID and then break out. Add one, subtract one and we got our next and previous photos. Now, the next code has to deal with some navigation quirks. In my gallery, I wanted the user to be sent to the next photo if they actually clicked on the photo being displayed. However, once they get to the end, it needs to send them back a photo since there is nowhere else to go. The following code does just that.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | if ( isset($attachments[$next]) ) { $next_exists = 1; $next_link = "<a href='" . get_attachment_link( $attachments[$next]->ID ) . "'> next image >></a>"; $img_link = "<a href='" . get_attachment_link( $attachments[$next]->ID ) . "'>"; } if ( isset($attachments[$prev]) ) { $prev_exists = 1; $prev_link = "<a href='" . get_attachment_link( $attachments[$prev]->ID ) . "'> << previous image</a>"; if (!$next_exists) { $img_link = "<a href='" . get_attachment_link( $attachments[$prev]->ID ) . "'>"; } } if (!$next_exists and !$prev_exists) { $img_link = "<a href='" . get_attachment_link( $attachments[$k]->ID ) . "'>"; } |
Basically, we test to make sure there is another item after us in the list. If there is, we set the image to shoot us to the next link, as well as create the link for our ‘next’ navigation button and lastly, set a flag that there is a ‘next’ photo. We then test if there is a ‘previous’ photo in the list and if there is, we set the ‘previous’ navigation link and a flag gets turned on. Then we test the state of the ‘next’ flag, because if there isn’t another photo in the list to go to, we have to set the image’s link somewhere else. In this case, we set it to the previous image if there is no next image.
Lastly, we check if either of the flags are set. If neither of them were turned on, that means there is no next or previous photo to go to so we just set the image’s link to reference itself.
The last step of the main bulk of our php code is to get some EXIF data, which is basically data that some cameras embed into the photo. PHP supports this if it’s compiled in so your web hosting vendor may or may not have this. Mine does ( yay! ) so I was able to support this. Here’s the code again:
43 44 45 46 47 48 49 | $img_url = wp_get_attachment_url( $attachments[$k]->ID ); preg_match("/.*(/wp-content/uploads/S+.S+)/", $img_url, $matches); if (sizeof($matches) > 1) { $fn = "/home/phasenet/public_html" . $matches[1]; $exif_data = read_exif_data($fn); } |
The read_exif_data function requires an actual filename and does not work with a URL unfortunately. Because of this, I have to figure out where on the web host my file actually resides. I do this by getting the URL from the attachment, then doing a small sanity check just to make sure that it matches the upload directory that Wordpress uses. I then test the size of the result to make sure it’s more than 1. preg_match basically returns the item matched against and then any matches that were captured. If I receive a match, I create the filename and then just read in the exif data.
The last part of this is really just output. I display my image and link it to the URL we created earlier. You actually get the image via the wp_get_attachment_image function. After that, I just create a table and display the data from my *$exif_data* array.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | <p class="attachment"><?php echo $img_link; echo wp_get_attachment_image( $post->ID, 'medium' ); ?></a></p> <div class="caption"><?php if ( !empty($post->post_excerpt) ) the_excerpt(); ?></div> <?php the_content('<p class="serif">Read the rest of this entry »</p>'); ?> <table id='photo-details'> <tr> <th> Original Image: </th> <td> <a href="<?php echo $img_url ?>"><?php print $exif_data['COMPUTED']['Width'] . "x" . $exif_data['COMPUTED']['Height']; ?></a>, <?php echo exif_filesize($exif_data['FileSize']); ?></td> </tr> <tr> <th> Camera: </th> <td> <?php print $exif_data['Model'] ?> </td> </tr> <tr> <th> Focal Length: </th> <td> <?php if ($exif_data['FocalLength']) print exif_divide($exif_data['FocalLength']); else print "Not available" ?> </td> </tr> <tr> <th> Aperture: </th> <td> <?php print $exif_data['COMPUTED']['ApertureFNumber'] ?> </td> </tr> <tr> <th> Shutter: </th> <td> <?php if ($exif_data['ExposureTime']) print $exif_data['ExposureTime']; else print "Not available"; ?> </td> </tr> <tr> <th> ISO: </th> <td> <?php if ($exif_data['ImageInfo'][2]) print $exif_data['ImageInfo'][2]; else print "Not available"; ?> </td> </tr> </table> |
And last, but not least, I create the navigation links, print out the comments template and the footer of the page.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | <div class="navigation"> <div class="alignleft"><?php echo $prev_link ?></div> <div class="alignright"><?php echo $next_link ?></div> </div> <br class="clear" /> </div> </div> <?php comments_template(); ?> <?php endwhile; else: ?> <p>Sorry, no attachments matched your criteria.</p> <?php endif; ?> </div> <?php get_footer(); ?> |
Next up is how I modified the gallery main page.
Recent Comments