From 6b6e493c63e21e60bd0449c8354a9987ca75ac79 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Fri, 21 Jul 2023 12:27:05 +0100 Subject: [PATCH 01/14] Add a shortcircuit to bypass the SEO urls --- php/connect/class-api.php | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/php/connect/class-api.php b/php/connect/class-api.php index 1a91ff23f..75c2f092c 100644 --- a/php/connect/class-api.php +++ b/php/connect/class-api.php @@ -196,7 +196,19 @@ public function url( $resource, $function = null, $endpoint = false ) { $parts[] = $this->credentials['cloud_name']; } - if ( false === $endpoint && 'image' === $resource && 'upload' === $function ) { + /** + * Bypass Cloudinary's SEO URLs. + * + * @hook cloudinary_bypass_seo_url + * @since 3.1.4 + * + * @param $bypass_seo_url {bool} Whether to bypass SEO URLs. + * + * @return bool + */ + $bypass_seo_url = apply_filters( 'cloudinary_bypass_seo_url', false ); + + if ( false === $endpoint && 'image' === $resource && 'upload' === $function && ! $bypass_seo_url ) { $parts[] = 'images'; } else { $parts[] = $resource; @@ -283,9 +295,24 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra 'https:/', $this->url( $args['resource_type'], $asset_endpoint ), ); + + /** + * Bypass Cloudinary's SEO URLs. + * + * @hook cloudinary_bypass_seo_url + * @since 3.1.4 + * + * @param $bypass_seo_url {bool} Whether to bypass SEO URLs. + * + * @return {bool} + */ + $bypass_seo_url = apply_filters( 'cloudinary_bypass_seo_url', false ); + + $original_public_id = $public_id; + $base = Utils::pathinfo( $public_id ); // Only do dynamic naming and sizes if upload type. - if ( 'image' === $args['resource_type'] && 'upload' === $args['delivery_type'] ) { + if ( 'image' === $args['resource_type'] && 'upload' === $args['delivery_type'] && ! $bypass_seo_url ) { $new_path = $base['filename'] . '/' . $base['basename']; $public_id = str_replace( $base['basename'], $new_path, $public_id ); } From 7fa15188969267cee4e965d79a14c7b811eadc0c Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Fri, 21 Jul 2023 12:28:13 +0100 Subject: [PATCH 02/14] Add a filter for the public ID suffix --- php/connect/class-api.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/php/connect/class-api.php b/php/connect/class-api.php index 75c2f092c..752dc8f79 100644 --- a/php/connect/class-api.php +++ b/php/connect/class-api.php @@ -331,6 +331,22 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra $url_parts[] = self::generate_transformation_string( $args['transformation'], $args['resource_type'] ); } + if ( 'image' === $args['resource_type'] && 'upload' === $args['delivery_type'] && ! $bypass_seo_url ) { + /** + * Filter the SEO public ID. + * + * @hook cloudinary_seo_public_id + * @since 3.1.4 + * + * @param $public_id {string} The suffixed public_id. + * @param $original_public_id {string} The original public_id. + * @param $base {array} The pathinfo of the public_id. + * + * @return {string} + */ + $public_id = apply_filters( 'cloudinary_seo_public_id', $public_id, $original_public_id, $base ); + } + $url_parts[] = $args['version']; $url_parts[] = $public_id; From 4767e93ef084449d6bc2e9ccb83ee048fb0059d3 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Wed, 27 Sep 2023 18:21:28 +0100 Subject: [PATCH 03/14] Update documentation --- php/connect/class-api.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/php/connect/class-api.php b/php/connect/class-api.php index 752dc8f79..0e97937c3 100644 --- a/php/connect/class-api.php +++ b/php/connect/class-api.php @@ -200,11 +200,11 @@ public function url( $resource, $function = null, $endpoint = false ) { * Bypass Cloudinary's SEO URLs. * * @hook cloudinary_bypass_seo_url - * @since 3.1.4 + * @since 3.1.5 * * @param $bypass_seo_url {bool} Whether to bypass SEO URLs. * - * @return bool + * @return {bool} */ $bypass_seo_url = apply_filters( 'cloudinary_bypass_seo_url', false ); @@ -300,7 +300,7 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra * Bypass Cloudinary's SEO URLs. * * @hook cloudinary_bypass_seo_url - * @since 3.1.4 + * @since 3.1.5 * * @param $bypass_seo_url {bool} Whether to bypass SEO URLs. * @@ -336,7 +336,7 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra * Filter the SEO public ID. * * @hook cloudinary_seo_public_id - * @since 3.1.4 + * @since 3.1.5 * * @param $public_id {string} The suffixed public_id. * @param $original_public_id {string} The original public_id. From 46e65b705912115971f41378a2162403e5ebbe3b Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Thu, 28 Sep 2023 13:38:32 +0100 Subject: [PATCH 04/14] Add SEO support for lazy loaded images --- php/class-delivery.php | 16 ++++++++++++++++ src/js/inline-loader.js | 9 +++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/php/class-delivery.php b/php/class-delivery.php index 87321f0e8..7b06b56f6 100644 --- a/php/class-delivery.php +++ b/php/class-delivery.php @@ -1154,6 +1154,22 @@ protected function standardize_tag( $tag_element ) { $tag_element['atts']['data-version'] = $this->media->get_cloudinary_version( $tag_element['id'] ); + /** + * Bypass Cloudinary's SEO URLs. + * + * @hook cloudinary_bypass_seo_url + * @since 3.1.5 + * + * @param $bypass_seo_url {bool} Whether to bypass SEO URLs. + * + * @return {bool} + */ + $bypass_seo_url = apply_filters( 'cloudinary_bypass_seo_url', false ); + + $tag_element['atts']['data-seo'] = ! $bypass_seo_url; + + $tag_element['atts']['data-public-id'] = $this->plugin->get_component( 'connect' )->api->get_public_id( $tag_element['id'] ); + return $tag_element; } diff --git a/src/js/inline-loader.js b/src/js/inline-loader.js index 45a4c9573..5fe8ee4c0 100644 --- a/src/js/inline-loader.js +++ b/src/js/inline-loader.js @@ -215,13 +215,15 @@ const CloudinaryLoader = { nameExtension: scaledWidth + 'x' + scaledHeight, }; }, + getDeliveryMethod( image ) { + return image.dataset.seo && 'upload' === image.dataset.delivery ? 'images' : 'image/' + image.dataset.delivery; + }, getSizeURL( image, width ) { const newSize = this.scaleSize( image, width, true ); const parts = [ this.config.base_url, - 'image', - image.dataset.delivery, + this.getDeliveryMethod( image ),, 'upload' === image.dataset.delivery ? newSize.transformation : '', image.dataset.transformations, 'v' + image.dataset.version, @@ -236,8 +238,7 @@ const CloudinaryLoader = { const parts = [ this.config.base_url, - 'image', - image.dataset.delivery, + this.getDeliveryMethod( image ), newSize.transformation, this.config.placeholder, image.dataset.publicId From fdba5e476a639d1811340d9fbe1553c20f714a18 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Thu, 28 Sep 2023 13:41:27 +0100 Subject: [PATCH 05/14] Centralize the source of truth --- php/class-delivery.php | 3 ++- php/class-media.php | 2 +- php/connect/class-api.php | 12 +++++++----- php/relate/class-relationship.php | 1 + 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/php/class-delivery.php b/php/class-delivery.php index 7b06b56f6..84813752e 100644 --- a/php/class-delivery.php +++ b/php/class-delivery.php @@ -1198,9 +1198,10 @@ public function rebuild_tag( $tag_element ) { if ( apply_filters( 'cloudinary_apply_breakpoints', true ) ) { $meta = wp_get_attachment_metadata( $tag_element['id'] ); if ( ! empty( $meta['width'] ) && ! empty( $meta['height'] ) ) { + $relationship = Relationship::get_relationship( $tag_element['id'] ); // Check overwrite. $meta['overwrite_transformations'] = $tag_element['overwrite_transformations']; - $meta['cloudinary_id'] = $tag_element['atts']['data-public-id']; + $meta['cloudinary_id'] = $relationship->public_id; $meta['transformations'] = $tag_element['transformations']; // Add new srcset. $element = wp_image_add_srcset_and_sizes( $tag_element['original'], $meta, $tag_element['id'] ); diff --git a/php/class-media.php b/php/class-media.php index 180919a5b..5b5e41667 100644 --- a/php/class-media.php +++ b/php/class-media.php @@ -1397,7 +1397,7 @@ public function cloudinary_url( $attachment_id, $size = array(), $transformation // Make a copy as not to destroy the options in \Cloudinary::cloudinary_url(). $args = $pre_args; - $url = $this->plugin->components['connect']->api->cloudinary_url( $cloudinary_id, $args, $set_size ); + $url = $this->plugin->components['connect']->api->cloudinary_url( $cloudinary_id, $args, $set_size, $attachment_id ); // Check if this type is a preview only type. i.e PDF. if ( ! empty( $set_size ) && $this->is_preview_only( $attachment_id ) ) { diff --git a/php/connect/class-api.php b/php/connect/class-api.php index 0e97937c3..5a3b779d2 100644 --- a/php/connect/class-api.php +++ b/php/connect/class-api.php @@ -7,8 +7,9 @@ namespace Cloudinary\Connect; +use Cloudinary\Relate\Relationship; +use Cloudinary\Sync; use Cloudinary\Utils; -use function Cloudinary\get_plugin_instance; use Cloudinary\Plugin; use Cloudinary\Media; @@ -264,13 +265,14 @@ function ( $item ) use ( $transformation_index ) { /** * Generate a Cloudinary URL. * - * @param string|null $public_id The Public ID to get a url for. - * @param array $args Additional args. - * @param array $size The WP Size array. + * @param string|null $public_id The Public ID to get a url for. + * @param array $args Additional args. + * @param array $size The WP Size array. + * @param int|null $attachment_id The attachment ID. * * @return string */ - public function cloudinary_url( $public_id = null, $args = array(), $size = array() ) { + public function cloudinary_url( $public_id = null, $args = array(), $size = array(), $attachment_id = null ) { if ( null === $public_id ) { return 'https://' . $this->url( null, null ); diff --git a/php/relate/class-relationship.php b/php/relate/class-relationship.php index 56a1b9489..13a9b22ca 100644 --- a/php/relate/class-relationship.php +++ b/php/relate/class-relationship.php @@ -19,6 +19,7 @@ * @property string|null $public_id * @property string|null $signature * @property string|null $transformations + * @property string|null $sized_url */ class Relationship { From 932d5890bca51e6b2b8d961e80c1946f0291f924 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Thu, 28 Sep 2023 13:42:34 +0100 Subject: [PATCH 06/14] Centralize the get public id for Cloudinary assets --- php/connect/class-api.php | 87 ++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/php/connect/class-api.php b/php/connect/class-api.php index 5a3b779d2..c5998cfcb 100644 --- a/php/connect/class-api.php +++ b/php/connect/class-api.php @@ -200,8 +200,8 @@ public function url( $resource, $function = null, $endpoint = false ) { /** * Bypass Cloudinary's SEO URLs. * - * @hook cloudinary_bypass_seo_url - * @since 3.1.5 + * @hook cloudinary_bypass_seo_url + * @since 3.1.5 * * @param $bypass_seo_url {bool} Whether to bypass SEO URLs. * @@ -298,27 +298,7 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra $this->url( $args['resource_type'], $asset_endpoint ), ); - /** - * Bypass Cloudinary's SEO URLs. - * - * @hook cloudinary_bypass_seo_url - * @since 3.1.5 - * - * @param $bypass_seo_url {bool} Whether to bypass SEO URLs. - * - * @return {bool} - */ - $bypass_seo_url = apply_filters( 'cloudinary_bypass_seo_url', false ); - - $original_public_id = $public_id; - - $base = Utils::pathinfo( $public_id ); - // Only do dynamic naming and sizes if upload type. - if ( 'image' === $args['resource_type'] && 'upload' === $args['delivery_type'] && ! $bypass_seo_url ) { - $new_path = $base['filename'] . '/' . $base['basename']; - $public_id = str_replace( $base['basename'], $new_path, $public_id ); - } - + $base = Utils::pathinfo( $public_id ); // Add size. if ( ! empty( $size ) && is_array( $size ) ) { if ( ! empty( $size['transformation'] ) ) { @@ -333,20 +313,8 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra $url_parts[] = self::generate_transformation_string( $args['transformation'], $args['resource_type'] ); } - if ( 'image' === $args['resource_type'] && 'upload' === $args['delivery_type'] && ! $bypass_seo_url ) { - /** - * Filter the SEO public ID. - * - * @hook cloudinary_seo_public_id - * @since 3.1.5 - * - * @param $public_id {string} The suffixed public_id. - * @param $original_public_id {string} The original public_id. - * @param $base {array} The pathinfo of the public_id. - * - * @return {string} - */ - $public_id = apply_filters( 'cloudinary_seo_public_id', $public_id, $original_public_id, $base ); + if ( $attachment_id ) { + $public_id = $this->get_public_id( $attachment_id, $public_id ); } $url_parts[] = $args['version']; @@ -825,6 +793,51 @@ public function get_upload_prefix() { return $upload_prefix; } + /** + * Get the Cloudinary public_id. + * + * @param int $attachment_id The attachment ID. + * @param null|string $original_public_id The original public ID. + * + * @return string + */ + public function get_public_id( $attachment_id, $original_public_id = null ) { + + $relationship = Relationship::get_relationship( $attachment_id ); + $public_id = $relationship->public_id; + $delivery = $this->media->get_post_meta( $attachment_id, Sync::META_KEYS['delivery'], true ); + + /** + * Bypass Cloudinary's SEO URLs. + * + * @hook cloudinary_bypass_seo_url + * @since 3.1.5 + * + * @param $bypass_seo_url {bool} Whether to bypass SEO URLs. + * + * @return {bool} + */ + $bypass_seo_url = apply_filters( 'cloudinary_bypass_seo_url', false ); + + if ( $public_id && 'upload' === $delivery && ! $bypass_seo_url ) { + + /** + * Filter the SEO public ID. + * + * @hook cloudinary_seo_public_id + * @since 3.1.5 + * + * @param $public_id {string} The suffixed public_id. + * @param $original_public_id {string} The original public_id. + * + * @return {string} + */ + $public_id = apply_filters( 'cloudinary_seo_public_id', $public_id, $original_public_id ); + } + + return $public_id; + } + /** * Check if a string is a qualified `upload_prefix`. * From 6dca6e17974025e7388c6ce3c15c5c323499da42 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Thu, 28 Sep 2023 13:43:03 +0100 Subject: [PATCH 07/14] Update compiled assets --- js/inline-loader.asset.php | 2 +- js/inline-loader.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/inline-loader.asset.php b/js/inline-loader.asset.php index 3a34e2f86..380f5c0cf 100644 --- a/js/inline-loader.asset.php +++ b/js/inline-loader.asset.php @@ -1 +1 @@ - array(), 'version' => '25ccbb8ce37353267420'); + array(), 'version' => '4e42165f1fda84e18ed5'); diff --git a/js/inline-loader.js b/js/inline-loader.js index 2471a028c..e2c766225 100644 --- a/js/inline-loader.js +++ b/js/inline-loader.js @@ -1 +1 @@ -!function(){"use strict";function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,r=new Array(e);i%26%23x26A0%3B︎',e.rObserver.unobserve(t)}))):this.setupFallback(t)},buildImage:function(t){t.dataset.srcset?(t.cld_loaded=!0,t.srcset=t.dataset.srcset):(t.src=this.getSizeURL(t),t.dataset.responsive&&this.rObserver.observe(t))},inInitialView:function(t){var e=t.getBoundingClientRect();return this.aboveFold=e.top=e;)t-=i,this.sizeBands.push(t);"undefined"!=typeof IntersectionObserver&&this._setupObservers(),this.enabled=!0},_setupObservers:function(){var t=this,e={rootMargin:this.lazyThreshold+"px 0px "+this.lazyThreshold+"px 0px"},i=this.minPlaceholderThreshold<2*this.lazyThreshold?2*this.lazyThreshold:this.minPlaceholderThreshold,r={rootMargin:i+"px 0px "+i+"px 0px"};this.rObserver=new ResizeObserver((function(e,i){e.forEach((function(e){e.target.cld_loaded&&e.contentRect.width>=e.target.cld_loaded&&(e.target.src=t.getSizeURL(e.target))}))})),this.iObserver=new IntersectionObserver((function(e,i){e.forEach((function(e){e.isIntersecting&&(t.buildImage(e.target),i.unobserve(e.target),t.pObserver.unobserve(e.target))}))}),e),this.pObserver=new IntersectionObserver((function(e,i){e.forEach((function(e){e.isIntersecting&&(e.target.src=t.getPlaceholderURL(e.target),i.unobserve(e.target))}))}),r)},_calcThreshold:function(){var t=this.config.lazy_threshold.replace(/[^0-9]/g,""),e=0;switch(this.config.lazy_threshold.replace(/[0-9]/g,"").toLowerCase()){case"em":e=parseFloat(getComputedStyle(document.body).fontSize)*t;break;case"rem":e=parseFloat(getComputedStyle(document.documentElement).fontSize)*t;break;case"vh":e=window.innerHeight/t*100;break;default:e=t}this.lazyThreshold=parseInt(e,10)},_getDensity:function(){var t=this.config.dpr?this.config.dpr.replace("X",""):"off";if("off"===t)return this.density=1,1;var e=this.deviceDensity;"max"!==t&&"auto"!==e&&(t=parseFloat(t),e=e>Math.ceil(t)?t:e),this.density=e},scaleWidth:function(t,e,i){var r=parseInt(this.config.max_width),n=Math.round(r/i);if(!e){e=t.width;for(var a=Math.round(e/i);-1===this.sizeBands.indexOf(e)&&ar&&(e=r),t.originalWidtht.length)&&(e=t.length);for(var i=0,r=new Array(e);i%26%23x26A0%3B︎',e.rObserver.unobserve(t)}))):this.setupFallback(t)},buildImage:function(t){t.dataset.srcset?(t.cld_loaded=!0,t.srcset=t.dataset.srcset):(t.src=this.getSizeURL(t),t.dataset.responsive&&this.rObserver.observe(t))},inInitialView:function(t){var e=t.getBoundingClientRect();return this.aboveFold=e.top=e;)t-=i,this.sizeBands.push(t);"undefined"!=typeof IntersectionObserver&&this._setupObservers(),this.enabled=!0},_setupObservers:function(){var t=this,e={rootMargin:this.lazyThreshold+"px 0px "+this.lazyThreshold+"px 0px"},i=this.minPlaceholderThreshold<2*this.lazyThreshold?2*this.lazyThreshold:this.minPlaceholderThreshold,r={rootMargin:i+"px 0px "+i+"px 0px"};this.rObserver=new ResizeObserver((function(e,i){e.forEach((function(e){e.target.cld_loaded&&e.contentRect.width>=e.target.cld_loaded&&(e.target.src=t.getSizeURL(e.target))}))})),this.iObserver=new IntersectionObserver((function(e,i){e.forEach((function(e){e.isIntersecting&&(t.buildImage(e.target),i.unobserve(e.target),t.pObserver.unobserve(e.target))}))}),e),this.pObserver=new IntersectionObserver((function(e,i){e.forEach((function(e){e.isIntersecting&&(e.target.src=t.getPlaceholderURL(e.target),i.unobserve(e.target))}))}),r)},_calcThreshold:function(){var t=this.config.lazy_threshold.replace(/[^0-9]/g,""),e=0;switch(this.config.lazy_threshold.replace(/[0-9]/g,"").toLowerCase()){case"em":e=parseFloat(getComputedStyle(document.body).fontSize)*t;break;case"rem":e=parseFloat(getComputedStyle(document.documentElement).fontSize)*t;break;case"vh":e=window.innerHeight/t*100;break;default:e=t}this.lazyThreshold=parseInt(e,10)},_getDensity:function(){var t=this.config.dpr?this.config.dpr.replace("X",""):"off";if("off"===t)return this.density=1,1;var e=this.deviceDensity;"max"!==t&&"auto"!==e&&(t=parseFloat(t),e=e>Math.ceil(t)?t:e),this.density=e},scaleWidth:function(t,e,i){var r=parseInt(this.config.max_width),n=Math.round(r/i);if(!e){e=t.width;for(var a=Math.round(e/i);-1===this.sizeBands.indexOf(e)&&ar&&(e=r),t.originalWidth Date: Tue, 3 Oct 2023 14:05:50 +0100 Subject: [PATCH 08/14] Match Cloudinary naming convention --- php/class-media.php | 2 +- php/connect/class-api.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/php/class-media.php b/php/class-media.php index 5b5e41667..3443c3570 100644 --- a/php/class-media.php +++ b/php/class-media.php @@ -1383,7 +1383,7 @@ public function cloudinary_url( $attachment_id, $size = array(), $transformation 'secure' => is_ssl(), 'version' => $this->get_cloudinary_version( $attachment_id ), 'resource_type' => $resource_type, - 'delivery_type' => $delivery, + 'delivery' => $delivery, ); $set_size = array(); if ( 'upload' === $delivery ) { diff --git a/php/connect/class-api.php b/php/connect/class-api.php index c5998cfcb..162ebde8d 100644 --- a/php/connect/class-api.php +++ b/php/connect/class-api.php @@ -279,7 +279,7 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra } $defaults = array( 'resource_type' => 'image', - 'delivery_type' => 'upload', + 'delivery' => 'upload', 'version' => 'v1', ); $args = wp_parse_args( array_filter( $args ), $defaults ); @@ -291,7 +291,7 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra // Determine if we're dealing with a fetched. // ...or uploaded image and update the URL accordingly. - $asset_endpoint = filter_var( $public_id, FILTER_VALIDATE_URL ) ? 'fetch' : $args['delivery_type']; + $asset_endpoint = filter_var( $public_id, FILTER_VALIDATE_URL ) ? 'fetch' : $args['delivery']; $url_parts = array( 'https:/', From c107f0e9c4983c3930b4d5014ad4e769deb7365e Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Tue, 3 Oct 2023 14:12:15 +0100 Subject: [PATCH 09/14] Add `resource_type` and `asset_type` variables to define the `public_id` --- php/class-delivery.php | 9 ++++++++- php/connect/class-api.php | 29 ++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/php/class-delivery.php b/php/class-delivery.php index 84813752e..749ee7690 100644 --- a/php/class-delivery.php +++ b/php/class-delivery.php @@ -1168,7 +1168,14 @@ protected function standardize_tag( $tag_element ) { $tag_element['atts']['data-seo'] = ! $bypass_seo_url; - $tag_element['atts']['data-public-id'] = $this->plugin->get_component( 'connect' )->api->get_public_id( $tag_element['id'] ); + $resource_type = in_array( $tag_element['type'], array( 'image', 'video' ), true ) ? $tag_element['type'] : 'raw'; + + $args = array( + 'delivery' => $this->media->get_media_delivery( $tag_element['id'] ), + 'resource_type' => $resource_type, + ); + + $tag_element['atts']['data-public-id'] = $this->plugin->get_component( 'connect' )->api->get_public_id( $tag_element['id'], '', $args ); return $tag_element; } diff --git a/php/connect/class-api.php b/php/connect/class-api.php index 162ebde8d..a5b4b4d3d 100644 --- a/php/connect/class-api.php +++ b/php/connect/class-api.php @@ -314,7 +314,7 @@ public function cloudinary_url( $public_id = null, $args = array(), $size = arra } if ( $attachment_id ) { - $public_id = $this->get_public_id( $attachment_id, $public_id ); + $public_id = $this->get_public_id( $attachment_id, $public_id, $args ); } $url_parts[] = $args['version']; @@ -798,14 +798,18 @@ public function get_upload_prefix() { * * @param int $attachment_id The attachment ID. * @param null|string $original_public_id The original public ID. + * @param array $args The args. * * @return string */ - public function get_public_id( $attachment_id, $original_public_id = null ) { + public function get_public_id( $attachment_id, $original_public_id = null, $args = array() ) { $relationship = Relationship::get_relationship( $attachment_id ); - $public_id = $relationship->public_id; - $delivery = $this->media->get_post_meta( $attachment_id, Sync::META_KEYS['delivery'], true ); + $public_id = null; + + if ( $relationship instanceof Relationship ) { + $public_id = $relationship->public_id; + } /** * Bypass Cloudinary's SEO URLs. @@ -819,7 +823,22 @@ public function get_public_id( $attachment_id, $original_public_id = null ) { */ $bypass_seo_url = apply_filters( 'cloudinary_bypass_seo_url', false ); - if ( $public_id && 'upload' === $delivery && ! $bypass_seo_url ) { + if ( + $public_id + && ! $bypass_seo_url + && ( + // Get the SEO `public_id` for images with `upload` delivery. + ( + ! empty( $args['resource_type'] ) && 'image' === $args['resource_type'] + && ! empty( $args['delivery'] ) && 'upload' === $args['delivery'] + ) + // Get the SEO `public_id` for PDFs as they are regarded as images. + || ( + ! empty( $args['resource_type'] ) && 'image' === $args['resource_type'] + && 'application' === $relationship->asset_type + ) + ) + ) { /** * Filter the SEO public ID. From 3f410f3ac9795d697bc0287ba2715750a319b2c9 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Tue, 3 Oct 2023 14:12:38 +0100 Subject: [PATCH 10/14] Fix SEO `public_id` --- php/connect/class-api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/connect/class-api.php b/php/connect/class-api.php index a5b4b4d3d..4fac23922 100644 --- a/php/connect/class-api.php +++ b/php/connect/class-api.php @@ -851,7 +851,7 @@ public function get_public_id( $attachment_id, $original_public_id = null, $args * * @return {string} */ - $public_id = apply_filters( 'cloudinary_seo_public_id', $public_id, $original_public_id ); + $public_id = apply_filters( 'cloudinary_seo_public_id', "{$public_id}/{$public_id}.{$relationship->format}", $original_public_id ); } return $public_id; From 9c8d3970579572bfe313e2ba780e17c6d6e42f9d Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Tue, 3 Oct 2023 14:13:26 +0100 Subject: [PATCH 11/14] Cleanup --- php/class-delivery.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php/class-delivery.php b/php/class-delivery.php index 749ee7690..51c48257c 100644 --- a/php/class-delivery.php +++ b/php/class-delivery.php @@ -1140,7 +1140,7 @@ protected function standardize_tag( $tag_element ) { $local_size = filesize( get_attached_file( $tag_element['id'] ) ); } $remote_size = get_post_meta( $tag_element['id'], Sync::META_KEYS['remote_size'], true ); - $tag_element['atts']['data-filesize'] = size_format( $local_size ); + $tag_element['atts']['data-filesize'] = size_format( $local_size ); $tag_element['atts']['data-optsize'] = size_format( $remote_size ); $tag_element['atts']['data-optformat'] = get_post_meta( $tag_element['id'], Sync::META_KEYS['remote_format'], true ); if ( ! empty( $local_size ) && ! empty( $remote_size ) ) { @@ -1342,7 +1342,7 @@ public function parse_element( $element ) { $tag_element['height'] = ! empty( $attributes['height'] ) ? $attributes['height'] : $item['height']; $attributes['data-public-id'] = $public_id; $tag_element['format'] = $item['format']; - + if ( 'img' === $tag_element['tag'] ) { // Check if this is a crop or a scale. $has_size = $this->media->get_size_from_url( $this->sanitize_url( $raw_url ) ); From 0b985f7b33f4c166fa7af6fdfb087323cf6b6d1a Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Tue, 3 Oct 2023 14:28:14 +0100 Subject: [PATCH 12/14] Cleanup --- src/js/inline-loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/inline-loader.js b/src/js/inline-loader.js index 5fe8ee4c0..18a54019a 100644 --- a/src/js/inline-loader.js +++ b/src/js/inline-loader.js @@ -223,7 +223,7 @@ const CloudinaryLoader = { const parts = [ this.config.base_url, - this.getDeliveryMethod( image ),, + this.getDeliveryMethod( image ), 'upload' === image.dataset.delivery ? newSize.transformation : '', image.dataset.transformations, 'v' + image.dataset.version, From ea78a5c68ad4538d7322b055cfb11f0cb91d5918 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Tue, 3 Oct 2023 17:07:45 +0100 Subject: [PATCH 13/14] Prevent replacing shorter URLs too early --- php/class-delivery.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/php/class-delivery.php b/php/class-delivery.php index 51c48257c..41f050e9b 100644 --- a/php/class-delivery.php +++ b/php/class-delivery.php @@ -1032,6 +1032,10 @@ public function convert_tags( $content, $context = 'view' ) { $replacements = array_merge( $replacements, $aliases ); } + // Sort by length, so we replace the longest first and prevent early replacements. + $keys = array_map( 'strlen', array_keys( $replacements ) ); + array_multisort( $keys, SORT_DESC, $replacements ); + // Update the post meta cache. if ( is_singular() ) { $has_cache = array(); From 7d698881d36c1462d57c29270f10033a92720fc1 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Tue, 3 Oct 2023 18:44:15 +0100 Subject: [PATCH 14/14] =?UTF-8?q?The=20`public=5Fid=C2=B4=20might=20includ?= =?UTF-8?q?e=20a=20folder=20structure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- php/connect/class-api.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/php/connect/class-api.php b/php/connect/class-api.php index 4fac23922..a3f392c12 100644 --- a/php/connect/class-api.php +++ b/php/connect/class-api.php @@ -840,6 +840,9 @@ public function get_public_id( $attachment_id, $original_public_id = null, $args ) ) { + $parts = explode( '/', $public_id ); + $filename = end( $parts ); + /** * Filter the SEO public ID. * @@ -851,7 +854,7 @@ public function get_public_id( $attachment_id, $original_public_id = null, $args * * @return {string} */ - $public_id = apply_filters( 'cloudinary_seo_public_id', "{$public_id}/{$public_id}.{$relationship->format}", $original_public_id ); + $public_id = apply_filters( 'cloudinary_seo_public_id', "{$public_id}/{$filename}.{$relationship->format}", $original_public_id ); } return $public_id;