Display WordPress featured image, thumbnail, or YouTube thumb

Huge thanks to Vladimir Prelovac, who wrote the original function. I use it a ton and have adapted it a bit to check for:

  1. Featured image; then
  2. First image attached to the post; then
  3. The first image inserted in the post; then
  4. The thumbnail of the first YouTube video inserted in the post

All I added was the featured image bit. :)

Here’s the full function, plus 3 helper functions, which should all be inserted in your theme’s functions.php file:

  • [UPDATED 2013.03.09 to return correct size for inserted images AND to allow for the function to return the featured-image only. This baby is getting long, let me know if you find a way to hone it down!]
/**** 
IMAGE PARSING FUNCTIONS 
****/

/** HELPER FUNCTION 1: **/
// GET YOUTUBE ID FROM URL
// see http://webgarb.com/tutorials/how-to-get-youtube-video-id-from-url-perfect-way/
function youtubeID($url){
     $res = explode("v=",$url);
     if(isset($res[1])) {
        $res1 = explode('&',$res[1]);
        if(isset($res1[1])){
            $res[1] = $res1[0];
        }
        $res1 = explode('#',$res[1]);
        if(isset($res1[1])){
            $res[1] = $res1[0];
        }
     }
     return substr($res[1],0,12);
     return false;
}

/*** HELPER FUNCTION 2: ***/
// FIND YOUTUBE URLS IN CONTENT AND CONVERT TO SIMPLE FORMAT
// adapted from answer here: http://stackoverflow.com/a/5831191/107244 
function parseYouTubeURLs($mm_text) {
    $mm_text = preg_replace('~
        # Match non-linked youtube URL in the wild. (Rev:20111012)
        https?://         # Required scheme. Either http or https.
        (?:[0-9A-Z-]+\.)? # Optional subdomain.
        (?:               # Group host alternatives.
          youtu\.be/      # Either youtu.be,
        | youtube\.com    # or youtube.com followed by
          \S*             # Allow anything up to VIDEO_ID,
          [^\w\-\s]       # but char before ID is non-ID char.
        )                 # End host alternatives.
        ([\w\-]{11})      # $1: VIDEO_ID is exactly 11 chars.
        (?=[^\w\-]|$)     # Assert next char is non-ID or EOS.
        [?=&+%\w-]*        # Consume any URL (query) remainder.
        ~ix', 
        'http://www.youtube.com/watch?v=$1',
        $mm_text);
    return $mm_text;
}

/*** HELPER FUNCTION 3: ***/
// GET ATTACHMENT ID
// see http://wordpress.stackexchange.com/a/7094
if ( ! function_exists( 'get_attachment_id' ) ) {
    /**
     * Get the Attachment ID for a given image URL.
     *
     * @link   http://wordpress.stackexchange.com/a/7094
     *
     * @param  string $url
     *
     * @return boolean|integer
     */
    function get_attachment_id( $url ) {

        $dir = wp_upload_dir();

        // baseurl never has a trailing slash
        if ( false === strpos( $url, $dir['baseurl'] . '/' ) ) {
            // URL points to a place outside of upload directory
            return false;
        }

        $file  = basename( $url );
        $query = array(
            'post_type'  => 'attachment',
            'fields'     => 'ids',
            'meta_query' => array(
                array(
                    'value'   => $file,
                    'compare' => 'LIKE',
                ),
            )
        );

        $query['meta_query'][0]['key'] = '_wp_attached_file';

        // query attachments
        $ids = get_posts( $query );

        if ( ! empty( $ids ) ) {

            foreach ( $ids as $id ) {

                // first entry of returned array is the URL
                if ( $url === array_shift( wp_get_attachment_image_src( $id, 'full' ) ) )
                    return $id;
            }
        }

        $query['meta_query'][0]['key'] = '_wp_attachment_metadata';

        // query attachments again
        $ids = get_posts( $query );

        if ( empty( $ids) )
            return false;

        foreach ( $ids as $id ) {

            $meta = wp_get_attachment_metadata( $id );

            foreach ( $meta['sizes'] as $size => $values ) {

                if ( $values['file'] === $file && $url === array_shift( wp_get_attachment_image_src( $id, $size ) ) )
                    return $id;
            }
        }

        return false;
    }
}

