Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,134 @@ public function init( $args, $assoc_args ) {
}
}

/**
* Points scaled-down photos back at their original files.
*
* Photos uploaded while a lower 'big_image_size_threshold' was in effect
* have a "-scaled" copy as their attached file, so their "Original Size"
* download served the copy. The original file is still stored next to it,
* and the "-scaled" copy is left in place.
*
* ## OPTIONS
*
* [--dry-run]
* : List the photos that would be updated without changing them.
*
* ## EXAMPLES
*
* # Preview which photos would be updated.
* $ wp photos restore-originals --dry-run
*
* # Update them.
* $ wp photos restore-originals
*
* @param array $args Positional arguments. Unused.
* @param array $assoc_args Associative arguments.
*
* @subcommand restore-originals
* @when after_wp_load
*/
public function restore_originals( $args, $assoc_args ) {
require_once ABSPATH . 'wp-admin/includes/image.php';

$dry_run = $assoc_args['dry-run'] ?? false;
$threshold = Uploads::big_image_size_threshold( 0 );
$updated = 0;

$attachment_ids = get_posts(
[
'post_type' => 'attachment',
'post_status' => 'inherit',
'posts_per_page' => -1,
'fields' => 'ids',
'meta_query' => [
[
'key' => '_wp_attachment_metadata',
'value' => 'original_image',
'compare' => 'LIKE',
],
],
]
);

foreach ( $attachment_ids as $attachment_id ) {
$parent = get_post_parent( $attachment_id );
if ( ! $parent || Registrations::get_post_type() !== $parent->post_type ) {
continue;
}

$meta = wp_get_attachment_metadata( $attachment_id );
if ( empty( $meta['original_image'] ) || empty( $meta['file'] ) ) {
continue;
}

// Core also sets 'original_image' for copies that were only EXIF-rotated.
if ( ! str_contains( wp_basename( $meta['file'] ), '-scaled.' ) ) {
continue;
}

$original_path = wp_get_original_image_path( $attachment_id );
$image_size = $original_path ? wp_getimagesize( $original_path ) : false;

if ( ! $image_size ) {
WP_CLI::warning( "Photo {$parent->ID}: original file {$meta['original_image']} could not be read." );
continue;
}

// Still above the current threshold, so scaling it was intended.
if ( max( $image_size[0], $image_size[1] ) > $threshold ) {
continue;
}

// Core rotates the copy per the original's EXIF orientation, but stores the original unrotated.
$exif = wp_read_image_metadata( $original_path );
if ( ( $exif['orientation'] ?? 0 ) > 1 || ( $meta['width'] > $meta['height'] ) !== ( $image_size[0] > $image_size[1] ) ) {
WP_CLI::warning( "Photo {$parent->ID}: {$meta['file']} was rotated from its original, skipping." );
continue;
}

$file = path_join( dirname( $meta['file'] ), $meta['original_image'] );

WP_CLI::log( "Photo {$parent->ID}: {$meta['file']} ({$meta['width']}x{$meta['height']}) -> {$file} ({$image_size[0]}x{$image_size[1]})" );
++$updated;

if ( $dry_run ) {
continue;
}

update_attached_file( $attachment_id, $file );

// Keep the "-scaled" copy tracked so deleting the photo deletes it too.
$meta['sizes']['scaled'] = [
'file' => wp_basename( $meta['file'] ),
'width' => $meta['width'],
'height' => $meta['height'],
'mime-type' => get_post_mime_type( $attachment_id ),
];

$meta['file'] = $file;
$meta['width'] = $image_size[0];
$meta['height'] = $image_size[1];
$meta['filesize'] = wp_filesize( $original_path );
unset( $meta['original_image'] );

if ( isset( $meta['gcs_name'] ) ) {
$meta['gcs_name'] = $file;
}
if ( isset( $meta['gcs_url'] ) ) {
$meta['gcs_url'] = wp_get_attachment_url( $attachment_id );
}

wp_update_attachment_metadata( $attachment_id, $meta );
}

if ( $dry_run ) {
WP_CLI::success( "{$updated} photo(s) would be updated." );
} else {
WP_CLI::success( "{$updated} photo(s) updated." );
}
}

}

WP_CLI::add_command( 'photos', 'WordPressdotorg\Photo_Directory\CLI' );
Loading