Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to delete unknown image sizes #199

Merged
merged 3 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
31 changes: 25 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ wp media

# Import a local image and set it to be the featured image for a post.
$ wp media import ~/Downloads/image.png --post_id=123 --title="A downloaded picture" --featured_image
Success: Imported file '/home/person/Downloads/image.png' as attachment ID 1753 and attached to post 123 as featured image.
Imported file '/home/person/Downloads/image.png' as attachment ID 1753 and attached to post 123 as featured image.
Success: Imported 1 of 1 images.

# List all registered image sizes
$ wp media image-size
Expand All @@ -46,14 +47,19 @@ wp media
| thumbnail | 150 | 150 | hard |
+---------------------------+-------+--------+-------+

# Fix orientation for specific images.
$ wp media fix-orientation 63
1/1 Fixing orientation for "Portrait_6" (ID 63).
Success: Fixed 1 of 1 images.



### wp media import

Creates attachments from local files or URLs.

~~~
wp media import <file>... [--post_id=<post_id>] [--title=<title>] [--caption=<caption>] [--alt=<alt_text>] [--desc=<description>] [--skip-copy] [--preserve-filetime] [--featured_image] [--porcelain]
wp media import <file>... [--post_id=<post_id>] [--post_name=<post_name>] [--file_name=<name>] [--title=<title>] [--caption=<caption>] [--alt=<alt_text>] [--desc=<description>] [--skip-copy] [--preserve-filetime] [--featured_image] [--porcelain[=<field>]]
~~~

