PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / 2.5.7
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization v2.5.7
4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 2.5.5 2.5.6 2.5.7 3.0.0 3.0.1 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.11.0 3.11.1 3.11.2 3.11.3 3.12.0 3.12.1 All 134 releases
optimole-wp / inc / url_replacer.php

url_replacer.php in Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization 2.5.7, at inc/url_replacer.php

241 lines 7.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The class handles the url replacements.
5 *
6 * @package \Optml\Inc
7 * @author Optimole <friends@optimole.com>
8 */
9 final class Optml_Url_Replacer extends Optml_App_Replacer {
10
11 use Optml_Validator;
12 use Optml_Normalizer;
13
14 /**
15 * Cached object instance.
16 *
17 * @var Optml_Url_Replacer
18 */
19 protected static $instance = null;
20
21 /**
22 * Class instance method.
23 *
24 * @codeCoverageIgnore
25 * @static
26 * @return Optml_Url_Replacer
27 * @since 1.0.0
28 * @access public
29 */
30 public static function instance() {
31 if ( null === self::$instance ) {
32 self::$instance = new self();
33 add_action( 'optml_replacer_setup', [ self::$instance, 'init' ] );
34 }
35
36 return self::$instance;
37 }
38
39 /**
40 * A filter which turns a local url into an optimized CDN image url or an array of image urls.
41 *
42 * @param string $url The url which should be replaced.
43 *
44 * @return string Replaced url.
45 */
46 public function replace_option_url( $url ) {
47 if ( empty( $url ) ) {
48 return $url;
49 }
50 // $url might be an array or an json encoded array with urls.
51 if ( is_array( $url ) || filter_var( $url, FILTER_VALIDATE_URL ) === false ) {
52 $array = $url;
53 $encoded = false;
54
55 // it might a json encoded array
56 if ( is_string( $url ) ) {
57 $array = json_decode( $url, true );
58 $encoded = true;
59 }
60
61 // in case there is an array, apply it recursively.
62 if ( is_array( $array ) ) {
63 foreach ( $array as $index => $value ) {
64 $array[ $index ] = $this->replace_option_url( $value );
65 }
66
67 if ( $encoded ) {
68 return json_encode( $array );
69 }
70
71 return $array;
72 }
73
74 if ( filter_var( $url, FILTER_VALIDATE_URL ) === false ) {
75 return $url;
76 }
77 }
78
79 return apply_filters( 'optml_content_url', $url );
80 }
81
82 /**
83 * The initialize method.
84 */
85 public function init() {
86
87 add_filter( 'optml_replace_image', [ $this, 'build_url' ], 10, 2 );
88 parent::init();
89
90 Optml_Quality::$default_quality = $this->to_accepted_quality( $this->settings->get_quality() );
91 Optml_Image::$watermark = new Optml_Watermark( $this->settings->get_site_settings()['watermark'] );
92 Optml_Resize::$default_enlarge = apply_filters( 'optml_always_enlarge', false );
93 add_filter( 'optml_content_url', [ $this, 'build_url' ], 1, 2 );
94
95 }
96
97 /**
98 * Returns a signed image url authorized to be used in our CDN.
99 *
100 * @param string $url The url which should be signed.
101 * @param array $args Dimension params; Supports `width` and `height`.
102 *
103 * @return string
104 */
105 public function build_url(
106 $url, $args = [
107 'width' => 'auto',
108 'height' => 'auto',
109 ]
110 ) {
111 if ( apply_filters( 'optml_dont_replace_url', false, $url ) ) {
112 return $url;
113 }
114
115 $original_url = $url;
116
117 $is_slashed = strpos( $url, '\/' ) !== false;
118
119 // We do a little hack here, for json unicode chars we first replace them with html special chars,
120 // we then strip slashes to normalize the URL and last we convert html special chars back to get a clean URL
121 $url = $is_slashed ? html_entity_decode( stripslashes( preg_replace( '/\\\u([\da-fA-F]{4})/', '&#x\1;', $url ) ) ) : ( $url );
122 if ( strpos( $url, Optml_Config::$service_url ) !== false ) {
123 return $original_url;
124 }
125
126 if ( ! $this->can_replace_url( $url ) ) {
127 return $original_url;
128 }
129
130 // Remove any query strings that might affect conversion.
131 $url = strtok( $url, '?' );
132 $ext = $this->is_valid_mimetype_from_url( $url, self::$filters[ Optml_Settings::FILTER_TYPE_OPTIMIZE ][ Optml_Settings::FILTER_EXT ] );
133 if ( false === $ext ) {
134 return $original_url;
135 }
136
137 if ( isset( $args['quality'] ) && ! empty( $args['quality'] ) ) {
138 $args['quality'] = $this->to_accepted_quality( $args['quality'] );
139 }
140
141 if ( isset( $args['minify'] ) && ! empty( $args['minify'] ) ) {
142 $args['minify'] = $this->to_accepted_minify( $args['minify'] );
143 }
144
145 // this will authorize the image
146 if ( ! empty( $this->site_mappings ) ) {
147 $url = str_replace( array_keys( $this->site_mappings ), array_values( $this->site_mappings ), $url );
148 }
149 if ( substr( $url, 0, 2 ) === '//' ) {
150 $url = sprintf( '%s:%s', is_ssl() ? 'https' : 'http', $url );
151 }
152 if ( isset( Optml_Config::$image_extensions[ strtolower( $ext ) ] ) ) {
153 $new_url = $this->normalize_image( $url, $original_url, $args );
154 } else {
155 $new_url = ( new Optml_Asset( $url, $args, $this->active_cache_buster, $this->is_css_minify_on, $this->is_js_minify_on ) )->get_url();
156 }
157 return $is_slashed ? addcslashes( $new_url, '/' ) : $new_url;
158 }
159
160 /**
161 * Apply extra normalization to image.
162 *
163 * @param string $url Image url.
164 * @param string $original_url Original image url.
165 * @param array $args Args.
166 *
167 * @return string
168 */
169 private function normalize_image( $url, $original_url, $args ) {
170
171 $new_url = $this->strip_image_size_from_url( $url );
172
173 if ( $new_url !== $url ) {
174 if ( ! isset( $args['quality'] ) || $args['quality'] !== 'eco' ) {
175 list( $args['width'], $args['height'], $crop ) = $this->parse_dimensions_from_filename( $url );
176 if ( ! $crop ) {
177 $sizes2crop = self::size_to_crop();
178 $crop = isset( $sizes2crop[ $args['width'] . $args['height'] ] ) ? $sizes2crop[ $args['width'] . $args['height'] ] : false;
179 }
180 if ( $crop ) {
181 $args['resize'] = $this->to_optml_crop( $crop );
182 }
183 }
184 $url = $new_url;
185 }
186 $args['width'] = (int) $args['width'];
187 $args['height'] = (int) $args['height'];
188 if ( $args['width'] > 0 && $args['height'] > 0 ) {
189 list( $args['width'], $args['height'] ) = wp_constrain_dimensions( $args['width'], $args['height'], $this->max_width, $this->max_height );
190 } elseif ( $args['width'] > 0 ) {
191 $args['width'] = $args['width'] > $this->max_width ? $this->max_width : $args['width'];
192 } elseif ( $args['height'] > 0 ) {
193 $args['height'] = $args['height'] > $this->max_height ? $this->max_height : $args['height'];
194 }
195 if ( isset( $args['resize'], $args['resize']['gravity'] ) && $this->settings->is_smart_cropping() ) {
196 $args['resize']['gravity'] = Optml_Resize::GRAVITY_SMART;
197 }
198 $args = apply_filters( 'optml_image_args', $args, $original_url );
199
200 $arguments = [
201 'apply_watermark' => apply_filters( 'optml_apply_watermark_for', true, $url ),
202 ];
203
204 if ( isset( $args['format'] ) && ! empty( $args['format'] ) ) {
205 $arguments['format'] = $args['format'];
206 }
207
208 return ( new Optml_Image( $url, $args, $this->active_cache_buster ) )->get_url( $arguments );
209
210 }
211
212 /**
213 * Throw error on object clone
214 *
215 * The whole idea of the singleton design pattern is that there is a single
216 * object therefore, we don't want the object to be cloned.
217 *
218 * @codeCoverageIgnore
219 * @access public
220 * @return void
221 * @since 1.0.0
222 */
223 public function __clone() {
224 // Cloning instances of the class is forbidden.
225 _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'optimole-wp' ), '1.0.0' );
226 }
227
228 /**
229 * Disable unserializing of the class
230 *
231 * @codeCoverageIgnore
232 * @access public
233 * @return void
234 * @since 1.0.0
235 */
236 public function __wakeup() {
237 // Unserializing instances of the class is forbidden.
238 _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'optimole-wp' ), '1.0.0' );
239 }
240 }
241