PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / trunk
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization vtrunk
4.2.14 4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 2.5.5 2.5.6 2.5.7 3.0.0 3.0.1 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.11.0 3.11.1 3.11.2 3.11.3 3.12.0 All 135 releases
← All changes | inc/lazyload_replacer.php +167 -57 3.1.3 → trunk View file →
@@ -1,6 +1,9 @@
1 1 <?php
2 2
3 +use OptimoleWP\PageProfiler\Profile;
4 +use OptimoleWP\Preload\Links;
5 +
3 6 /**
4 7 * The class handles the img tag replacements for lazyload.
5 8 *
6 9 * @package \Optml\Inc
@@ -8,8 +11,9 @@
8 11 */
9 12 final class Optml_Lazyload_Replacer extends Optml_App_Replacer {
10 13 use Optml_Normalizer;
11 14 use Optml_Validator;
15 + use Optml_Dam_Offload_Utils;
12 16
13 17 const IFRAME_PLACEHOLDER_CLASS = '
14 18 iframe[data-opt-src]:not([data-opt-lazy-loaded]) {
15 19 background-color: #ffffff;
@@ -26,9 +30,9 @@
26 30 const IFRAME_PLACEHOLDER_STYLE = '<style type="text/css">' . self::IFRAME_PLACEHOLDER_CLASS . '</style>';
27 31
28 32 const IFRAME_TEMP_COMMENT = '/** optmliframelazyloadplaceholder */';
29 33
30 - const SVG_PLACEHOLDER = 'data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%20#width#%20#height#%22%20width%3D%22#width#%22%20height%3D%22#height#%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3C%2Fsvg%3E';
34 + const SVG_PLACEHOLDER = 'data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%20#width#%20#height#%22%20width%3D%22#width#%22%20height%3D%22#height#%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20width%3D%22#width#%22%20height%3D%22#height#%22%20fill%3D%22#fill#%22%2F%3E%3C%2Fsvg%3E';
31 35 /**
32 36 * If frame lazyload is present on page.
33 37 *
34 38 * @var bool Whether or not at least one iframe has been lazyloaded.
@@ -36,9 +40,9 @@
36 40 private static $found_iframe = false;
37 41 /**
38 42 * Cached object instance.
39 43 *
40 - * @var Optml_Tag_Replacer
44 + * @var Optml_Lazyload_Replacer
41 45 */
42 46 protected static $instance = null;
43 47 /**
44 48 * Holds the number of images to skip from lazyload.
@@ -81,13 +85,8 @@
81 85 *
82 86 * @var bool Lazyload placeholder flag.
83 87 */
84 88 private static $is_lazyload_placeholder = false;
85 - /**
86 - * Holds flags which remove noscript tag bundle causing issues on render, i.e slider plugins.
87 - *
88 - * @var array Noscript flags.
89 - */
90 89
91 90 /**
92 91 * Class instance method.
93 92 *
@@ -92,9 +91,9 @@
92 91 * Class instance method.
93 92 *
94 93 * @codeCoverageIgnore
95 94 * @static
96 - * @return Optml_Tag_Replacer
95 + * @return Optml_Lazyload_Replacer
97 96 * @since 1.0.0
98 97 * @access public
99 98 */
100 99 public static function instance() {
@@ -111,21 +110,26 @@
111 110 *
112 111 * @return array Lazyload selectors.
113 112 */
114 113 public static function get_background_lazyload_selectors() {
114 + if ( null !== self::$background_lazyload_selectors ) {
115 + return self::$background_lazyload_selectors;
116 + }
115 117
116 - if ( ! empty( self::$background_lazyload_selectors ) && is_array( self::$background_lazyload_selectors ) ) {
118 + if ( self::instance()->settings === null ) {
119 + self::$background_lazyload_selectors = [];
120 +
117 121 return self::$background_lazyload_selectors;
118 122 }
119 123 if ( self::instance()->settings->get( 'bg_replacer' ) === 'disabled' ) {
120 124 self::$background_lazyload_selectors = [];
121 -
122 125 return self::$background_lazyload_selectors;
123 126 }
124 127 $default_watchers = [
125 - '.elementor-section[data-settings*="background_background"]',
126 - '.elementor-section > .elementor-background-overlay',
127 - '.wp-block-cover[style*="background-image"]',
128 + '[class*="wp-block-cover"][style*="background-image"]',
129 + '[style*="background-image:url("]', '[style*="background-image: url("]',
130 + '[style*="background:url("]', '[style*="background: url("]',
131 + '[class*="wp-block-group"][style*="background-image"]',
128 132 ];
129 133
130 134 $saved_watchers = self::instance()->settings->get_watchers();
131 135
@@ -150,10 +154,9 @@
150 154 *
151 155 * @return array
152 156 */
153 157 public static function get_lazyload_bg_classes() {
154 -
155 - if ( ! empty( self::$lazyload_background_classes ) && is_array( self::$lazyload_background_classes ) ) {
158 + if ( null !== self::$lazyload_background_classes ) {
156 159 return self::$lazyload_background_classes;
157 160 }
158 161
159 162 self::$lazyload_background_classes = apply_filters( 'optml_lazyload_bg_classes', [] );
@@ -169,8 +172,9 @@
169 172
170 173 if ( self::$skip_lazyload_images !== null ) {
171 174 return self::$skip_lazyload_images;
172 175 }
176 +
173 177 self::$skip_lazyload_images = apply_filters( 'optml_lazyload_images_skip', self::instance()->settings->get( 'skip_lazyload_images' ) );
174 178 return self::$skip_lazyload_images;
175 179 }
176 180 /**
@@ -178,10 +182,9 @@
178 182 *
179 183 * @return array
180 184 */
181 185 public static function get_watcher_lz_classes() {
182 -
183 - if ( ! empty( self::$lazyload_watcher_classes ) && is_array( self::$lazyload_watcher_classes ) ) {
186 + if ( null !== self::$lazyload_watcher_classes ) {
184 187 return self::$lazyload_watcher_classes;
185 188 }
186 189
187 190 self::$lazyload_watcher_classes = apply_filters( 'optml_watcher_lz_classes', [] );
@@ -197,24 +200,18 @@
197 200
198 201 if ( ! $this->settings->use_lazyload() ) {
199 202 return;
200 203 }
201 - if ( ! Optml_Filters::should_do_page( self::$filters[ Optml_Settings::FILTER_TYPE_LAZYLOAD ][ Optml_Settings::FILTER_URL ] ) ) {
204 + $filters = $this->settings->get_filters();
205 + if ( ! Optml_Filters::should_do_page( $filters[ Optml_Settings::FILTER_TYPE_LAZYLOAD ][ Optml_Settings::FILTER_URL ], $filters[ Optml_Settings::FILTER_TYPE_LAZYLOAD ][ Optml_Settings::FILTER_URL_MATCH ] ) ) {
202 206 return;
203 207 }
204 208
205 - add_filter(
206 - 'max_srcset_image_width',
207 - function () {
208 - return 1;
209 - }
210 - );
211 209 self::$is_lazyload_placeholder = self::$instance->settings->get( 'lazyload_placeholder' ) === 'enabled';
212 210
213 211 add_filter( 'optml_tag_replace', [ $this, 'lazyload_tag_replace' ], 2, 6 );
214 212
215 - add_filter( 'optml_video_replace', [$this, 'lazyload_video_replace'], 2, 1 );
216 -
213 + add_filter( 'optml_video_replace', [ $this, 'lazyload_video_replace' ], 2, 1 );
217 214 }
218 215 /**
219 216 * Check if there are lazyloaded iframes.
220 217 *
@@ -224,8 +221,25 @@
224 221 return self::$found_iframe;
225 222 }
226 223
227 224 /**
225 + * Check if the img tag should be lazyloaded early.
226 + *
227 + * @param string $image_tag The image tag.
228 + * @return bool Whether the image tag should be lazyloaded early or not.
229 + */
230 + public function should_lazyload_early( $image_tag ) {
231 + $flags = apply_filters( 'optml_lazyload_early_flags', [] );
232 +
233 + foreach ( $flags as $flag ) {
234 + if ( strpos( $image_tag, $flag ) !== false ) {
235 + return true;
236 + }
237 + }
238 +
239 + return false;
240 + }
241 + /**
228 242 * Replaces the tags with lazyload tags.
229 243 *
230 244 * @param string $new_tag The new tag.
231 245 * @param string $original_url The original URL.
@@ -238,16 +252,49 @@
238 252 */
239 253 public function lazyload_tag_replace( $new_tag, $original_url, $new_url, $optml_args, $is_slashed = false, $full_tag = '' ) {
240 254
241 255 if ( ! $this->can_lazyload_for( $original_url, $full_tag ) ) {
256 +
242 257 return Optml_Tag_Replacer::instance()->regular_tag_replace( $new_tag, $original_url, $new_url, $optml_args, $is_slashed );
243 258 }
259 + // Remove fetchpriority high attribute when the image is lazyloaded
260 + if ( strpos( $new_tag, 'fetchpriority' ) !== false ) {
261 + $new_tag = str_ireplace(
262 + [
263 + 'fetchpriority=high',
264 + 'fetchpriority="high"',
265 + "fetchpriority='high'",
266 + 'fetchpriority=\"high\"',
267 + "fetchpriority=\'high\'",
268 + ],
269 + '',
270 + $new_tag
271 + );
272 + }
273 +
274 + if ( self::instance()->settings->get( 'native_lazyload' ) === 'enabled' ) {
275 + // First check if loading attribute already exists
276 + if ( strpos( $new_tag, 'loading=' ) !== false ) {
277 + // Replace existing loading attribute with lazy
278 + $loading_attr = $is_slashed ? 'loading=\"lazy\"' : 'loading="lazy"';
279 + $new_tag = preg_replace( '/loading=(["\'])[^"\']*\1/i', $loading_attr, $new_tag );
280 + } else {
281 + // No loading attribute exists, add it after <img
282 + $loading_attr = $is_slashed ? ' loading=\"lazy\"' : ' loading="lazy"';
283 + $new_tag = preg_replace( '/<img/i', '<img' . $loading_attr, $new_tag, 1 );
284 + }
285 + return $new_tag;
286 + }
287 +
288 + // we remove the loading attribute if it exists with strpos
289 + $new_tag = preg_replace( '/loading=(["\'])[^"\']*\1/i', '', $new_tag );
290 +
244 291 $should_ignore_rescale = ! $this->is_valid_mimetype_from_url( $original_url, [ 'gif' => true, 'svg' => true ] );
245 292
246 293 if ( ! self::$is_lazyload_placeholder && ! $should_ignore_rescale ) {
247 294 $optml_args['quality'] = 'eco';
248 295 $optml_args['resize'] = [];
249 - $low_url = apply_filters( 'optml_content_url', $original_url, $optml_args );
296 + $low_url = apply_filters( 'optml_content_url', $this->get_unoptimized_url( $original_url ), $optml_args );
250 297 $low_url = $is_slashed ? addcslashes( $low_url, '/' ) : $low_url;
251 298 } else {
252 299 $low_url = $this->get_svg_for(
253 300 isset( $optml_args['width'] ) ? $optml_args['width'] : '100%',
@@ -254,20 +301,28 @@
254 301 isset( $optml_args['height'] ) ? $optml_args['height'] : '100%',
255 302 ( $should_ignore_rescale ? null : $original_url )
256 303 );
257 304 }
258 -
259 305 $opt_format = '';
260 306
261 307 if ( $this->should_add_data_tag( $full_tag ) ) {
262 308 $opt_format = ' data-opt-src="%s" ';
309 + $custom_class = '';
310 +
263 311 if ( $should_ignore_rescale ) {
312 + $custom_class .= 'optimole-lazy-only ';
313 + }
314 + if ( $this->should_lazyload_early( $full_tag ) ) {
315 + $custom_class .= 'optimole-load-early';
316 + }
317 +
318 + if ( ! empty( $custom_class ) ) {
264 319 if ( strpos( $new_tag, 'class=' ) === false ) {
265 - $opt_format .= ' class="optimole-lazy-only" ';
320 + $opt_format .= ' class="' . $custom_class . '" ';
266 321 } else {
267 322 $new_tag = str_replace(
268 323 ( $is_slashed ? 'class=\"' : 'class="' ),
269 - ( $is_slashed ? 'class=\"optimole-lazy-only ' : 'class="optimole-lazy-only ' ),
324 + ( $is_slashed ? 'class=\"' . $custom_class . ' ' : 'class="' . $custom_class . ' ' ),
270 325 $new_tag
271 326 );
272 327 }
273 328 }
@@ -293,12 +348,16 @@
293 348 ],
294 349 $new_tag,
295 350 1
296 351 );
352 +
353 + // We remove srcset and sizes attributes since our lazyload does not need them.
354 + $pattern = '/\s+(?:srcset|sizes)=("[^"]*"|\'[^\']*\'|\\\\"[^\\\\"]*\\\\")/i';
355 + $new_tag = preg_replace( $pattern, '', $new_tag );
356 +
357 + // We keep this for srcset lazyload compatibility that might break our mechanism.
297 358 $new_tag = str_replace( 'srcset=', 'old-srcset=', $new_tag );
298 - if ( strpos( $new_tag, 'loading=' ) === false && self::instance()->settings->get( 'native_lazyload' ) === 'enabled' ) {
299 - $new_tag = preg_replace( '/<img/im', $is_slashed ? '<img loading=\"lazy\"' : '<img loading="lazy"', $new_tag );
300 - }
359 +
301 360 if ( ! $this->should_add_noscript( $new_tag ) ) {
302 361 return $new_tag;
303 362 }
304 363
@@ -315,14 +374,16 @@
315 374 $video_tags = [];
316 375 $iframes = [];
317 376 $videos = [];
318 377 preg_match_all( '#(?:<noscript\s*>\s*)?<iframe(.*?)></iframe>(?:\s*</noscript\s*>)?#is', $content, $iframes );
319 - preg_match_all( '#(?:<noscript\s*>\s*)?<video(.*?)></video>(?:\s*</noscript\s*>)?#is', $content, $videos );
378 + preg_match_all( '#(?:<noscript\s*>\s*)?<video(.*?)>.*?</video>(?:\s*</noscript\s*>)?#is', $content, $videos );
320 379 $video_tags = array_merge( $iframes[0], $videos[0] );
321 380
322 381 $search = [];
323 382 $replace = [];
383 +
324 384 foreach ( $video_tags as $video_tag ) {
385 +
325 386 if ( ! $this->should_lazyload_iframe( $video_tag ) ) {
326 387 continue;
327 388 }
328 389 if ( preg_match( "/ data-opt-src=['\"]/is", $video_tag ) ) {
@@ -327,8 +388,9 @@
327 388 }
328 389 if ( preg_match( "/ data-opt-src=['\"]/is", $video_tag ) ) {
329 390 continue;
330 391 }
392 + $should_add_noscript = true;
331 393 $original_tag = $video_tag;
332 394 // replace the src and add the data-opt-src attribute
333 395 if ( strpos( $video_tag, 'iframe' ) !== false ) {
334 396 $video_tag = preg_replace( '/iframe(.*?)src=/is', 'iframe$1 src="about:blank" data-opt-src=', $video_tag );
@@ -334,9 +396,10 @@
334 396 $video_tag = preg_replace( '/iframe(.*?)src=/is', 'iframe$1 src="about:blank" data-opt-src=', $video_tag );
335 397 } elseif ( strpos( $video_tag, 'video' ) !== false ) {
336 398 if ( strpos( $video_tag, 'source' ) !== false ) {
337 399 if ( strpos( $video_tag, 'preload' ) === false ) {
338 - $video_tag = preg_replace( '/video(.*?)>/is', 'video$1 preload=none>', $video_tag, 1 );
400 + $video_tag = preg_replace( '/video(.*?)>/is', 'video$1 preload="metadata">', $video_tag, 1 );
401 + $should_add_noscript = false;
339 402 } else {
340 403 continue;
341 404 }
342 405 } else {
@@ -342,9 +405,9 @@
342 405 } else {
343 406 $video_tag = preg_replace( '/video(.*?)src=/is', 'video$1 data-opt-src=', $video_tag );
344 407 }
345 408 }
346 - if ( $this->should_add_noscript( $video_tag ) ) {
409 + if ( $this->should_add_noscript( $video_tag ) && $should_add_noscript ) {
347 410 $video_tag .= '<noscript>' . $original_tag . '</noscript>';
348 411 }
349 412 array_push( $search, $original_tag );
350 413 array_push( $replace, $video_tag );
@@ -364,8 +427,11 @@
364 427 *
365 428 * @return bool We can lazyload?
366 429 */
367 430 public function can_lazyload_for( $url, $tag = '' ) {
431 + if ( OPTML_DEBUG ) {
432 + do_action( 'optml_log', 'can_lazyload_for: ' . $url . ' ' . $tag );
433 + }
368 434 foreach ( self::possible_lazyload_flags() as $banned_string ) {
369 435 if ( strpos( $tag, $banned_string ) !== false ) {
370 436 return false;
371 437 }
@@ -379,9 +445,9 @@
379 445 basename( $url ),
380 446 Optml_Config::$image_extensions
381 447 );
382 448
383 - if ( ! isset( $type['ext'] ) || empty( $type['ext'] ) ) {
449 + if ( empty( $type['ext'] ) ) {
384 450 return false;
385 451 }
386 452
387 453 if ( false === Optml_Filters::should_do_extension( self::$filters[ Optml_Settings::FILTER_TYPE_LAZYLOAD ][ Optml_Settings::FILTER_EXT ], $type['ext'] ) ) {
@@ -390,9 +456,35 @@
390 456
391 457 if ( defined( 'OPTML_DISABLE_PNG_LAZYLOAD' ) && OPTML_DISABLE_PNG_LAZYLOAD ) {
392 458 return $type['ext'] !== 'png';
393 459 }
394 - if ( Optml_Tag_Replacer::$lazyload_skipped_images < self::get_skip_lazyload_limit() ) {
460 +
461 + $no_viewport_data_available = true;
462 +
463 + if ( $this->settings->is_lazyload_type_viewport() ) {
464 + $image_id = $this->get_id_by_url( $url );
465 + $is_in_all_viewports = Optml_Manager::instance()->page_profiler->is_in_all_viewports( $image_id );
466 + $is_lcp_image = Optml_Manager::instance()->page_profiler->is_lcp_image_in_all_viewports( $image_id );
467 + $no_viewport_data_available = ! Optml_Manager::instance()->page_profiler->is_data_available();
468 +
469 + if ( OPTML_DEBUG ) {
470 + if ( $is_in_all_viewports ) {
471 + do_action( 'optml_log', 'Lazyload skipped image is in all viewports ' . $url . '|' . $image_id );
472 + } elseif ( $is_lcp_image ) {
473 + do_action( 'optml_log', 'Lazyload skipped image is LCP ' . $url . '|' . $image_id );
474 + }
475 + }
476 +
477 + if ( $is_in_all_viewports || $is_lcp_image ) {
478 + return false;
479 + }
480 + }
481 +
482 + if (
483 + $no_viewport_data_available &&
484 + $this->settings->is_lazyload_type_fixed() &&
485 + Optml_Tag_Replacer::$lazyload_skipped_images < self::get_skip_lazyload_limit()
486 + ) {
395 487 return false;
396 488 }
397 489 return true;
398 490 }
@@ -416,10 +508,10 @@
416 508
417 509 /**
418 510 * Get SVG markup with specific width/height.
419 511 *
420 - * @param int $width Markup Width.
421 - * @param int $height Markup Height.
512 + * @param int|string $width Markup Width.
513 + * @param int|string $height Markup Height.
422 514 * @param string|null $url Original URL.
423 515 *
424 516 * @return string SVG code.
425 517 */
@@ -436,23 +528,39 @@
436 528 $sizes = getimagesize( $filepath );
437 529 wp_cache_add( $key, [ $sizes[0], $sizes[1] ], 'optml_sources', DAY_IN_SECONDS );
438 530 }
439 531 }
440 - list( $width, $height ) = $sizes;
532 + // Check if $sizes is an array before list() assignment to prevent fatal error on PHP 8.2+
533 + // when the image file is missing (e.g., offloaded to CDN or deleted).
534 + if ( is_array( $sizes ) ) {
535 + list( $width, $height ) = $sizes;
536 + }
441 537 }
538 + // If the width is not found the url might be an offloaded attachment so we can get the width and height from the metadata.
539 + if ( ! is_numeric( $width ) && ! empty( $url ) ) {
540 + $attachment_id = $this->attachment_url_to_post_id( $url );
541 + $meta = wp_get_attachment_metadata( $attachment_id );
542 + $width = $meta['width'] ?? false;
543 + $height = $meta['height'] ?? false;
544 + }
442 545
443 546 $width = ! is_numeric( $width ) ? '100%' : $width;
444 547 $height = ! is_numeric( $height ) ? '100%' : $height;
548 + $fill = $this->settings->get( 'placeholder_color' );
445 549
446 - return
447 - str_replace(
448 - [ '#width#', '#height#' ],
449 - [
450 - $width,
451 - $height,
452 - ],
453 - self::SVG_PLACEHOLDER
454 - );
550 + if ( empty( $fill ) ) {
551 + $fill = 'transparent';
552 + }
553 +
554 + return str_replace(
555 + [ '#width#', '#height#', '#fill#' ],
556 + [
557 + $width,
558 + $height,
559 + urlencode( $fill ),
560 + ],
561 + self::SVG_PLACEHOLDER
562 + );
455 563 }
456 564
457 565 /**
458 566 * Check if we should add the noscript tag.
@@ -461,8 +569,11 @@
461 569 *
462 570 * @return bool Should add?
463 571 */
464 572 public function should_add_noscript( $tag ) {
573 + if ( $this->settings->get( 'no_script' ) === 'disabled' ) {
574 + return false;
575 + }
465 576 foreach ( self::get_ignore_noscript_flags() as $banned_string ) {
466 577 if ( strpos( $tag, $banned_string ) !== false ) {
467 578 return false;
468 579 }
@@ -477,8 +588,9 @@
477 588 *
478 589 * @return bool Should add?
479 590 */
480 591 public function should_lazyload_iframe( $tag ) {
592 +
481 593 foreach ( self::get_iframe_lazyload_flags() as $banned_string ) {
482 594 if ( strpos( $tag, $banned_string ) !== false ) {
483 595 return false;
484 596 }
@@ -492,14 +604,13 @@
492 604 *
493 605 * @return array
494 606 */
495 607 public static function get_ignore_noscript_flags() {
496 -
497 - if ( ! empty( self::$ignore_no_script_flags ) && is_array( self::$ignore_no_script_flags ) ) {
608 + if ( null !== self::$ignore_no_script_flags ) {
498 609 return self::$ignore_no_script_flags;
499 610 }
500 611
501 - self::$ignore_no_script_flags = apply_filters( 'optml_ignore_noscript_on', [] );
612 + self::$ignore_no_script_flags = apply_filters( 'optml_ignore_noscript_on', [ '<noscript' ] );
502 613
503 614 return self::$ignore_no_script_flags;
504 615 }
505 616 /**
@@ -507,14 +618,14 @@
507 618 *
508 619 * @return array
509 620 */
510 621 public static function get_iframe_lazyload_flags() {
511 -
512 - if ( ! empty( self::$iframe_lazyload_flags ) && is_array( self::$iframe_lazyload_flags ) ) {
622 + if ( null !== self::$iframe_lazyload_flags ) {
513 623 return self::$iframe_lazyload_flags;
514 624 }
515 625
516 - self::$iframe_lazyload_flags = apply_filters( 'optml_iframe_lazyload_flags', [ 'gform_ajax_frame', '<noscript', 'recaptcha', 'original-src' ] );
626 + self::$iframe_lazyload_flags = self::possible_lazyload_flags();
627 + self::$iframe_lazyload_flags = array_merge( self::$iframe_lazyload_flags, apply_filters( 'optml_iframe_lazyload_flags', [ 'gform_ajax_frame', '<noscript', 'recaptcha', '-src' ] ) );
517 628
518 629 return self::$iframe_lazyload_flags;
519 630 }
520 631 /**
@@ -544,6 +655,5 @@
544 655 public function __wakeup() {
545 656 // Unserializing instances of the class is forbidden.
546 657 _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'optimole-wp' ), '1.0.0' );
547 658 }
548 -
549 659 }