wordpress gallery shortcode update.

some history: since shortly after the release of the [gallery] shortcode, I’ve been using a custom field called “useGallery” to conditionally show every thumbnail image attached to a particular post. i first did this after noticing in my log stats that users would bounce back and forth to get a look at all of the images included in a [gallery] posting. i thought it made more sense to have all of the thumbnail images available at once so users didn’t have to waste clicks.1 after using that bit of code for awhile, i made a modest upgrade that changed the border color of the active image being viewed using conditional logic and some simple css additions to my stylesheet.

For the geeks – here’s a look at the code that did it.

$useGallery = $wpdb->get_var("SELECT meta_value useGallery FROM $wpdb->postmeta WHERE meta_key = 'useGallery' and post_id = $post->post_parent");

if ($useGallery == 1) {

$oImages = $wpdb->get_results("SELECT i.id aID, i.post_excerpt altTitle, i.post_content, i.post_name iName
FROM wp_posts p 
join wp_posts i on p.id = i.post_parent 
join wp_postmeta m on i.id = m.post_id and m.meta_key = '_wp_attachment_metadata'
where i.post_parent = $post->post_parent
order by i.menu_order");

$rowcount = $wpdb->num_rows;

echo '
<h3>other images (' . $rowcount . ')</h3>';

$i = 0;
foreach($oImages as $oImage) : 
	$i = $i + 1;
	$imgText = get_image_tag($oImage->aID,$oImage->altTitle,$oImage->altTitle,'','thumbnail'); 
    $iref = get_permalink($post->post_parent) .  $oImage->iName;

    if(($i % 3) == 1){echo '<div class=\'gallery\'>';}

    if ($oImage->aID == $id) { echo('<dl class=\'gallery-current gallery-columns-3\'><dt class=\'gallery-icon\'>' . $imgText . '</dt></dl>'); } else {
echo'<dl class=\'gallery-item gallery-columns-3\'><dt class=\'gallery-icon\'><a href=' . $iref .'>' . $imgText . '</a></dt></dl>'; }

    if(($i % 3) == 0 || ($i == $rowcount)){echo '</div>';}
endforeach;

echo '<br style=\'clear: both;\' />';
}

For you nongeeks – this is what’s happening in “plain” english: first check to see if useGallery is set, then get all images from the post that this image we are currently looking at is attached to, count how many you have, loop over those images and display a thumbnail. while displaying a thumbnail, determine if the one you are currently looking at up top is the thumbnail you are displaying and give that a different css class so that you can shade it’s border a different color. also, check to see if you’re a multiple of 3, or, if you’re at the end of the images. basically, my goal was to mimic the function of wp’s built in gallery shortcode with, admittedly, a very simple tweak.

the problem: after the big change to the site, i realized i would have to make a change to every post that used the shortcode gallery. my new, slimmer, trimmer 420px column on the frontpage did not play well w/galleries that had more than 2 columns and used thumbnail images with a width of 200px. now, that meant that i’d have to hunt down every post that i used the gallery shortcode2 in or make a global change to the code that runs the gallery shortcode. because those lovely people over at WP left a comment in their code3 i was able to go right to the source and make an edit to change the default columns to 2 and that took care of my initial problem. while poking around in there, i noticed a commented line which read, “// Allow plugins/themes to override the default gallery template.

There’s more than one way to skin a cat, but, if you’re skinning said cat somewhere close to a factory that creates cat-skinning lasers, you may want to put down your trusty swiss army knife.

i figured, if they wanted you to override the gallery template, they’d probably have some way to do it, so off i went to the codex to find out the best way to do so. the fourth example on that page had almost everything i wasted XX number of lines writing above, and more, a means of using the underlying code that would mean i only needed to update in one place.

 <?php
    $gallery_shortcode = '[ gallery id="' . intval( $post->post_parent ) . '"]';
    print apply_filters( 'the_content', $gallery_shortcode );
 ?>

in geek, this is clearly a RTFM issue. in non-geek, that says, “you should have read the fn manual.” this was great, i would be able to replace my custom code with the actual gallery shortcode that WP uses. after a tiny tweak i’d be able to take care of my 3 column issue at the slight cost that I would need to change it every time i upgraded WP. or, at least i thought i would until i came across this bit of genius from esmi which could easily solve my problem.

remove_shortcode('gallery');
add_shortcode('gallery', 'theme_gallery_shortcode');

simple enough to geeks and non-geeks: screw their shortcode, use your own!

the revised gallery shortcode sits below

function h_gallery_shortcode($attr) {
	global $post;

	static $instance = 0;
	$instance++;

	// Allow plugins/themes to override the default gallery template.
	$output = apply_filters('post_gallery', '', $attr);
	if ( $output != '' )
		return $output;

	// We're trusting author input, so let's at least make sure it looks like a valid orderby statement
	if ( isset( $attr['orderby'] ) ) {
		$attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
		if ( !$attr['orderby'] )
			unset( $attr['orderby'] );
	}

	extract(shortcode_atts(array(
		'order'      => 'ASC',
		'orderby'    => 'menu_order ID',
		'id'         => $post->ID,
		'itemtag'    => 'dl',
		'icontag'    => 'dt',
		'captiontag' => 'dd',
		'columns'    => 2,
		'size'       => 'thumbnail',
		'currentid'  => '0'
	), $attr));

	$id = intval($id);
	$attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );

	if ( empty($attachments) )
		return '';

	if ( is_feed() ) {
		$output = "\n";
		foreach ( $attachments as $att_id => $attachment )
			$output .= wp_get_attachment_link($att_id, $size, true) . "\n";
		return $output;
	}

	$itemtag = tag_escape($itemtag);
	$captiontag = tag_escape($captiontag);
	$columns = intval($columns);
	$itemwidth = $columns > 0 ? floor(100/$columns) : 100;

	$selector = "gallery-{$instance}";

	$output = apply_filters('gallery_style', "
		<style type='text/css'>
			#{$selector} {
				margin: auto;
			}
			#{$selector} .gallery-item {
				float: left;
				margin-top: 10px;
				text-align: center;
				width: {$itemwidth}%;
			}
		</style>
		<div id='$selector' class='gallery galleryid-{$id}'>");

	$i = 0;
	foreach ( $attachments as $id => $attachment ) {
		$link = isset($attr['link']) && 'file' == $attr['link'] ? wp_get_attachment_link($id, $size, false, false) : wp_get_attachment_link($id, $size, true, false);
		$currentclass = ($id == $currentid) ? 'gallery-current' : 'gallery-item';

		$output .= "<{$itemtag} class='$currentclass'>";
		$output .= "
			<{$icontag} class='gallery-icon'>
				$link
			</{$icontag}>";
		if ( $captiontag && trim($attachment->post_excerpt) ) {
			$output .= "
				<{$captiontag} class='gallery-caption'>
				" . wptexturize($attachment->post_excerpt) . "
				</{$captiontag}>";
		}
		$output .= "</{$itemtag}>";
		if ( $columns > 0 && ++$i % $columns == 0 )
			$output .= '<br style="clear: both" />';
	}

	$output .= "
			<br style='clear: both;' />
		</div>\n";

	return $output;
}

