Skip to content

Commit 6d30ccb

Browse files
committed
Update existing mechanism to generate the edited sources
Reuse the same function for initial creation but with the context addition. So the logic can be adjust based on the update mechanism in order to prevent infinite loops and reset the values of each existing mime type if was already defined.
1 parent 7408083 commit 6d30ccb

File tree

3 files changed

+84
-163
lines changed

3 files changed

+84
-163
lines changed

‎modules/images/webp-uploads/load.php‎

Lines changed: 46 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@
2323
* @see wp_generate_attachment_metadata()
2424
* @see webp_uploads_get_upload_image_mime_transforms()
2525
*
26-
* @param array $metadata An array with the metadata from this attachment.
27-
* @param int $attachment_id The ID of the attachment where the hook was dispatched.
26+
* @param array $metadata An array with the metadata from this attachment.
27+
* @param int $attachment_id The ID of the attachment where the hook was dispatched.
28+
* @param string $context The context of the current operation either: create or update.
2829
* @return array An array with the updated structure for the metadata before is stored in the database.
2930
*/
30-
function webp_uploads_create_sources_property( array $metadata, $attachment_id ) {
31+
function webp_uploads_create_sources_property( array $metadata, $attachment_id, $context = 'create' ) {
3132
// This should take place only on the JPEG image.
3233
$valid_mime_transforms = webp_uploads_get_upload_image_mime_transforms();
3334

@@ -37,7 +38,21 @@ function webp_uploads_create_sources_property( array $metadata, $attachment_id )
3738
return $metadata;
3839
}
3940

40-
$file = get_attached_file( $attachment_id, true );
41+
$is_update = 'update' === $context;
42+
if ( $is_update ) {
43+
if ( empty( $metadata['file'] ) ) {
44+
return $metadata;
45+
}
46+
$uploads = wp_get_upload_dir();
47+
if ( isset( $uploads['basedir'] ) ) {
48+
$file = path_join( $uploads['basedir'], $metadata['file'] );
49+
} else {
50+
return $metadata;
51+
}
52+
} else {
53+
$file = get_attached_file( $attachment_id, true );
54+
}
55+
4156
// File does not exist.
4257
if ( ! file_exists( $file ) ) {
4358
return $metadata;
@@ -48,15 +63,18 @@ function webp_uploads_create_sources_property( array $metadata, $attachment_id )
4863
$metadata['sources'] = array();
4964
}
5065

51-
if (
52-
empty( $metadata['sources'][ $mime_type ] ) &&
53-
in_array( $mime_type, $valid_mime_transforms[ $mime_type ], true )
54-
) {
55-
$metadata['sources'][ $mime_type ] = array(
56-
'file' => wp_basename( $file ),
57-
'filesize' => filesize( $file ),
58-
);
59-
wp_update_attachment_metadata( $attachment_id, $metadata );
66+
if ( $is_update && has_filter( 'wp_update_attachment_metadata', 'webp_uploads_update_attachment_metadata' ) ) {
67+
remove_filter( 'wp_update_attachment_metadata', 'webp_uploads_update_attachment_metadata' );
68+
}
69+
70+
if ( in_array( $mime_type, $valid_mime_transforms[ $mime_type ], true ) ) {
71+
if ( empty( $metadata['sources'][ $mime_type ] ) || $is_update ) {
72+
$metadata['sources'][ $mime_type ] = array(
73+
'file' => wp_basename( $file ),
74+
'filesize' => filesize( $file ),
75+
);
76+
wp_update_attachment_metadata( $attachment_id, $metadata );
77+
}
6078
}
6179

6280
$original_size_data = array(
@@ -71,8 +89,8 @@ function webp_uploads_create_sources_property( array $metadata, $attachment_id )
7189

7290
// Create the sources for the full sized image.
7391
foreach ( $valid_mime_transforms[ $mime_type ] as $targeted_mime ) {
74-
// If this property exists no need to create the image again.
75-
if ( ! empty( $metadata['sources'][ $targeted_mime ] ) ) {
92+
// If this property exists no need to create the image again unless is an update.
93+
if ( ! empty( $metadata['sources'][ $targeted_mime ] ) && ! $is_update ) {
7694
continue;
7795
}
7896

@@ -95,6 +113,11 @@ function webp_uploads_create_sources_property( array $metadata, $attachment_id )
95113

96114
// Make sure we have some sizes to work with, otherwise avoid any work.
97115
if ( empty( $metadata['sizes'] ) || ! is_array( $metadata['sizes'] ) ) {
116+
117+
if ( $is_update && ! has_filter( 'wp_update_attachment_metadata', 'webp_uploads_update_attachment_metadata' ) ) {
118+
add_filter( 'wp_update_attachment_metadata', 'webp_uploads_update_attachment_metadata', 10, 3 );
119+
}
120+
98121
return $metadata;
99122
}
100123

@@ -122,7 +145,7 @@ function webp_uploads_create_sources_property( array $metadata, $attachment_id )
122145
$properties['sources'] = array();
123146
}
124147

125-
if ( empty( $properties['sources'][ $current_mime ] ) ) {
148+
if ( empty( $properties['sources'][ $current_mime ] ) || $is_update ) {
126149
$properties['sources'][ $current_mime ] = array(
127150
'file' => isset( $properties['file'] ) ? $properties['file'] : '',
128151
'filesize' => 0,
@@ -138,7 +161,7 @@ function webp_uploads_create_sources_property( array $metadata, $attachment_id )
138161

139162
foreach ( $valid_mime_transforms[ $mime_type ] as $mime ) {
140163
// If this property exists no need to create the image again.
141-
if ( ! empty( $properties['sources'][ $mime ] ) ) {
164+
if ( ! empty( $properties['sources'][ $mime ] ) && ! $is_update ) {
142165
continue;
143166
}
144167

@@ -155,9 +178,13 @@ function webp_uploads_create_sources_property( array $metadata, $attachment_id )
155178
$metadata['sizes'][ $size_name ] = $properties;
156179
}
157180

181+
if ( $is_update && ! has_filter( 'wp_update_attachment_metadata', 'webp_uploads_update_attachment_metadata' ) ) {
182+
add_filter( 'wp_update_attachment_metadata', 'webp_uploads_update_attachment_metadata', 10, 3 );
183+
}
184+
158185
return $metadata;
159186
}
160-
add_filter( 'wp_generate_attachment_metadata', 'webp_uploads_create_sources_property', 10, 2 );
187+
add_filter( 'wp_generate_attachment_metadata', 'webp_uploads_create_sources_property', 10, 3 );
161188

162189
/**
163190
* Filter the image editor default output format mapping to select the most appropriate
@@ -684,139 +711,6 @@ function webp_uploads_update_rest_attachment( WP_REST_Response $response, WP_Pos
684711
}
685712
add_filter( 'rest_prepare_attachment', 'webp_uploads_update_rest_attachment', 10, 3 );
686713

687-
/**
688-
* Adds sources to metadata for an attachment.
689-
*
690-
* @since n.e.x.t
691-
*
692-
* @param array $metadata Metadata of the attachment.
693-
* @param array $valid_mime_transforms List of valid mime transforms for current image mime type.
694-
* @param string $file Path to original file.
695-
* @param array $main_images Path of all main image files of all mime types.
696-
* @param array $subsized_images Path of all subsized image file of all mime types.
697-
* @return array Metadata with sources added.
698-
*/
699-
function webp_uploads_update_sources( $metadata, $valid_mime_transforms, $file, $main_images, $subsized_images ) {
700-
$original_directory = pathinfo( $file, PATHINFO_DIRNAME );
701-
702-
foreach ( $valid_mime_transforms as $targeted_mime ) {
703-
// Add sources to original image metadata.
704-
$image_file = $main_images[ $targeted_mime ]['path'];
705-
706-
if ( ! file_exists( $image_file ) ) {
707-
continue;
708-
}
709-
710-
$metadata['sources'][ $targeted_mime ] = array(
711-
'file' => wp_basename( $image_file ),
712-
'filesize' => filesize( $image_file ),
713-
);
714-
715-
foreach ( $metadata['sizes'] as $size => $size_details ) {
716-
// Add sources to resized image metadata.
717-
$image_file = $original_directory . '/' . $subsized_images[ $targeted_mime ][ $size ]['file'];
718-
719-
if ( ! file_exists( $image_file ) ) {
720-
continue;
721-
}
722-
723-
$metadata['sizes'][ $size ]['sources'][ $targeted_mime ] = array(
724-
'file' => $subsized_images[ $targeted_mime ][ $size ]['file'],
725-
'filesize' => filesize( $image_file ),
726-
);
727-
}
728-
}
729-
730-
return $metadata;
731-
}
732-
733-
/**
734-
* Creates additional image formats when original image is edited.
735-
*
736-
* @since n.e.x.t
737-
*
738-
* @param bool|null $override Value to return instead of saving. Default null.
739-
* @param string $file Name of the file to be saved.
740-
* @param WP_Image_Editor $editor The image editor instance.
741-
* @param string $mime_type The mime type of the image.
742-
* @param int $post_id Attachment post ID.
743-
* @return bool|null Potentially modified $override value.
744-
*/
745-
function webp_uploads_update_image_onchange( $override, $file, $editor, $mime_type, $post_id ) {
746-
if ( null !== $override ) {
747-
return $override;
748-
}
749-
750-
$transforms = webp_uploads_get_upload_image_mime_transforms();
751-
if ( empty( $transforms[ $mime_type ] ) ) {
752-
return null;
753-
}
754-
755-
$mime_transforms = $transforms[ $mime_type ];
756-
add_filter(
757-
'wp_update_attachment_metadata',
758-
function ( $metadata, $post_meta_id ) use ( $post_id, $file, $mime_type, $editor, $mime_transforms ) {
759-
if ( $post_meta_id !== $post_id ) {
760-
return $metadata;
761-
}
762-
763-
// No sizes to be created.
764-
if ( empty( $metadata['sizes'] ) ) {
765-
return $metadata;
766-
}
767-
768-
$old_metadata = wp_get_attachment_metadata( $post_id );
769-
$resize_sizes = array();
770-
771-
foreach ( $old_metadata['sizes'] as $size_name => $size_details ) {
772-
if ( isset( $metadata['sizes'][ $size_name ] ) && ! empty( $metadata['sizes'][ $size_name ] ) &&
773-
$metadata['sizes'][ $size_name ]['file'] !== $old_metadata['sizes'][ $size_name ]['file'] ) {
774-
$resize_sizes[ $size_name ] = $metadata['sizes'][ $size_name ];
775-
}
776-
}
777-
778-
$allowed_mimes = array_flip( wp_get_mime_types() );
779-
$original_directory = pathinfo( $file, PATHINFO_DIRNAME );
780-
$filename = pathinfo( $file, PATHINFO_FILENAME );
781-
$main_images = array();
782-
$subsized_images = array();
783-
foreach ( $mime_transforms as $targeted_mime ) {
784-
if ( $targeted_mime === $mime_type ) {
785-
$main_images[ $targeted_mime ] = array( 'path' => $file );
786-
$subsized_images[ $targeted_mime ] = $metadata['sizes'];
787-
continue;
788-
}
789-
790-
if ( ! isset( $allowed_mimes[ $targeted_mime ] ) || ! is_string( $allowed_mimes[ $targeted_mime ] ) ) {
791-
continue;
792-
}
793-
794-
if ( ! $editor::supports_mime_type( $targeted_mime ) ) {
795-
continue;
796-
}
797-
798-
$extension = explode( '|', $allowed_mimes[ $targeted_mime ] );
799-
$destination = trailingslashit( $original_directory ) . "{$filename}.{$extension[0]}";
800-
801-
$result = $editor->save( $destination, $targeted_mime );
802-
803-
if ( is_wp_error( $result ) ) {
804-
continue;
805-
}
806-
807-
$subsized_images[ $targeted_mime ] = $editor->multi_resize( $resize_sizes );
808-
}
809-
810-
return webp_uploads_update_sources( $metadata, $mime_transforms, $file, $main_images, $subsized_images );
811-
},
812-
10,
813-
2
814-
);
815-
816-
return null;
817-
}
818-
add_filter( 'wp_save_image_editor_file', 'webp_uploads_update_image_onchange', 10, 7 );
819-
820714
/**
821715
* Inspect if the current call to `wp_update_attachment_metadata()` was done from within the context
822716
* of an edit to an attachment either restore or other type of edit, in that case we perform operations
@@ -841,7 +735,7 @@ function webp_uploads_update_attachment_metadata( $data, $attachment_id ) {
841735
switch ( $element['function'] ) {
842736
case 'wp_save_image':
843737
// Right after an image has been edited.
844-
return webp_uploads_backup_sources( $attachment_id, $data );
738+
return webp_uploads_create_sources_property( webp_uploads_backup_sources( $attachment_id, $data ), $attachment_id, 'update' );
845739
case 'wp_restore_image':
846740
// When an image has been restored.
847741
return webp_uploads_restore_image( $attachment_id, $data );

‎tests/modules/images/webp-uploads/webp-uploads-test.php‎

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -873,15 +873,31 @@ public function it_should_restore_the_sources_array_from_the_backup_when_an_imag
873873

874874
wp_restore_image( $attachment_id );
875875

876+
$this->assertImageHasSource( $attachment_id, 'image/jpeg' );
877+
$this->assertImageHasSource( $attachment_id, 'image/webp' );
878+
876879
$metadata = wp_get_attachment_metadata( $attachment_id );
877-
$this->assertArrayHasKey( 'sources', $metadata );
880+
878881
$this->assertSame( $backup_sources['full-orig'], $metadata['sources'] );
879882
$this->assertSame( $backup_sources, get_post_meta( $attachment_id, '_wp_attachment_backup_sources', true ) );
880883

881884
$backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
882-
foreach ( $metadata['sizes'] as $size_name => $properties ) {
883-
$this->assertArrayHasKey( 'sources', $backup_sizes[ $size_name . '-orig' ] );
884-
$this->assertSame( $backup_sizes[ $size_name . '-orig' ]['sources'], $properties['sources'] );
885+
foreach ( $backup_sizes as $size_name => $properties ) {
886+
// We are only interested in the original filenames to be compared against the backup and restored values.
887+
if ( false === strpos( $size_name, '-orig' ) ) {
888+
$this->assertSizeNameIsHashed( '', $size_name, "{$size_name} is not a valid edited name" );
889+
continue;
890+
}
891+
892+
$size_name = str_replace( '-orig', '', $size_name );
893+
// Full name is verified above.
894+
if ( 'full' === $size_name ) {
895+
continue;
896+
}
897+
898+
$this->assertArrayHasKey( $size_name, $metadata['sizes'] );
899+
$this->assertArrayHasKey( 'sources', $metadata['sizes'][ $size_name ] );
900+
$this->assertSame( $properties['sources'], $metadata['sizes'][ $size_name ]['sources'] );
885901
}
886902
}
887903

@@ -959,7 +975,16 @@ public function it_should_backup_the_image_when_all_images_except_the_thumbnail_
959975
$this->assertArrayHasKey( 'full-orig', $backup_sources );
960976
$this->assertSame( $metadata['sources'], $backup_sources['full-orig'] );
961977

962-
$this->assertArrayNotHasKey( 'sources', wp_get_attachment_metadata( $attachment_id ), 'The sources attributes was not removed from the metadata.' );
978+
$updated_metadata = wp_get_attachment_metadata( $attachment_id );
979+
980+
$this->assertArrayHasKey( 'sources', $updated_metadata );
981+
$this->assertNotSame( $metadata['sources'], $updated_metadata['sources'] );
982+
$this->assertImageHasSource( $attachment_id, 'image/jpeg' );
983+
$this->assertImageHasSource( $attachment_id, 'image/webp' );
984+
985+
foreach ( $updated_metadata['sources'] as $properties ) {
986+
$this->assertFileNameIsEdited( $properties['file'] );
987+
}
963988

964989
$backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
965990
$this->assertIsArray( $backup_sizes );

‎tests/utils/TestCase/ImagesTestCase.php‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
* @method void assertImageHasSizeSource( $attachment_id, $size, $mime_type, $message ) Asserts that the image has the appropriate source for the subsize.
1414
* @method void assertImageNotHasSource( $attachment_id, $mime_type, $message ) Asserts that the image doesn't have the appropriate source.
1515
* @method void assertImageNotHasSizeSource( $attachment_id, $size, $mime_type, $message ) Asserts that the image doesn't have the appropriate source for the subsize.
16-
* @method void assertFileNameIsEdited( string $filename ) Asserts that the provided file name was edited by WordPress contains an e{WITH_13_DIGITS} on the filename.
17-
* @method void assertSizeNameIsHashed( string $size_name, string $hashed_size_name ) Asserts that the provided size name is an edited name that contains a hash with digits.
16+
* @method void assertFileNameIsEdited( string $filename, string $message = '' ) Asserts that the provided file name was edited by WordPress contains an e{WITH_13_DIGITS} on the filename.
17+
* @method void assertSizeNameIsHashed( string $size_name, string $hashed_size_name, string $message = '' ) Asserts that the provided size name is an edited name that contains a hash with digits.
1818
*/
1919
abstract class ImagesTestCase extends WP_UnitTestCase {
2020

@@ -82,20 +82,22 @@ public static function assertImageNotHasSizeSource( $attachment_id, $size, $mime
8282
* Asserts that the provided file name was edited by WordPress contains an e{WITH_13_DIGITS} on the filename.
8383
*
8484
* @param string $filename The name of the filename to be asserted.
85+
* @param string $message The Error message used to display when the assertion fails.
8586
* @return void
8687
*/
87-
public static function assertFileNameIsEdited( $filename ) {
88-
self::assertRegExp( '/e\d{13}/', $filename );
88+
public static function assertFileNameIsEdited( $filename, $message = '' ) {
89+
self::assertRegExp( '/e\d{13}/', $filename, $message );
8990
}
9091

9192
/**
9293
* Asserts that the provided size name is an edited name that contains a hash with digits.
9394
*
9495
* @param string $size_name The size name we are looking for.
9596
* @param string $hashed_size_name The current size name we are comparing against.
97+
* @param string $message The Error message used to display when the assertion fails.
9698
* @return void
9799
*/
98-
public static function assertSizeNameIsHashed( $size_name, $hashed_size_name ) {
99-
self::assertRegExp( "/{$size_name}-\d{13}/", $hashed_size_name );
100+
public static function assertSizeNameIsHashed( $size_name, $hashed_size_name, $message = '' ) {
101+
self::assertRegExp( "/{$size_name}-\d{13}/", $hashed_size_name, $message );
100102
}
101103
}

0 commit comments

Comments
 (0)