Getting the latest posts with a gallery is simple: search for posts with the string '[gallery'
.
$posts = get_posts(
array (
's' => '[gallery'
)
);
Getting the first image from each gallery is harder, because you have to render the gallery
shortcode. I would not use the default handler, it does much more than we need here. It would waste too much time.
Step by step …
The main function
Let’s start with a function to retrieve a list of latest gallery posts with two parameters: the number of posts and a formatting helper:
function t5_list_galleries( $num = 10, $formatter = 't5_gallery_list_formatter' )
{
$posts = get_posts(
array (
's' => '[gallery',
'numberposts' => (int) $num
)
);
if ( ! $posts )
return FALSE;
$list = new T5_Gallery_Image_Extractor( $posts );
$html = call_user_func( $formatter, $list->get_results() );
return $html;
}
As you can see we need a class T5_Gallery_Image_Extractor
to build the list and a formatting function to create the Markup. I haven’t put the formatter into the gallery extractor to stay flexible: You might use the function in a widget or in a shortcode with different formatters.
The class T5_Gallery_Image_Extractor
The class constructor expects a list of posts. It doesn’t care about how we got that list, so we can build is manually with a completely different main function.
Internally, it replaces the default shortcode handler for gallery
with a simplified version to get just the first image from the first gallery in a post.
The public method get_results()
returns an array like this:
Array
(
[0] => Array
(
[url] => http://single.wp/blog/gallery-2/
[img] => <img width="150" height="150" src="http://content.wp/singlewp/uploads/2013/01/git-bash-150x150.png" class="attachment-thumbnail" alt="git-bash" />
[title] => Gallery 2
)
[1] => Array
(
[url] => http://single.wp/blog/gallery-1/
[img] => <img width="150" height="150" src="http://content.wp/singlewp/uploads/2013/01/hat-150x150.png" class="attachment-thumbnail" alt="hat" />
[title] => Gallery 1
)
)
So we get the post URL, the image markup and the post title for each post with a gallery.
The code, sorry, no time for comments, maybelater. :)
class T5_Gallery_Image_Extractor
{
protected $results = array ();
protected $current_post = NULL;
protected $old_gallery_handler = FALSE;
public function __construct( $posts )
{
$this->replace_gallery_shortcode();
foreach ( $posts as $post )
$this->collect_first_image( $post );
}
public function get_results()
{
remove_shortcode( 'gallery' );
if ( $this->old_gallery_handler )
add_shortcode( 'gallery', $this->old_gallery_handler );
return $this->results;
}
protected function collect_first_image( $post )
{
$this->current_post = $post;
do_shortcode( $post->post_content );
$this->current_post = NULL;
}
protected function replace_gallery_shortcode()
{
// replace the old gallery shortcode
if ( isset( $GLOBALS['shortcode_tags']['gallery'] ) )
$this->old_gallery_handler = $GLOBALS['shortcode_tags']['gallery'];
remove_shortcode( 'gallery' );
add_shortcode( 'gallery', array ( $this, 'gallery_shortcode' ) );
}
public function gallery_shortcode( $attr )
{
static $processed_posts = array ();
$post = $this->current_post;
if ( in_array( $post->ID, $processed_posts) )
return; // no need to run through all galleries of a post.
$processed_posts[] = $post->ID;
if ( ! empty ( $attr['ids'] ) )
{
if ( empty ( $attr['orderby'] ) )
$attr['orderby'] = 'post__in';
$attr['include'] = $attr['ids'];
}
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,
'include' => '',
'exclude' => ''
), $attr));
$id = intval($id);
if ( 'RAND' == $order )
$orderby = 'none';
$att_args = array (
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => $order,
'orderby' => $orderby,
'numberposts' => 1
);
if ( ! empty ( $include ) )
{
$att_args['include'] = $include;
$attachments = get_posts( $att_args );
}
else
{
$att_args['post_parent'] = $post->ID;
if ( ! empty ( $exclude ) )
$att_args['exclude'] = $exclude;
$attachments = get_children( $att_args );
}
$this->results[] = array (
'url' => get_permalink( $post->ID ),
'img' => wp_get_attachment_image( current( $attachments )->ID ),
'title' => $post_title = esc_attr( $post->post_title )
);
}
}
The formatter
Dead simple: just convert the array from above into a HTML list.
function t5_gallery_list_formatter( $list )
{
$output = '<ul class="t5-gallery-list">';
foreach ( $list as $item )
$output .= sprintf(
'<li><a href="%1$s" title="%2$s">%3$s</a></li>',
$item['url'],
$item['title'],
$item['img']
);
return "$output</ul>";
}
Now we can use the main function wherever we need it:
print t5_list_galleries();
And the result is a nice list of the latest ten posts with a gallery, the first image from the first gallery is used as link text.
Visual formatting is left to the stylesheet:
.t5-gallery-list {
/* here be dragon rules */
}