How do I hook into WordPress to save an uploaded photo as an alternate size to an existing photo?

This can be done by using:

wp_get_attachment_metadata();

wp_update_attachment_metadata();

You’d get the meta data for it and change it around then save it.
The $data array you get contains another array named sizes, this array contains all the different size images connected to the attachment.

You want this to update automatically when you upload images that are conveniently named. I don’t quite see why it would be worth it but lets take a look.

This takes a little doing and this is probably not the optimal way to do it but it works and will give you an idea of how it can be done.

// hooking in to the add_attachment action just like you did
add_action('add_attachment', function ( $post_ID ) {
    // we need to work with the database
    global $wpdb;

    // get the attachment
    $post = get_post( $post_ID );

    // remove the _x2 suffix to help find the original
    $attachment_name = str_replace( '_x2', '', $post->post_title );

    // did this file have an _x2 suffix?
    $is_x2 = ( $attachment_name == $post->post_title ) ? FALSE : TRUE;

    // get the attachments extension
    $extension = pathinfo( $post->guid, PATHINFO_EXTENSION );

    // if there is a large file, it would be called:
    $large_file = $attachment_name . '_large.' . $extension;

    // time to see if we have a large file saved
    // wordpress stores the relative path from the uploads directory
    // we use a like query to find the file in any year/month subdir
    $result = $wpdb->get_row($wpdb->prepare(
        "SELECT * FROM $wpdb->postmeta
            WHERE meta_value LIKE %s",
        '%' . $wpdb->esc_like($large_file)
    ));

    // did we find a file?
    if( !empty( $result ) ) {
        // yep we found a file, get its meta
        $attachment_meta = wp_get_attachment_metadata( $result->post_id );

        // get meta data on the new file
        $meta = get_post_meta( $post->ID, '_wp_attached_file', TRUE );

        // manually read the size of the new image
        $upl = wp_upload_dir();
        $new_file = $upl['basedir'] . "https://wordpress.stackexchange.com/" . $meta;
        $sizes = getimagesize( $new_file );

        // what should the thumbnail be called?
        // remember we checked if the file had the _x2 suffix before?
        $thumb_name = ( $is_x2 ) ? 'x2' : 'thumb';

        // time to add the new size to the meta data of the large file
        $attachment_meta['sizes'][$thumb_name] = array(
            'file' => basename($post->guid),
            'width' => $sizes[0],
            'height' => $sizes[1],
            'mime-type' => $sizes['mime']
        );

        // save the new meta data to the large file
        wp_update_attachment_metadata( $result->post_id, $attachment_meta );

        // now we delete all references to the new file that was uploaded
        // by manually deleting it from the database the file will be kept on disk
        // this step is optional, WordPress will behave a bit funny when uploading if used
        $wpdb->query($wpdb->prepare(
            "DELETE FROM $wpdb->posts
                WHERE $wpdb->posts.ID = %d", 
            $post->ID
        ));

        $wpdb->query($wpdb->prepare(
            "DELETE FROM $wpdb->postmeta 
                WHERE $wpdb->postmeta.post_id = %d", 
            $post->ID
        ));        
    }
});

The last 2 delete queries are optional, you said you didn’t want new entries in the database for the new image and those will delete the new entries. WordPress won’t like that thoose references are removed though, it will act a bit funny when uploading but it won’t break anything.

Now you can easily fetch your thumbnails like you would with any other.
Assuming you have attached the large file as a featured image to a post:

global $post;

// the filename_large.jpg file
echo get_the_post_thumbnail($post->ID);

// the filename.jpg file
echo get_the_post_thumbnail($post->ID, 'thumb');

// the filename_x2.jpg file
echo get_the_post_thumbnail($post->ID, 'x2');

You can change what the thumbnails are called with the $thumb_name variable where we saved the new attachment meta data.

This will work regardless of wheter you use the optional delete queries or not, if you only wanted to do this for the convenience then I say don’t use the queries.
If you really don’t want the thumbnails to show up as individual images then use them.

Leave a Comment