**OPTIONS**
Expand All @@ -66,6 +72,12 @@ wp media import <file>... [--post_id=<post_id>] [--title=<title>] [--caption=<ca
[--post_id=<post_id>]
ID of the post to attach the imported files to.

[--post_name=<post_name>]
Name of the post to attach the imported files to.

[--file_name=<name>]
Attachment name (post_name field).

[--title=<title>]
Attachment title (post title field).

Expand All @@ -87,10 +99,14 @@ wp media import <file>... [--post_id=<post_id>] [--title=<title>] [--caption=<ca
Remote files will always use the current time.

[--featured_image]
If set, set the imported image as the Featured Image of the post its attached to.
If set, set the imported image as the Featured Image of the post it is attached to.

[--porcelain]
Output just the new attachment ID.
[--porcelain[=<field>]]
Output a single field for each imported image. Defaults to attachment ID when used as flag.
---
options:
- url
---

**EXAMPLES**

Expand Down Expand Up @@ -129,7 +145,7 @@ wp media import <file>... [--post_id=<post_id>] [--title=<title>] [--caption=<ca
Regenerates thumbnails for one or more attachments.

~~~
wp media regenerate [<attachment-id>...] [--image_size=<image_size>] [--skip-delete] [--only-missing] [--yes]
wp media regenerate [<attachment-id>...] [--image_size=<image_size>] [--skip-delete] [--only-missing] [--delete-unknown] [--yes]
~~~

**OPTIONS**
Expand All @@ -146,6 +162,9 @@ wp media regenerate [<attachment-id>...] [--image_size=<image_size>] [--skip-del
[--only-missing]
Only generate thumbnails for images missing image sizes.

[--delete-unknown]
Only delete thumbnails for old unregistered image sizes.

[--yes]
Answer yes to the confirmation message. Confirmation only shows when no IDs passed as arguments.

Expand Down
36 changes: 36 additions & 0 deletions features/media-regenerate.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1685,3 +1685,39 @@ Feature: Regenerate WordPress attachments
Warning: No editor could be selected.
"""
And the return code should be 1

Scenario: Only delete missing image sizes
Given download:
| path | url |
| {CACHE_DIR}/large-image.jpg | http://wp-cli.org/behat-data/large-image.jpg |
And a wp-content/mu-plugins/media-settings.php file:
"""
<?php
add_action( 'after_setup_theme', function(){
add_image_size( 'test1', 125, 125, true );
});
"""
And I run `wp option update uploads_use_yearmonth_folders 0`

When I run `wp media import {CACHE_DIR}/large-image.jpg --title="My imported attachment" --porcelain`
Then save STDOUT as {ATTACHMENT_ID}
And the wp-content/uploads/large-image-125x125.jpg file should exist

Given a wp-content/mu-plugins/media-settings.php file:
"""
<?php
add_action( 'after_setup_theme', function(){
add_image_size( 'test2', 200, 200, true );
});
"""
When I try `wp media regenerate --delete-unknown --yes`
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
Then STDOUT should contain:
"""
Success: Regenerated 1 of 1 images.
"""
And STDOUT should contain:
"""
Deleted unknown image sizes for "My imported attachment"
"""
And the wp-content/uploads/large-image-125x125.jpg file should not exist
And the wp-content/uploads/large-image-200x200.jpg file should not exist
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
84 changes: 79 additions & 5 deletions src/Media_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class Media_Command extends WP_CLI_Command {
* [--only-missing]
* : Only generate thumbnails for images missing image sizes.
*
* [--delete-unknown]
* : Only delete thumbnails for old unregistered image sizes.
*
* [--yes]
* : Answer yes to the confirmation message. Confirmation only shows when no IDs passed as arguments.
*
Expand Down Expand Up @@ -130,6 +133,11 @@ public function regenerate( $args, $assoc_args = array() ) {
$skip_delete = true;
}

$delete_unknown = Utils\get_flag_value( $assoc_args, 'delete-unknown' );
if ( $delete_unknown ) {
$skip_delete = false;
}

$additional_mime_types = array();

if ( Utils\wp_version_compare( '4.7', '>=' ) ) {
Expand Down Expand Up @@ -165,7 +173,7 @@ public function regenerate( $args, $assoc_args = array() ) {
if ( 0 === $number % self::WP_CLEAR_OBJECT_CACHE_INTERVAL ) {
Utils\wp_clear_object_cache();
}
$this->process_regeneration( $post_id, $skip_delete, $only_missing, $image_size, $number . '/' . $count, $successes, $errors, $skips );
$this->process_regeneration( $post_id, $skip_delete, $only_missing, $delete_unknown, $image_size, $number . '/' . $count, $successes, $errors, $skips );
}

if ( $image_size ) {
Expand Down Expand Up @@ -587,7 +595,7 @@ private function make_copy( $path ) {
return $filename;
}

private function process_regeneration( $id, $skip_delete, $only_missing, $image_size, $progress, &$successes, &$errors, &$skips ) {
private function process_regeneration( $id, $skip_delete, $only_missing, $delete_unknown, $image_size, $progress, &$successes, &$errors, &$skips ) {

$title = get_the_title( $id );
if ( '' === $title ) {
Expand Down Expand Up @@ -615,6 +623,14 @@ private function process_regeneration( $id, $skip_delete, $only_missing, $image_

$original_meta = wp_get_attachment_metadata( $id );

if ( $delete_unknown ) {
$this->delete_unknown_image_sizes( $id, $fullsizepath );

WP_CLI::log( "$progress Deleted unknown image sizes for $att_desc." );
++$successes;
return;
}

$needs_regeneration = $this->needs_regeneration( $id, $fullsizepath, $is_pdf, $image_size, $skip_delete, $skip_it );

if ( $skip_it ) {
Expand Down Expand Up @@ -730,7 +746,7 @@ private function needs_regeneration( $att_id, $fullsizepath, $is_pdf, $image_siz
return true;
}

// Have sizes - check whether there're new ones or they've changed. Note that an attachment can have no sizes if it's on or below the thumbnail threshold.
// Have sizes - check whether they're new ones or they've changed. Note that an attachment can have no sizes if it's on or below the thumbnail threshold.

if ( $image_size ) {
if ( empty( $image_sizes[ $image_size ] ) ) {
Expand Down Expand Up @@ -778,8 +794,19 @@ private function image_sizes_differ( $image_sizes, $meta_sizes ) {
return false;
}

// Like WP's get_intermediate_image_sizes(), but removes sizes that won't be generated for a particular attachment due to its being on or below their thresholds,
// and returns associative array with size name => width/height entries, resolved to crop values if applicable.
/**
* Returns image sizes for a given attachment.
*
* Like WP's get_intermediate_image_sizes(), but removes sizes that won't be generated for a particular attachment due to it being on or below their thresholds,
* and returns associative array with size name => width/height entries, resolved to crop values if applicable.
*
* @param string $fullsizepath Filepath of the attachment
* @param bool $is_pdf Whether it is a PDF.
* @param array $metadata Attachment metadata.
* @param int $att_id Attachment ID.
*
* @return array|WP_Error Image sizes on success, WP_Error instance otherwise.
*/
private function get_intermediate_image_sizes_for_attachment( $fullsizepath, $is_pdf, $metadata, $att_id ) {

// Need to get width, height of attachment for image_resize_dimensions().
Expand Down Expand Up @@ -1323,4 +1350,51 @@ private function get_image_name( $basename, $slug ) {

return $slug . '.' . $extension;
}

/**
* Removes files for unknown/unregistered image sizes.
*
* Similar to {@see self::remove_old_images} but also updates metadata afterwards.
*
* @param int $id Attachment ID.
* @param string $fullsizepath Filepath of the attachment.
*
* @return void
*/
private function delete_unknown_image_sizes( $id, $fullsizepath ) {
$original_meta = wp_get_attachment_metadata( $id );

$image_sizes = wp_list_pluck( $this->get_registered_image_sizes(), 'name' );

$dir_path = dirname( $fullsizepath ) . '/';

$sizes_to_delete = array();

if ( isset( $original_meta['sizes'] ) ) {
foreach ( $original_meta['sizes'] as $size_name => $size_meta ) {
if ( 'full' === $size_name ) {
continue;
}

if ( ! in_array( $size_name, $image_sizes, true ) ) {
$intermediate_path = $dir_path . $size_meta['file'];
if ( $intermediate_path === $fullsizepath ) {
continue;
}

if ( file_exists( $intermediate_path ) ) {
unlink( $intermediate_path );
}

$sizes_to_delete[] = $size_name;
}
}

foreach ( $sizes_to_delete as $size_name ) {
unset( $original_meta['sizes'][ $size_name ] );
}
}

wp_update_attachment_metadata( $id, $original_meta );
}
}