Image optimization & Lazy Load by Optimole - Version 2.2.7

Version Description

Download this release

Release Info

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

Code changes from version 2.2.6 to 2.2.7

CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  #### [Version 2.2.6](https://github.com/Codeinwp/optimole-wp/compare/v2.2.5...v2.2.6) (2019-12-02)
2
 
3
  * **Bug Fixes**
1
+ #### [Version 2.2.7](https://github.com/Codeinwp/optimole-wp/compare/v2.2.6...v2.2.7) (2019-12-17)
2
+
3
+ * **Bug Fixes**
4
+ * blur remaining outside of an image after it gets lazyloaded ([0df2633](https://github.com/Codeinwp/optimole-wp/commit/0df2633))
5
+ * blur remaining outside of an image after it gets lazyloaded, references Codeinwp/optimole_js_lib[#55](https://github.com/Codeinwp/optimole-wp/issues/55) ([001bfe5](https://github.com/Codeinwp/optimole-wp/commit/001bfe5))
6
+ * edge case lazyload replacement when noscript images are present ([c788c3f](https://github.com/Codeinwp/optimole-wp/commit/c788c3f))
7
+ * improve compatibility with Divi builder ([7d1c469](https://github.com/Codeinwp/optimole-wp/commit/7d1c469))
8
+ * improve compatibility with W3TC minification system ([bf9f058](https://github.com/Codeinwp/optimole-wp/commit/bf9f058))
9
+ * improve compatibility with WP Migrate DB ([02df077](https://github.com/Codeinwp/optimole-wp/commit/02df077))
10
+ * improve lazyload and replacement on json strings ([b7f67fd](https://github.com/Codeinwp/optimole-wp/commit/b7f67fd))
11
+ * removed blur from lazyload placeholders ([2c7d66d](https://github.com/Codeinwp/optimole-wp/commit/2c7d66d))
12
+ * safari blur problem ([5e31ec3](https://github.com/Codeinwp/optimole-wp/commit/5e31ec3))
13
+ * safari blur problem ([2ea1d82](https://github.com/Codeinwp/optimole-wp/commit/2ea1d82))
14
+
15
+ * **Features**
16
+ * adds compatibility for schemaless and relative image URLs ([e3886eb](https://github.com/Codeinwp/optimole-wp/commit/e3886eb))
17
+ * hide Optimole menu via constant [#196](https://github.com/Codeinwp/optimole-wp/issues/196) ([e0268fa](https://github.com/Codeinwp/optimole-wp/commit/e0268fa))
18
+ * skip lazyload on images with skip-lazy flag ([4d9219f](https://github.com/Codeinwp/optimole-wp/commit/4d9219f))
19
+
20
  #### [Version 2.2.6](https://github.com/Codeinwp/optimole-wp/compare/v2.2.5...v2.2.6) (2019-12-02)
21
 
22
  * **Bug Fixes**
README.md CHANGED
@@ -89,6 +89,27 @@ Premium users will be able to optimize images for more than 25k monthly active u
89
 
90
  ## Changelog ##
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  #### [Version 2.2.6](https://github.com/Codeinwp/optimole-wp/compare/v2.2.5...v2.2.6) (2019-12-02)
93
 
94
  * **Bug Fixes**
89
 
90
  ## Changelog ##
91
 
92
+ #### [Version 2.2.7](https://github.com/Codeinwp/optimole-wp/compare/v2.2.6...v2.2.7) (2019-12-17)
93
+
94
+ * **Bug Fixes**
95
+ * blur remaining outside of an image after it gets lazyloaded ([0df2633](https://github.com/Codeinwp/optimole-wp/commit/0df2633))
96
+ * blur remaining outside of an image after it gets lazyloaded, references Codeinwp/optimole_js_lib[#55](https://github.com/Codeinwp/optimole-wp/issues/55) ([001bfe5](https://github.com/Codeinwp/optimole-wp/commit/001bfe5))
97
+ * edge case lazyload replacement when noscript images are present ([c788c3f](https://github.com/Codeinwp/optimole-wp/commit/c788c3f))
98
+ * improve compatibility with Divi builder ([7d1c469](https://github.com/Codeinwp/optimole-wp/commit/7d1c469))
99
+ * improve compatibility with W3TC minification system ([bf9f058](https://github.com/Codeinwp/optimole-wp/commit/bf9f058))
100
+ * improve compatibility with WP Migrate DB ([02df077](https://github.com/Codeinwp/optimole-wp/commit/02df077))
101
+ * improve lazyload and replacement on json strings ([b7f67fd](https://github.com/Codeinwp/optimole-wp/commit/b7f67fd))
102
+ * removed blur from lazyload placeholders ([2c7d66d](https://github.com/Codeinwp/optimole-wp/commit/2c7d66d))
103
+ * safari blur problem ([5e31ec3](https://github.com/Codeinwp/optimole-wp/commit/5e31ec3))
104
+ * safari blur problem ([2ea1d82](https://github.com/Codeinwp/optimole-wp/commit/2ea1d82))
105
+
106
+ * **Features**
107
+ * adds compatibility for schemaless and relative image URLs ([e3886eb](https://github.com/Codeinwp/optimole-wp/commit/e3886eb))
108
+ * hide Optimole menu via constant [#196](https://github.com/Codeinwp/optimole-wp/issues/196) ([e0268fa](https://github.com/Codeinwp/optimole-wp/commit/e0268fa))
109
+ * skip lazyload on images with skip-lazy flag ([4d9219f](https://github.com/Codeinwp/optimole-wp/commit/4d9219f))
110
+
111
+
112
+
113
  #### [Version 2.2.6](https://github.com/Codeinwp/optimole-wp/compare/v2.2.5...v2.2.6) (2019-12-02)
114
 
115
  * **Bug Fixes**
inc/admin.php CHANGED
@@ -60,6 +60,7 @@ class Optml_Admin {
60
  * Adds script for lazyload/js replacement.
61
  */
62
  public function inline_bootstrap_script() {
 
63
  $domain = 'https://' . OPTML_JS_CDN;
64
 
65
  $min = ! OPTML_DEBUG ? '.min' : '';
@@ -85,7 +86,6 @@ class Optml_Admin {
85
  }
86
  img[data-opt-src]:not([data-opt-lazy-loaded]) {
87
  opacity: .75;
88
- filter: blur(5px);
89
  }
90
 
91
  </style>
@@ -439,6 +439,9 @@ class Optml_Admin {
439
  * Add the dashboard page.
440
  */
441
  public function add_dashboard_page() {
 
 
 
442
  add_media_page( 'Optimole', 'Optimole', 'manage_options', 'optimole', array( $this, 'render_dashboard_page' ) );
443
  }
444
 
60
  * Adds script for lazyload/js replacement.
61
  */
62
  public function inline_bootstrap_script() {
63
+
64
  $domain = 'https://' . OPTML_JS_CDN;
65
 
66
  $min = ! OPTML_DEBUG ? '.min' : '';
86
  }
87
  img[data-opt-src]:not([data-opt-lazy-loaded]) {
88
  opacity: .75;
 
89
  }
90
 
91
  </style>
439
  * Add the dashboard page.
440
  */
441
  public function add_dashboard_page() {
442
+ if ( defined( 'OPTIOMLE_HIDE_ADMIN_AREA' ) && OPTIOMLE_HIDE_ADMIN_AREA ) {
443
+ return;
444
+ }
445
  add_media_page( 'Optimole', 'Optimole', 'manage_options', 'optimole', array( $this, 'render_dashboard_page' ) );
446
  }
447
 
inc/app_replacer.php CHANGED
@@ -130,7 +130,7 @@ abstract class Optml_App_Replacer {
130
  return self::$ignore_lazyload_strings;
131
  }
132
 
133
- self::$possible_src_attributes = apply_filters( 'optml_possible_lazyload_flags', [] );
134
 
135
  return array_merge( self::$possible_src_attributes, [ '<noscript' ] );
136
  }
@@ -271,10 +271,11 @@ abstract class Optml_App_Replacer {
271
  self::$filters = $this->settings->get_filters();
272
  add_filter(
273
  'optml_possible_lazyload_flags',
274
- function( $strings = array() ) {
275
  foreach ( self::$filters[ Optml_Settings::FILTER_TYPE_LAZYLOAD ][ Optml_Settings::FILTER_CLASS ] as $rule_flag => $status ) {
276
  $strings[] = $rule_flag;
277
  }
 
278
  return $strings;
279
  },
280
  10,
@@ -310,9 +311,6 @@ abstract class Optml_App_Replacer {
310
  'secret' => $service_data['cdn_secret'],
311
  )
312
  );
313
- $this->site_mappings['//i0.wp.com/'] = '//';
314
- $this->site_mappings['//i1.wp.com/'] = '//';
315
- $this->site_mappings['//i2.wp.com/'] = '//';
316
 
317
  if ( defined( 'OPTML_SITE_MIRROR' ) && constant( 'OPTML_SITE_MIRROR' ) ) {
318
  $this->site_mappings[ rtrim( get_home_url(), '/' ) ] = rtrim( constant( 'OPTML_SITE_MIRROR' ), '/' );
@@ -326,9 +324,12 @@ abstract class Optml_App_Replacer {
326
  )
327
  );
328
 
329
- $this->allowed_sources = $this->extract_domain_from_urls( $service_data['whitelist'] );
330
-
331
- $this->is_allowed_site = count( array_diff_key( $this->possible_sources, $this->allowed_sources ) ) > 0;
 
 
 
332
 
333
  $this->max_height = $this->settings->get( 'max_height' );
334
  $this->max_width = $this->settings->get( 'max_width' );
@@ -342,6 +343,15 @@ abstract class Optml_App_Replacer {
342
  );
343
  }
344
 
 
 
 
 
 
 
 
 
 
345
  /**
346
  * List to resizes and save the crop for later re-use.
347
  *
130
  return self::$ignore_lazyload_strings;
131
  }
132
 
133
+ self::$possible_src_attributes = apply_filters( 'optml_possible_lazyload_flags', [ 'skip-lazy' ] );
134
 
135
  return array_merge( self::$possible_src_attributes, [ '<noscript' ] );
136
  }
271
  self::$filters = $this->settings->get_filters();
272
  add_filter(
273
  'optml_possible_lazyload_flags',
274
+ function ( $strings = array() ) {
275
  foreach ( self::$filters[ Optml_Settings::FILTER_TYPE_LAZYLOAD ][ Optml_Settings::FILTER_CLASS ] as $rule_flag => $status ) {
276
  $strings[] = $rule_flag;
277
  }
278
+
279
  return $strings;
280
  },
281
  10,
311
  'secret' => $service_data['cdn_secret'],
312
  )
313
  );
 
 
 
314
 
315
  if ( defined( 'OPTML_SITE_MIRROR' ) && constant( 'OPTML_SITE_MIRROR' ) ) {
316
  $this->site_mappings[ rtrim( get_home_url(), '/' ) ] = rtrim( constant( 'OPTML_SITE_MIRROR' ), '/' );
324
  )
325
  );
326
 
327
+ $this->allowed_sources = $this->extract_domain_from_urls( $service_data['whitelist'] );
328
+ // Allways allow Photon urls.
329
+ $this->allowed_sources['i0.wp.com'] = true;
330
+ $this->allowed_sources['i1.wp.com'] = true;
331
+ $this->allowed_sources['i2.wp.com'] = true;
332
+ $this->is_allowed_site = count( array_diff_key( $this->possible_sources, $this->allowed_sources ) ) > 0;
333
 
334
  $this->max_height = $this->settings->get( 'max_height' );
335
  $this->max_width = $this->settings->get( 'max_width' );
343
  );
344
  }
345
 
346
+ /**
347
+ * Method to expose upload resource property.
348
+ *
349
+ * @return null
350
+ */
351
+ public function get_upload_resource() {
352
+ return $this->upload_resource;
353
+ }
354
+
355
  /**
356
  * List to resizes and save the crop for later re-use.
357
  *
inc/compatibilities/divi_builder.php CHANGED
@@ -30,7 +30,7 @@ class Optml_divi_builder extends Optml_compatibility {
30
  $all_watchers[] = '.et_pb_slides > .et_pb_slide';
31
  $all_watchers[] = '.et_parallax_bg';
32
  $all_watchers[] = '.et_pb_video_overlay';
33
- $all_watchers[] = '.et_pb_module';
34
  $all_watchers[] = '.et_pb_row';
35
  $all_watchers[] = '.et_pb_with_background';
36
  return $all_watchers;
30
  $all_watchers[] = '.et_pb_slides > .et_pb_slide';
31
  $all_watchers[] = '.et_parallax_bg';
32
  $all_watchers[] = '.et_pb_video_overlay';
33
+ $all_watchers[] = '.et_pb_module:not(.et_pb_blog_grid_wrapper)';
34
  $all_watchers[] = '.et_pb_row';
35
  $all_watchers[] = '.et_pb_with_background';
36
  return $all_watchers;
inc/config.php CHANGED
@@ -26,7 +26,8 @@ class Optml_Config {
26
  *
27
  * @var string
28
  */
29
- public static $chars = '@%A-Za-z-ÁÀȦÂÄǞǍĂĀÃÅǺǼǢĆĊĈČĎḌḐḒÉÈĖÊËĚĔĒẼE̊ẸǴĠĜǦĞG̃ĢĤḤáàȧâäǟǎăāãåǻǽǣćċĉčďḍḑḓéèėêëěĕēẽe̊ẹǵġĝǧğg̃ģĥḥÍÌİÎÏǏĬĪĨỊĴĶǨĹĻĽĿḼM̂M̄ʼNŃN̂ṄN̈ŇN̄ÑŅṊÓÒȮȰÔÖȪǑŎŌÕȬŐỌǾƠíìiîïǐĭīĩịĵķǩĺļľŀḽm̂m̄ʼnńn̂ṅn̈ňn̄ñņṋóòôȯȱöȫǒŏōõȭőọǿơP̄ŔŘŖŚŜṠŠȘṢŤȚṬṰÚÙÛÜǓŬŪŨŰŮỤẂẀŴẄÝỲŶŸȲỸŹŻŽẒǮp̄ŕřŗśŝṡšşṣťțṭṱúùûüǔŭūũűůụẃẁŵẅýỳŷÿȳỹźżžẓǯßœŒçÇ';
 
30
 
31
  /**
32
  * Service api key.
26
  *
27
  * @var string
28
  */
29
+
30
+ public static $chars = '\/:,\\\\.\-\d_@%A-Za-z-ÁÀȦÂÄǞǍĂĀÃÅǺǼǢĆĊĈČĎḌḐḒÉÈĖÊËĚĔĒẼE̊ẸǴĠĜǦĞG̃ĢĤḤáàȧâäǟǎăāãåǻǽǣćċĉčďḍḑḓéèėêëěĕēẽe̊ẹǵġĝǧğg̃ģĥḥÍÌİÎÏǏĬĪĨỊĴĶǨĹĻĽĿḼM̂M̄ʼNŃN̂ṄN̈ŇN̄ÑŅṊÓÒȮȰÔÖȪǑŎŌÕȬŐỌǾƠíìiîïǐĭīĩịĵķǩĺļľŀḽm̂m̄ʼnńn̂ṅn̈ňn̄ñņṋóòôȯȱöȫǒŏōõȭőọǿơP̄ŔŘŖŚŜṠŠȘṢŤȚṬṰÚÙÛÜǓŬŪŨŰŮỤẂẀŴẄÝỲŶŸȲỸŹŻŽẒǮp̄ŕřŗśŝṡšşṣťțṭṱúùûüǔŭūũűůụẃẁŵẅýỳŷÿȳỹźżžẓǯßœŒçÇ';
31
 
32
  /**
33
  * Service api key.
inc/conflicts/divi.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Optml_Divi
5
+ *
6
+ * An example of a conflict.
7
+ */
8
+ class Optml_Divi extends Optml_abstract_conflict {
9
+
10
+ /**
11
+ * Optml_Divi constructor.
12
+ */
13
+ public function __construct() {
14
+ $this->priority = 2;
15
+ $this->severity = self::SEVERITY_HIGH;
16
+ parent::__construct();
17
+ }
18
+
19
+ /**
20
+ * Set the message property
21
+ *
22
+ * @since 2.2.6
23
+ * @access public
24
+ */
25
+ public function define_message() {
26
+ $this->message = sprintf( __( 'It seems your are using %1$sDivi%2$s right now. %3$s In order for Optimole to replace the images in your Divi pages, you will need to go to %4$sDivi -> Theme Options -> Builder -> Advanced -> Static CSS File Generations%5$s and click on Clear for the images to be processed. ', 'optimole-wp' ), '<b>', '</b>', '<br/>', '<a target="_blank" href="' . admin_url( 'admin.php?page=et_divi_options' ) . '">', '</a>' );
27
+ }
28
+
29
+
30
+ /**
31
+ * Determine if conflict is applicable.
32
+ *
33
+ * @return bool
34
+ * @since 2.2.6
35
+ * @access public
36
+ */
37
+ public function is_conflict_valid() {
38
+ if ( ! is_plugin_active( 'divi-builder/divi-builder.php' ) ) {
39
+ return false;
40
+ }
41
+
42
+ $theme = wp_get_theme();
43
+ // No divi, no child theme.
44
+ if ( strcmp( $theme->get( 'Name' ), 'Divi' ) !== 0 && $theme->parent() === false ) {
45
+ return false;
46
+ }
47
+ // Child theme, no parent divi.
48
+ if ( $theme->parent() !== false && strcmp( $theme->parent()->get( 'Name' ), 'Divi' ) !== 0 ) {
49
+ return false;
50
+ }
51
+ if ( ! function_exists( 'et_get_option' ) ) {
52
+ return false;
53
+ }
54
+ if ( 'off' === et_get_option( 'et_pb_static_css_file', 'on' ) ) {
55
+ return false;
56
+ }
57
+
58
+ return true;
59
+ }
60
+ }
inc/lazyload_replacer.php CHANGED
@@ -183,7 +183,7 @@ final class Optml_Lazyload_Replacer extends Optml_App_Replacer {
183
  if ( ! self::$is_lazyload_placeholder && ! $should_ignore_rescale ) {
184
  $optml_args['quality'] = 'eco';
185
  $optml_args['resize'] = [];
186
- $low_url = apply_filters( 'optml_content_url', $is_slashed ? stripslashes( $original_url ) : $original_url, $optml_args );
187
  $low_url = $is_slashed ? addcslashes( $low_url, '/' ) : $low_url;
188
  } else {
189
  $low_url = $this->get_svg_for(
@@ -221,12 +221,12 @@ final class Optml_Lazyload_Replacer extends Optml_App_Replacer {
221
  );
222
  $new_tag = preg_replace(
223
  [
224
- '/( src(?>=|"|\'|\s|\\\\)*)' . preg_quote( $original_url, '/' ) . '/m',
225
- '/ src=/m',
226
  ],
227
  [
228
  "$1$low_url",
229
- $opt_src . ' src=',
230
  ],
231
  $new_tag,
232
  1
183
  if ( ! self::$is_lazyload_placeholder && ! $should_ignore_rescale ) {
184
  $optml_args['quality'] = 'eco';
185
  $optml_args['resize'] = [];
186
+ $low_url = apply_filters( 'optml_content_url', $original_url, $optml_args );
187
  $low_url = $is_slashed ? addcslashes( $low_url, '/' ) : $low_url;
188
  } else {
189
  $low_url = $this->get_svg_for(
221
  );
222
  $new_tag = preg_replace(
223
  [
224
+ '/((?:\s|\'|"){1,}src(?>=|"|\'|\s|\\\\)*)' . preg_quote( $original_url, '/' ) . '/m',
225
+ '/<img/im',
226
  ],
227
  [
228
  "$1$low_url",
229
+ '<img' . $opt_src,
230
  ],
231
  $new_tag,
232
  1
inc/main.php CHANGED
@@ -97,6 +97,7 @@ final class Optml_Main {
97
  'Optml_Jetpack_Photon',
98
  'Optml_Jetpack_Lazyload',
99
  'Optml_Wprocket',
 
100
  )
101
  );
102
 
97
  'Optml_Jetpack_Photon',
98
  'Optml_Jetpack_Lazyload',
99
  'Optml_Wprocket',
100
+ 'Optml_Divi',
101
  )
102
  );
103
 
inc/manager.php CHANGED
@@ -200,6 +200,9 @@ final class Optml_Manager {
200
  if ( ! wp_doing_ajax() ) {
201
  return false;
202
  }
 
 
 
203
 
204
  return true;
205
  }
@@ -257,101 +260,13 @@ final class Optml_Manager {
257
  return $metadata;
258
  }
259
 
260
- return $this->process_urls_from_json( $current_meta );
261
  }
262
 
263
  // Return original if the check does not pass
264
  return $metadata;
265
  }
266
 
267
- /**
268
- * Process json string.
269
- *
270
- * @param string $json Json string.
271
- *
272
- * @return string Processed string.
273
- */
274
- public function process_urls_from_json( $json ) {
275
-
276
- $extracted_urls = $this->extract_urls_from_json( $json );
277
-
278
- return $this->do_url_replacement( $json, $extracted_urls );
279
- }
280
-
281
- /**
282
- * Extract urls used as values in json string, i.e not prefixed by =("|') char.
283
- *
284
- * @param string $content Raw json string.
285
- *
286
- * @return array array of urls.
287
- */
288
- public function extract_urls_from_json( $content ) {
289
- $regex = '/(?<!(=|\\\\)(?:"|\'|"))(?:http(?:s?):)(?:[\/\\\\|.|\w|\s|@|%|-])*\.(?:' . implode( '|', array_keys( Optml_Config::$extensions ) ) . ')(?:\??[\w|=|&|\-|\.|:]*)/';
290
- preg_match_all(
291
- $regex,
292
- $content,
293
- $urls
294
- );
295
-
296
- return $this->normalize_urls( $urls[0] );
297
- }
298
-
299
- /**
300
- * Normalize extracted urls.
301
- *
302
- * @param array $urls Raw urls extracted.
303
- *
304
- * @return array Normalized array.
305
- */
306
- private function normalize_urls( $urls ) {
307
-
308
- $urls = array_map(
309
- function ( $value ) {
310
- $value = str_replace( '&quot;', '', $value );
311
-
312
- return rtrim( $value, '\\";\'' );
313
- },
314
- $urls
315
- );
316
- $urls = array_unique( $urls );
317
-
318
- return array_values( $urls );
319
- }
320
-
321
- /**
322
- * Process string content and replace possible urls.
323
- *
324
- * @param string $html String content.
325
- * @param array $extracted_urls Urls to check.
326
- *
327
- * @return string Processed html.
328
- */
329
- private function do_url_replacement( $html, $extracted_urls ) {
330
- $extracted_urls = apply_filters( 'optml_extracted_urls', $extracted_urls );
331
-
332
- if ( empty( $extracted_urls ) ) {
333
- return $html;
334
- }
335
-
336
- $urls = array_combine( $extracted_urls, $extracted_urls );
337
- $urls = array_map(
338
- function ( $url ) {
339
- $is_slashed = strpos( $url, '\/' ) !== false;
340
- $url = html_entity_decode( $url );
341
- $new_url = apply_filters( 'optml_content_url', $url );
342
-
343
- return $is_slashed ? addcslashes( $new_url, '/' ) : $new_url;
344
- },
345
- $urls
346
- );
347
-
348
- foreach ( $urls as $origin => $replace ) {
349
- $html = preg_replace( '/(?<!\/)' . preg_quote( $origin, '/' ) . '/m', $replace, $html );
350
- }
351
-
352
- return $html;
353
- }
354
-
355
  /**
356
  * Filter raw HTML content for urls.
357
  *
@@ -434,8 +349,9 @@ final class Optml_Manager {
434
  $header_start = $matches[0][1];
435
  $header_end = $header_start + strlen( $matches[0][0] );
436
  }
 
437
 
438
- if ( preg_match_all( '/(?:<a[^>]+?href=["|\'](?P<link_url>[^\s]+?)["|\'][^>]*?>\s*)?(?P<img_tag>(?:<noscript\s*>\s*)?<img[^>]*?\s+?(?:' . implode( '|', array_merge( [ 'src' ], Optml_Tag_Replacer::possible_src_attributes() ) ) . ')=\\\\?["|\'](?P<img_url>[^\s]+?)["|\'].*?>(?:<\/noscript\s*>)?){1}(?:\s*<\/a>)?/ism', $content, $images, PREG_OFFSET_CAPTURE ) ) {
439
 
440
  foreach ( $images as $key => $unused ) {
441
  // Simplify the output as much as possible, mostly for confirming test results.
@@ -495,14 +411,88 @@ final class Optml_Manager {
495
  * @return array
496
  */
497
  public function extract_image_urls_from_content( $content ) {
498
- $regex = '/(?:http(?:s?):)(?:[\/\\\\|.|\w|\s|-])*(?:[' . Optml_Config::$chars . '])*\.(?:' . implode( '|', array_keys( Optml_Config::$extensions ) ) . ')(?:\?{1}[\w|=|&|\-|\.|:|;]*)?/';
 
499
  preg_match_all(
500
  $regex,
501
  $content,
502
  $urls
503
  );
504
 
505
- return $this->normalize_urls( $urls[0] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
  }
507
 
508
  /**
200
  if ( ! wp_doing_ajax() ) {
201
  return false;
202
  }
203
+ if ( isset( $_REQUEST['action'] ) && strpos( $_REQUEST['action'], 'wpmdb' ) !== false ) {
204
+ return false;
205
+ }
206
 
207
  return true;
208
  }
260
  return $metadata;
261
  }
262
 
263
+ return $this->replace_content( $current_meta );
264
  }
265
 
266
  // Return original if the check does not pass
267
  return $metadata;
268
  }
269
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  /**
271
  * Filter raw HTML content for urls.
272
  *
349
  $header_start = $matches[0][1];
350
  $header_end = $header_start + strlen( $matches[0][0] );
351
  }
352
+ $regex = '/(?:<a[^>]+?href=["|\'](?P<link_url>[^\s]+?)["|\'][^>]*?>\s*)?(?P<img_tag>(?:<noscript\s*>\s*)?<img[^>]*?\s?(?:' . implode( '|', array_merge( [ 'src' ], Optml_Tag_Replacer::possible_src_attributes() ) ) . ')=["\'\\\\]*?(?P<img_url>[' . Optml_Config::$chars . ']{10,}).*?>(?:\s*<\/noscript\s*>)?){1}(?:\s*<\/a>)?/ism';
353
 
354
+ if ( preg_match_all( $regex, $content, $images, PREG_OFFSET_CAPTURE ) ) {
355
 
356
  foreach ( $images as $key => $unused ) {
357
  // Simplify the output as much as possible, mostly for confirming test results.
411
  * @return array
412
  */
413
  public function extract_image_urls_from_content( $content ) {
414
+
415
+ $regex = '/(?:[(|\s\';",=])((?:http|\/|\\\\){1}(?:[' . Optml_Config::$chars . ']{10,}\.(?:' . implode( '|', array_keys( Optml_Config::$extensions ) ) . ')))(?=(?:|\?|"|&|,|\s|\'|\)|\||\\\\|}))/U';
416
  preg_match_all(
417
  $regex,
418
  $content,
419
  $urls
420
  );
421
 
422
+ return $this->normalize_urls( $urls[1] );
423
+ }
424
+
425
+ /**
426
+ * Normalize extracted urls.
427
+ *
428
+ * @param array $urls Raw urls extracted.
429
+ *
430
+ * @return array Normalized array.
431
+ */
432
+ private function normalize_urls( $urls ) {
433
+
434
+ $urls = array_map(
435
+ function ( $value ) {
436
+ $value = str_replace( '&quot;', '', $value );
437
+
438
+ return rtrim( $value, '\\";\'' );
439
+ },
440
+ $urls
441
+ );
442
+ $urls = array_unique( $urls );
443
+
444
+ return array_values( $urls );
445
+ }
446
+
447
+ /**
448
+ * Process string content and replace possible urls.
449
+ *
450
+ * @param string $html String content.
451
+ * @param array $extracted_urls Urls to check.
452
+ *
453
+ * @return string Processed html.
454
+ */
455
+ private function do_url_replacement( $html, $extracted_urls ) {
456
+ $extracted_urls = apply_filters( 'optml_extracted_urls', $extracted_urls );
457
+
458
+ if ( empty( $extracted_urls ) ) {
459
+ return $html;
460
+ }
461
+ $slashed_config = addcslashes( Optml_Config::$service_url, '/' );
462
+
463
+ $extracted_urls = array_filter(
464
+ $extracted_urls,
465
+ function ( $value ) use ( $slashed_config ) {
466
+ return strpos( $value, Optml_Config::$service_url ) === false && strpos( $value, $slashed_config ) === false;
467
+ }
468
+ );
469
+ $upload_resource = $this->tag_replacer->get_upload_resource();
470
+ $urls = array_combine( $extracted_urls, $extracted_urls );
471
+
472
+ $urls = array_map(
473
+ function ( $url ) use ( $upload_resource ) {
474
+ $is_slashed = strpos( $url, '\/' ) !== false;
475
+ $is_relative = strpos(
476
+ $url,
477
+ $is_slashed ?
478
+ addcslashes( $upload_resource['content_path'], '/' ) :
479
+ $upload_resource['content_path']
480
+ ) === 0;
481
+ if ( $is_relative ) {
482
+ $url = $upload_resource['content_host'] . $url;
483
+ }
484
+ $new_url = apply_filters( 'optml_content_url', $url );
485
+
486
+ return $new_url;
487
+ },
488
+ $urls
489
+ );
490
+
491
+ foreach ( $urls as $origin => $replace ) {
492
+ $html = preg_replace( '/(?<![\/|:|\\w])' . preg_quote( $origin, '/' ) . '/m', $replace, $html );
493
+ }
494
+
495
+ return $html;
496
  }
497
 
498
  /**
inc/tag_replacer.php CHANGED
@@ -143,7 +143,7 @@ final class Optml_Tag_Replacer extends Optml_App_Replacer {
143
 
144
  $is_slashed = strpos( $images['img_url'][ $index ], '\/' ) !== false;
145
 
146
- $src = $tmp = $is_slashed ? stripslashes( $images['img_url'][ $index ] ) : $images['img_url'][ $index ];
147
 
148
  if ( strpos( $src, $this->upload_resource['content_path'] ) === 0 ) {
149
  $src = $tmp = untrailingslashit( $this->upload_resource['content_host'] ) . $src;
143
 
144
  $is_slashed = strpos( $images['img_url'][ $index ], '\/' ) !== false;
145
 
146
+ $src = $tmp = $is_slashed ? $this->strip_slashes( $images['img_url'][ $index ] ) : $images['img_url'][ $index ];
147
 
148
  if ( strpos( $src, $this->upload_resource['content_path'] ) === 0 ) {
149
  $src = $tmp = untrailingslashit( $this->upload_resource['content_host'] ) . $src;
inc/traits/normalizer.php CHANGED
@@ -27,6 +27,16 @@ trait Optml_Normalizer {
27
  return boolval( $value );
28
  }
29
 
 
 
 
 
 
 
 
 
 
 
30
  /**
31
  * Normalize value to an integer within bounds.
32
  *
27
  return boolval( $value );
28
  }
29
 
30
+ /**
31
+ * Strip slashes on unicode encoded strings.
32
+ *
33
+ * @param string $string Input string.
34
+ *
35
+ * @return string Decoded string.
36
+ */
37
+ public function strip_slashes( $string ) {
38
+ return html_entity_decode( stripslashes( preg_replace( '/\\\u([\da-fA-F]{4})/', '&#x\1;', $string ) ) );
39
+ }
40
  /**
41
  * Normalize value to an integer within bounds.
42
  *
inc/url_replacer.php CHANGED
@@ -118,8 +118,7 @@ final class Optml_Url_Replacer extends Optml_App_Replacer {
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
-
123
  if ( strpos( $url, Optml_Config::$service_url ) !== false ) {
124
  return $original_url;
125
  }
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
  }
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.2.6
6
  * Author: Optimole
7
  * Author URI: https://optimole.com
8
  * License: GPL-2.0+
@@ -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.2.6' );
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.2.7
6
  * Author: Optimole
7
  * Author URI: https://optimole.com
8
  * License: GPL-2.0+
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.2.7' );
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
@@ -89,6 +89,27 @@ Premium users will be able to optimize images for more than 25k monthly active u
89
 
90
  == Changelog ==
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  #### [Version 2.2.6](https://github.com/Codeinwp/optimole-wp/compare/v2.2.5...v2.2.6) (2019-12-02)
93
 
94
  * **Bug Fixes**
89
 
90
  == Changelog ==
91
 
92
+ #### [Version 2.2.7](https://github.com/Codeinwp/optimole-wp/compare/v2.2.6...v2.2.7) (2019-12-17)
93
+
94
+ * **Bug Fixes**
95
+ * blur remaining outside of an image after it gets lazyloaded ([0df2633](https://github.com/Codeinwp/optimole-wp/commit/0df2633))
96
+ * blur remaining outside of an image after it gets lazyloaded, references Codeinwp/optimole_js_lib[#55](https://github.com/Codeinwp/optimole-wp/issues/55) ([001bfe5](https://github.com/Codeinwp/optimole-wp/commit/001bfe5))
97
+ * edge case lazyload replacement when noscript images are present ([c788c3f](https://github.com/Codeinwp/optimole-wp/commit/c788c3f))
98
+ * improve compatibility with Divi builder ([7d1c469](https://github.com/Codeinwp/optimole-wp/commit/7d1c469))
99
+ * improve compatibility with W3TC minification system ([bf9f058](https://github.com/Codeinwp/optimole-wp/commit/bf9f058))
100
+ * improve compatibility with WP Migrate DB ([02df077](https://github.com/Codeinwp/optimole-wp/commit/02df077))
101
+ * improve lazyload and replacement on json strings ([b7f67fd](https://github.com/Codeinwp/optimole-wp/commit/b7f67fd))
102
+ * removed blur from lazyload placeholders ([2c7d66d](https://github.com/Codeinwp/optimole-wp/commit/2c7d66d))
103
+ * safari blur problem ([5e31ec3](https://github.com/Codeinwp/optimole-wp/commit/5e31ec3))
104
+ * safari blur problem ([2ea1d82](https://github.com/Codeinwp/optimole-wp/commit/2ea1d82))
105
+
106
+ * **Features**
107
+ * adds compatibility for schemaless and relative image URLs ([e3886eb](https://github.com/Codeinwp/optimole-wp/commit/e3886eb))
108
+ * hide Optimole menu via constant [#196](https://github.com/Codeinwp/optimole-wp/issues/196) ([e0268fa](https://github.com/Codeinwp/optimole-wp/commit/e0268fa))
109
+ * skip lazyload on images with skip-lazy flag ([4d9219f](https://github.com/Codeinwp/optimole-wp/commit/4d9219f))
110
+
111
+
112
+
113
  #### [Version 2.2.6](https://github.com/Codeinwp/optimole-wp/compare/v2.2.5...v2.2.6) (2019-12-02)
114
 
115
  * **Bug Fixes**
themeisle-hash.json CHANGED
@@ -1 +1 @@
1
- {"optimole-wp.php":"a264f55269244fed4143b86a263fc6c6"}
1
+ {"optimole-wp.php":"a7c4f6a9fad954a565b076fde60beab7"}
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit0b6580d19fdcfda40f4987503eb13ec5::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInita2a71cedc61637a6775122c3b580ba36::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit0b6580d19fdcfda40f4987503eb13ec5
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit0b6580d19fdcfda40f4987503eb13ec5
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit0b6580d19fdcfda40f4987503eb13ec5', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit0b6580d19fdcfda40f4987503eb13ec5', '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\ComposerStaticInit0b6580d19fdcfda40f4987503eb13ec5::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit0b6580d19fdcfda40f4987503eb13ec5
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
- $includeFiles = Composer\Autoload\ComposerStaticInit0b6580d19fdcfda40f4987503eb13ec5::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
- composerRequire0b6580d19fdcfda40f4987503eb13ec5($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
- function composerRequire0b6580d19fdcfda40f4987503eb13ec5($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 ComposerAutoloaderInita2a71cedc61637a6775122c3b580ba36
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInita2a71cedc61637a6775122c3b580ba36', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInita2a71cedc61637a6775122c3b580ba36', '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\ComposerStaticInita2a71cedc61637a6775122c3b580ba36::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\ComposerStaticInita2a71cedc61637a6775122c3b580ba36::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequirea2a71cedc61637a6775122c3b580ba36($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
+ function composerRequirea2a71cedc61637a6775122c3b580ba36($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 ComposerStaticInit0b6580d19fdcfda40f4987503eb13ec5
8
  {
9
  public static $files = array (
10
  '9fef4034ed73e26a337d9856ea126f7f' => __DIR__ . '/..' . '/codeinwp/themeisle-sdk/load.php',
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInita2a71cedc61637a6775122c3b580ba36
8
  {
9
  public static $files = array (
10
  '9fef4034ed73e26a337d9856ea126f7f' => __DIR__ . '/..' . '/codeinwp/themeisle-sdk/load.php',