diff --git a/classes/Tools/Storage/CLI/StorageCommands.php b/classes/Tools/Storage/CLI/StorageCommands.php index bfe8818f..b2f903cd 100644 --- a/classes/Tools/Storage/CLI/StorageCommands.php +++ b/classes/Tools/Storage/CLI/StorageCommands.php @@ -881,6 +881,9 @@ public function syncLocal( $args, $assoc_args ) * - desc * --- * + * [--skip-processed] + * : Skips images that have already been processed. + * * @when after_wp_load * * @param $args diff --git a/classes/Tools/Storage/StorageContentHooks.php b/classes/Tools/Storage/StorageContentHooks.php index 8df14fc5..0ae729f7 100644 --- a/classes/Tools/Storage/StorageContentHooks.php +++ b/classes/Tools/Storage/StorageContentHooks.php @@ -704,10 +704,16 @@ public function filterContent($content, $context = 'post') { foreach($replacements as $idSize => $data) { $idSizeParts = explode(',', $idSize); $content = $this->replaceImageInContent($idSizeParts[0], $data, $content); + if ($this->settings->forceWebP) { + $content = str_replace('.webp.webp', '.webp', $content); + } } foreach($resizedReplacements as $id => $data) { $content = $this->replaceImageInContent($data['id'], $data, $content); + if ($this->settings->forceWebP) { + $content = str_replace('.webp.webp', '.webp', $content); + } } if ($this->settings->replaceAnchorHrefs) { diff --git a/classes/Tools/Storage/StorageTool.php b/classes/Tools/Storage/StorageTool.php index ef40d4cd..830d6b73 100644 --- a/classes/Tools/Storage/StorageTool.php +++ b/classes/Tools/Storage/StorageTool.php @@ -2146,6 +2146,15 @@ public function getAttachmentURLFromMeta( $meta ) } $cdn = apply_filters( 'media-cloud/storage/override-cdn', StorageToolSettings::cdn() ); $docCdn = apply_filters( 'media-cloud/storage/override-doc-cdn', StorageToolSettings::docCdn() ); + $hasWebP = false; + $oldKey = $key = arrayPath( $meta, 's3/key', null ); + + if ( !empty($this->settings->forceWebP) && !empty(arrayPath( $meta, 's3/formats/webp', null )) ) { + $hasWebP = true; + $oldKey = $key; + $key = arrayPath( $meta, 's3/formats/webp', null ); + } + $type = typeFromMeta( $meta ); $privacy = arrayPath( $meta, 's3/privacy', 'private' ); $doSign = $this->client->usesSignedURLs( $type ) && $privacy != 'public-read' || $privacy !== 'public-read' && is_admin(); @@ -2155,9 +2164,9 @@ public function getAttachmentURLFromMeta( $meta ) if ( $doSign ) { if ( $privacy !== 'public-read' && is_admin() ) { - $url = $this->client->presignedUrl( $meta['s3']['key'], $this->client->signedURLExpirationForType( $type ) ); + $url = $this->client->presignedUrl( $key, $this->client->signedURLExpirationForType( $type ) ); } else { - $url = $this->client->url( $meta['s3']['key'], $type ); + $url = $this->client->url( $key, $type ); } @@ -2180,7 +2189,7 @@ public function getAttachmentURLFromMeta( $meta ) } else { if ( !empty($cdn) && empty($ignoreCDN) ) { - return $cdn . '/' . $meta['s3']['key']; + return $cdn . '/' . $key; } else { if ( isset( $meta['s3']['url'] ) ) { @@ -2195,11 +2204,14 @@ public function getAttachmentURLFromMeta( $meta ) 'png' ); if ( !in_array( $ext, $image_exts ) ) { - return trim( $docCdn, '/' ) . '/' . $meta['s3']['key']; + return trim( $docCdn, '/' ) . '/' . $key; } } $new_url = $meta['s3']['url']; + if ( $hasWebP && $this->settings->forceWebP ) { + $new_url = str_replace( $oldKey, $key, $new_url ); + } if ( !empty($new_url) ) { if ( strpos( $new_url, '//s3-.amazonaws' ) !== false ) { $new_url = str_replace( '//s3-.amazonaws', '//s3.amazonaws', $new_url ); @@ -2211,10 +2223,10 @@ public function getAttachmentURLFromMeta( $meta ) } try { - return $this->client->url( $meta['s3']['key'] ); + return $this->client->url( $key ); } catch ( \Exception $ex ) { Logger::error( - "Error trying to generate url for {$meta['s3']['key']}. Message:" . $ex->getMessage(), + "Error trying to generate url for {$key}. Message:" . $ex->getMessage(), [], __METHOD__, __LINE__ diff --git a/classes/Tools/Storage/StorageToolSettings.php b/classes/Tools/Storage/StorageToolSettings.php index 86fc878a..effa22cc 100644 --- a/classes/Tools/Storage/StorageToolSettings.php +++ b/classes/Tools/Storage/StorageToolSettings.php @@ -69,6 +69,7 @@ * @property bool $disableSrcSet * @property bool $disableEWWWBackgroundProcessing * @property bool $extractPDFPageSize + * @property bool $forceWebP * */ class StorageToolSettings extends ToolSettings { @@ -115,6 +116,7 @@ class StorageToolSettings extends ToolSettings { "disableEWWWBackgroundProcessing" => ["mcloud-storage-disable-eww-background-processing", null, true], 'queuedDeletesDelay' => ["mcloud-storage-queue-deletes-delay", null, 2], 'extractPDFPageSize' => ["mcloud-storage-extract-pdf-page-size", null, false], + 'forceWebP' => ["mcloud-storage-force-webp", null, false], ]; diff --git a/config/storage.config.php b/config/storage.config.php index 545b034f..f58718e0 100644 --- a/config/storage.config.php +++ b/config/storage.config.php @@ -376,6 +376,12 @@ "title" => "URL Replacement", "description" => "", "options" => [ + "mcloud-storage-force-webp" => [ + "title" => "Force WebP", + "description" => "When this is enabled, Media Cloud will output URLs for webp images, if a webp image has been generated for an attachment via the EWWW Image Optimization plugin.", + "type" => "checkbox", + "default" => false + ], "mcloud-storage-filter-content" => [ "title" => "Replace URLs", "description" => "When this is enabled, Media Cloud will replace URLs in content on the fly. You should not turn this off in most circumstances. However, if you've been using Media Cloud since day zero of your WordPress site, you may be able to turn this setting off.", diff --git a/ilab-media-tools.php b/ilab-media-tools.php index 45b506c6..a700db76 100644 --- a/ilab-media-tools.php +++ b/ilab-media-tools.php @@ -5,7 +5,7 @@ Plugin URI: https://github.com/interfacelab/ilab-media-tools Description: Automatically upload media to Amazon S3 and integrate with Imgix, a real-time image processing CDN. Boosts site performance and simplifies workflows. Author: interfacelab -Version: 4.5.17 +Version: 4.5.19 Requires PHP: 7.4 Author URI: http://interfacelab.io */ @@ -114,7 +114,7 @@ } // Version Defines -define( 'MEDIA_CLOUD_VERSION', '4.5.17' ); +define( 'MEDIA_CLOUD_VERSION', '4.5.19' ); define( 'MEDIA_CLOUD_INFO_VERSION', '4.0.2' ); define( 'MCLOUD_IS_BETA', false ); // Debugging diff --git a/readme.txt b/readme.txt index ac7b568d..8f931eeb 100644 --- a/readme.txt +++ b/readme.txt @@ -5,7 +5,7 @@ Requires at least: 4.9 Tested up to: 6.1 License: GPLv3 or later License URI: http://www.gnu.org/licenses/gpl-3.0.html -Stable tag: 4.5.17 +Stable tag: 4.5.19 Requires PHP: 7.4 Automatically store media on Amazon S3, Cloudflare R2, Google Cloud Storage, DigitalOcean Spaces + others. Serve CSS/JS assets through CDNs. Integrate with Imgix. @@ -105,6 +105,15 @@ Imgix is a content delivery network with a twist. In addition to distributing y == Changelog == += 4.5.19 - 12/9/2022 = + +* Added `--skip-processed` flag to `mediacloud:storage makewebp` command to skip any attachments that already have webp + metadata associated with them. (Premium) +* Added a setting to *Cloud Storage* settings called *Force WebP* that forces Media Cloud to return .webp urls for images + that have webp metadata associated with them. Note this does not do any sort of content negotiation or browser + sniffing, it simply returns the webp url for the image. Consider that only IE 11 and much older versions of Safari + do not support webp. + = 4.5.17 - 12/8/2022 = * Added `wp mediacloud:storage syncAllLocal` command to download all cloud storage files to your local server.