diff --git a/modules/images/webp-uploads/load.php b/modules/images/webp-uploads/load.php
index 1e16b26bf0..8ffbcfad8c 100644
--- a/modules/images/webp-uploads/load.php
+++ b/modules/images/webp-uploads/load.php
@@ -486,16 +486,38 @@ function webp_uploads_img_tag_update_mime_type( $image, $context, $attachment_id
$basename = wp_basename( $metadata['file'] );
if ( $basename !== $replacement_source ) {
- $image = str_replace(
- $basename,
- $replacement_source,
- $image
- );
+
+ /**
+ * Filter to replace additional image source file, by locating the original
+ * mime types of the file and return correct file path in the end.
+ *
+ * Altering the $image tag through this filter effectively short-circuits the default replacement logic using the preferred MIME type.
+ *
+ * @since n.e.x.t
+ *
+ * @param string $image An
tag where the urls would be updated.
+ * @param int $attachment_id The ID of the attachment being modified.
+ * @param string $size The size name that would be used to create this image, out of the registered subsizes.
+ * @param string $target_mime The target mime in which the image should be created.
+ * @param string $context The context where this is function is being used.
+ */
+ $filtered_image = (string) apply_filters( 'webp_uploads_pre_replace_additional_image_source', $image, $attachment_id, 'full', $target_mime, $context );
+
+ // If filtered image is same as the image, run our own replacement logic, otherwise rely on the filtered image.
+ if ( $filtered_image === $image ) {
+ $image = str_replace(
+ $basename,
+ $metadata['sources'][ $target_mime ]['file'],
+ $image
+ );
+ } else {
+ $image = $filtered_image;
+ }
}
}
// Replace sub sizes for the image if present.
- foreach ( $metadata['sizes'] as $name => $size_data ) {
+ foreach ( $metadata['sizes'] as $size => $size_data ) {
if ( empty( $size_data['file'] ) ) {
continue;
}
@@ -518,11 +540,19 @@ function webp_uploads_img_tag_update_mime_type( $image, $context, $attachment_id
continue;
}
- $image = str_replace(
- $size_data['file'],
- $size_data['sources'][ $target_mime ]['file'],
- $image
- );
+ /** This filter is documented in modules/images/webp-uploads/load.php */
+ $filtered_image = (string) apply_filters( 'webp_uploads_pre_replace_additional_image_source', $image, $attachment_id, $size, $target_mime, $context );
+
+ // If filtered image is same as the image, run our own replacement logic, otherwise rely on the filtered image.
+ if ( $filtered_image === $image ) {
+ $image = str_replace(
+ $size_data['file'],
+ $size_data['sources'][ $target_mime ]['file'],
+ $image
+ );
+ } else {
+ $image = $filtered_image;
+ }
}
return $image;
diff --git a/tests/modules/images/webp-uploads/load-tests.php b/tests/modules/images/webp-uploads/load-tests.php
index 2d384be08e..dfd41c658c 100644
--- a/tests/modules/images/webp-uploads/load-tests.php
+++ b/tests/modules/images/webp-uploads/load-tests.php
@@ -608,4 +608,27 @@ public function it_should_replace_the_featured_image_to_web_p_when_requesting_th
$this->assertStringContainsString( '.webp', $featured_image );
$this->assertStringNotContainsString( '.jpeg', $featured_image );
}
+
+ /**
+ * Prevent replacing an image if image was uploaded via external source or plugin.
+ *
+ * @group webp_uploads_update_image_references
+ *
+ * @test
+ */
+ public function it_should_prevent_replacing_an_image_uploaded_via_external_source() {
+ remove_all_filters( 'webp_uploads_pre_replace_additional_image_source' );
+
+ add_filter(
+ 'webp_uploads_pre_replace_additional_image_source',
+ function() {
+ return '
';
+ }
+ );
+
+ $attachment_id = $this->factory->attachment->create_upload_object( TESTS_PLUGIN_DIR . '/tests/testdata/modules/images/car.jpeg' );
+
+ $tag = wp_get_attachment_image( $attachment_id, 'medium', false, array( 'class' => "wp-image-{$attachment_id}" ) );
+ $this->assertNotSame( $tag, webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ) );
+ }
}