i’ve trimmed the css and added the “currentid” attribute. the highlighted lines4 show the code used to add the “currentid” attribute. my huge chunk of code from the beginning now appears as 9 simple lines.

$useGallery = $wpdb->get_var("SELECT meta_value useGallery FROM $wpdb->postmeta WHERE meta_key = 'useGallery' and post_id = $post->post_parent");

if ($useGallery == 1) {

echo '<h3>other images</h3>';

    $gallery_shortcode = '[ gallery columns="3" currentid="' . intval($id) . '" id="' . intval( $post->post_parent ) . '"]';
    print apply_filters( 'the_content', $gallery_shortcode );
}

overall, this was a huge success. i was able to eliminate my duplicate code, i was able to fix the 3 column default issue w/out worrying about it being overwritten in an upgrade and i (re)learned one of life’s most important lessons — RTFM. the biggest thing that i took away from this experience is that you can rewrite a bunch of the “core” functions/tags/etc that are available in WP. one guy even created a plugin that turns template tags into shortcodes. this lets me know that before i go off and try to rewrite history, a little more time on teh googz can stop me from having to cut ~30 lines of code down to five. now all i’ll need is someone to draw me a picture of a cat skinning laser factory and this might be a perfect post.

notes:
  1. it’s what i would want a website to do. []
  2. which, by default, uses 3 columns []
  3. <!– see gallery_shortcode() in wp-includes/media.php –> []
  4. 27 – add a comma to the end of the line
    28 – add entire line
    68 – tertiary operator to determine if thumbnail matches image
    70 – replace class with $currentclass variable []

Comment (1)

  1. Hi, thanks for the post, I’m also trying to modify the [gallery] shortcode so this is a welcome bit of explaining!
    However, in your case couldn’t you use the wordpress regex plugin to change the shortcodes in the database?

    Sunday, November 11, 2012 at 10:52 #