Image optimization & Lazy Load by Optimole - Version 2.0.4

Version Description

Download this release

Release Info

Developer optimole
Plugin Icon 128x128 Image optimization & Lazy Load by Optimole
Version 2.0.4
Comparing to
See all releases

Code changes from version 2.0.3 to 2.0.4

CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
#### [Version 2.0.3](https://github.com/Codeinwp/optimole-wp/compare/v2.0.2...v2.0.3) (2019-02-13)
2
3
* **Bug Fixes**
1
+ #### [Version 2.0.4](https://github.com/Codeinwp/optimole-wp/compare/v2.0.3...v2.0.4) (2019-03-11)
2
+
3
+ * **Bug Fixes**
4
+ * adds full compatibility with Envira gallery ([7fd618f](https://github.com/Codeinwp/optimole-wp/commit/7fd618f))
5
+ * compatibility with Foogallery plugin when the gallery uses lazyload too ([67991dc](https://github.com/Codeinwp/optimole-wp/commit/67991dc))
6
+ * compatibility with images which contains query arguments, causing broken image urls ([56108be](https://github.com/Codeinwp/optimole-wp/commit/56108be))
7
+ * compatibility with relative image urls ([8089610](https://github.com/Codeinwp/optimole-wp/commit/8089610))
8
+ * compatibility with Revolution slider, adds support for background images lazyload and exact match ([0bbd254](https://github.com/Codeinwp/optimole-wp/commit/0bbd254))
9
+ * compatibility with shortcode ultimate plugin ([164ba35](https://github.com/Codeinwp/optimole-wp/commit/164ba35))
10
+ * compatibility with Woocommerce, solving issue with zoom image on single product pages ([1692e2b](https://github.com/Codeinwp/optimole-wp/commit/1692e2b))
11
+ * image replacement on WordPress REST api responses ([24d191b](https://github.com/Codeinwp/optimole-wp/commit/24d191b))
12
+ * image url replacement on custom WordPress directory structure, fixes [#79](https://github.com/Codeinwp/optimole-wp/issues/79), thanks [@hackles](https://github.com/hackles) for reporting ([980fcef](https://github.com/Codeinwp/optimole-wp/commit/980fcef))
13
+
14
+ * **Features**
15
+ * tested up compatibility with WordPress 5.1 ([12726b6](https://github.com/Codeinwp/optimole-wp/commit/12726b6))
16
+ * **api:** adds filter for restricting watermark based on image source urls ([337d7fa](https://github.com/Codeinwp/optimole-wp/commit/337d7fa))
17
+ * **api:** adds filter to disable image replacement on a specific page/ur ([3250a8d](https://github.com/Codeinwp/optimole-wp/commit/3250a8d))
18
+
19
#### [Version 2.0.3](https://github.com/Codeinwp/optimole-wp/compare/v2.0.2...v2.0.3) (2019-02-13)
20
21
* **Bug Fixes**
README.md CHANGED
@@ -2,7 +2,7 @@
2
**Contributors:** [optimole](https://profiles.wordpress.org/optimole)
3
**Tags:** image optimization, cdn, image compression, compress image, images, optimization, perfomance, photos
4
**Requires at least:** 4.7
5
- **Tested up to:** 5.0
6
**Requires PHP:** 5.4
7
**License:** GPLv3
8
**License URI:** https://www.gnu.org/licenses/gpl-3.0.en.html
@@ -91,6 +91,26 @@ Premium users will be able to optimize 10GB images per month with a 50GB viewing
91
92
## Changelog ##
93
94
#### [Version 2.0.3](https://github.com/Codeinwp/optimole-wp/compare/v2.0.2...v2.0.3) (2019-02-13)
95
96
* **Bug Fixes**
2
**Contributors:** [optimole](https://profiles.wordpress.org/optimole)
3
**Tags:** image optimization, cdn, image compression, compress image, images, optimization, perfomance, photos
4
**Requires at least:** 4.7
5
+ **Tested up to:** 5.1
6
**Requires PHP:** 5.4
7
**License:** GPLv3
8
**License URI:** https://www.gnu.org/licenses/gpl-3.0.en.html
91
92
## Changelog ##
93
94
+ #### [Version 2.0.4](https://github.com/Codeinwp/optimole-wp/compare/v2.0.3...v2.0.4) (2019-03-11)
95
+
96
+ * **Bug Fixes**
97
+ * adds full compatibility with Envira gallery ([7fd618f](https://github.com/Codeinwp/optimole-wp/commit/7fd618f))
98
+ * compatibility with Foogallery plugin when the gallery uses lazyload too ([67991dc](https://github.com/Codeinwp/optimole-wp/commit/67991dc))
99
+ * compatibility with images which contains query arguments, causing broken image urls ([56108be](https://github.com/Codeinwp/optimole-wp/commit/56108be))
100
+ * compatibility with relative image urls ([8089610](https://github.com/Codeinwp/optimole-wp/commit/8089610))
101
+ * compatibility with Revolution slider, adds support for background images lazyload and exact match ([0bbd254](https://github.com/Codeinwp/optimole-wp/commit/0bbd254))
102
+ * compatibility with shortcode ultimate plugin ([164ba35](https://github.com/Codeinwp/optimole-wp/commit/164ba35))
103
+ * compatibility with Woocommerce, solving issue with zoom image on single product pages ([1692e2b](https://github.com/Codeinwp/optimole-wp/commit/1692e2b))
104
+ * image replacement on WordPress REST api responses ([24d191b](https://github.com/Codeinwp/optimole-wp/commit/24d191b))
105
+ * image url replacement on custom WordPress directory structure, fixes [#79](https://github.com/Codeinwp/optimole-wp/issues/79), thanks [@hackles](https://github.com/hackles) for reporting ([980fcef](https://github.com/Codeinwp/optimole-wp/commit/980fcef))
106
+
107
+ * **Features**
108
+ * tested up compatibility with WordPress 5.1 ([12726b6](https://github.com/Codeinwp/optimole-wp/commit/12726b6))
109
+ * **api:** adds filter for restricting watermark based on image source urls ([337d7fa](https://github.com/Codeinwp/optimole-wp/commit/337d7fa))
110
+ * **api:** adds filter to disable image replacement on a specific page/ur ([3250a8d](https://github.com/Codeinwp/optimole-wp/commit/3250a8d))
111
+
112
+
113
+
114
#### [Version 2.0.3](https://github.com/Codeinwp/optimole-wp/compare/v2.0.2...v2.0.3) (2019-02-13)
115
116
* **Bug Fixes**
inc/admin.php CHANGED
@@ -57,7 +57,12 @@ class Optml_Admin {
57
public function inline_bootstrap_script() {
58
$domain = 'https://' . OPTML_JS_CDN;
59
60
- $min = ! OPTML_DEBUG ? '.min' : '';
61
62
$output = sprintf(
63
'
@@ -72,6 +77,7 @@ class Optml_Admin {
72
opacity: .75;
73
filter: blur(5px);
74
}
75
</style>
76
<script type="application/javascript">
77
(function(w, d){
@@ -81,13 +87,21 @@ class Optml_Admin {
81
s.async = true;
82
s.src = "%s/v2/latest/optimole_lib" + v + "%s.js";
83
b.appendChild(s);
84
85
}(window, document));
86
87
document.addEventListener( "DOMContentLoaded", function() { document.body.className = document.body.className.replace("optimole-no-script",""); } );
88
</script>',
89
esc_url( $domain ),
90
- $min
91
);
92
echo $output;
93
}
57
public function inline_bootstrap_script() {
58
$domain = 'https://' . OPTML_JS_CDN;
59
60
+ $min = ! OPTML_DEBUG ? '.min' : '';
61
+ $bgclasses = Optml_Lazyload_Replacer::get_lazyload_bg_classes();
62
+ $watcher_classes = Optml_Lazyload_Replacer::get_watcher_lz_classes();
63
+
64
+ $bgclasses = empty( $bgclasses ) ? '' : sprintf( '"%s"', implode( '","', (array) $bgclasses ) );
65
+ $watcher_classes = empty( $watcher_classes ) ? '' : sprintf( '"%s"', implode( '","', (array) $watcher_classes ) );
66
67
$output = sprintf(
68
'
77
opacity: .75;
78
filter: blur(5px);
79
}
80
+
81
</style>
82
<script type="application/javascript">
83
(function(w, d){
87
s.async = true;
88
s.src = "%s/v2/latest/optimole_lib" + v + "%s.js";
89
b.appendChild(s);
90
+ w.optimoleData = {
91
+ backgroundReplaceClasses: [%s],
92
+ watchClasses: [%s],
93
+ quality: %d
94
+ }
95
96
}(window, document));
97
98
document.addEventListener( "DOMContentLoaded", function() { document.body.className = document.body.className.replace("optimole-no-script",""); } );
99
</script>',
100
esc_url( $domain ),
101
+ $min,
102
+ $bgclasses,
103
+ $watcher_classes,
104
+ $this->settings->get_numeric_quality()
105
);
106
echo $output;
107
}
inc/api.php CHANGED
@@ -57,7 +57,7 @@ final class Optml_Api {
57
// Grab the url to which we'll be making the request.
58
$url = $this->api_root;
59
$headers = array(
60
- 'Optml-Site' => get_site_url(),
61
);
62
if ( ! empty( $this->api_key ) ) {
63
$headers['Authorization'] = 'Bearer ' . $this->api_key;
@@ -139,7 +139,7 @@ final class Optml_Api {
139
'POST',
140
array(
141
'email' => $email,
142
- 'site' => get_site_url(),
143
)
144
);
145
}
57
// Grab the url to which we'll be making the request.
58
$url = $this->api_root;
59
$headers = array(
60
+ 'Optml-Site' => get_home_url(),
61
);
62
if ( ! empty( $this->api_key ) ) {
63
$headers['Authorization'] = 'Bearer ' . $this->api_key;
139
'POST',
140
array(
141
'email' => $email,
142
+ 'site' => get_home_url(),
143
)
144
);
145
}
inc/app_replacer.php CHANGED
@@ -20,6 +20,24 @@ abstract class Optml_App_Replacer {
20
* @var array
21
*/
22
protected static $size_to_crop = array();
23
/**
24
* Settings handler.
25
*
@@ -74,6 +92,54 @@ abstract class Optml_App_Replacer {
74
*/
75
protected $is_allowed_site = array();
76
77
/**
78
* Size to crop maping.
79
*
@@ -149,52 +215,23 @@ abstract class Optml_App_Replacer {
149
*/
150
public function init() {
151
$this->settings = new Optml_Settings();
152
-
153
- if ( ! $this->should_replace() ) {
154
- return false; // @codeCoverageIgnore
155
- }
156
$this->set_properties();
157
158
- return true;
159
}
160
161
- /**
162
- * Check if we should rewrite the urls.
163
- *
164
- * @return bool If we can replace the image.
165
- */
166
- public function should_replace() {
167
- if ( Optml_Manager::is_ajax_request() ) {
168
- return true;
169
- }
170
- if ( is_admin() || ! $this->settings->is_connected() || ! $this->settings->is_enabled() || is_customize_preview() ) {
171
- return false; // @codeCoverageIgnore
172
- }
173
-
174
- if ( array_key_exists( 'preview', $_GET ) && 'true' == $_GET['preview'] ) {
175
- return false; // @codeCoverageIgnore
176
- }
177
-
178
- if ( array_key_exists( 'optml_off', $_GET ) && 'true' == $_GET['optml_off'] ) {
179
- return false; // @codeCoverageIgnore
180
- }
181
- if ( array_key_exists( 'elementor-preview', $_GET ) && ! empty( $_GET['elementor-preview'] ) ) {
182
- return false; // @codeCoverageIgnore
183
- }
184
-
185
- return true;
186
- }
187
188
/**
189
* Set the cdn url based on the current connected user.
190
*/
191
public function set_properties() {
192
- $upload_data = wp_upload_dir();
193
- $this->upload_resource = array(
194
'url' => str_replace( array( 'https://', 'http://' ), '', $upload_data['baseurl'] ),
195
'directory' => $upload_data['basedir'],
196
);
197
- $this->upload_resource['url_length'] = strlen( $this->upload_resource['url'] );
198
199
$service_data = $this->settings->get( 'service_data' );
200
@@ -209,12 +246,12 @@ abstract class Optml_App_Replacer {
209
$this->site_mappings['//i2.wp.com/'] = '//';
210
211
if ( defined( 'OPTML_SITE_MIRROR' ) && constant( 'OPTML_SITE_MIRROR' ) ) {
212
- $this->site_mappings[ rtrim( get_site_url(), '/' ) ] = rtrim( constant( 'OPTML_SITE_MIRROR' ), '/' );
213
}
214
215
$this->possible_sources = $this->extract_domain_from_urls(
216
array_merge(
217
- array( get_site_url() ),
218
array_values( $this->site_mappings ),
219
array_keys( $this->site_mappings )
220
)
@@ -226,6 +263,9 @@ abstract class Optml_App_Replacer {
226
227
$this->max_height = $this->settings->get( 'max_height' );
228
$this->max_width = $this->settings->get( 'max_width' );
229
}
230
231
/**
@@ -279,6 +319,7 @@ abstract class Optml_App_Replacer {
279
if ( ! isset( $url['host'] ) ) {
280
return false;
281
}
282
return isset( $this->possible_sources[ $url['host'] ] ) || isset( $this->allowed_sources[ $url['host'] ] );
283
}
284
@@ -289,9 +330,9 @@ abstract class Optml_App_Replacer {
289
*
290
* @return string
291
**/
292
- protected function strip_image_size_from_url( $url ) {
293
294
- if ( preg_match( '#(-\d+x\d+)\.(' . implode( '|', array_keys( Optml_Config::$extensions ) ) . '){1}$#i', $url, $src_parts ) ) {
295
$stripped_url = str_replace( $src_parts[1], '', $url );
296
// Extracts the file path to the image minus the base url
297
$file_path = substr( $stripped_url, strpos( $stripped_url, $this->upload_resource['url'] ) + $this->upload_resource['url_length'] );
@@ -313,15 +354,15 @@ abstract class Optml_App_Replacer {
313
protected function parse_dimensions_from_filename( $src ) {
314
$width_height_string = array();
315
$extensions = array_keys( Optml_Config::$extensions );
316
- if ( preg_match( '#-(\d+)x(\d+)\.(?:' . implode( '|', $extensions ) . '){1}$#i', $src, $width_height_string ) ) {
317
$width = (int) $width_height_string[1];
318
$height = (int) $width_height_string[2];
319
-
320
if ( $width && $height ) {
321
- return array( $width, $height );
322
}
323
}
324
325
- return array( false, false );
326
}
327
}
20
* @var array
21
*/
22
protected static $size_to_crop = array();
23
+ /**
24
+ * Holds possible src attributes.
25
+ *
26
+ * @var array
27
+ */
28
+ protected static $possible_src_attributes = null;
29
+ /**
30
+ * Holds possible lazyload flags where we should ignore our lazyload.
31
+ *
32
+ * @var array
33
+ */
34
+ protected static $ignore_lazyload_strings = null;
35
+ /**
36
+ * Holds flags that should ignore the data-opt-tag format.
37
+ *
38
+ * @var array
39
+ */
40
+ protected static $ignore_data_opt_attribute = null;
41
/**
42
* Settings handler.
43
*
92
*/
93
protected $is_allowed_site = array();
94
95
+ /**
96
+ * Returns possible src attributes.
97
+ *
98
+ * @return array
99
+ */
100
+ public static function possible_src_attributes() {
101
+
102
+ if ( null != self::$possible_src_attributes && is_array( self::$possible_src_attributes ) ) {
103
+ return self::$possible_src_attributes;
104
+ }
105
+
106
+ self::$possible_src_attributes = apply_filters( 'optml_possible_src_attributes', [] );
107
+
108
+ return self::$possible_src_attributes;
109
+ }
110
+
111
+ /**
112
+ * Returns possible src attributes.
113
+ *
114
+ * @return array
115
+ */
116
+ public static function possible_lazyload_flags() {
117
+
118
+ if ( null != self::$ignore_lazyload_strings && is_array( self::$ignore_lazyload_strings ) ) {
119
+ return self::$ignore_lazyload_strings;
120
+ }
121
+
122
+ self::$possible_src_attributes = apply_filters( 'optml_possible_lazyload_flags', [] );
123
+
124
+ return array_merge( self::$possible_src_attributes, [ '<noscript' ] );
125
+ }
126
+
127
+ /**
128
+ * Returns possible data-opt-src ignore flags attributes.
129
+ *
130
+ * @return array
131
+ */
132
+ public static function possible_data_ignore_flags() {
133
+
134
+ if ( null != self::$ignore_data_opt_attribute && is_array( self::$ignore_data_opt_attribute ) ) {
135
+ return self::$ignore_data_opt_attribute;
136
+ }
137
+
138
+ self::$ignore_data_opt_attribute = apply_filters( 'optml_ignore_data_opt_flag', [] );
139
+
140
+ return self::$ignore_data_opt_attribute;
141
+ }
142
+
143
/**
144
* Size to crop maping.
145
*
215
*/
216
public function init() {
217
$this->settings = new Optml_Settings();
218
$this->set_properties();
219
220
}
221
222
223
/**
224
* Set the cdn url based on the current connected user.
225
*/
226
public function set_properties() {
227
+
228
+ $upload_data = wp_upload_dir();
229
+ $this->upload_resource = array(
230
'url' => str_replace( array( 'https://', 'http://' ), '', $upload_data['baseurl'] ),
231
'directory' => $upload_data['basedir'],
232
);
233
+ $this->upload_resource['url_length'] = strlen( $this->upload_resource['url'] );
234
+ $this->upload_resource['content_path'] = str_replace( get_home_url(), '', content_url() );
235
236
$service_data = $this->settings->get( 'service_data' );
237
246
$this->site_mappings['//i2.wp.com/'] = '//';
247
248
if ( defined( 'OPTML_SITE_MIRROR' ) && constant( 'OPTML_SITE_MIRROR' ) ) {
249
+ $this->site_mappings[ rtrim( get_home_url(), '/' ) ] = rtrim( constant( 'OPTML_SITE_MIRROR' ), '/' );
250
}
251
252
$this->possible_sources = $this->extract_domain_from_urls(
253
array_merge(
254
+ array( get_home_url() ),
255
array_values( $this->site_mappings ),
256
array_keys( $this->site_mappings )
257
)
263
264
$this->max_height = $this->settings->get( 'max_height' );
265
$this->max_width = $this->settings->get( 'max_width' );
266
+
267
+ add_filter( 'optml_strip_image_size_from_url', [ $this, 'strip_image_size_from_url' ], 10, 1 );
268
+
269
}
270
271
/**
319
if ( ! isset( $url['host'] ) ) {
320
return false;
321
}
322
+
323
return isset( $this->possible_sources[ $url['host'] ] ) || isset( $this->allowed_sources[ $url['host'] ] );
324
}
325
330
*
331
* @return string
332
**/
333
+ public function strip_image_size_from_url( $url ) {
334
335
+ if ( preg_match( '#(-\d+x\d+(?:_c)?)\.(' . implode( '|', array_keys( Optml_Config::$extensions ) ) . '){1}$#i', $url, $src_parts ) ) {
336
$stripped_url = str_replace( $src_parts[1], '', $url );
337
// Extracts the file path to the image minus the base url
338
$file_path = substr( $stripped_url, strpos( $stripped_url, $this->upload_resource['url'] ) + $this->upload_resource['url_length'] );
354
protected function parse_dimensions_from_filename( $src ) {
355
$width_height_string = array();
356
$extensions = array_keys( Optml_Config::$extensions );
357
+ if ( preg_match( '#-(\d+)x(\d+)(:?_c)?\.(?:' . implode( '|', $extensions ) . '){1}$#i', $src, $width_height_string ) ) {
358
$width = (int) $width_height_string[1];
359
$height = (int) $width_height_string[2];
360
+ $crop = ( isset( $width_height_string[3] ) && $width_height_string[3] === '_c' );
361
if ( $width && $height ) {
362
+ return array( $width, $height, $crop );
363
}
364
}
365
366
+ return array( false, false, false );
367
}
368
}
inc/compatibilities/compatibility.php ADDED
@@ -0,0 +1,17 @@
1
+ <?php
2
+ /**
3
+ * Class Optml_compatibility.
4
+ */
5
+ abstract class Optml_compatibility {
6
+ /**
7
+ * Register compatibility actions/filters.
8
+ */
9
+ abstract function register();
10
+
11
+ /**
12
+ * Should we load the compatibility?
13
+ *
14
+ * @return bool Compatiblity
15
+ */
16
+ abstract function should_load();
17
+ }
inc/compatibilities/envira.php ADDED
@@ -0,0 +1,95 @@
1
+ <?php
2
+
3
+ /**
4
+ * Class Optml_shortcode_ultimate.
5
+ *
6
+ * @reason The gallery output contains a different src attribute used for lazyload
7
+ * which prevented optimole to parse the tag.
8
+ */
9
+ class Optml_envira extends Optml_compatibility {
10
+
11
+ /**
12
+ * Should we load the integration logic.
13
+ *
14
+ * @return bool Should we load.
15
+ */
16
+ function should_load() {
17
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
18
+
19
+ return ( is_plugin_active( 'envira-gallery-lite/envira-gallery-lite.php' ) || is_plugin_active( 'envira-gallery/envira-gallery.php' ) );
20
+ }
21
+
22
+ /**
23
+ * Register integration details.
24
+ */
25
+ public function register() {
26
+ add_filter( 'optml_possible_src_attributes', [ $this, 'add_lazysrc' ], 10, 3 );
27
+ add_filter( 'optml_possible_lazyload_flags', [ $this, 'add_lazyflag' ], 10, 3 );
28
+ add_filter( 'optml_parse_resize_from_tag', [ $this, 'check_resize_tag' ], 10, 2 );
29
+ add_filter( 'envira_gallery_image_src', [ $this, 'revert_src' ], 10, 1 );
30
+ }
31
+
32
+ /**
33
+ * Revert the optimole url to the original state in
34
+ * order to allow to be parsed by the image tag parser.
35
+ *
36
+ * @param string $image Image url.
37
+ *
38
+ * @return string Original url.
39
+ */
40
+ function revert_src( $image ) {
41
+
42
+ if ( ( $pos = strpos( $image, '/http' ) ) !== false ) {
43
+ return ltrim( substr( $image, $pos ), '/' );
44
+ }
45
+
46
+ return $image;
47
+ }
48
+
49
+ /**
50
+ * Alter default resize for image tag parsing.
51
+ *
52
+ * @param array $old_resize Old array, if any.
53
+ * @param string $tag Image tag.
54
+ *
55
+ * @return array Resize conf.
56
+ */
57
+ function check_resize_tag( $old_resize, $tag ) {
58
+ if ( preg_match( '/(_c)\.(?:' . implode( '|', array_keys( Optml_Config::$extensions ) ) . ')/i', $tag, $match ) ) {
59
+ return [
60
+ 'type' => Optml_Resize::RESIZE_FILL,
61
+ 'gravity' => Optml_Resize::GRAVITY_CENTER,
62
+ ];
63
+ }
64
+
65
+ return [];
66
+ }
67
+
68
+ /**
69
+ * Add envira lazyload flag.
70
+ *
71
+ * @param array $strings Old strings.
72
+ *
73
+ * @return array New flags.
74
+ */
75
+ function add_lazyflag( $strings = array() ) {
76
+
77
+ $strings[] = 'envira-lazy';
78
+
79
+ return $strings;
80
+ }
81
+
82
+ /**
83
+ * Add Envira lazysrc attribute.
84
+ *
85
+ * @param array $attributes Old src attributes.
86
+ *
87
+ * @return array New src attributes.
88
+ */
89
+ function add_lazysrc( $attributes = array() ) {
90
+
91
+ $attributes[] = 'data-envira-src';
92
+
93
+ return $attributes;
94
+ }
95
+ }
inc/compatibilities/foogallery.php ADDED
@@ -0,0 +1,43 @@
1
+ <?php
2
+
3
+ /**
4
+ * Class Optml_shortcode_ultimate.
5
+ *
6
+ * @reason The gallery output contains a different src attribute used for lazyload
7
+ * which prevented optimole to parse the tag.
8
+ */
9
+ class Optml_foogallery extends Optml_compatibility {
10
+
11
+ /**
12
+ * Should we load the integration logic.
13
+ *
14
+ * @return bool Should we load.
15
+ */
16
+ function should_load() {
17
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
18
+
19
+ return is_plugin_active( 'foogallery/foogallery.php' );
20
+ }
21
+
22
+ /**
23
+ * Register integration details.
24
+ */
25
+ public function register() {
26
+ add_filter( 'optml_possible_src_attributes', [ $this, 'add_lazysrc' ], 10, 3 );
27
+ add_filter( 'optml_possible_lazyload_flags', [ $this, 'add_lazysrc' ], 10, 3 );
28
+ }
29
+
30
+ /**
31
+ * Add foogallery lazysrc attribute.
32
+ *
33
+ * @param array $attributes Old src attributes.
34
+ *
35
+ * @return array New src attributes.
36
+ */
37
+ function add_lazysrc( $attributes = array() ) {
38
+
39
+ $attributes[] = 'data-src-fg';
40
+
41
+ return $attributes;
42
+ }
43
+ }
inc/compatibilities/revslider.php ADDED
@@ -0,0 +1,55 @@
1
+ <?php
2
+
3
+ /**
4
+ * Class Optml_revslider.
5
+ *
6
+ * @reason The slider output dont needs the data-opt-src and uses a background lazyload approach.
7
+ */
8
+ class Optml_revslider extends Optml_compatibility {
9
+
10
+ /**
11
+ * Should we load the integration logic.
12
+ *
13
+ * @return bool Should we load.
14
+ */
15
+ function should_load() {
16
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
17
+
18
+ return is_plugin_active( 'revslider/revslider.php' );
19
+ }
20
+
21
+ /**
22
+ * Register integration details.
23
+ */
24
+ public function register() {
25
+ add_filter( 'optml_ignore_data_opt_flag', [ $this, 'add_data_ignore' ], 10, 3 );
26
+ add_filter( 'optml_lazyload_bg_classes', [ $this, 'add_bg_class' ], 10, 1 );
27
+ }
28
+
29
+ /**
30
+ * Add classes for lazyload on background.
31
+ *
32
+ * @param string $classes Old classes.
33
+ *
34
+ * @return array New classes.
35
+ */
36
+ public function add_bg_class( $classes = array() ) {
37
+ $classes[] = 'tp-bgimg';
38
+
39
+ return $classes;
40
+ }
41
+
42
+ /**
43
+ * Adds flag that should ignore applying the data-opt-src
44
+ *
45
+ * @param string $flags Flag that should ignore.
46
+ *
47
+ * @return array New flags.
48
+ */
49
+ public function add_data_ignore( $flags = array() ) {
50
+ $flags[] = 'rev-slidebg';
51
+
52
+ return $flags;
53
+ }
54
+
55
+ }
inc/compatibilities/shortcode_ultimate.php ADDED
@@ -0,0 +1,76 @@
1
+ <?php
2
+
3
+ /**
4
+ * Class Optml_shortcode_ultimate.
5
+ *
6
+ * @reason Shortcode Ultimate uses a strange image resizing feature
7
+ * which has by default the hard cropping on. As we are following the WordPress
8
+ * image size defaults, we need to change the default cropping
9
+ * for shortcode's output.
10
+ */
11
+ class Optml_shortcode_ultimate extends Optml_compatibility {
12
+ /**
13
+ * Tags where we subscribe the compatibility.
14
+ *
15
+ * @var array Allowed tags.
16
+ */
17
+ private $allowed_tags = [
18
+ 'su_slider' => true,
19
+ 'su_carousel' => true,
20
+ 'su_custom_gallery' => true,
21
+ ];
22
+
23
+ /**
24
+ * Should we load the integration logic.
25
+ *
26
+ * @return bool Should we load.
27
+ */
28
+ function should_load() {
29
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
30
+
31
+ return is_plugin_active( 'shortcodes-ultimate/shortcodes-ultimate.php' );
32
+ }
33
+
34
+ /**
35
+ * Register integration details.
36
+ */
37
+ public function register() {
38
+ add_filter( 'do_shortcode_tag', [ $this, 'alter_shortcode_output' ], 10, 3 );
39
+ }
40
+
41
+ /**
42
+ * Alter shortcode output by replacing the image urls.
43
+ *
44
+ * @param string $output Previous shortcode output.
45
+ * @param string $tag Shortcode tag.
46
+ * @param array $attr Shortcode attrs.
47
+ *
48
+ * @return mixed New output.
49
+ */
50
+ function alter_shortcode_output( $output, $tag, $attr ) {
51
+
52
+ if ( ! isset( $this->allowed_tags[ $tag ] ) ) {
53
+ return $output;
54
+ }
55
+
56
+ add_filter( 'optml_default_crop', [ $this, 'change_default_crop' ] );
57
+
58
+ $output = Optml_Main::instance()->manager->process_images_from_content( $output );
59
+
60
+ remove_filter( 'optml_default_crop', [ $this, 'change_default_crop' ] );
61
+
62
+ return $output;
63
+ }
64
+
65
+ /**
66
+ * Change default crop.
67
+ *
68
+ * @return array New default cropping.
69
+ */
70
+ public function change_default_crop() {
71
+ return array(
72
+ 'type' => Optml_Resize::RESIZE_FILL,
73
+ 'gravity' => Optml_Resize::GRAVITY_CENTER,
74
+ );
75
+ }
76
+ }
inc/compatibilities/woocommerce.php ADDED
@@ -0,0 +1,41 @@
1
+ <?php
2
+
3
+ /**
4
+ * Class Optml_woocommerce.
5
+ *
6
+ * @reason Zoom image on product pages uses a the lqip placeholder instead of the full size image.
7
+ */
8
+ class Optml_woocommerce extends Optml_compatibility {
9
+
10
+ /**
11
+ * Should we load the integration logic.
12
+ *
13
+ * @return bool Should we load.
14
+ */
15
+ function should_load() {
16
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
17
+
18
+ return is_plugin_active( 'woocommerce/woocommerce.php' );
19
+ }
20
+
21
+ /**
22
+ * Register integration details.
23
+ */
24
+ public function register() {
25
+ add_filter( 'optml_watcher_lz_classes', [ $this, 'add_watcher_class' ], 10, 1 );
26
+ }
27
+
28
+ /**
29
+ * Add classes for watching for late lazyload.
30
+ *
31
+ * @param string $classes Old classes.
32
+ *
33
+ * @return array New classes.
34
+ */
35
+ public function add_watcher_class( $classes = array() ) {
36
+ $classes[] = 'zoomImg';
37
+
38
+ return $classes;
39
+ }
40
+
41
+ }
inc/image.php CHANGED
@@ -93,11 +93,11 @@ class Optml_Image {
93
/**
94
* Return transformed url.
95
*
96
- * @param bool $signed Either will be signed or not.
97
*
98
* @return string Transformed image url.
99
*/
100
- public function get_url( $signed = false ) {
101
$path_parts = array();
102
103
$path_parts[] = $this->width->toString();
@@ -108,7 +108,7 @@ class Optml_Image {
108
$path_parts[] = $this->resize->toString();
109
}
110
111
- if ( is_array( self::$watermark->get() ) && isset( self::$watermark->get()['id'] ) && self::$watermark->get()['id'] > 0 ) {
112
$path_parts[] = self::$watermark->toString();
113
}
114
@@ -116,7 +116,7 @@ class Optml_Image {
116
117
$path = sprintf( '/%s%s', implode( '/', $path_parts ), $path );
118
119
- if ( $signed ) {
120
$path = sprintf( '/%s%s', $this->get_signature( $path ), $path );
121
}
122
93
/**
94
* Return transformed url.
95
*
96
+ * @param array $params Either will be signed or not.
97
*
98
* @return string Transformed image url.
99
*/
100
+ public function get_url( $params = [] ) {
101
$path_parts = array();
102
103
$path_parts[] = $this->width->toString();
108
$path_parts[] = $this->resize->toString();
109
}
110
111
+ if ( isset( $params['apply_watermark'] ) && $params['apply_watermark'] && is_array( self::$watermark->get() ) && isset( self::$watermark->get()['id'] ) && self::$watermark->get()['id'] > 0 ) {
112
$path_parts[] = self::$watermark->toString();
113
}
114
116
117
$path = sprintf( '/%s%s', implode( '/', $path_parts ), $path );
118
119
+ if ( isset( $params['signed'] ) && $params['signed'] ) {
120
$path = sprintf( '/%s%s', $this->get_signature( $path ), $path );
121
}
122
inc/lazyload_replacer.php CHANGED
@@ -16,6 +16,18 @@ final class Optml_Lazyload_Replacer extends Optml_App_Replacer {
16
* @var Optml_Tag_Replacer
17
*/
18
protected static $instance = null;
19
20
/**
21
* Class instance method.
@@ -27,32 +39,63 @@ final class Optml_Lazyload_Replacer extends Optml_App_Replacer {
27
* @return Optml_Tag_Replacer
28
*/
29
public static function instance() {
30
- if ( is_null( self::$instance ) ) {
31
self::$instance = new self();
32
- add_action( 'after_setup_theme', array( self::$instance, 'init' ) );
33
}
34
35
return self::$instance;
36
}
37
38
/**
39
* The initialize method.
40
*/
41
public function init() {
42
43
- if ( ! parent::init() ) {
44
- return; // @codeCoverageIgnore
45
}
46
47
- if ( $this->settings->use_lazyload() ) {
48
- add_filter(
49
- 'max_srcset_image_width',
50
- function () {
51
- return 1;
52
- }
53
- );
54
- add_filter( 'optml_tag_replace', array( $this, 'lazyload_tag_replace' ), 2, 5 );
55
- }
56
}
57
58
/**
@@ -72,13 +115,17 @@ final class Optml_Lazyload_Replacer extends Optml_App_Replacer {
72
return Optml_Tag_Replacer::instance()->regular_tag_replace( $new_tag, $original_url, $new_url, $optml_args, $is_slashed );
73
}
74
$optml_args['quality'] = 'eco';
75
- $low_url = apply_filters( 'optml_content_url', $is_slashed ? stripslashes( $original_url ) : $original_url, $optml_args );
76
- $low_url = $is_slashed ? addcslashes( $low_url, '/' ) : $low_url;
77
78
- $opt_format = ' data-opt-src="%s" ';
79
80
- $opt_format = $is_slashed ? addslashes( $opt_format ) : $opt_format;
81
- $new_url = $is_slashed ? addcslashes( $new_url, '/' ) : $new_url;
82
83
$opt_src = sprintf( $opt_format, $new_url );
84
@@ -113,9 +160,12 @@ final class Optml_Lazyload_Replacer extends Optml_App_Replacer {
113
* @return bool We can lazyload?
114
*/
115
public function can_lazyload_for( $url, $tag = '' ) {
116
- if ( strpos( $tag, '<noscript' ) !== false ) {
117
- return false;
118
}
119
if ( ! defined( 'OPTML_DISABLE_PNG_LAZYLOAD' ) ) {
120
return true;
121
}
@@ -135,6 +185,23 @@ final class Optml_Lazyload_Replacer extends Optml_App_Replacer {
135
return false;
136
}
137
138
/**
139
* Throw error on object clone
140
*
16
* @var Optml_Tag_Replacer
17
*/
18
protected static $instance = null;
19
+ /**
20
+ * Holds classes for listening to lazyload on background.
21
+ *
22
+ * @var array Lazyload background classes.
23
+ */
24
+ private static $lazyload_background_classes = null;
25
+ /**
26
+ * Holds classes responsabile for watching lazyload behaviour.
27
+ *
28
+ * @var array Lazyload classes.
29
+ */
30
+ private static $lazyload_watcher_classes = null;
31
32
/**
33
* Class instance method.
39
* @return Optml_Tag_Replacer
40
*/
41
public static function instance() {
42
+ if ( null === self::$instance ) {
43
self::$instance = new self();
44
+ add_action( 'optml_replacer_setup', array( self::$instance, 'init' ) );
45
}
46
47
return self::$instance;
48
}
49
50
+ /**
51
+ * Returns background classes for lazyload.
52
+ *
53
+ * @return array
54
+ */
55
+ public static function get_lazyload_bg_classes() {
56
+
57
+ if ( null != self::$lazyload_background_classes && is_array( self::$lazyload_background_classes ) ) {
58
+ return self::$lazyload_background_classes;
59
+ }
60
+
61
+ self::$lazyload_background_classes = apply_filters( 'optml_lazyload_bg_classes', [] );
62
+
63
+ return self::$lazyload_background_classes;
64
+ }
65
+
66
+ /**
67
+ * Returns classes for lazyload additional watch.
68
+ *
69
+ * @return array
70
+ */
71
+ public static function get_watcher_lz_classes() {
72
+
73
+ if ( null != self::$lazyload_watcher_classes && is_array( self::$lazyload_watcher_classes ) ) {
74
+ return self::$lazyload_watcher_classes;
75
+ }
76
+
77
+ self::$lazyload_watcher_classes = apply_filters( 'optml_watcher_lz_classes', [] );
78
+
79
+ return self::$lazyload_watcher_classes;
80
+ }
81
+
82
/**
83
* The initialize method.
84
*/
85
public function init() {
86
+ parent::init();
87
88
+ if ( ! $this->settings->use_lazyload() ) {
89
+ return;
90
}
91
+ add_filter(
92
+ 'max_srcset_image_width',
93
+ function () {
94
+ return 1;
95
+ }
96
+ );
97
+ add_filter( 'optml_tag_replace', array( $this, 'lazyload_tag_replace' ), 2, 5 );
98
99
}
100
101
/**
115
return Optml_Tag_Replacer::instance()->regular_tag_replace( $new_tag, $original_url, $new_url, $optml_args, $is_slashed );
116
}
117
$optml_args['quality'] = 'eco';
118
119
+ $low_url = apply_filters( 'optml_content_url', $is_slashed ? stripslashes( $original_url ) : $original_url, $optml_args );
120
+ $low_url = $is_slashed ? addcslashes( $low_url, '/' ) : $low_url;
121
+ $opt_format = '';
122
123
+ if ( $this->should_add_data_tag( $new_tag ) ) {
124
+ $opt_format = ' data-opt-src="%s" ';
125
+ $opt_format = $is_slashed ? addslashes( $opt_format ) : $opt_format;
126
+ }
127
+
128
+ $new_url = $is_slashed ? addcslashes( $new_url, '/' ) : $new_url;
129
130
$opt_src = sprintf( $opt_format, $new_url );
131
160
* @return bool We can lazyload?
161
*/
162
public function can_lazyload_for( $url, $tag = '' ) {
163
+ foreach ( self::possible_lazyload_flags() as $banned_string ) {
164
+ if ( strpos( $tag, $banned_string ) !== false ) {
165
+ return false;
166
+ }
167
}
168
+
169
if ( ! defined( 'OPTML_DISABLE_PNG_LAZYLOAD' ) ) {
170
return true;
171
}
185
return false;
186
}
187
188
+ /**
189
+ * Check if we should add the data-opt-tag.
190
+ *
191
+ * @param string $tag Html tag.
192
+ *
193
+ * @return bool Should add?
194
+ */
195
+ public function should_add_data_tag( $tag ) {
196
+ foreach ( self::possible_data_ignore_flags() as $banned_string ) {
197
+ if ( strpos( $tag, $banned_string ) !== false ) {
198
+ return false;
199
+ }
200
+ }
201
+
202
+ return true;
203
+ }
204
+
205
/**
206
* Throw error on object clone
207
*
inc/main.php CHANGED
@@ -13,32 +13,6 @@ final class Optml_Main {
13
*/
14
private static $_instance = null;
15
16
- /**
17
- * Holds the url replacer class.
18
- *
19
- * @access public
20
- * @since 1.0.0
21
- * @var Optml_Url_Replacer Replacer instance.
22
- */
23
- public $url_replacer;
24
-
25
- /**
26
- * Holds the tag replacer class.
27
- *
28
- * @access public
29
- * @since 1.0.0
30
- * @var Optml_Tag_Replacer Replacer instance.
31
- */
32
- public $tag_replacer;
33
-
34
- /**
35
- * Holds the lazyload replacer class.
36
- *
37
- * @access public
38
- * @since 1.0.0
39
- * @var Optml_Lazyload_Replacer Replacer instance.
40
- */
41
- public $lazyload_replacer;
42
43
/**
44
* Holds the manager class.
@@ -84,20 +58,17 @@ final class Optml_Main {
84
* @return Optml_Main Plugin instance.
85
*/
86
public static function instance() {
87
- if ( is_null( self::$_instance ) ) {
88
add_filter( 'themeisle_sdk_products', array( __CLASS__, 'register_sdk' ) );
89
add_filter( 'optimole-wp_uninstall_feedback_icon', array( __CLASS__, 'change_icon' ) );
90
add_filter( 'optimole_wp_uninstall_feedback_after_css', array( __CLASS__, 'adds_uf_css' ) );
91
add_filter( 'optimole_wp_feedback_review_message', array( __CLASS__, 'change_review_message' ) );
92
add_filter( 'optimole_wp_logger_heading', array( __CLASS__, 'change_review_message' ) );
93
add_filter( 'optml_default_settings', array( __CLASS__, 'change_lazyload_default' ) );
94
- self::$_instance = new self();
95
- self::$_instance->url_replacer = Optml_Url_Replacer::instance();
96
- self::$_instance->tag_replacer = Optml_Tag_Replacer::instance();
97
- self::$_instance->lazyload_replacer = Optml_Lazyload_Replacer::instance();
98
- self::$_instance->manager = Optml_Manager::instance();
99
- self::$_instance->rest = new Optml_Rest();
100
- self::$_instance->admin = new Optml_Admin();
101
}
102
$vendor_file = OPTML_PATH . 'vendor/autoload.php';
103
if ( is_readable( $vendor_file ) ) {
13
*/
14
private static $_instance = null;
15
16
17
/**
18
* Holds the manager class.
58
* @return Optml_Main Plugin instance.
59
*/
60
public static function instance() {
61
+ if ( null === self::$_instance ) {
62
add_filter( 'themeisle_sdk_products', array( __CLASS__, 'register_sdk' ) );
63
add_filter( 'optimole-wp_uninstall_feedback_icon', array( __CLASS__, 'change_icon' ) );
64
add_filter( 'optimole_wp_uninstall_feedback_after_css', array( __CLASS__, 'adds_uf_css' ) );
65
add_filter( 'optimole_wp_feedback_review_message', array( __CLASS__, 'change_review_message' ) );
66
add_filter( 'optimole_wp_logger_heading', array( __CLASS__, 'change_review_message' ) );
67
add_filter( 'optml_default_settings', array( __CLASS__, 'change_lazyload_default' ) );
68
+ self::$_instance = new self();
69
+ self::$_instance->manager = Optml_Manager::instance();
70
+ self::$_instance->rest = new Optml_Rest();
71
+ self::$_instance->admin = new Optml_Admin();
72
}
73
$vendor_file = OPTML_PATH . 'vendor/autoload.php';
74
if ( is_readable( $vendor_file ) ) {
inc/manager.php CHANGED
@@ -15,6 +15,52 @@ final class Optml_Manager {
15
*/
16
protected static $instance = null;
17
18
/**
19
* Class instance method.
20
*
@@ -25,8 +71,11 @@ final class Optml_Manager {
25
* @return Optml_Manager
26
*/
27
public static function instance() {
28
- if ( is_null( self::$instance ) ) {
29
- self::$instance = new self();
30
add_action( 'after_setup_theme', array( self::$instance, 'init' ) );
31
}
32
@@ -37,22 +86,42 @@ final class Optml_Manager {
37
* The initialize method.
38
*/
39
public function init() {
40
- add_filter( 'init', array( $this, 'filter_options_and_mods' ) );
41
- add_filter( 'the_content', array( $this, 'process_images_from_content' ), PHP_INT_MAX );
42
- /**
43
- * When we have to process cdn images, i.e MIRROR is defined,
44
- * we need this as late as possible for other replacers to occur.
45
- * Otherwise, we can hook first to avoid any other plugins to take care of replacement.
46
- */
47
- add_action(
48
- self::is_ajax_request() ? 'init' : 'template_redirect',
49
- array(
50
- $this,
51
- 'process_template_redirect_content',
52
- ),
53
- defined( 'OPTML_SITE_MIRROR' ) ? PHP_INT_MAX : PHP_INT_MIN
54
- );
55
- add_action( 'get_post_metadata', array( $this, 'replace_meta' ), PHP_INT_MAX, 4 );
56
}
57
58
/**
@@ -81,68 +150,44 @@ final class Optml_Manager {
81
}
82
83
/**
84
- * Handles the url replacement in options and theme mods.
85
*/
86
- public function filter_options_and_mods() {
87
/**
88
- * `optml_imgcdn_options_with_url` is a filter that allows themes or plugins to select which option
89
- * holds an url and needs an optimization.
90
*/
91
- $options_list = apply_filters(
92
- 'optml_imgcdn_options_with_url',
93
array(
94
- 'theme_mods_' . get_option( 'stylesheet' ),
95
- 'theme_mods_' . get_option( 'template' ),
96
- )
97
);
98
99
- foreach ( $options_list as $option ) {
100
- add_filter( "option_$option", array( $this, 'replace_option_url' ) );
101
- }
102
-
103
- }
104
105
- /**
106
- * A filter which turns a local url into an optimized CDN image url or an array of image urls.
107
- *
108
- * @param string $url The url which should be replaced.
109
- *
110
- * @return string Replaced url.
111
- */
112
- public function replace_option_url( $url ) {
113
- if ( empty( $url ) ) {
114
- return $url;
115
- }
116
- // $url might be an array or an json encoded array with urls.
117
- if ( is_array( $url ) || filter_var( $url, FILTER_VALIDATE_URL ) === false ) {
118
- $array = $url;
119
- $encoded = false;
120
-
121
- // it might a json encoded array
122
- if ( is_string( $url ) ) {
123
- $array = json_decode( $url, true );
124
- $encoded = true;
125
- }
126
-
127
- // in case there is an array, apply it recursively.
128
- if ( is_array( $array ) ) {
129
- foreach ( $array as $index => $value ) {
130
- $array[ $index ] = $this->replace_option_url( $value );
131
- }
132
-
133
- if ( $encoded ) {
134
- return json_encode( $array );
135
- }
136
-
137
- return $array;
138
- }
139
140
- if ( filter_var( $url, FILTER_VALIDATE_URL ) === false ) {
141
- return $url;
142
}
143
}
144
-
145
- return apply_filters( 'optml_content_url', $url );
146
}
147
148
/**
@@ -198,7 +243,7 @@ final class Optml_Manager {
198
* @return array array of urls.
199
*/
200
public function extract_urls_from_json( $content ) {
201
- $regex = '/(?<!(=|\\\\)(?:"|\'|"))(?:http(?:s?):)(?:[\/\\\\|.|\w|\s|-])*\.(?:' . implode( '|', array_keys( Optml_Config::$extensions ) ) . ')/';
202
preg_match_all(
203
$regex,
204
$content,
@@ -288,7 +333,6 @@ final class Optml_Manager {
288
return $content;
289
}
290
$images = self::parse_images_from_html( $content );
291
-
292
if ( empty( $images ) ) {
293
return $content;
294
}
@@ -333,7 +377,7 @@ final class Optml_Manager {
333
$images = array();
334
335
$content = self::strip_header_from_content( $content );
336
- if ( preg_match_all( '/(?:<a[^>]+?href=["|\'](?P<link_url>[^\s]+?)["|\'][^>]*?>\s*)?(?P<img_tag>(?:<\s*noscript\s*>\s*)?<img[^>]*?\s+?src=\\\\?["|\'](?P<img_url>[^\s]+?)["|\'].*?>){1}(?:\s*<\/a>)?/ism', $content, $images ) ) {
337
338
foreach ( $images as $key => $unused ) {
339
// Simplify the output as much as possible, mostly for confirming test results.
@@ -392,7 +436,7 @@ final class Optml_Manager {
392
* @return array
393
*/
394
public function extract_image_urls_from_content( $content ) {
395
- $regex = '/(?:http(?:s?):)(?:[\/\\\\|.|\w|\s|-])*\.(?:' . implode( '|', array_keys( Optml_Config::$extensions ) ) . ')/';
396
preg_match_all(
397
$regex,
398
$content,
15
*/
16
protected static $instance = null;
17
18
+ /**
19
+ * Holds the url replacer class.
20
+ *
21
+ * @access public
22
+ * @since 1.0.0
23
+ * @var Optml_Url_Replacer Replacer instance.
24
+ */
25
+ public $url_replacer;
26
+
27
+ /**
28
+ * Holds the tag replacer class.
29
+ *
30
+ * @access public
31
+ * @since 1.0.0
32
+ * @var Optml_Tag_Replacer Replacer instance.
33
+ */
34
+ public $tag_replacer;
35
+
36
+ /**
37
+ * Holds the lazyload replacer class.
38
+ *
39
+ * @access public
40
+ * @since 1.0.0
41
+ * @var Optml_Lazyload_Replacer Replacer instance.
42
+ */
43
+ public $lazyload_replacer;
44
+ /**
45
+ * Holds plugin settings.
46
+ *
47
+ * @var Optml_Settings WordPress settings.
48
+ */
49
+ protected $settings;
50
+
51
+ /**
52
+ * Possible integrations with different plugins.
53
+ *
54
+ * @var array Integrations classes.
55
+ */
56
+ private $compatibilities = array(
57
+ 'shortcode_ultimate',
58
+ 'foogallery',
59
+ 'envira',
60
+ 'revslider',
61
+ 'woocommerce',
62
+ );
63
+
64
/**
65
* Class instance method.
66
*
71
* @return Optml_Manager
72
*/
73
public static function instance() {
74
+ if ( null === self::$instance ) {
75
+ self::$instance = new self();
76
+ self::$instance->url_replacer = Optml_Url_Replacer::instance();
77
+ self::$instance->tag_replacer = Optml_Tag_Replacer::instance();
78
+ self::$instance->lazyload_replacer = Optml_Lazyload_Replacer::instance();
79
add_action( 'after_setup_theme', array( self::$instance, 'init' ) );
80
}
81
86
* The initialize method.
87
*/
88
public function init() {
89
+
90
+ $this->settings = new Optml_Settings();
91
+
92
+ if ( ! $this->should_replace() ) {
93
+ return;
94
+ }
95
+ $this->register_hooks();
96
+ }
97
+
98
+ /**
99
+ * Check if we should rewrite the urls.
100
+ *
101
+ * @return bool If we can replace the image.
102
+ */
103
+ public function should_replace() {
104
+
105
+ if ( apply_filters( 'optml_should_replace_page', false ) ) {
106
+ return false;
107
+ }
108
+
109
+ if ( ( is_admin() && ! self::is_ajax_request() ) || ! $this->settings->is_connected() || ! $this->settings->is_enabled() || is_customize_preview() ) {
110
+ return false; // @codeCoverageIgnore
111
+ }
112
+
113
+ if ( array_key_exists( 'preview', $_GET ) && 'true' == $_GET['preview'] ) {
114
+ return false; // @codeCoverageIgnore
115
+ }
116
+
117
+ if ( array_key_exists( 'optml_off', $_GET ) && 'true' == $_GET['optml_off'] ) {
118
+ return false; // @codeCoverageIgnore
119
+ }
120
+ if ( array_key_exists( 'elementor-preview', $_GET ) && ! empty( $_GET['elementor-preview'] ) ) {
121
+ return false; // @codeCoverageIgnore
122
+ }
123
+
124
+ return true;
125
}
126
127
/**
150
}
151
152
/**
153
+ * Register frontend replacer hooks.
154
*/
155
+ public function register_hooks() {
156
+
157
+ do_action( 'optml_replacer_setup' );
158
+
159
+ add_filter( 'the_content', array( $this, 'process_images_from_content' ), PHP_INT_MAX );
160
/**
161
+ * When we have to process cdn images, i.e MIRROR is defined,
162
+ * we need this as late as possible for other replacers to occur.
163
+ * Otherwise, we can hook first to avoid any other plugins to take care of replacement.
164
*/
165
+ add_action(
166
+ self::is_ajax_request() ? 'init' : 'template_redirect',
167
array(
168
+ $this,
169
+ 'process_template_redirect_content',
170
+ ),
171
+ defined( 'OPTML_SITE_MIRROR' ) ? PHP_INT_MAX : PHP_INT_MIN
172
);
173
174
+ add_action( 'rest_api_init', array( $this, 'process_template_redirect_content' ), PHP_INT_MIN );
175
176
+ add_action( 'get_post_metadata', array( $this, 'replace_meta' ), PHP_INT_MAX, 4 );
177
178
+ foreach ( $this->compatibilities as $compatibility_class ) {
179
+ $compatibility_class = 'Optml_' . $compatibility_class;
180
+ $compatibility = new $compatibility_class;
181
+
182
+ /**
183
+ * Check if we should load compatibility.
184
+ *
185
+ * @var Optml_compatibility $compatibility Class to register.
186
+ */
187
+ if ( $compatibility->should_load() ) {
188
+ $compatibility->register();
189
}
190
}
191
}
192
193
/**
243
* @return array array of urls.
244
*/
245
public function extract_urls_from_json( $content ) {
246
+ $regex = '/(?<!(=|\\\\)(?:"|\'|"))(?:http(?:s?):)(?:[\/\\\\|.|\w|\s|-])*\.(?:' . implode( '|', array_keys( Optml_Config::$extensions ) ) . ')(?:\??[\w|=|&|\-|\.|:]*)/';
247
preg_match_all(
248
$regex,
249
$content,
333
return $content;
334
}
335
$images = self::parse_images_from_html( $content );
336
if ( empty( $images ) ) {
337
return $content;
338
}
377
$images = array();
378
379
$content = self::strip_header_from_content( $content );
380
+ if ( preg_match_all( '/(?:<a[^>]+?href=["|\'](?P<link_url>[^\s]+?)["|\'][^>]*?>\s*)?(?P<img_tag>(?:<\s*noscript\s*>\s*)?<img[^>]*?\s+?(?:' . implode( '|', array_merge( [ 'src' ], Optml_Tag_Replacer::possible_src_attributes() ) ) . ')=\\\\?["|\'](?P<img_url>[^\s]+?)["|\'].*?>){1}(?:\s*<\/a>)?/ism', $content, $images ) ) {
381
382
foreach ( $images as $key => $unused ) {
383
// Simplify the output as much as possible, mostly for confirming test results.
436
* @return array
437
*/
438
public function extract_image_urls_from_content( $content ) {
439
+ $regex = '/(?:http(?:s?):)(?:[\/\\\\|.|\w|\s|-])*\.(?:' . implode( '|', array_keys( Optml_Config::$extensions ) ) . ')(?:\??[\w|=|&|\-|\.|:]*)/';
440
preg_match_all(
441
$regex,
442
$content,
inc/settings.php CHANGED
@@ -251,6 +251,17 @@ class Optml_Settings {
251
);
252
}
253
254
/**
255
* Check if replacer is enabled.
256
*
251
);
252
}
253
254
+ /**
255
+ * Get numeric quality used by the service.
256
+ *
257
+ * @return int Numeric quality.
258
+ */
259
+ public function get_numeric_quality() {
260
+ $value = $this->get_quality();
261
+
262
+ return (int) $this->to_accepted_quality( $value );
263
+ }
264
+
265
/**
266
* Check if replacer is enabled.
267
*
inc/tag_replacer.php CHANGED
@@ -27,9 +27,9 @@ final class Optml_Tag_Replacer extends Optml_App_Replacer {
27
* @return Optml_Tag_Replacer
28
*/
29
public static function instance() {
30
- if ( is_null( self::$instance ) ) {
31
self::$instance = new self();
32
- add_action( 'after_setup_theme', array( self::$instance, 'init' ) );
33
}
34
35
return self::$instance;
@@ -40,18 +40,18 @@ final class Optml_Tag_Replacer extends Optml_App_Replacer {
40
*/
41
public function init() {
42
43
- if ( ! parent::init() ) {
44
return;
45
}
46
47
- add_filter( 'optml_content_images_tags', array( $this, 'process_image_tags' ), 1, 2 );
48
49
- if ( ! $this->settings->use_lazyload() ) {
50
- add_filter( 'optml_tag_replace', array( $this, 'regular_tag_replace' ), 1, 5 );
51
- add_filter( 'image_downsize', array( $this, 'filter_image_downsize' ), PHP_INT_MAX, 3 );
52
- add_filter( 'wp_calculate_image_srcset', array( $this, 'filter_srcset_attr' ), PHP_INT_MAX, 5 );
53
- add_filter( 'wp_calculate_image_sizes', array( $this, 'filter_sizes_attr' ), 1, 2 );
54
- }
55
}
56
57
/**
@@ -68,20 +68,24 @@ final class Optml_Tag_Replacer extends Optml_App_Replacer {
68
69
foreach ( $images[0] as $index => $tag ) {
70
$width = $height = false;
71
- $resize = array();
72
$new_tag = $tag;
73
74
$is_slashed = strpos( $images['img_url'][ $index ], '\/' ) !== false;
75
76
$src = $tmp = $is_slashed ? stripslashes( $images['img_url'][ $index ] ) : $images['img_url'][ $index ];
77
78
if ( apply_filters( 'optml_ignore_image_link', false, $src ) ||
79
false !== strpos( $src, Optml_Config::$service_url ) ||
80
! $this->can_replace_url( $src )
81
) {
82
continue; // @codeCoverageIgnore
83
}
84
85
list( $width, $height, $resize ) = self::parse_dimensions_from_tag(
86
$images['img_tag'][ $index ],
87
$image_sizes,
@@ -92,11 +96,12 @@ final class Optml_Tag_Replacer extends Optml_App_Replacer {
92
)
93
);
94
if ( false === $width && false === $height ) {
95
- list( $width, $height ) = $this->parse_dimensions_from_filename( $tmp );
96
}
97
-
98
if ( empty( $resize ) && isset( $sizes2crop[ $width . $height ] ) ) {
99
$resize = $this->to_optml_crop( $sizes2crop[ $width . $height ] );
100
}
101
102
$optml_args = [ 'width' => $width, 'height' => $height, 'resize' => $resize ];
@@ -148,6 +153,7 @@ final class Optml_Tag_Replacer extends Optml_App_Replacer {
148
}
149
if ( preg_match( '#class=["|\']?[^"\']*size-([^"\'\s]+)[^"\']*["|\']?#i', $tag, $size ) ) {
150
$size = array_pop( $size );
151
if ( false === $args['width'] && false === $args['height'] && 'full' != $size && array_key_exists( $size, $image_sizes ) ) {
152
$args['width'] = (int) $image_sizes[ $size ]['width'];
153
$args['height'] = (int) $image_sizes[ $size ]['height'];
@@ -155,6 +161,8 @@ final class Optml_Tag_Replacer extends Optml_App_Replacer {
155
if ( 'full' != $size && array_key_exists( $size, $image_sizes ) ) {
156
$args['resize'] = $this->to_optml_crop( $image_sizes[ $size ]['crop'] );
157
}
158
}
159
160
return array( $args['width'], $args['height'], $args['resize'] );
@@ -196,14 +204,15 @@ final class Optml_Tag_Replacer extends Optml_App_Replacer {
196
return $sources;
197
}
198
$original_url = null;
199
- $cropping = null;
200
if ( count( $size_array ) === 2 ) {
201
$sizes = self::size_to_crop();
202
$cropping = isset( $sizes[ $size_array[0] . $size_array[1] ] ) ? $this->to_optml_crop( $sizes[ $size_array[0] . $size_array[1] ] ) : null;
203
}
204
foreach ( $sources as $i => $source ) {
205
$url = $source['url'];
206
- list( $width, $height ) = $this->parse_dimensions_from_filename( $url );
207
208
if ( empty( $width ) ) {
209
$width = $image_meta['width'];
@@ -212,6 +221,7 @@ final class Optml_Tag_Replacer extends Optml_App_Replacer {
212
if ( empty( $height ) ) {
213
$height = $image_meta['height'];
214
}
215
if ( $original_url === null ) {
216
if ( ! empty( $attachment_id ) ) {
217
$original_url = wp_get_attachment_url( $attachment_id );
@@ -230,6 +240,8 @@ final class Optml_Tag_Replacer extends Optml_App_Replacer {
230
}
231
if ( $cropping !== null ) {
232
$args['resize'] = $cropping;
233
}
234
$sources[ $i ]['url'] = apply_filters( 'optml_content_url', $original_url, $args );
235
}
27
* @return Optml_Tag_Replacer
28
*/
29
public static function instance() {
30
+ if ( null === self::$instance ) {
31
self::$instance = new self();
32
+ add_action( 'optml_replacer_setup', array( self::$instance, 'init' ) );
33
}
34
35
return self::$instance;
40
*/
41
public function init() {
42
43
+ parent::init();
44
+ add_filter( 'optml_content_images_tags', array( $this, 'process_image_tags' ), 1, 2 );
45
+
46
+ if ( $this->settings->use_lazyload() ) {
47
return;
48
}
49
50
+ add_filter( 'optml_tag_replace', array( $this, 'regular_tag_replace' ), 1, 5 );
51
+ add_filter( 'image_downsize', array( $this, 'filter_image_downsize' ), PHP_INT_MAX, 3 );
52
+ add_filter( 'wp_calculate_image_srcset', array( $this, 'filter_srcset_attr' ), PHP_INT_MAX, 5 );
53
+ add_filter( 'wp_calculate_image_sizes', array( $this, 'filter_sizes_attr' ), 1, 2 );
54
55
}
56
57
/**
68
69
foreach ( $images[0] as $index => $tag ) {
70
$width = $height = false;
71
$new_tag = $tag;
72
73
$is_slashed = strpos( $images['img_url'][ $index ], '\/' ) !== false;
74
75
$src = $tmp = $is_slashed ? stripslashes( $images['img_url'][ $index ] ) : $images['img_url'][ $index ];
76
77
+ $src = $tmp = strpos( $src, $this->upload_resource['content_path'] ) === 0 ? untrailingslashit( get_home_url() ) . $src : $src;
78
+
79
if ( apply_filters( 'optml_ignore_image_link', false, $src ) ||
80
false !== strpos( $src, Optml_Config::$service_url ) ||
81
! $this->can_replace_url( $src )
82
) {
83
+
84
continue; // @codeCoverageIgnore
85
}
86
87
+ $resize = apply_filters( 'optml_default_crop', array() );
88
+
89
list( $width, $height, $resize ) = self::parse_dimensions_from_tag(
90
$images['img_tag'][ $index ],
91
$image_sizes,
96
)
97
);
98
if ( false === $width && false === $height ) {
99
+ list( $width, $height, $crop ) = $this->parse_dimensions_from_filename( $tmp );
100
}
101
if ( empty( $resize ) && isset( $sizes2crop[ $width . $height ] ) ) {
102
$resize = $this->to_optml_crop( $sizes2crop[ $width . $height ] );
103
+ } elseif ( isset( $crop ) ) {
104
+ $resize = $this->to_optml_crop( $crop );
105
}
106
107
$optml_args = [ 'width' => $width, 'height' => $height, 'resize' => $resize ];
153
}
154
if ( preg_match( '#class=["|\']?[^"\']*size-([^"\'\s]+)[^"\']*["|\']?#i', $tag, $size ) ) {
155
$size = array_pop( $size );
156
+
157
if ( false === $args['width'] && false === $args['height'] && 'full' != $size && array_key_exists( $size, $image_sizes ) ) {
158
$args['width'] = (int) $image_sizes[ $size ]['width'];
159
$args['height'] = (int) $image_sizes[ $size ]['height'];
161
if ( 'full' != $size && array_key_exists( $size, $image_sizes ) ) {
162
$args['resize'] = $this->to_optml_crop( $image_sizes[ $size ]['crop'] );
163
}
164
+ } else {
165
+ $args['resize'] = apply_filters( 'optml_parse_resize_from_tag', [], $tag );
166
}
167
168
return array( $args['width'], $args['height'], $args['resize'] );
204
return $sources;
205
}
206
$original_url = null;
207
+ $cropping = null;
208
if ( count( $size_array ) === 2 ) {
209
$sizes = self::size_to_crop();
210
$cropping = isset( $sizes[ $size_array[0] . $size_array[1] ] ) ? $this->to_optml_crop( $sizes[ $size_array[0] . $size_array[1] ] ) : null;
211
}
212
+
213
foreach ( $sources as $i => $source ) {
214
$url = $source['url'];
215
+ list( $width, $height, $file_crop ) = $this->parse_dimensions_from_filename( $url );
216
217
if ( empty( $width ) ) {
218
$width = $image_meta['width'];
221
if ( empty( $height ) ) {
222
$height = $image_meta['height'];
223
}
224
+
225
if ( $original_url === null ) {
226
if ( ! empty( $attachment_id ) ) {
227
$original_url = wp_get_attachment_url( $attachment_id );
240
}
241
if ( $cropping !== null ) {
242
$args['resize'] = $cropping;
243
+ } else {
244
+ $args['resize'] = $this->to_optml_crop( $file_crop );
245
}
246
$sources[ $i ]['url'] = apply_filters( 'optml_content_url', $original_url, $args );
247
}
inc/url_replacer.php CHANGED
@@ -28,24 +28,88 @@ final class Optml_Url_Replacer extends Optml_App_Replacer {
28
* @return Optml_Url_Replacer
29
*/
30
public static function instance() {
31
- if ( is_null( self::$instance ) ) {
32
self::$instance = new self();
33
- add_action( 'after_setup_theme', array( self::$instance, 'init' ) );
34
}
35
36
return self::$instance;
37
}
38
39
/**
40
* The initialize method.
41
*/
42
public function init() {
43
44
add_filter( 'optml_replace_image', array( $this, 'build_image_url' ), 10, 2 );
45
-
46
- if ( ! parent::init() ) {
47
- return; // @codeCoverageIgnore
48
- }
49
50
Optml_Quality::$default_quality = $this->to_accepted_quality( $this->settings->get_quality() );
51
Optml_Image::$watermark = new Optml_Watermark( $this->settings->get_site_settings()['watermark'] );
@@ -83,6 +147,9 @@ final class Optml_Url_Replacer extends Optml_App_Replacer {
83
if ( ! $this->can_replace_url( $url ) ) {
84
return $url;
85
}
86
if ( ! $this->is_valid_mimetype_from_url( $url ) ) {
87
return $url;
88
}
@@ -101,7 +168,10 @@ final class Optml_Url_Replacer extends Optml_App_Replacer {
101
$new_url = $this->strip_image_size_from_url( $url );
102
103
if ( $new_url !== $url ) {
104
- list( $args['width'], $args['height'] ) = $this->parse_dimensions_from_filename( $url );
105
$url = $new_url;
106
}
107
$args['width'] = (int) $args['width'];
@@ -114,7 +184,12 @@ final class Optml_Url_Replacer extends Optml_App_Replacer {
114
$args['height'] = $args['height'] > $this->max_height ? $this->max_height : $args['height'];
115
}
116
117
- $new_url = ( new Optml_Image( $url, $args ) )->get_url( $this->settings->use_lazyload() ? false : $this->is_allowed_site );
118
119
return $is_slashed ? addcslashes( $new_url, '/' ) : $new_url;
120
}
28
* @return Optml_Url_Replacer
29
*/
30
public static function instance() {
31
+ if ( null === self::$instance ) {
32
self::$instance = new self();
33
+ add_action( 'optml_replacer_setup', array( self::$instance, 'init' ) );
34
}
35
36
return self::$instance;
37
}
38
39
+
40
+ /**
41
+ * Handles the url replacement in options and theme mods.
42
+ */
43
+ public function filter_options_and_mods() {
44
+ /**
45
+ * `optml_imgcdn_options_with_url` is a filter that allows themes or plugins to select which option
46
+ * holds an url and needs an optimization.
47
+ */
48
+ $options_list = apply_filters(
49
+ 'optml_imgcdn_options_with_url',
50
+ array(
51
+ 'theme_mods_' . get_option( 'stylesheet' ),
52
+ 'theme_mods_' . get_option( 'template' ),
53
+ )
54
+ );
55
+
56
+ foreach ( $options_list as $option ) {
57
+ add_filter( "option_$option", array( $this, 'replace_option_url' ) );
58
+ }
59
+
60
+ }
61
+
62
+ /**
63
+ * A filter which turns a local url into an optimized CDN image url or an array of image urls.
64
+ *
65
+ * @param string $url The url which should be replaced.
66
+ *
67
+ * @return string Replaced url.
68
+ */
69
+ public function replace_option_url( $url ) {
70
+ if ( empty( $url ) ) {
71
+ return $url;
72
+ }
73
+ // $url might be an array or an json encoded array with urls.
74
+ if ( is_array( $url ) || filter_var( $url, FILTER_VALIDATE_URL ) === false ) {
75
+ $array = $url;
76
+ $encoded = false;
77
+
78
+ // it might a json encoded array
79
+ if ( is_string( $url ) ) {
80
+ $array = json_decode( $url, true );
81
+ $encoded = true;
82
+ }
83
+
84
+ // in case there is an array, apply it recursively.
85
+ if ( is_array( $array ) ) {
86
+ foreach ( $array as $index => $value ) {
87
+ $array[ $index ] = $this->replace_option_url( $value );
88
+ }
89
+
90
+ if ( $encoded ) {
91
+ return json_encode( $array );
92
+ }
93
+
94
+ return $array;
95
+ }
96
+
97
+ if ( filter_var( $url, FILTER_VALIDATE_URL ) === false ) {
98
+ return $url;
99
+ }
100
+ }
101
+
102
+ return apply_filters( 'optml_content_url', $url );
103
+ }
104
+
105
/**
106
* The initialize method.
107
*/
108
public function init() {
109
110
add_filter( 'optml_replace_image', array( $this, 'build_image_url' ), 10, 2 );
111
+ add_filter( 'init', array( $this, 'filter_options_and_mods' ) );
112
+ parent::init();
113
114
Optml_Quality::$default_quality = $this->to_accepted_quality( $this->settings->get_quality() );
115
Optml_Image::$watermark = new Optml_Watermark( $this->settings->get_site_settings()['watermark'] );
147
if ( ! $this->can_replace_url( $url ) ) {
148
return $url;
149
}
150
+ // Remove any query strings that might affect conversion.
151
+ $url = strtok( $url, '?' );
152
+
153
if ( ! $this->is_valid_mimetype_from_url( $url ) ) {
154
return $url;
155
}
168
$new_url = $this->strip_image_size_from_url( $url );
169
170
if ( $new_url !== $url ) {
171
+ list( $args['width'], $args['height'], $crop ) = $this->parse_dimensions_from_filename( $url );
172
+ if ( $crop ) {
173
+ $args['resize'] = $this->to_optml_crop( $crop );
174
+ }
175
$url = $new_url;
176
}
177
$args['width'] = (int) $args['width'];
184
$args['height'] = $args['height'] > $this->max_height ? $this->max_height : $args['height'];
185
}
186
187
+ $new_url = ( new Optml_Image( $url, $args ) )->get_url(
188
+ [
189
+ 'signed' => $this->settings->use_lazyload() ? false : $this->is_allowed_site,
190
+ 'apply_watermark' => apply_filters( 'optml_apply_watermark_for', true, $url ),
191
+ ]
192
+ );
193
194
return $is_slashed ? addcslashes( $new_url, '/' ) : $new_url;
195
}
optimole-wp.php CHANGED
@@ -2,7 +2,7 @@
2
/**
3
* Plugin Name: Image optimization service by Optimole
4
* Description: Complete handling of your website images.
5
- * Version: 2.0.3
6
* Author: Optimole
7
* Author URI: https://optimole.com
8
* License: GPL-2.0+
@@ -26,7 +26,7 @@ function optml_autoload( $class ) {
26
if ( strpos( $class, $prefix ) !== 0 ) {
27
return;
28
}
29
- foreach ( array( '/inc/', '/inc/traits/', '/inc/image_properties/' ) as $folder ) {
30
$file = str_replace( $prefix . '_', '', $class );
31
$file = strtolower( $file );
32
$file = dirname( __FILE__ ) . $folder . $file . '.php';
@@ -75,7 +75,7 @@ function optml() {
75
define( 'OPTML_URL', plugin_dir_url( __FILE__ ) );
76
define( 'OPTML_JS_CDN', 'd5jmkjjpb7yfg.cloudfront.net' );
77
define( 'OPTML_PATH', plugin_dir_path( __FILE__ ) );
78
- define( 'OPTML_VERSION', '2.0.3' );
79
define( 'OPTML_NAMESPACE', 'optml' );
80
define( 'OPTML_BASEFILE', __FILE__ );
81
// Fallback for old PHP versions when this constant is not defined.
2
/**
3
* Plugin Name: Image optimization service by Optimole
4
* Description: Complete handling of your website images.
5
+ * Version: 2.0.4
6
* Author: Optimole
7
* Author URI: https://optimole.com
8
* License: GPL-2.0+
26
if ( strpos( $class, $prefix ) !== 0 ) {
27
return;
28
}
29
+ foreach ( array( '/inc/', '/inc/traits/', '/inc/image_properties/', '/inc/compatibilities/' ) as $folder ) {
30
$file = str_replace( $prefix . '_', '', $class );
31
$file = strtolower( $file );
32
$file = dirname( __FILE__ ) . $folder . $file . '.php';
75
define( 'OPTML_URL', plugin_dir_url( __FILE__ ) );
76
define( 'OPTML_JS_CDN', 'd5jmkjjpb7yfg.cloudfront.net' );
77
define( 'OPTML_PATH', plugin_dir_path( __FILE__ ) );
78
+ define( 'OPTML_VERSION', '2.0.4' );
79
define( 'OPTML_NAMESPACE', 'optml' );
80
define( 'OPTML_BASEFILE', __FILE__ );
81
// Fallback for old PHP versions when this constant is not defined.
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
Contributors: optimole
3
Tags: image optimization, cdn, image compression, compress image, images, optimization, perfomance, photos
4
Requires at least: 4.7
5
- Tested up to: 5.0
6
Requires PHP: 5.4
7
License: GPLv3
8
License URI: https://www.gnu.org/licenses/gpl-3.0.en.html
@@ -91,6 +91,26 @@ Premium users will be able to optimize 10GB images per month with a 50GB viewing
91
92
== Changelog ==
93
94
#### [Version 2.0.3](https://github.com/Codeinwp/optimole-wp/compare/v2.0.2...v2.0.3) (2019-02-13)
95
96
* **Bug Fixes**
2
Contributors: optimole
3
Tags: image optimization, cdn, image compression, compress image, images, optimization, perfomance, photos
4
Requires at least: 4.7
5
+ Tested up to: 5.1
6
Requires PHP: 5.4
7
License: GPLv3
8
License URI: https://www.gnu.org/licenses/gpl-3.0.en.html
91
92
== Changelog ==
93
94
+ #### [Version 2.0.4](https://github.com/Codeinwp/optimole-wp/compare/v2.0.3...v2.0.4) (2019-03-11)
95
+
96
+ * **Bug Fixes**
97
+ * adds full compatibility with Envira gallery ([7fd618f](https://github.com/Codeinwp/optimole-wp/commit/7fd618f))
98
+ * compatibility with Foogallery plugin when the gallery uses lazyload too ([67991dc](https://github.com/Codeinwp/optimole-wp/commit/67991dc))
99
+ * compatibility with images which contains query arguments, causing broken image urls ([56108be](https://github.com/Codeinwp/optimole-wp/commit/56108be))
100
+ * compatibility with relative image urls ([8089610](https://github.com/Codeinwp/optimole-wp/commit/8089610))
101
+ * compatibility with Revolution slider, adds support for background images lazyload and exact match ([0bbd254](https://github.com/Codeinwp/optimole-wp/commit/0bbd254))
102
+ * compatibility with shortcode ultimate plugin ([164ba35](https://github.com/Codeinwp/optimole-wp/commit/164ba35))
103
+ * compatibility with Woocommerce, solving issue with zoom image on single product pages ([1692e2b](https://github.com/Codeinwp/optimole-wp/commit/1692e2b))
104
+ * image replacement on WordPress REST api responses ([24d191b](https://github.com/Codeinwp/optimole-wp/commit/24d191b))
105
+ * image url replacement on custom WordPress directory structure, fixes [#79](https://github.com/Codeinwp/optimole-wp/issues/79), thanks [@hackles](https://github.com/hackles) for reporting ([980fcef](https://github.com/Codeinwp/optimole-wp/commit/980fcef))
106
+
107
+ * **Features**
108
+ * tested up compatibility with WordPress 5.1 ([12726b6](https://github.com/Codeinwp/optimole-wp/commit/12726b6))
109
+ * **api:** adds filter for restricting watermark based on image source urls ([337d7fa](https://github.com/Codeinwp/optimole-wp/commit/337d7fa))
110
+ * **api:** adds filter to disable image replacement on a specific page/ur ([3250a8d](https://github.com/Codeinwp/optimole-wp/commit/3250a8d))
111
+
112
+
113
+
114
#### [Version 2.0.3](https://github.com/Codeinwp/optimole-wp/compare/v2.0.2...v2.0.3) (2019-02-13)
115
116
* **Bug Fixes**
themeisle-hash.json CHANGED
@@ -1 +1 @@
1
- {"optimole-wp.php":"eec35058fe695c524bad4c3ac6522e13"}
1
+ {"optimole-wp.php":"ee446ee3680afc37f3935c414c20e3da"}
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
5
require_once __DIR__ . '/composer/autoload_real.php';
6
7
- return ComposerAutoloaderInita736db24c5967be69c4f5a7bf289fe2f::getLoader();
4
5
require_once __DIR__ . '/composer/autoload_real.php';
6
7
+ return ComposerAutoloaderInit91e3c305c500afd7731152212c1c7f2f::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
3
// autoload_real.php @generated by Composer
4
5
- class ComposerAutoloaderInita736db24c5967be69c4f5a7bf289fe2f
6
{
7
private static $loader;
8
@@ -19,15 +19,15 @@ class ComposerAutoloaderInita736db24c5967be69c4f5a7bf289fe2f
19
return self::$loader;
20
}
21
22
- spl_autoload_register(array('ComposerAutoloaderInita736db24c5967be69c4f5a7bf289fe2f', 'loadClassLoader'), true, true);
23
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInita736db24c5967be69c4f5a7bf289fe2f', 'loadClassLoader'));
25
26
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
if ($useStaticLoader) {
28
require_once __DIR__ . '/autoload_static.php';
29
30
- call_user_func(\Composer\Autoload\ComposerStaticInita736db24c5967be69c4f5a7bf289fe2f::getInitializer($loader));
31
} else {
32
$map = require __DIR__ . '/autoload_namespaces.php';
33
foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInita736db24c5967be69c4f5a7bf289fe2f
48
$loader->register(true);
49
50
if ($useStaticLoader) {
51
- $includeFiles = Composer\Autoload\ComposerStaticInita736db24c5967be69c4f5a7bf289fe2f::$files;
52
} else {
53
$includeFiles = require __DIR__ . '/autoload_files.php';
54
}
55
foreach ($includeFiles as $fileIdentifier => $file) {
56
- composerRequirea736db24c5967be69c4f5a7bf289fe2f($fileIdentifier, $file);
57
}
58
59
return $loader;
60
}
61
}
62
63
- function composerRequirea736db24c5967be69c4f5a7bf289fe2f($fileIdentifier, $file)
64
{
65
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
require $file;
2
3
// autoload_real.php @generated by Composer
4
5
+ class ComposerAutoloaderInit91e3c305c500afd7731152212c1c7f2f
6
{
7
private static $loader;
8
19
return self::$loader;
20
}
21
22
+ spl_autoload_register(array('ComposerAutoloaderInit91e3c305c500afd7731152212c1c7f2f', 'loadClassLoader'), true, true);
23
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit91e3c305c500afd7731152212c1c7f2f', 'loadClassLoader'));
25
26
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
if ($useStaticLoader) {
28
require_once __DIR__ . '/autoload_static.php';
29
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit91e3c305c500afd7731152212c1c7f2f::getInitializer($loader));
31
} else {
32
$map = require __DIR__ . '/autoload_namespaces.php';
33
foreach ($map as $namespace => $path) {
48
$loader->register(true);
49
50
if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInit91e3c305c500afd7731152212c1c7f2f::$files;
52
} else {
53
$includeFiles = require __DIR__ . '/autoload_files.php';
54
}
55
foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequire91e3c305c500afd7731152212c1c7f2f($fileIdentifier, $file);
57
}
58
59
return $loader;
60
}
61
}
62
63
+ function composerRequire91e3c305c500afd7731152212c1c7f2f($fileIdentifier, $file)
64
{
65
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
5
namespace Composer\Autoload;
6
7
- class ComposerStaticInita736db24c5967be69c4f5a7bf289fe2f
8
{
9
public static $files = array (
10
'9fef4034ed73e26a337d9856ea126f7f' => __DIR__ . '/..' . '/codeinwp/themeisle-sdk/load.php',
4
5
namespace Composer\Autoload;
6
7
+ class ComposerStaticInit91e3c305c500afd7731152212c1c7f2f
8
{
9
public static $files = array (
10
'9fef4034ed73e26a337d9856ea126f7f' => __DIR__ . '/..' . '/codeinwp/themeisle-sdk/load.php',