| 1 |
<?php |
| 2 |
namespace SqueezeFree; |
| 3 |
|
| 4 |
// Exit if accessed directly. |
| 5 |
if ( ! defined( 'ABSPATH' ) ) { |
| 6 |
exit; |
| 7 |
} |
| 8 |
|
| 9 |
/** |
| 10 |
* WP Offload Media (amazon-s3-and-cloudfront) compatibility for Squeeze. |
| 11 |
* |
| 12 |
* Responsibilities: |
| 13 |
* |
| 14 |
* 1. `squeeze_additional_base_urls` filter — feeds the provider/CDN domain(s) |
| 15 |
* into Squeeze's URL resolver so that provider URLs in page HTML are correctly |
| 16 |
* mapped back to local paths. This lets Squeeze download images from external |
| 17 |
* storage without CORS issues when the AJAX proxy is used. |
| 18 |
* |
| 19 |
* Note: the "Rewrite <img> src to WebP URLs in HTML" delivery mode is NOT |
| 20 |
* compatible with WP Offload Media. When images are offloaded to an external |
| 21 |
* provider the squeeze-webp/ WebP sidecar files are never pushed to the |
| 22 |
* provider, so they cannot be served from there. Use the "Direct WebP" |
| 23 |
* conversion mode instead — it converts the image in-place and WP Offload |
| 24 |
* Media handles the rest automatically. |
| 25 |
* |
| 26 |
* @since 1.7.10 |
| 27 |
*/ |
| 28 |
class SqueezeOffloadMedia { |
| 29 |
|
| 30 |
public function __construct() { |
| 31 |
if ( did_action( 'as3cf_ready' ) ) { |
| 32 |
$this->register_integration_hooks(); |
| 33 |
} else { |
| 34 |
add_action( 'as3cf_ready', array( $this, 'register_integration_hooks' ) ); |
| 35 |
} |
| 36 |
} |
| 37 |
|
| 38 |
// ------------------------------------------------------------------------- |
| 39 |
// Detection |
| 40 |
// ------------------------------------------------------------------------- |
| 41 |
|
| 42 |
/** |
| 43 |
* Returns true when WP Offload Media (free or Pro) is active. |
| 44 |
*/ |
| 45 |
public static function is_active(): bool { |
| 46 |
return ( |
| 47 |
class_exists( 'Amazon_S3_And_CloudFront' ) |
| 48 |
|| defined( 'AS3CF_PLUGIN_FILE' ) |
| 49 |
|| defined( 'AS3CF_VERSION' ) |
| 50 |
|| defined( 'AS3CF_PRO_PLUGIN_FILE' ) |
| 51 |
|| isset( $GLOBALS['as3cf'] ) |
| 52 |
); |
| 53 |
} |
| 54 |
|
| 55 |
// ------------------------------------------------------------------------- |
| 56 |
// Hooks |
| 57 |
// ------------------------------------------------------------------------- |
| 58 |
|
| 59 |
public function register_integration_hooks(): void { |
| 60 |
if ( ! self::is_active() ) { |
| 61 |
return; |
| 62 |
} |
| 63 |
add_filter( 'squeeze_additional_base_urls', array( $this, 'add_provider_base_urls' ), 10, 1 ); |
| 64 |
} |
| 65 |
|
| 66 |
// ------------------------------------------------------------------------- |
| 67 |
// squeeze_additional_base_urls — expose the provider/CDN origin to Squeeze |
| 68 |
// ------------------------------------------------------------------------- |
| 69 |
|
| 70 |
/** |
| 71 |
* Appends the WP Offload Media provider/CDN base URL(s) to Squeeze's URL |
| 72 |
* resolver list. This lets Squeeze translate provider URLs in page HTML back |
| 73 |
* to local paths so it can download them for compression. |
| 74 |
* |
| 75 |
* @param array $urls Existing list of base URLs. |
| 76 |
* @return array |
| 77 |
*/ |
| 78 |
public function add_provider_base_urls( array $urls ): array { |
| 79 |
global $as3cf; |
| 80 |
|
| 81 |
if ( ! isset( $as3cf ) ) { |
| 82 |
return $urls; |
| 83 |
} |
| 84 |
|
| 85 |
$provider_urls = array(); |
| 86 |
// AS3CF "domain" setting is a delivery *mode* enum (path|cloudfront|...), not a hostname. |
| 87 |
$delivery_mode_enums = array( 'path', 'cloudfront', 'amazon', 'aws', 'storage', 'cdn' ); |
| 88 |
|
| 89 |
// Attempt 1: real custom/CDN hostname (CloudFront or delivery-domain), never the mode enum. |
| 90 |
if ( method_exists( $as3cf, 'get_setting' ) ) { |
| 91 |
$candidates = array( |
| 92 |
(string) $as3cf->get_setting( 'cloudfront' ), |
| 93 |
(string) $as3cf->get_setting( 'delivery-domain' ), |
| 94 |
); |
| 95 |
foreach ( $candidates as $domain ) { |
| 96 |
$domain = trim( $domain, " \t\n\r\0\x0B/" ); |
| 97 |
if ( $domain === '' || in_array( strtolower( $domain ), $delivery_mode_enums, true ) ) { |
| 98 |
continue; |
| 99 |
} |
| 100 |
// Require a hostname-like value (must contain a dot) to avoid mode strings. |
| 101 |
$host = $domain; |
| 102 |
if ( strpos( $domain, '//' ) !== false ) { |
| 103 |
$host = (string) wp_parse_url( $domain, PHP_URL_HOST ); |
| 104 |
} |
| 105 |
if ( $host === '' || strpos( $host, '.' ) === false ) { |
| 106 |
continue; |
| 107 |
} |
| 108 |
if ( strpos( $domain, '//' ) === false ) { |
| 109 |
$domain = 'https://' . $domain; |
| 110 |
} |
| 111 |
$provider_urls[] = rtrim( $domain, '/' ); |
| 112 |
} |
| 113 |
} |
| 114 |
|
| 115 |
// Attempt 2: get_provider_url_prefix (v3.x) — merge when available (path-style delivery). |
| 116 |
if ( method_exists( $as3cf, 'get_provider_url_prefix' ) ) { |
| 117 |
$prefix = rtrim( (string) $as3cf->get_provider_url_prefix(), '/' ); |
| 118 |
if ( '' !== $prefix && strpos( $prefix, '.' ) !== false ) { |
| 119 |
$provider_urls[] = $prefix; |
| 120 |
} |
| 121 |
} |
| 122 |
|
| 123 |
// Attempt 3: derive provider URL prefixes from bucket. |
| 124 |
// Staging evidence: delivery host was {bucket}.storage.googleapis.com while we only |
| 125 |
// emitted S3 amazonaws hosts — add both GCS and S3 shapes so either provider matches. |
| 126 |
if ( method_exists( $as3cf, 'get_setting' ) ) { |
| 127 |
$bucket = trim( (string) $as3cf->get_setting( 'bucket' ) ); |
| 128 |
$region = trim( (string) $as3cf->get_setting( 'region' ) ); |
| 129 |
if ( $bucket !== '' ) { |
| 130 |
// Google Cloud Storage (virtual-hosted + path-style). |
| 131 |
$provider_urls[] = 'https://' . $bucket . '.storage.googleapis.com'; |
| 132 |
$provider_urls[] = 'https://storage.googleapis.com/' . $bucket; |
| 133 |
|
| 134 |
// Amazon S3 (virtual-hosted + path-style). |
| 135 |
if ( $region !== '' && $region !== 'us-east-1' ) { |
| 136 |
$provider_urls[] = 'https://' . $bucket . '.s3.' . $region . '.amazonaws.com'; |
| 137 |
$provider_urls[] = 'https://s3.' . $region . '.amazonaws.com/' . $bucket; |
| 138 |
} |
| 139 |
$provider_urls[] = 'https://' . $bucket . '.s3.amazonaws.com'; |
| 140 |
$provider_urls[] = 'https://s3.amazonaws.com/' . $bucket; |
| 141 |
} |
| 142 |
} |
| 143 |
|
| 144 |
// Add both http and https variants so we match regardless of scheme. |
| 145 |
$all_urls = array(); |
| 146 |
foreach ( $provider_urls as $url ) { |
| 147 |
$all_urls[] = preg_replace( '#^https?:#', 'https:', $url ); |
| 148 |
$all_urls[] = preg_replace( '#^https?:#', 'http:', $url ); |
| 149 |
} |
| 150 |
|
| 151 |
return array_merge( $urls, array_filter( array_unique( $all_urls ) ) ); |
| 152 |
} |
| 153 |
} |
| 154 |
|