Set first image (external) as featured image / thumbnail

I recently released a plugin that imports any external images found in a post and imports them into the media library, attaches them to the post and sets the first image found as the featured image.

http://wordpress.org/extend/plugins/media-tools/

I’m posting the basic function that gets the external image and sets it as the featured image. In the plugin this is done through an admin page via ajax but you could add it to the save_post hook as Milo mentions in his answer.

function process_image() {
    $response="";
    $data[] = '';
    $error = 0;

    $img = $this->extract_image( $post );
        if( empty( $img ) ) {
            $response .=  'No images found <br>';
            die( sprintf( $response . '<br>Media tool complete (Post ID %1$s) in %2$s seconds. %3$d errors', esc_html( $post->ID ), timer_stop(), $error = $error  > 0 ? $error : 'no' ) );
         }

    /** @var $file string or WP_Error of image attached to the post  */
    $file = media_sideload_image( $img, (int)$post->ID );
    if ( is_wp_error( $file ) ) {
        $response .= '<span style="color:red">Upload Error: Could not upload image. Check for malformed img src url</span><br>';
        $error++;
    } else {
        $atts = $this->get_attach( $post->ID );
        foreach ( $atts as $a ) {
           $img = set_post_thumbnail( $post->ID, $a['ID'] );
           if ( $img ) {
              $thumb = wp_get_attachment_thumb_url( $a['ID'] );
              $response .= '<img src="'.esc_url( $thumb ).'" /><br>';
              $response .= '<a href="' . wp_nonce_url( get_edit_post_link( $a['ID'], true ) ) . '" >' . get_the_title( $a['ID'] ) . '</a>  Set as Featured Image</p><br>';
       }
    }
    unset( $atts );
    unset( $a );
    }
    return $response;
}

This is not meant to be copied and pasted. It is an example of how to do this and the code will need to be adapted to your specific situation. This code is inside a class and the $response variable gets returned via ajax in my plugin.

The function that is called in the above code to extract the image:

/**
 * Extracts the first image in the post content
 * @param object $post the post object
 * @return bool|string false if no images or img src
 */
function extract_image( $post ) {
    $html = $post->post_content;
    if ( stripos( $html, '<img' ) !== false ) {
        $regex = '#<\s*img [^\>]*src\s*=\s*(["\'])(.*?)\1#im';
        preg_match( $regex, $html, $matches );
        unset( $regex );
        unset( $html );
        if ( is_array( $matches ) && ! empty( $matches ) ) {
            return  $matches[2];

        } else {
            return false;
        }
    } else {
        return false;
    }
}

The get_attach function called that gets the attachments:

/**
 * Queries for attached images
 * @param int $post_id The post id to check if attachments exist
 * @return array|bool The 1st attached on success false if no attachments
 */
function get_attach( $post_id ) {
    return get_children( array (
            'post_parent'    => $post_id,
            'post_type'      => 'attachment',
            'post_mime_type' => 'image',
            'posts_per_page'  => (int)1
        ), ARRAY_A );
}

Leave a Comment