From 9715eaf6a7068c781aabfe297b118f77fbb74b64 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 09:05:04 +0000 Subject: [PATCH 1/8] chore(deps-dev): bump phpstan/phpstan from 2.1.31 to 2.1.32 --- updated-dependencies: - dependency-name: phpstan/phpstan dependency-version: 2.1.32 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index d743021e..18aefafa 100644 --- a/composer.lock +++ b/composer.lock @@ -904,11 +904,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.31", + "version": "2.1.32", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ead89849d879fe203ce9292c6ef5e7e76f867b96", - "reference": "ead89849d879fe203ce9292c6ef5e7e76f867b96", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e126cad1e30a99b137b8ed75a85a676450ebb227", + "reference": "e126cad1e30a99b137b8ed75a85a676450ebb227", "shasum": "" }, "require": { @@ -953,7 +953,7 @@ "type": "github" } ], - "time": "2025-10-10T14:14:11+00:00" + "time": "2025-11-11T15:18:17+00:00" }, { "name": "phpunit/php-code-coverage", From 49dffaf6a9c499df04e462e5ab47f773063f5fec Mon Sep 17 00:00:00 2001 From: Soare Robert-Daniel Date: Wed, 19 Nov 2025 17:09:54 +0200 Subject: [PATCH 2/8] fix: type verification for filter values Re-add the extra type verification for values that are computed with filters. --- inc/admin.php | 7 +++++-- inc/app_replacer.php | 10 +++++----- inc/tag_replacer.php | 15 +++++++++------ phpstan-baseline.neon | 12 ------------ 4 files changed, 19 insertions(+), 25 deletions(-) diff --git a/inc/admin.php b/inc/admin.php index 6f9f8884..0b5b705c 100755 --- a/inc/admin.php +++ b/inc/admin.php @@ -575,11 +575,14 @@ public function inline_bootstrap_script() { /** * Add settings links in the plugin listing page. * - * @param string[] $links Old plugin links. + * @param string[]|mixed $links Old plugin links. * - * @return string[] Altered links. + * @return string[]|mixed Altered links. */ public function add_action_links( $links ) { + if ( ! is_array( $links ) ) { + return $links; + } return array_merge( $links, [ diff --git a/inc/app_replacer.php b/inc/app_replacer.php index 6ed4dbc2..a76d7654 100644 --- a/inc/app_replacer.php +++ b/inc/app_replacer.php @@ -654,10 +654,10 @@ public function url_has_dam_flag( $url ) { /** * Get the optimized image url for the image url. * - * @param string $url The image URL. - * @param mixed $width The image width. - * @param mixed $height The image height. - * @param array $resize The resize properties. + * @param string $url The image URL. + * @param mixed $width The image width. + * @param mixed $height The image height. + * @param array|mixed $resize The resize properties. * * @return string */ @@ -668,7 +668,7 @@ protected function get_optimized_image_url( $url, $width, $height, $resize = [] ->width( $width ) ->height( $height ); - if ( ! empty( $resize['type'] ) ) { + if ( is_array( $resize ) && ! empty( $resize['type'] ) ) { $optimized_image->resize( $resize['type'], $resize['gravity'] ?? Position::CENTER, $resize['enlarge'] ?? false ); } diff --git a/inc/tag_replacer.php b/inc/tag_replacer.php index 75372f50..78cc5f87 100644 --- a/inc/tag_replacer.php +++ b/inc/tag_replacer.php @@ -809,15 +809,18 @@ public function change_url_for_size( $original_url, $width, $height, $dpr = 1 ) /** * Replace image URLs in the srcset attributes and in case there is a resize in action, also replace the sizes. * - * @param array $sources Array of image sources. - * @param array{0: int, 1: int}|int[] $size_array Array of width and height values in pixels (in that order). - * @param string $image_src The 'src' of the image. - * @param array $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'. - * @param int $attachment_id Image attachment ID or 0. + * @param array|mixed $sources Array of image sources. + * @param array{0: int, 1: int}|int[] $size_array Array of width and height values in pixels (in that order). + * @param string $image_src The 'src' of the image. + * @param array $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'. + * @param int $attachment_id Image attachment ID or 0. * - * @return array + * @return array|mixed */ public function filter_srcset_attr( $sources = [], $size_array = [], $image_src = '', $image_meta = [], $attachment_id = 0 ) { + if ( ! is_array( $sources ) ) { + return $sources; + } if ( Optml_Media_Offload::is_uploaded_image( $image_src ) ) { return $sources; } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index deb5805c..a002da25 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -516,12 +516,6 @@ parameters: count: 1 path: inc/app_replacer.php - - - message: '#^Method Optml_App_Replacer\:\:get_optimized_image_url\(\) has parameter \$resize with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: inc/app_replacer.php - - message: '#^Method Optml_App_Replacer\:\:get_upload_resource\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue @@ -2790,12 +2784,6 @@ parameters: count: 1 path: inc/tag_replacer.php - - - message: '#^Method Optml_Tag_Replacer\:\:filter_srcset_attr\(\) return type has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: inc/tag_replacer.php - - message: '#^Method Optml_Tag_Replacer\:\:init\(\) has no return type specified\.$#' identifier: missingType.return From a0cb5e05f36bdb20151f969f8723a3e0ba3b84d8 Mon Sep 17 00:00:00 2001 From: selul Date: Wed, 3 Dec 2025 15:01:30 +0200 Subject: [PATCH 3/8] attempt to fix https://wordpress.org/support/topic/fatal-error-on-lazy-load-is-breaking-woocommerce-add-to-cart-for-mix-and-match/ --- inc/lazyload_replacer.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/inc/lazyload_replacer.php b/inc/lazyload_replacer.php index 15fd4534..6d4ebb71 100644 --- a/inc/lazyload_replacer.php +++ b/inc/lazyload_replacer.php @@ -115,6 +115,11 @@ public static function get_background_lazyload_selectors() { return self::$background_lazyload_selectors; } + if ( ! isset( self::instance()->settings ) ) { + self::$background_lazyload_selectors = []; + + return self::$background_lazyload_selectors; + } if ( self::instance()->settings->get( 'bg_replacer' ) === 'disabled' ) { self::$background_lazyload_selectors = []; return self::$background_lazyload_selectors; From 4f49a2da77df2a1f820af6f147d5ccb43169d4f3 Mon Sep 17 00:00:00 2001 From: selul Date: Wed, 3 Dec 2025 15:09:39 +0200 Subject: [PATCH 4/8] attempt to fix https://wordpress.org/support/topic/fatal-error-on-lazy-load-is-breaking-woocommerce-add-to-cart-for-mix-and-match/ --- .github/workflows/test-php.yml | 2 +- inc/lazyload_replacer.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-php.yml b/.github/workflows/test-php.yml index 9d019b4d..f4d3c4d8 100644 --- a/.github/workflows/test-php.yml +++ b/.github/workflows/test-php.yml @@ -41,7 +41,7 @@ jobs: - name: Setup PHP version uses: shivammathur/setup-php@v2 with: - php-version: ${{ matrix.php-version }} + php-version: ${{ matrix.php-versions }} extensions: simplexml, mysql tools: phpunit-polyfills:1.1 - name: Checkout source code diff --git a/inc/lazyload_replacer.php b/inc/lazyload_replacer.php index 6d4ebb71..1284a71e 100644 --- a/inc/lazyload_replacer.php +++ b/inc/lazyload_replacer.php @@ -115,7 +115,7 @@ public static function get_background_lazyload_selectors() { return self::$background_lazyload_selectors; } - if ( ! isset( self::instance()->settings ) ) { + if ( self::instance()->settings === null ) { self::$background_lazyload_selectors = []; return self::$background_lazyload_selectors; From e6ef894a7a87cec7e43f04883c90f8c3dd4f25f1 Mon Sep 17 00:00:00 2001 From: selul Date: Wed, 3 Dec 2025 15:12:25 +0200 Subject: [PATCH 5/8] fix tests compats --- tests/test-lazyload-viewport.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-lazyload-viewport.php b/tests/test-lazyload-viewport.php index dfeb8c66..93930c70 100644 --- a/tests/test-lazyload-viewport.php +++ b/tests/test-lazyload-viewport.php @@ -489,7 +489,7 @@ private function storeMockProfileData( $deviceType, $above_fold_images = [], $bgSelectors = [], - $lcpData = [], + $lcpData = [] ) { Optml_Manager::instance()->page_profiler->store( $profileId, From 4514c15ba346f510c1ebdd626468aef3536ddd47 Mon Sep 17 00:00:00 2001 From: selul Date: Wed, 3 Dec 2025 15:16:33 +0200 Subject: [PATCH 6/8] fix tests compats --- .github/workflows/test-php.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-php.yml b/.github/workflows/test-php.yml index f4d3c4d8..134fd5f2 100644 --- a/.github/workflows/test-php.yml +++ b/.github/workflows/test-php.yml @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: [ '7.4', '8.0', '8.1', '8.2', '8.3' ] + php-versions: [ '8.0', '8.1', '8.2', '8.3' ] services: database: image: mysql:latest From 6d050108c20efe3d26b75cfa81ed51364ecd9bd0 Mon Sep 17 00:00:00 2001 From: selul Date: Thu, 4 Dec 2025 14:10:43 +0200 Subject: [PATCH 7/8] Enhance image URL handling when the image is from DAM inside the editor - Added logic to extract the original URL from Optimole URLs in the `get_optimized_image_url` method. - Moved the `is_dam_url` method to the `Optml_Dam_Offload_Utils` trait for better organization. - Updated the `Normalizer` trait to handle specific URL patterns. - Introduced new tests for `get_unoptimized_url` to cover various scenarios, including non-Optimole URLs and edge cases. - Prevented cache clearing actions during tests to avoid errors related to cache compatibility. https://secure.helpscout.net/conversation/3142052654/476408?viewId=2353196 --- inc/app_replacer.php | 3 + inc/traits/dam_offload_utils.php | 86 +++++++++++++---- inc/traits/normalizer.php | 4 + inc/url_replacer.php | 10 -- tests/bootstrap.php | 5 + tests/test-generic.php | 153 +++++++++++++++++++++++++++++++ 6 files changed, 231 insertions(+), 30 deletions(-) diff --git a/inc/app_replacer.php b/inc/app_replacer.php index a76d7654..48be9566 100644 --- a/inc/app_replacer.php +++ b/inc/app_replacer.php @@ -664,6 +664,9 @@ public function url_has_dam_flag( $url ) { protected function get_optimized_image_url( $url, $width, $height, $resize = [] ) { $width = is_int( $width ) ? $width : 'auto'; $height = is_int( $height ) ? $height : 'auto'; + // If the image is already using Optimole URL, we extract the source to rebuild it. + $url = $this->get_unoptimized_url( $url ); + $optimized_image = Optimole::image( $url, $this->settings->get( 'cache_buster' ) ) ->width( $width ) ->height( $height ); diff --git a/inc/traits/dam_offload_utils.php b/inc/traits/dam_offload_utils.php index 08509975..ec9e6764 100644 --- a/inc/traits/dam_offload_utils.php +++ b/inc/traits/dam_offload_utils.php @@ -3,6 +3,16 @@ trait Optml_Dam_Offload_Utils { use Optml_Normalizer; + /** + * Check if this contains the DAM flag. + * + * @param string $url The URL to check. + * + * @return bool + */ + private function is_dam_url( $url ) { + return strpos( $url, Optml_Dam::URL_DAM_FLAG ) !== false; + } /** * Checks that the attachment is a DAM image. * @@ -239,6 +249,31 @@ private function is_completed_offload( $id ) { return false; } + /** + * Get the attachment ID from optimole ID. + * + * @param string $optimole_id The optimole ID. + * + * @return int + */ + private function get_attachement_id_from_optimole_id( string $optimole_id ): int { + global $wpdb; + + $id = $wpdb->get_var( + $wpdb->prepare( + " + SELECT post_id + FROM {$wpdb->postmeta} + WHERE meta_key = %s + AND meta_value = %s + LIMIT 1 + ", + Optml_Dam::OM_DAM_IMPORTED_FLAG, + $optimole_id + ) + ); + return empty( $id ) ? 0 : (int) $id; + } /** * Get the attachment ID from URL. * @@ -253,32 +288,43 @@ private function attachment_url_to_post_id( $input_url ) { return (int) $cached; } - $url = $this->strip_image_size( $input_url ); + if ( $this->is_dam_url( $input_url ) ) { + // The DAM are stored as attachments of format /id:/ + $pattern = '#/' . Optml_Media_Offload::KEYS['uploaded_flag'] . '([^/]+)#'; + if ( preg_match( $pattern, $input_url, $m ) ) { + $attachment_id = $this->get_attachement_id_from_optimole_id( $m[1] ); + } else { + $attachment_id = 0; + } + } else { - $attachment_id = attachment_url_to_postid( $url ); + $url = $this->strip_image_size( $input_url ); - if ( $attachment_id === 0 && ! $this->is_scaled_url( $url ) ) { - $scaled_url = $this->get_scaled_url( $url ); + $attachment_id = attachment_url_to_postid( $url ); - $attachment_id = attachment_url_to_postid( $scaled_url ); - } + if ( $attachment_id === 0 && ! $this->is_scaled_url( $url ) ) { + $scaled_url = $this->get_scaled_url( $url ); - /* - * TODO: The logic is a mess, we need to refactor at some point. - * Websites may transition between 'www' subdomains and apex domains, potentially breaking references to hosted images. This can cause issues when attempting to match attachment IDs if images are linked using outdated domains. The logic is checking for alternative domains and consider the use of 'scaled' prefixes in image URLs for large images, which might affect ID matching. - */ - if ( $attachment_id === 0 ) { - if ( strpos( $url, 'www.' ) !== false ) { - $variant_url = str_replace( 'www.', '', $url ); - $attachment_id = attachment_url_to_postid( $variant_url ); - } else { - $variant_url = str_replace( '://', '://www.', $url ); - $attachment_id = attachment_url_to_postid( $variant_url ); + $attachment_id = attachment_url_to_postid( $scaled_url ); } - if ( $attachment_id === 0 && ! $this->is_scaled_url( $variant_url ) ) { - $scaled_url = $this->get_scaled_url( $variant_url ); - $attachment_id = attachment_url_to_postid( $scaled_url ); + /* + * TODO: The logic is a mess, we need to refactor at some point. + * Websites may transition between 'www' subdomains and apex domains, potentially breaking references to hosted images. This can cause issues when attempting to match attachment IDs if images are linked using outdated domains. The logic is checking for alternative domains and consider the use of 'scaled' prefixes in image URLs for large images, which might affect ID matching. + */ + if ( $attachment_id === 0 ) { + if ( strpos( $url, 'www.' ) !== false ) { + $variant_url = str_replace( 'www.', '', $url ); + $attachment_id = attachment_url_to_postid( $variant_url ); + } else { + $variant_url = str_replace( '://', '://www.', $url ); + $attachment_id = attachment_url_to_postid( $variant_url ); + } + if ( $attachment_id === 0 && ! $this->is_scaled_url( $variant_url ) ) { + $scaled_url = $this->get_scaled_url( $variant_url ); + + $attachment_id = attachment_url_to_postid( $scaled_url ); + } } } Optml_Attachment_Cache::set_cached_attachment_id( $input_url, $attachment_id ); diff --git a/inc/traits/normalizer.php b/inc/traits/normalizer.php index e1bd1522..a0c2f713 100644 --- a/inc/traits/normalizer.php +++ b/inc/traits/normalizer.php @@ -53,6 +53,10 @@ public function get_unoptimized_url( $url ) { } // If the url is an uploaded image, return the url if ( Optml_Media_Offload::is_uploaded_image( $url ) ) { + $pattern = '#/id:([^/]+)/((?:https?|http)://\S+)#'; + if ( preg_match( $pattern, $url, $matches ) ) { + $url = $matches[0]; + } return $url; } diff --git a/inc/url_replacer.php b/inc/url_replacer.php index f6eca2a4..1540f90c 100644 --- a/inc/url_replacer.php +++ b/inc/url_replacer.php @@ -409,16 +409,6 @@ private function get_dam_url( Image $image ) { return $url; } - /** - * Check if this contains the DAM flag. - * - * @param string $url The URL to check. - * - * @return bool - */ - private function is_dam_url( $url ) { - return strpos( $url, Optml_Dam::URL_DAM_FLAG ) !== false; - } /** * Check if the URL is offloaded. diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 3e4a50c0..ea778477 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -66,6 +66,10 @@ function( $message ) { } } require dirname( dirname( __FILE__ ) ) . '/optimole-wp.php'; + + // Prevent cache clearing actions during tests to avoid errors from cache compatibility classes + // This filter prevents optml_settings_updated and optml_clear_cache from being triggered + add_filter( 'optml_dont_trigger_settings_updated', '__return_true' ); } tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' ); @@ -83,6 +87,7 @@ function( $message ) { // Activate Optimole plugin activate_plugin( 'optimole-wp/optimole-wp.php' ); + // Set up the current logged in user global $current_user; diff --git a/tests/test-generic.php b/tests/test-generic.php index 538fcc59..fef9a2a9 100644 --- a/tests/test-generic.php +++ b/tests/test-generic.php @@ -44,4 +44,157 @@ function test_domain_hash() { $this->assertEquals( $this->to_domain_hash("//www.domain.com/"), $value ); $this->assertNotEquals( $this->to_domain_hash("https://something.com/"), $value ); } + + /** + * Test get_unoptimized_url with non-Optimole URLs. + */ + function test_get_unoptimized_url_non_optimole() { + // Initialize config for testing + $settings = new Optml_Settings(); + $settings->update( 'service_data', [ + 'cdn_key' => 'test123', + 'cdn_secret' => '12345', + 'whitelist' => [ 'example.com', 'example.org' ], + ] ); + Optml_Config::init( [ + 'key' => 'test123', + 'secret' => '12345', + ] ); + + // Non-Optimole URLs should be returned as-is + $url = 'http://example.org/wp-content/uploads/image.jpg'; + $this->assertEquals( $url, $this->get_unoptimized_url( $url ) ); + + $url = 'https://example.com/image.png'; + $this->assertEquals( $url, $this->get_unoptimized_url( $url ) ); + + $url = '/wp-content/uploads/image.jpg'; + $this->assertEquals( $url, $this->get_unoptimized_url( $url ) ); + } + + /** + * Test get_unoptimized_url with Optimole URLs (regular images). + */ + function test_get_unoptimized_url_optimole_regular() { + // Initialize config for testing + $settings = new Optml_Settings(); + $settings->update( 'service_data', [ + 'cdn_key' => 'test123', + 'cdn_secret' => '12345', + 'whitelist' => [ 'example.com', 'example.org' ], + ] ); + Optml_Config::init( [ + 'key' => 'test123', + 'secret' => '12345', + ] ); + + // Optimole URL with regular image - should extract original URL after second 'http' + $optimole_url = 'https://test123.i.optimole.com/cb:test/w:800/h:600/q:mauto/http://example.org/wp-content/uploads/image.jpg'; + $expected = 'http://example.org/wp-content/uploads/image.jpg'; + $this->assertEquals( $expected, $this->get_unoptimized_url( $optimole_url ) ); + + // Optimole URL with https in original + $optimole_url = 'https://test123.i.optimole.com/cb:test/w:800/h:600/q:mauto/https://example.org/wp-content/uploads/image.jpg'; + $expected = 'https://example.org/wp-content/uploads/image.jpg'; + $this->assertEquals( $expected, $this->get_unoptimized_url( $optimole_url ) ); + + // Optimole URL with query parameters + $optimole_url = 'https://test123.i.optimole.com/cb:test/w:800/h:600/q:mauto/http://example.org/wp-content/uploads/image.jpg?param=value'; + $expected = 'http://example.org/wp-content/uploads/image.jpg?param=value'; + $this->assertEquals( $expected, $this->get_unoptimized_url( $optimole_url ) ); + } + + /** + * Test get_unoptimized_url with uploaded images (offloaded images). + */ + function test_get_unoptimized_url_uploaded_image() { + // Initialize config for testing + $settings = new Optml_Settings(); + $settings->update( 'service_data', [ + 'cdn_key' => 'test123', + 'cdn_secret' => '12345', + 'whitelist' => [ 'example.com', 'example.org' ], + ] ); + Optml_Config::init( [ + 'key' => 'test123', + 'secret' => '12345', + ] ); + + // Uploaded image URL with /id: pattern - should extract original URL + $uploaded_url = 'https://test123.i.optimole.com/cb:test/w:800/h:600/q:mauto/id:abc123/http://example.org/wp-content/uploads/image.jpg'; + $expected = '/id:abc123/http://example.org/wp-content/uploads/image.jpg'; + $result = $this->get_unoptimized_url( $uploaded_url ); + $this->assertStringContainsString( '/id:abc123/', $result ); + $this->assertStringContainsString( 'http://example.org/wp-content/uploads/image.jpg', $result ); + + // Uploaded image URL with https in original + $uploaded_url = 'https://test123.i.optimole.com/cb:test/w:800/h:600/q:mauto/id:xyz789/https://example.org/wp-content/uploads/image.jpg'; + $expected = '/id:xyz789/https://example.org/wp-content/uploads/image.jpg'; + $result = $this->get_unoptimized_url( $uploaded_url ); + $this->assertStringContainsString( '/id:xyz789/', $result ); + $this->assertStringContainsString( 'https://example.org/wp-content/uploads/image.jpg', $result ); + } + + /** + * Test get_unoptimized_url edge cases. + */ + function test_get_unoptimized_url_edge_cases() { + // Initialize config for testing + $settings = new Optml_Settings(); + $settings->update( 'service_data', [ + 'cdn_key' => 'test123', + 'cdn_secret' => '12345', + 'whitelist' => [ 'example.com', 'example.org' ], + ] ); + Optml_Config::init( [ + 'key' => 'test123', + 'secret' => '12345', + ] ); + + // Optimole URL without second 'http' - should return as-is + $optimole_url = 'https://test123.i.optimole.com/cb:test/w:800/h:600/q:mauto'; + $this->assertEquals( $optimole_url, $this->get_unoptimized_url( $optimole_url ) ); + + // Empty string + $this->assertEquals( '', $this->get_unoptimized_url( '' ) ); + + // URL with only one 'http' occurrence + $optimole_url = 'https://test123.i.optimole.com/cb:test/w:800/h:600/q:mauto/image.jpg'; + $this->assertEquals( $optimole_url, $this->get_unoptimized_url( $optimole_url ) ); + + // Uploaded image URL without matching pattern - should return as-is + $uploaded_url = 'https://test123.i.optimole.com/cb:test/w:800/h:600/q:mauto/id:abc123/image.jpg'; + $result = $this->get_unoptimized_url( $uploaded_url ); + // Should return the URL as-is since pattern doesn't match + $this->assertEquals( $uploaded_url, $result ); + } + + /** + * Test get_unoptimized_url with custom domain configuration. + */ + function test_get_unoptimized_url_custom_domain() { + // Initialize config with custom domain + $settings = new Optml_Settings(); + $settings->update( 'service_data', [ + 'cdn_key' => 'test123', + 'cdn_secret' => '12345', + 'whitelist' => [ 'example.com', 'example.org' ], + 'domain' => 'cdn.example.com', + 'is_cname_assigned' => 'yes', + ] ); + Optml_Config::init( [ + 'key' => 'test123', + 'secret' => '12345', + 'domain' => 'cdn.example.com', + ] ); + + // Custom domain Optimole URL + $optimole_url = 'https://cdn.example.com/cb:test/w:800/h:600/q:mauto/http://example.org/wp-content/uploads/image.jpg'; + $expected = 'http://example.org/wp-content/uploads/image.jpg'; + $this->assertEquals( $expected, $this->get_unoptimized_url( $optimole_url ) ); + + // Non-Optimole URL should still return as-is + $url = 'http://example.org/wp-content/uploads/image.jpg'; + $this->assertEquals( $url, $this->get_unoptimized_url( $url ) ); + } } From 02ce6f2d18f7cafd0e5be4841d93a789fb370820 Mon Sep 17 00:00:00 2001 From: selul Date: Thu, 4 Dec 2025 21:07:09 +0200 Subject: [PATCH 8/8] Refactor attachment ID retrieval logic in DAM URL handling --- inc/traits/dam_offload_utils.php | 54 +++++++++++++++++--------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/inc/traits/dam_offload_utils.php b/inc/traits/dam_offload_utils.php index ec9e6764..4f455363 100644 --- a/inc/traits/dam_offload_utils.php +++ b/inc/traits/dam_offload_utils.php @@ -288,43 +288,45 @@ private function attachment_url_to_post_id( $input_url ) { return (int) $cached; } - if ( $this->is_dam_url( $input_url ) ) { + if ( Optml_Media_Offload::is_uploaded_image( $input_url ) ) { // The DAM are stored as attachments of format /id:/ $pattern = '#/' . Optml_Media_Offload::KEYS['uploaded_flag'] . '([^/]+)#'; if ( preg_match( $pattern, $input_url, $m ) ) { $attachment_id = $this->get_attachement_id_from_optimole_id( $m[1] ); - } else { - $attachment_id = 0; + if ( $attachment_id !== 0 ) { + Optml_Attachment_Cache::set_cached_attachment_id( $input_url, $attachment_id ); + + return $attachment_id; + } } - } else { + } - $url = $this->strip_image_size( $input_url ); + $url = $this->strip_image_size( $input_url ); - $attachment_id = attachment_url_to_postid( $url ); + $attachment_id = attachment_url_to_postid( $url ); - if ( $attachment_id === 0 && ! $this->is_scaled_url( $url ) ) { - $scaled_url = $this->get_scaled_url( $url ); + if ( $attachment_id === 0 && ! $this->is_scaled_url( $url ) ) { + $scaled_url = $this->get_scaled_url( $url ); - $attachment_id = attachment_url_to_postid( $scaled_url ); - } + $attachment_id = attachment_url_to_postid( $scaled_url ); + } - /* - * TODO: The logic is a mess, we need to refactor at some point. - * Websites may transition between 'www' subdomains and apex domains, potentially breaking references to hosted images. This can cause issues when attempting to match attachment IDs if images are linked using outdated domains. The logic is checking for alternative domains and consider the use of 'scaled' prefixes in image URLs for large images, which might affect ID matching. - */ - if ( $attachment_id === 0 ) { - if ( strpos( $url, 'www.' ) !== false ) { - $variant_url = str_replace( 'www.', '', $url ); - $attachment_id = attachment_url_to_postid( $variant_url ); - } else { - $variant_url = str_replace( '://', '://www.', $url ); - $attachment_id = attachment_url_to_postid( $variant_url ); - } - if ( $attachment_id === 0 && ! $this->is_scaled_url( $variant_url ) ) { - $scaled_url = $this->get_scaled_url( $variant_url ); + /* + * TODO: The logic is a mess, we need to refactor at some point. + * Websites may transition between 'www' subdomains and apex domains, potentially breaking references to hosted images. This can cause issues when attempting to match attachment IDs if images are linked using outdated domains. The logic is checking for alternative domains and consider the use of 'scaled' prefixes in image URLs for large images, which might affect ID matching. + */ + if ( $attachment_id === 0 ) { + if ( strpos( $url, 'www.' ) !== false ) { + $variant_url = str_replace( 'www.', '', $url ); + $attachment_id = attachment_url_to_postid( $variant_url ); + } else { + $variant_url = str_replace( '://', '://www.', $url ); + $attachment_id = attachment_url_to_postid( $variant_url ); + } + if ( $attachment_id === 0 && ! $this->is_scaled_url( $variant_url ) ) { + $scaled_url = $this->get_scaled_url( $variant_url ); - $attachment_id = attachment_url_to_postid( $scaled_url ); - } + $attachment_id = attachment_url_to_postid( $scaled_url ); } } Optml_Attachment_Cache::set_cached_attachment_id( $input_url, $attachment_id );