Differentiate Featured Image from Post Images upon Upload

You could do this by filtering the meta value for _thumbnail_id.

add_filter( 'update_post_metadata', 'generate_featured_image_sizes', 10, 5 );
add_filter( 'add_post_metadata', 'generate_featured_image_sizes', 10, 5 );

function generate_featured_image_sizes( $check, $object_id, $meta_key, $meta_value, $unique_or_prev ) {
    if ( $meta_key == '_thumbnail_id' ) {

        // regenerate previous featured image thumbs if it exists
        if ( false !== ( $prev_thumb_id = get_post_meta( $object_id, '_thumbnail_id', true ) ) ) {
            $prev_new_metadata = wp_generate_attachment_metadata( $prev_thumb_id, get_attached_file( $prev_thumb_id ) );
            if ( ! is_wp_error( $prev_new_metadata ) )
                wp_update_attachment_metadata( $prev_thumb_id, $prev_new_metadata );
        }

                    // remove all normal image sizes before we add our filter
                    cleanup_attachment_images( $meta_value );

        // filter image sizes for featured
        add_filter( 'intermediate_image_sizes', 'featured_image_sizes', 9999 );

        // regenerate thumbnails for featured
        $new_metadata = wp_generate_attachment_metadata( $meta_value, get_attached_file( $meta_value ) );
        if ( ! is_wp_error( $new_metadata ) )
            wp_update_attachment_metadata( $meta_value, $new_metadata );

                    // remove featured sizes from previous featured image
                    if ( isset( $prev_thumb_id ) && $prev_thumb_id )
                        cleanup_attachment_images( $prev_thumb_id );

        // tidy up
        remove_filter( 'intermediate_image_sizes', 'featured_image_sizes', 9999 );
    }

    return $check;
}

function featured_image_sizes( $sizes ) {
    return array( 'large', 'featured', 'slider' );
}

function cleanup_attachment_images( $attachment_id ) {
    $uploadpath = wp_upload_dir();
    $intermediate_sizes = array();
    foreach ( get_intermediate_image_sizes() as $size ) {
        if ( $intermediate = image_get_intermediate_size( $attachment_id, $size ) )
            $intermediate_sizes[] = $intermediate;
    }
    // remove intermediate and backup images if there are any
    foreach ( $intermediate_sizes as $intermediate ) {
        /** This filter is documented in wp-admin/custom-header.php */
        $intermediate_file = apply_filters( 'wp_delete_file', $intermediate[ 'path' ] );
        @ unlink( path_join( $uploadpath[ 'basedir' ], $intermediate_file ) );
    }
}

Recreating the thumbnails is just a case of generating and updating the attachment metadata so by regenerating whenever the featured image is changed you should get the desired effect.

This will work on upload but also when the featured image is changed. In addition it will regenerate thumbs for the old thumbnail so it’s like a normal image with the normal sizes again.

The reason for using the add_post_metadata and update_post_metadata hooks is so that we have access to the current value before it gets updated in the database.

NOTE
There’s no real difference between the add media popup for the featured image or the editor, those links just open the popup in a different state so there’s no easy way to tell which state was requested (featured image or editor) when images are being uploaded, hence the approach I’ve shown above.

UPDATE
I added a function that you could call to delete sets of generated thumbnails for an attachment. You’d call this before generating new attachment metadata. You could even filter the image sizes it removes or modify the function so you can pass them as an argument.

Leave a Comment