/*** MAIN FUNCTION, GET THUMBNAIL ***/
// Your theme must support post thumbnails for this function to work. If you are getting an error try adding add_theme_support('post-thumbnails'); to your functions.php file 
// NOTE: If $feature is set to true, the image will only be returned if it is set as a featured image.
function vp_get_thumb_url($text, $size, $feature = false) {
    global $post;
    $imageurl="";

    // Check to see which image is set as "Featured Image"
    $featuredimg = get_post_thumbnail_id($post->ID);
    // Get source for featured image
    $img_src = wp_get_attachment_image_src($featuredimg, $size);
    // Set $imageurl to Featured Image
    $imageurl = $img_src[0];

    // if not returning only the featured image, move on and get something else
    if ($feature == false) {

        // If there is no "Featured Image" set, move on and get the first image attached to the post
        if (!$imageurl) {
            // Extract the thumbnail from the first attached imaged
            $allimages =&get_children('post_type=attachment&post_mime_type=image&post_parent=' . $post->ID );

            foreach ($allimages as $img){
                $img_src = wp_get_attachment_image_src($img->ID, $size);
                break;
            }
            // Set $imageurl to first attached image
            $imageurl=$img_src[0];
        }

        // If there is no image attached to the post, look for anything that looks like an image and get that
        if (!$imageurl) {
            preg_match('/<\s*img [^\>]*src\s*=\s*[\""\']?([^\""\'>]*)/i' , $text, $matches);
            $imageurl=$matches[1];

            // get image ID - uses helper function get_attachment_id() )
            $image_id = get_attachment_id($imageurl);

            // retrieve the relevant size of our image
            $image_src = wp_get_attachment_image_src($image_id, $size);

            // set $imageurl to first inserted image
            $imageurl = $image_src[0];
        }

        // YOUTUBE
        // If there's no image attached or inserted in the post, look for a YouTube video
        if (!$imageurl) {

            // FIND FIRST YOUTUBE URL IN CONTENT
            // uses helper function parseYouTubeURLs
            $youtubeurl = parseYouTubeURLs($text);

            // GET YOUTUBE ID FROM URL
            // users helper function youtubeID();
            $videokey = youtubeID($youtubeurl);

            if ($videokey) {
                // Get the thumbnail YouTube automatically generates
                // '0' is the biggest version, use 1 2 or 3 for smaller versions
                $imageurl = "http://i.ytimg.com/vi/{$videokey}/0.jpg";
            }
        }

        // DEFAULT IMAGE
        // if there's no image or embedded YouTube, show a default image
        if (!$imageurl) {

        }

    } // feature = false

    // Spit out the image path
    return $imageurl;
}
/*** END FEATURED IMAGE PARSING FUNCTIONS ***/

And to display the image in your theme, often on archive.php or index.php within the loop, add this:

// Show featured image, or first image if no featured, or YouTube thumbnail
if (function_exists('vp_get_thumb_url')) {

	// Set the desired image size. Swap out 'thumbnail' for 'medium', 'large', or custom size
	$thumb=vp_get_thumb_url($post->post_content, 'thumbnail');

	if ($thumb!='') { ?>

		<a href="<?php the_permalink() ?>" title="<?php the_title(); ?>" rel="bookmark"><img class="alignleft" src="<?php echo $thumb; ?>" alt="<?php get_the_title(); ?>" /></a>

	<?php }
}
Body classes with page-parent-name and page-name

Add post/page name + page parent name to body class

This will add a page-slug class and a page-parent-slug class to your body tag, along with all the other defaults. Put this in your functions.php file:

function wpprogrammer_post_name_in_body_class( $classes ){
if( is_singular() ) {
     global $post;
     $parent = get_page($post->post_parent);
     array_push( $classes, "{$post->post_type}-{$post->post_name}" );
     array_push( $classes, "{$post->post_type}-parent-{$parent->post_name}" );
     }
return $classes;
}
add_filter( 'body_class', 'wpprogrammer_post_name_in_body_class' );

Also make sure your open body tag looks like this (you can probably find it in header.php):


<body <?php body_class(); ?>>

Many thanks to Utkarsh Kuketri for the original function!

The somewhat official blog of Friendly Web Consulting