WordPress Hacking – Finding all images in a post

This is a continuation of the series where I attempt to build a solution to display WordPress posts with attached images such that the post content itself doesn’t show any of the images and the sidebar instead displays the images. In my previous post I described creating a simple WordPress plugin with an empty widget.

Now it is time to make the widget do something interesting. In my case, I wanted the widget to display something only if it was being shown in the context of a single post. That is, if you’re viewing a page of posts in the WordPress site, this sidebar widget should not display anything. A bit of searching in the WordPress Codex lead me to the is_single function which allows us to distinguish between a single post or page and a page of posts.

The next task was to figure out how to extract the images associated with a post. WordPress function get_children allows you to do exactly this. Once we get this list, the widget can then output the appropriate HTML to display the images in the sidebar. Here’s the widget function that extracts all the images from a single post and displays them in the sidebar widget only for single posts:

function widget($args) {
    global $post;

    extract($args);

    if ( is_single() ) {
        echo $before_widget;
        echo $before_title . 'Snapshots' . $after_title;
        $imgfilter = array(
            'order' => 'ASC',
            'post_mime_type' => 'image',
            'post_parent' => $post->ID,
            'post_status' => 'inherit',
            'post_type' => 'attachment',);

        $attachments = get_children( $imgfilter );

        if ( $attachments ) {
            $images = array();
            foreach ( $attachments as $attachment ) {
                $imgUrl = wp_get_attachment_url( $attachment->ID );
                $isMatch = strpos($imgUrl, '_thumb.jpg');
                if ( $isMatch === false ) {
                    $isMatch = strpos($imgUrl, 'Emoticon');
                }
                if ( $isMatch === false ) {
                    $images[] = $attachment;
                }
            }

            foreach ( $images as $image ) {
                $imageSrc = wp_get_attachment_image_src( $image->ID, 'medium' );
                echo '<a href="' . wp_get_attachment_url( $image->ID ) . '" class="cboxElement">' . 
                     '<img src="' . $imageSrc[0] . '" class="colorbox-' . $post->ID . '"></a>';
            }
        }
        else {
            echo __('No Images', 'text_domain');
        }
        echo $after_widget;
    }
}

We first specify a filter for get_children that finds the images attached to the current post (note that the current post is available to us in the global $post). Once we have this set of attachments we loop through it, do a bit of pre-processing on it and obtain an array of URLs that we can use in the <img> tags.

In this case, I wanted to make sure that posts that simply showed a NextGen Gallery are treated specially and the images appear in the body of the post and not in the sidebar. I accomplished this by filtering out any image URL that matches _thumb.jpg. Additionally, Windows Live Writer adds images for any emoticons used in a post. Clearly we shouldn’t be moving these out of the post and into the sidebar. This is accomplished by filtering out any image that has Emoticon in the URL. Note that both these filters are excellent “hacks” but not fool-proof. They work well enough for the problem I was trying to solve and I used them.

Once we have the filtered set of images, we just loop through them and emit the HTML required to get them to show up in the sidebar. Note that anything that you echo in the widget method basically gets displayed in the sidebar that has your widget. The code adds the images (at medium size) as clickable links with the same colorbox CSS class thus essentially converting the pictures in the post to a clickable slideshow with medium size thumbnails shown in the sidebar. We only have one more step left – hide the images in the original post content.

Leave a Reply

Your email address will not be published. Required fields are marked *