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

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

543 lines 18.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The class handles the img tag replacements for lazyload.
5 *
6 * @package \Optml\Inc
7 * @author Optimole <friends@optimole.com>
8 */
9 final class Optml_Lazyload_Replacer extends Optml_App_Replacer {
10 use Optml_Normalizer;
11 use Optml_Validator;
12
13 const IFRAME_PLACEHOLDER_CLASS = '
14 iframe[data-opt-src]:not([data-opt-lazy-loaded]) {
15 background-color: #ffffff;
16 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2240%22%20height%3D%2240%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20style%3D%22-webkit-transform-origin%3A50%25%2050%25%3B-webkit-animation%3Aspin%201.5s%20linear%20infinite%3B-webkit-backface-visibility%3Ahidden%3Banimation%3Aspin%201.5s%20linear%20infinite%22%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20stroke-linejoin%3D%22round%22%20stroke-miterlimit%3D%221.414%22%3E%3Cdefs%3E%3Cstyle%3E%3C%21%5BCDATA%5B%40-webkit-keyframes%20spin%7Bfrom%7B-webkit-transform%3Arotate%280deg%29%7Dto%7B-webkit-transform%3Arotate%28-359deg%29%7D%7D%40keyframes%20spin%7Bfrom%7Btransform%3Arotate%280deg%29%7Dto%7Btransform%3Arotate%28-359deg%29%7D%7D%5D%5D%3E%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22outer%22%3E%3Cpath%20d%3D%22M20%200a3.994%203.994%200%20110%207.988A3.994%203.994%200%200120%200z%22%2F%3E%3Cpath%20d%3D%22M5.858%205.858a3.994%203.994%200%20115.648%205.648%203.994%203.994%200%2001-5.648-5.648z%22%20fill%3D%22%23d2d2d2%22%2F%3E%3Cpath%20d%3D%22M20%2032.012A3.994%203.994%200%201120%2040a3.994%203.994%200%20010-7.988z%22%20fill%3D%22%23828282%22%2F%3E%3Cpath%20d%3D%22M28.494%2028.494a3.994%203.994%200%20115.648%205.648%203.994%203.994%200%2001-5.648-5.648z%22%20fill%3D%22%23656565%22%2F%3E%3Cpath%20d%3D%22M3.994%2016.006a3.994%203.994%200%20110%207.988%203.994%203.994%200%20010-7.988z%22%20fill%3D%22%23bbb%22%2F%3E%3Cpath%20d%3D%22M5.858%2028.494a3.994%203.994%200%20115.648%205.648%203.994%203.994%200%2001-5.648-5.648z%22%20fill%3D%22%23a4a4a4%22%2F%3E%3Cpath%20d%3D%22M36.006%2016.006a3.994%203.994%200%20110%207.988%203.994%203.994%200%20010-7.988z%22%20fill%3D%22%234a4a4a%22%2F%3E%3Cpath%20d%3D%22M28.494%205.858a3.994%203.994%200%20115.648%205.648%203.994%203.994%200%2001-5.648-5.648z%22%20fill%3D%22%23323232%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
17 background-repeat: no-repeat;
18 background-position: 50% 50%;
19 }
20 video[data-opt-src]:not([data-opt-lazy-loaded]) {
21 background-color: #ffffff;
22 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2240%22%20height%3D%2240%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20style%3D%22-webkit-transform-origin%3A50%25%2050%25%3B-webkit-animation%3Aspin%201.5s%20linear%20infinite%3B-webkit-backface-visibility%3Ahidden%3Banimation%3Aspin%201.5s%20linear%20infinite%22%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20stroke-linejoin%3D%22round%22%20stroke-miterlimit%3D%221.414%22%3E%3Cdefs%3E%3Cstyle%3E%3C%21%5BCDATA%5B%40-webkit-keyframes%20spin%7Bfrom%7B-webkit-transform%3Arotate%280deg%29%7Dto%7B-webkit-transform%3Arotate%28-359deg%29%7D%7D%40keyframes%20spin%7Bfrom%7Btransform%3Arotate%280deg%29%7Dto%7Btransform%3Arotate%28-359deg%29%7D%7D%5D%5D%3E%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22outer%22%3E%3Cpath%20d%3D%22M20%200a3.994%203.994%200%20110%207.988A3.994%203.994%200%200120%200z%22%2F%3E%3Cpath%20d%3D%22M5.858%205.858a3.994%203.994%200%20115.648%205.648%203.994%203.994%200%2001-5.648-5.648z%22%20fill%3D%22%23d2d2d2%22%2F%3E%3Cpath%20d%3D%22M20%2032.012A3.994%203.994%200%201120%2040a3.994%203.994%200%20010-7.988z%22%20fill%3D%22%23828282%22%2F%3E%3Cpath%20d%3D%22M28.494%2028.494a3.994%203.994%200%20115.648%205.648%203.994%203.994%200%2001-5.648-5.648z%22%20fill%3D%22%23656565%22%2F%3E%3Cpath%20d%3D%22M3.994%2016.006a3.994%203.994%200%20110%207.988%203.994%203.994%200%20010-7.988z%22%20fill%3D%22%23bbb%22%2F%3E%3Cpath%20d%3D%22M5.858%2028.494a3.994%203.994%200%20115.648%205.648%203.994%203.994%200%2001-5.648-5.648z%22%20fill%3D%22%23a4a4a4%22%2F%3E%3Cpath%20d%3D%22M36.006%2016.006a3.994%203.994%200%20110%207.988%203.994%203.994%200%20010-7.988z%22%20fill%3D%22%234a4a4a%22%2F%3E%3Cpath%20d%3D%22M28.494%205.858a3.994%203.994%200%20115.648%205.648%203.994%203.994%200%2001-5.648-5.648z%22%20fill%3D%22%23323232%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
23 background-repeat: no-repeat;
24 background-position: 50% 50%;
25 }';
26 const IFRAME_PLACEHOLDER_STYLE = '<style type="text/css">' . self::IFRAME_PLACEHOLDER_CLASS . '</style>';
27
28 const IFRAME_TEMP_COMMENT = '/** optmliframelazyloadplaceholder */';
29
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';
31 /**
32 * If frame lazyload is present on page.
33 *
34 * @var bool Whether or not at least one iframe has been lazyloaded.
35 */
36 private static $found_iframe = false;
37 /**
38 * Cached object instance.
39 *
40 * @var Optml_Tag_Replacer
41 */
42 protected static $instance = null;
43 /**
44 * Holds the number of images to skip from lazyload.
45 *
46 * @var integer The number image tags to skip.
47 */
48 private static $skip_lazyload_images = null;
49 /**
50 * Holds classes for listening to lazyload on background.
51 *
52 * @var array Lazyload background classes.
53 */
54 private static $lazyload_background_classes = null;
55 /**
56 * Selectors used for background lazyload.
57 *
58 * @var array Lazyload background CSS selectors.
59 */
60 private static $background_lazyload_selectors = null;
61 /**
62 * Holds flags which remove noscript tag bundle causing issues on render, i.e slider plugins.
63 *
64 * @var array Noscript flags.
65 */
66 private static $ignore_no_script_flags = null;
67 /**
68 * Holds possible iframe lazyload flags where we should ignore our lazyload.
69 *
70 * @var array
71 */
72 protected static $iframe_lazyload_flags = null;
73 /**
74 * Holds classes responsabile for watching lazyload behaviour.
75 *
76 * @var array Lazyload classes.
77 */
78 private static $lazyload_watcher_classes = null;
79 /**
80 * Should we use the generic placeholder?
81 *
82 * @var bool Lazyload placeholder flag.
83 */
84 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
91 /**
92 * Class instance method.
93 *
94 * @codeCoverageIgnore
95 * @static
96 * @return Optml_Tag_Replacer
97 * @since 1.0.0
98 * @access public
99 */
100 public static function instance() {
101 if ( null === self::$instance ) {
102 self::$instance = new self();
103 add_action( 'optml_replacer_setup', [ self::$instance, 'init' ] );
104 }
105
106 return self::$instance;
107 }
108
109 /**
110 * Return lazyload selectors for background images.
111 *
112 * @return array Lazyload selectors.
113 */
114 public static function get_background_lazyload_selectors() {
115
116 if ( ! empty( self::$background_lazyload_selectors ) && is_array( self::$background_lazyload_selectors ) ) {
117 return self::$background_lazyload_selectors;
118 }
119 if ( self::instance()->settings->get( 'bg_replacer' ) === 'disabled' ) {
120 self::$background_lazyload_selectors = [];
121
122 return self::$background_lazyload_selectors;
123 }
124 $default_watchers = [
125 '.elementor-section[data-settings*="background_background"]',
126 '.elementor-section > .elementor-background-overlay',
127 '.wp-block-cover[style*="background-image"]',
128 ];
129
130 $saved_watchers = self::instance()->settings->get_watchers();
131
132 $saved_watchers = str_replace( [ "\n", "\r" ], ',', $saved_watchers );
133 $saved_watchers = explode( ',', $saved_watchers );
134 $all_watchers = array_merge( $default_watchers, $saved_watchers );
135 $all_watchers = apply_filters( 'optml_lazyload_bg_selectors', $all_watchers );
136 $all_watchers = array_filter(
137 $all_watchers,
138 function ( $value ) {
139 return ! empty( $value ) && strlen( $value ) >= 2;
140 }
141 );
142
143 self::$background_lazyload_selectors = $all_watchers;
144
145 return self::$background_lazyload_selectors;
146 }
147
148 /**
149 * Returns background classes for lazyload.
150 *
151 * @return array
152 */
153 public static function get_lazyload_bg_classes() {
154
155 if ( ! empty( self::$lazyload_background_classes ) && is_array( self::$lazyload_background_classes ) ) {
156 return self::$lazyload_background_classes;
157 }
158
159 self::$lazyload_background_classes = apply_filters( 'optml_lazyload_bg_classes', [] );
160
161 return self::$lazyload_background_classes;
162 }
163 /**
164 * Returns the number of images to skip from lazyload.
165 *
166 * @return integer
167 */
168 public static function get_skip_lazyload_limit() {
169
170 if ( self::$skip_lazyload_images !== null ) {
171 return self::$skip_lazyload_images;
172 }
173 self::$skip_lazyload_images = apply_filters( 'optml_lazyload_images_skip', self::instance()->settings->get( 'skip_lazyload_images' ) );
174 return self::$skip_lazyload_images;
175 }
176 /**
177 * Returns classes for lazyload additional watch.
178 *
179 * @return array
180 */
181 public static function get_watcher_lz_classes() {
182
183 if ( ! empty( self::$lazyload_watcher_classes ) && is_array( self::$lazyload_watcher_classes ) ) {
184 return self::$lazyload_watcher_classes;
185 }
186
187 self::$lazyload_watcher_classes = apply_filters( 'optml_watcher_lz_classes', [] );
188
189 return self::$lazyload_watcher_classes;
190 }
191
192 /**
193 * The initialize method.
194 */
195 public function init() {
196 parent::init();
197
198 if ( ! $this->settings->use_lazyload() ) {
199 return;
200 }
201 if ( ! Optml_Filters::should_do_page( self::$filters[ Optml_Settings::FILTER_TYPE_LAZYLOAD ][ Optml_Settings::FILTER_URL ] ) ) {
202 return;
203 }
204
205 add_filter(
206 'max_srcset_image_width',
207 function () {
208 return 1;
209 }
210 );
211 self::$is_lazyload_placeholder = self::$instance->settings->get( 'lazyload_placeholder' ) === 'enabled';
212
213 add_filter( 'optml_tag_replace', [ $this, 'lazyload_tag_replace' ], 2, 6 );
214
215 add_filter( 'optml_video_replace', [$this, 'lazyload_video_replace'], 2, 1 );
216
217 }
218 /**
219 * Check if there are lazyloaded iframes.
220 *
221 * @return bool Whether an iframe was lazyloaded on the page or not.
222 */
223 public static function found_iframe() {
224 return self::$found_iframe;
225 }
226
227 /**
228 * Replaces the tags with lazyload tags.
229 *
230 * @param string $new_tag The new tag.
231 * @param string $original_url The original URL.
232 * @param string $new_url The optimized URL.
233 * @param array $optml_args Options passed for URL optimization.
234 * @param bool $is_slashed If the url needs slashes.
235 * @param string $full_tag Full tag, wrapper included.
236 *
237 * @return string
238 */
239 public function lazyload_tag_replace( $new_tag, $original_url, $new_url, $optml_args, $is_slashed = false, $full_tag = '' ) {
240
241 if ( ! $this->can_lazyload_for( $original_url, $full_tag ) ) {
242 return Optml_Tag_Replacer::instance()->regular_tag_replace( $new_tag, $original_url, $new_url, $optml_args, $is_slashed );
243 }
244 $should_ignore_rescale = ! $this->is_valid_mimetype_from_url( $original_url, [ 'gif' => true, 'svg' => true ] );
245
246 if ( ! self::$is_lazyload_placeholder && ! $should_ignore_rescale ) {
247 $optml_args['quality'] = 'eco';
248 $optml_args['resize'] = [];
249 $low_url = apply_filters( 'optml_content_url', $original_url, $optml_args );
250 $low_url = $is_slashed ? addcslashes( $low_url, '/' ) : $low_url;
251 } else {
252 $low_url = $this->get_svg_for(
253 isset( $optml_args['width'] ) ? $optml_args['width'] : '100%',
254 isset( $optml_args['height'] ) ? $optml_args['height'] : '100%',
255 ( $should_ignore_rescale ? null : $original_url )
256 );
257 }
258
259 $opt_format = '';
260
261 if ( $this->should_add_data_tag( $full_tag ) ) {
262 $opt_format = ' data-opt-src="%s" ';
263 if ( $should_ignore_rescale ) {
264 if ( strpos( $new_tag, 'class=' ) === false ) {
265 $opt_format .= ' class="optimole-lazy-only" ';
266 } else {
267 $new_tag = str_replace(
268 ( $is_slashed ? 'class=\"' : 'class="' ),
269 ( $is_slashed ? 'class=\"optimole-lazy-only ' : 'class="optimole-lazy-only ' ),
270 $new_tag
271 );
272 }
273 }
274 $opt_format = $is_slashed ? addslashes( $opt_format ) : $opt_format;
275 }
276 $new_url = $is_slashed ? addcslashes( $new_url, '/' ) : $new_url;
277
278 $opt_src = sprintf( $opt_format, $new_url );
279
280 $no_script_tag = str_replace(
281 $original_url,
282 $new_url,
283 $new_tag
284 );
285 $new_tag = preg_replace(
286 [
287 '/((?:\s|\'|"){1,}src(?>=|"|\'|\s|\\\\)*)' . preg_quote( $original_url, '/' ) . '/m',
288 '/<img/im',
289 ],
290 [
291 "$1$low_url",
292 '<img' . $opt_src,
293 ],
294 $new_tag,
295 1
296 );
297 $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 }
301 if ( ! $this->should_add_noscript( $new_tag ) ) {
302 return $new_tag;
303 }
304
305 return $new_tag . '<noscript>' . $no_script_tag . '</noscript>';
306 }
307 /**
308 * Replaces video embeds with lazyload embeds.
309 *
310 * @param string $content Html page content.
311 *
312 * @return string
313 */
314 public function lazyload_video_replace( $content ) {
315 $video_tags = [];
316 $iframes = [];
317 $videos = [];
318 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 );
320 $video_tags = array_merge( $iframes[0], $videos[0] );
321
322 $search = [];
323 $replace = [];
324 foreach ( $video_tags as $video_tag ) {
325 if ( ! $this->should_lazyload_iframe( $video_tag ) ) {
326 continue;
327 }
328 if ( preg_match( "/ data-opt-src=['\"]/is", $video_tag ) ) {
329 continue;
330 }
331 array_push( $search, $video_tag );
332 $no_script = $video_tag;
333 // replace the src and add the data-opt-src attribute
334 if ( strpos( $video_tag, 'iframe' ) !== false ) {
335 $video_tag = preg_replace( '/iframe(.*?)src=/is', 'iframe$1 src="about:blank" data-opt-src=', $video_tag );
336 } elseif ( strpos( $video_tag, 'video' ) !== false ) {
337 $video_tag = preg_replace( '/video(.*?)src=/is', 'video$1 data-opt-src=', $video_tag );
338 }
339
340 if ( $this->should_add_noscript( $video_tag ) ) {
341 $video_tag .= '<noscript>' . $no_script . '</noscript>';
342 }
343 array_push( $replace, $video_tag );
344 self::$found_iframe = true;
345 }
346 $search = array_unique( $search );
347 $replace = array_unique( $replace );
348 $content = str_replace( $search, $replace, $content );
349 return $content;
350 }
351
352 /**
353 * Check if the lazyload is allowed for this url.
354 *
355 * @param string $url Url.
356 * @param string $tag Html tag.
357 *
358 * @return bool We can lazyload?
359 */
360 public function can_lazyload_for( $url, $tag = '' ) {
361 foreach ( self::possible_lazyload_flags() as $banned_string ) {
362 if ( strpos( $tag, $banned_string ) !== false ) {
363 return false;
364 }
365 }
366 if ( false === Optml_Filters::should_do_image( $url, self::$filters[ Optml_Settings::FILTER_TYPE_LAZYLOAD ][ Optml_Settings::FILTER_FILENAME ] ) ) {
367 return false;
368 }
369 $url = strtok( $url, '?' );
370
371 $type = wp_check_filetype(
372 basename( $url ),
373 Optml_Config::$image_extensions
374 );
375
376 if ( ! isset( $type['ext'] ) || empty( $type['ext'] ) ) {
377 return false;
378 }
379
380 if ( false === Optml_Filters::should_do_extension( self::$filters[ Optml_Settings::FILTER_TYPE_LAZYLOAD ][ Optml_Settings::FILTER_EXT ], $type['ext'] ) ) {
381 return false;
382 }
383
384 if ( defined( 'OPTML_DISABLE_PNG_LAZYLOAD' ) && OPTML_DISABLE_PNG_LAZYLOAD ) {
385 return $type['ext'] !== 'png';
386 }
387 if ( Optml_Tag_Replacer::$lazyload_skipped_images < self::get_skip_lazyload_limit() ) {
388 return false;
389 }
390 return true;
391 }
392
393 /**
394 * Check if we should add the data-opt-tag.
395 *
396 * @param string $tag Html tag.
397 *
398 * @return bool Should add?
399 */
400 public function should_add_data_tag( $tag ) {
401 foreach ( self::possible_data_ignore_flags() as $banned_string ) {
402 if ( strpos( $tag, $banned_string ) !== false ) {
403 return false;
404 }
405 }
406
407 return true;
408 }
409
410 /**
411 * Get SVG markup with specific width/height.
412 *
413 * @param int $width Markup Width.
414 * @param int $height Markup Height.
415 * @param string|null $url Original URL.
416 *
417 * @return string SVG code.
418 */
419 public function get_svg_for( $width, $height, $url = null ) {
420
421 if ( $url !== null && ! is_numeric( $width ) ) {
422 $url = strtok( $url, '?' );
423 $key = crc32( $url );
424 $sizes = wp_cache_get( $key, 'optml_sources' );
425 if ( $sizes === false ) {
426 $filepath = substr( $url, strpos( $url, $this->upload_resource['content_folder'] ) + $this->upload_resource['content_folder_length'] );
427 $filepath = WP_CONTENT_DIR . $filepath;
428 if ( is_file( $filepath ) ) {
429 $sizes = getimagesize( $filepath );
430 wp_cache_add( $key, [ $sizes[0], $sizes[1] ], 'optml_sources', DAY_IN_SECONDS );
431 }
432 }
433 list( $width, $height ) = $sizes;
434 }
435
436 $width = ! is_numeric( $width ) ? '100%' : $width;
437 $height = ! is_numeric( $height ) ? '100%' : $height;
438
439 return
440 str_replace(
441 [ '#width#', '#height#' ],
442 [
443 $width,
444 $height,
445 ],
446 self::SVG_PLACEHOLDER
447 );
448 }
449
450 /**
451 * Check if we should add the noscript tag.
452 *
453 * @param string $tag Html tag.
454 *
455 * @return bool Should add?
456 */
457 public function should_add_noscript( $tag ) {
458 foreach ( self::get_ignore_noscript_flags() as $banned_string ) {
459 if ( strpos( $tag, $banned_string ) !== false ) {
460 return false;
461 }
462 }
463
464 return true;
465 }
466 /**
467 * Check if we should lazyload iframe.
468 *
469 * @param string $tag Html tag.
470 *
471 * @return bool Should add?
472 */
473 public function should_lazyload_iframe( $tag ) {
474 foreach ( self::get_iframe_lazyload_flags() as $banned_string ) {
475 if ( strpos( $tag, $banned_string ) !== false ) {
476 return false;
477 }
478 }
479
480 return true;
481 }
482
483 /**
484 * Returns flags for ignoring noscript tag additional watch.
485 *
486 * @return array
487 */
488 public static function get_ignore_noscript_flags() {
489
490 if ( ! empty( self::$ignore_no_script_flags ) && is_array( self::$ignore_no_script_flags ) ) {
491 return self::$ignore_no_script_flags;
492 }
493
494 self::$ignore_no_script_flags = apply_filters( 'optml_ignore_noscript_on', [] );
495
496 return self::$ignore_no_script_flags;
497 }
498 /**
499 * Returns possible lazyload flags for iframes.
500 *
501 * @return array
502 */
503 public static function get_iframe_lazyload_flags() {
504
505 if ( ! empty( self::$iframe_lazyload_flags ) && is_array( self::$iframe_lazyload_flags ) ) {
506 return self::$iframe_lazyload_flags;
507 }
508
509 self::$iframe_lazyload_flags = apply_filters( 'optml_iframe_lazyload_flags', [ 'gform_ajax_frame', '<noscript', 'recaptcha', 'original-src' ] );
510
511 return self::$iframe_lazyload_flags;
512 }
513 /**
514 * Throw error on object clone
515 *
516 * The whole idea of the singleton design pattern is that there is a single
517 * object therefore, we don't want the object to be cloned.
518 *
519 * @codeCoverageIgnore
520 * @access public
521 * @return void
522 * @since 1.0.0
523 */
524 public function __clone() {
525 // Cloning instances of the class is forbidden.
526 _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'optimole-wp' ), '1.0.0' );
527 }
528
529 /**
530 * Disable unserializing of the class
531 *
532 * @codeCoverageIgnore
533 * @access public
534 * @return void
535 * @since 1.0.0
536 */
537 public function __wakeup() {
538 // Unserializing instances of the class is forbidden.
539 _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'optimole-wp' ), '1.0.0' );
540 }
541
542 }
543