PluginProbe
Gallery : FooGallery / 3.3.0
Gallery : FooGallery v3.3.0
3.3.2 3.3.3 3.3.0 3.1.31 3.1.32 3.1.34 3.1.36 3.2.0 3.2.6 trunk 1.10.3 2.0.24 2.1.34 2.2.44 2.3.3 2.4.32 3.0.6 3.1.11 3.1.12 3.1.13 3.1.20 3.1.25 3.1.26 3.1.26.1 3.1.26.2
foogallery / includes / class-foogallery-delayed-runtime-loader.php
class-foogallery-delayed-runtime-loader.php
790 lines 22.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Delays the FooGallery frontend runtime when the current page is safe to do so.
4 */
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit;
8 }
9
10 if ( ! class_exists( 'FooGallery_Delayed_Runtime_Loader' ) ) {
11
12 /**
13 * Class FooGallery_Delayed_Runtime_Loader
14 */
15 class FooGallery_Delayed_Runtime_Loader {
16
17 const CORE_HANDLE = 'foogallery-core';
18 const READY_HANDLE = 'foogallery-ready';
19 const DELAYED_LOADER_ID = 'foogallery-delayed-loader';
20
21 /**
22 * Singleton instance.
23 *
24 * @var FooGallery_Delayed_Runtime_Loader
25 */
26 private static $instance;
27
28 /**
29 * Whether delayed loading is currently scheduled.
30 *
31 * @var bool
32 */
33 private $scheduled = false;
34
35 /**
36 * Whether the current page must use normal WordPress enqueueing.
37 *
38 * @var bool
39 */
40 private $normal_required = false;
41
42 /**
43 * The delayed runtime context for the page.
44 *
45 * @var array|null
46 */
47 private $context = null;
48
49 /**
50 * Get the shared instance.
51 *
52 * @return FooGallery_Delayed_Runtime_Loader
53 */
54 public static function instance() {
55 if ( ! isset( self::$instance ) ) {
56 self::$instance = new self();
57 }
58
59 return self::$instance;
60 }
61
62 /**
63 * Enqueue or schedule the FooGallery runtime.
64 *
65 * @param string[]|null $deps The script dependencies.
66 *
67 * @return void
68 */
69 public function enqueue_core_gallery_template_script( $deps = null ) {
70 $explicit_deps = isset( $deps );
71
72 if ( $explicit_deps ) {
73 $this->reset_core_handle();
74 } else {
75 $deps = apply_filters( 'foogallery_core_gallery_script_default_deps', $this->default_core_gallery_script_dependencies() );
76 }
77
78 $context = $this->build_core_gallery_script_context( $deps, $explicit_deps );
79
80 if ( $this->normal_required ) {
81 $context['fallback_reason'] = 'normal_enqueue_already_required';
82 $this->enqueue_normal_core_gallery_template_script( $context );
83 return;
84 }
85
86 if ( $this->should_delay_core_gallery_template_script( $context ) ) {
87 $this->schedule_delayed_core_gallery_template_script( $context );
88 return;
89 }
90
91 if ( $this->scheduled ) {
92 $this->cancel_delayed_core_gallery_template_script();
93 }
94
95 $this->normal_required = true;
96 $this->enqueue_normal_core_gallery_template_script( $context );
97 }
98
99 /**
100 * Get the default runtime dependencies.
101 *
102 * @return string[]
103 */
104 private function default_core_gallery_script_dependencies() {
105 return $this->is_frontend_request() ? array( 'jquery-core' ) : array( 'jquery' );
106 }
107
108 /**
109 * Check if the legacy runtime enqueue path should be forced.
110 *
111 * @return bool
112 */
113 private function force_legacy_runtime_scripts() {
114 if ( 'on' === foogallery_get_setting( 'force_legacy_runtime_scripts', false ) ) {
115 return true;
116 }
117
118 if ( $this->setting_has_explicit_value( 'force_legacy_runtime_scripts' ) ) {
119 return false;
120 }
121
122 if ( class_exists( 'FooGallery_Version_Check' ) ) {
123 $stored_version = FooGallery_Version_Check::get_stored_version();
124
125 if ( is_string( $stored_version ) && '' !== $stored_version && version_compare( $stored_version, '3.1.36', '<' ) ) {
126 return true;
127 }
128 }
129
130 return false;
131 }
132
133 /**
134 * Check if a setting is explicitly saved and not only supplied by defaults.
135 *
136 * @param string $key The setting key.
137 *
138 * @return bool
139 */
140 private function setting_has_explicit_value( $key ) {
141 $options = get_option( FOOGALLERY_SLUG );
142
143 if ( is_array( $options ) && array_key_exists( $key, $options ) ) {
144 return true;
145 }
146
147 if ( function_exists( 'is_multisite' ) && is_multisite() ) {
148 $site_options = get_site_option( FOOGALLERY_SLUG );
149
150 if ( is_array( $site_options ) && array_key_exists( $key, $site_options ) ) {
151 return true;
152 }
153 }
154
155 return false;
156 }
157
158 /**
159 * Build the runtime loading context.
160 *
161 * @param string[] $deps The script dependencies.
162 * @param bool $explicit_deps Whether dependencies were passed explicitly.
163 *
164 * @return array
165 */
166 public function build_core_gallery_script_context( $deps, $explicit_deps = false ) {
167 global $current_foogallery;
168 global $current_foogallery_template;
169
170 $filename_suffix = foogallery_is_debug() ? '' : '.min';
171 $js = apply_filters( 'foogallery_core_gallery_script', FOOGALLERY_DEFAULT_TEMPLATES_EXTENSION_SHARED_URL . 'js/foogallery' . $filename_suffix . '.js' );
172 $deps = apply_filters( 'foogallery_core_gallery_script_deps', $this->normalize_dependencies( $deps ) );
173 $polyfills = foogallery_get_setting( 'enqueue_polyfills', false );
174
175 if ( $polyfills ) {
176 foogallery_enqueue_polyfills();
177 $deps[] = 'foogallery-polyfills';
178 }
179
180 $deps = $this->normalize_dependencies( $deps );
181 $js = foogallery_resolve_asset_url( $js );
182 $ready_src = foogallery_resolve_asset_url( FOOGALLERY_DEFAULT_TEMPLATES_EXTENSION_SHARED_URL . 'js/foogallery.ready' . $filename_suffix . '.js' );
183 $feature_deps = apply_filters( 'foogallery_feature_script_deps', array( self::CORE_HANDLE ) );
184 $feature_deps = $this->normalize_dependencies( $feature_deps );
185 $custom_js = foogallery_get_setting( 'custom_js', '' );
186 $has_custom_js = is_string( $custom_js ) ? '' !== trim( $custom_js ) : ! empty( $custom_js );
187
188 $context = array(
189 'gallery' => $current_foogallery,
190 'template' => $current_foogallery_template,
191 'lightbox' => foogallery_gallery_template_setting_lightbox(),
192 'js' => $js,
193 'ready_src' => $ready_src,
194 'deps' => $deps,
195 'explicit_deps' => $explicit_deps,
196 'feature_deps' => $feature_deps,
197 'has_custom_js' => $has_custom_js,
198 'force_legacy_runtime_scripts' => $this->force_legacy_runtime_scripts(),
199 'polyfills_enabled' => (bool) $polyfills,
200 'legacy_lazyload' => $this->gallery_uses_legacy_lazyload( $current_foogallery ),
201 'dependency_assets' => array(),
202 'dependency_handles' => array(),
203 'missing_dependencies' => array(),
204 'fallback_reason' => '',
205 );
206
207 $dependency_data = $this->resolve_dependency_assets( $deps );
208 $context['dependency_assets'] = $dependency_data['assets'];
209 $context['dependency_handles'] = $dependency_data['handles'];
210 $context['missing_dependencies'] = $dependency_data['missing'];
211
212 return $context;
213 }
214
215 /**
216 * Check if the current runtime context can be delayed.
217 *
218 * @param array $context Runtime context.
219 *
220 * @return bool
221 */
222 public function should_delay_core_gallery_template_script( &$context ) {
223 $should_delay = true;
224 $reason = '';
225
226 if ( ! $this->is_frontend_request() ) {
227 $should_delay = false;
228 $reason = 'not_frontend';
229 } elseif ( empty( $context['gallery'] ) ) {
230 $should_delay = false;
231 $reason = 'missing_gallery';
232 } elseif ( 'foogallery' !== $context['lightbox'] ) {
233 $should_delay = false;
234 $reason = 'unsupported_lightbox';
235 } elseif ( $context['force_legacy_runtime_scripts'] ) {
236 $should_delay = false;
237 $reason = 'force_legacy_runtime_scripts';
238 } elseif ( $context['has_custom_js'] ) {
239 $should_delay = false;
240 $reason = 'custom_js';
241 } elseif ( $context['polyfills_enabled'] ) {
242 $should_delay = false;
243 $reason = 'polyfills';
244 } elseif ( $context['legacy_lazyload'] ) {
245 $should_delay = false;
246 $reason = 'legacy_lazyload';
247 } elseif ( ! empty( $context['missing_dependencies'] ) ) {
248 $should_delay = false;
249 $reason = 'missing_dependencies';
250 } elseif ( ! $this->dependencies_are_allowed( $context ) ) {
251 $should_delay = false;
252 $reason = 'unsupported_dependencies';
253 } elseif ( array( self::CORE_HANDLE ) !== array_values( $context['feature_deps'] ) ) {
254 $should_delay = false;
255 $reason = 'feature_dependencies';
256 } elseif ( $this->has_addon_dependencies( $context ) ) {
257 $should_delay = false;
258 $reason = 'addon_dependencies';
259 }
260
261 $context['fallback_reason'] = $reason;
262 $filtered_should_delay = (bool) apply_filters( 'foogallery_delay_core_gallery_script_until_window_load', $should_delay, $context );
263
264 if ( $should_delay && ! $filtered_should_delay && '' === $context['fallback_reason'] ) {
265 $context['fallback_reason'] = 'filter_disabled';
266 }
267
268 return $should_delay && $filtered_should_delay;
269 }
270
271 /**
272 * Schedule the delayed runtime loader for the footer.
273 *
274 * @param array $context Runtime context.
275 *
276 * @return void
277 */
278 public function schedule_delayed_core_gallery_template_script( $context ) {
279 $this->register_runtime_handles( $context );
280 do_action( 'foogallery_enqueue_script-core', $context['js'] );
281
282 $this->context = $context;
283 $this->scheduled = true;
284
285 if ( ! has_action( 'wp_footer', array( $this, 'print_delayed_core_gallery_template_script' ) ) ) {
286 add_action( 'wp_footer', array( $this, 'print_delayed_core_gallery_template_script' ), 100 );
287 }
288 }
289
290 /**
291 * Cancel a previously scheduled delayed runtime.
292 *
293 * @return void
294 */
295 public function cancel_delayed_core_gallery_template_script() {
296 remove_action( 'wp_footer', array( $this, 'print_delayed_core_gallery_template_script' ), 100 );
297
298 if ( $this->scheduled ) {
299 $this->reset_core_handle();
300 }
301
302 $this->scheduled = false;
303 $this->context = null;
304 }
305
306 /**
307 * Print the delayed runtime loader.
308 *
309 * @return void
310 */
311 public function print_delayed_core_gallery_template_script() {
312 if ( ! $this->scheduled || ! is_array( $this->context ) ) {
313 return;
314 }
315
316 $items = $this->build_delayed_loader_items( $this->context );
317
318 if ( empty( $items ) ) {
319 return;
320 }
321
322 $payload = wp_json_encode( $items );
323 if ( false === $payload ) {
324 return;
325 }
326
327 ob_start();
328 ?>
329 (function(items){
330 var loader = document.currentScript;
331 var nonce = loader ? (loader.nonce || loader.getAttribute("nonce") || "") : "";
332 function applyNonce(script){
333 if (nonce) {
334 script.setAttribute("nonce", nonce);
335 }
336 }
337 function runInline(code){
338 var script = document.createElement("script");
339 applyNonce(script);
340 script.text = code;
341 document.body.appendChild(script).parentNode.removeChild(script);
342 }
343 function reportFailure(item){
344 var event;
345 if (window.console && window.console.error) {
346 window.console.error("FooGallery delayed runtime failed to load: " + item.src);
347 }
348 try {
349 event = new CustomEvent("foogallery-runtime-error", { detail: item });
350 } catch (error) {
351 event = document.createEvent("CustomEvent");
352 event.initCustomEvent("foogallery-runtime-error", false, false, item);
353 }
354 document.dispatchEvent(event);
355 }
356 function loadScript(item, done){
357 if (item.handle === "jquery-core" && window.jQuery) {
358 done();
359 return;
360 }
361 var attempts = 0;
362 function attempt(){
363 var script = document.createElement("script");
364 attempts += 1;
365 applyNonce(script);
366 script.src = item.src;
367 script.async = false;
368 script.onload = done;
369 script.onerror = function(){
370 if (script.parentNode) {
371 script.parentNode.removeChild(script);
372 }
373 if (attempts < 2) {
374 window.setTimeout(attempt, 250);
375 return;
376 }
377 reportFailure(item);
378 };
379 document.body.appendChild(script);
380 }
381 attempt();
382 }
383 function next(index){
384 var item;
385 if (index >= items.length) {
386 return;
387 }
388 item = items[index];
389 if (item.type === "inline") {
390 runInline(item.code);
391 next(index + 1);
392 return;
393 }
394 loadScript(item, function(){
395 next(index + 1);
396 });
397 }
398 function start(){
399 next(0);
400 }
401 if (document.readyState === "complete") {
402 start();
403 } else {
404 window.addEventListener("load", start, { once: true });
405 }
406 })(<?php echo $payload; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>);
407 <?php
408 $loader_script = trim( ob_get_clean() );
409 $attributes = array( 'id' => self::DELAYED_LOADER_ID );
410
411 if ( function_exists( 'wp_get_inline_script_tag' ) ) {
412 // phpcs:ignore -- Compatibility is guarded by function_exists().
413 echo wp_get_inline_script_tag( $loader_script, $attributes ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Core constructs and filters the complete script tag.
414 } else {
415 echo '<script id="' . esc_attr( self::DELAYED_LOADER_ID ) . '">' . $loader_script . '</script>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- The script is generated above from JSON-encoded registered assets.
416 }
417 }
418
419 /**
420 * Check for add-on dependency signals.
421 *
422 * @param array $context Runtime context.
423 *
424 * @return bool
425 */
426 public function has_addon_dependencies( $context ) {
427 if ( array( self::CORE_HANDLE ) !== array_values( $context['feature_deps'] ) ) {
428 return true;
429 }
430
431 if ( function_exists( 'foogallery_social_is_enabled_for_current_gallery' ) && foogallery_social_is_enabled_for_current_gallery() ) {
432 return true;
433 }
434
435 if ( (bool) apply_filters( 'foogallery_is_social_addon_active', false ) ) {
436 return true;
437 }
438
439 return false;
440 }
441
442 /**
443 * Enqueue the runtime using the normal WordPress path.
444 *
445 * @param array $context Runtime context.
446 *
447 * @return void
448 */
449 private function enqueue_normal_core_gallery_template_script( $context ) {
450 wp_enqueue_script( self::CORE_HANDLE, $context['js'], $context['deps'], FOOGALLERY_VERSION );
451 do_action( 'foogallery_enqueue_script-core', $context['js'] );
452
453 $feature_deps = $context['feature_deps'];
454
455 if ( $context['has_custom_js'] ) {
456 $custom_assets = get_option( FOOGALLERY_OPTION_CUSTOM_ASSETS );
457 if ( is_array( $custom_assets ) && array_key_exists( 'script', $custom_assets ) ) {
458 wp_enqueue_script( 'foogallery-custom', $custom_assets['script'], $feature_deps, FOOGALLERY_VERSION );
459 $feature_deps[] = 'foogallery-custom';
460 }
461 }
462
463 wp_enqueue_script( self::READY_HANDLE, $context['ready_src'], $feature_deps, FOOGALLERY_VERSION );
464 }
465
466 /**
467 * Register handles needed for inline script collection.
468 *
469 * @param array $context Runtime context.
470 *
471 * @return void
472 */
473 private function register_runtime_handles( $context ) {
474 wp_register_script( self::CORE_HANDLE, $context['js'], $context['deps'], FOOGALLERY_VERSION );
475 wp_register_script( self::READY_HANDLE, $context['ready_src'], array( self::CORE_HANDLE ), FOOGALLERY_VERSION );
476 }
477
478 /**
479 * Reset the core runtime handles and their inline state.
480 *
481 * @return void
482 */
483 private function reset_core_handle() {
484 wp_deregister_script( self::CORE_HANDLE );
485 wp_deregister_script( self::READY_HANDLE );
486 do_action( 'foogallery_dequeue_script-core' );
487 }
488
489 /**
490 * Build the delayed loader payload.
491 *
492 * @param array $context Runtime context.
493 *
494 * @return array
495 */
496 private function build_delayed_loader_items( $context ) {
497 $items = array();
498
499 foreach ( $context['dependency_assets'] as $asset ) {
500 if ( $this->script_handle_is_done( $asset['handle'] ) ) {
501 continue;
502 }
503 $this->append_inline_items( $items, $asset['handle'], 'before' );
504 $this->append_inline_items( $items, $asset['handle'], 'data' );
505 $items[] = array(
506 'type' => 'script',
507 'handle' => $asset['handle'],
508 'src' => esc_url_raw( $asset['src'] ),
509 );
510 $this->append_inline_items( $items, $asset['handle'], 'after' );
511 }
512
513 $this->append_inline_items( $items, self::CORE_HANDLE, 'before' );
514 $this->append_inline_items( $items, self::CORE_HANDLE, 'data' );
515 $items[] = array(
516 'type' => 'script',
517 'handle' => self::CORE_HANDLE,
518 'src' => esc_url_raw( $context['js'] ),
519 );
520 $this->append_inline_items( $items, self::CORE_HANDLE, 'after' );
521 $this->append_inline_items( $items, self::READY_HANDLE, 'before' );
522 $this->append_inline_items( $items, self::READY_HANDLE, 'data' );
523 $items[] = array(
524 'type' => 'script',
525 'handle' => self::READY_HANDLE,
526 'src' => esc_url_raw( $context['ready_src'] ),
527 );
528 $this->append_inline_items( $items, self::READY_HANDLE, 'after' );
529
530 return $items;
531 }
532
533 /**
534 * Append inline scripts for a handle.
535 *
536 * @param array $items Loader items.
537 * @param string $handle Script handle.
538 * @param string $key Inline script key.
539 *
540 * @return void
541 */
542 private function append_inline_items( &$items, $handle, $key ) {
543 $wp_scripts = wp_scripts();
544 $data = $wp_scripts->get_data( $handle, $key );
545
546 if ( empty( $data ) ) {
547 return;
548 }
549
550 if ( ! is_array( $data ) ) {
551 $data = array( $data );
552 }
553
554 foreach ( $data as $script ) {
555 if ( '' === trim( $script ) ) {
556 continue;
557 }
558 $items[] = array(
559 'type' => 'inline',
560 'handle' => $handle,
561 'code' => $script,
562 );
563 }
564 }
565
566 /**
567 * Check if dependency handles are safe to delay.
568 *
569 * @param array $context Runtime context.
570 *
571 * @return bool
572 */
573 private function dependencies_are_allowed( $context ) {
574 $allowed = apply_filters(
575 'foogallery_delayed_runtime_allowed_script_dependencies',
576 array( 'jquery-core', 'jquery', 'jquery-migrate', 'masonry', 'imagesloaded' ),
577 $context
578 );
579
580 if ( ! is_array( $allowed ) ) {
581 $allowed = array();
582 }
583
584 $allowed = array_unique( array_map( 'strval', $allowed ) );
585 $handles = array_unique( array_merge( $context['deps'], $context['dependency_handles'] ) );
586
587 foreach ( $handles as $handle ) {
588 if ( ! in_array( $handle, $allowed, true ) ) {
589 return false;
590 }
591 }
592
593 return true;
594 }
595
596 /**
597 * Resolve script dependency handles to loadable assets.
598 *
599 * @param string[] $deps Script dependencies.
600 *
601 * @return array
602 */
603 private function resolve_dependency_assets( $deps ) {
604 $wp_scripts = wp_scripts();
605 $assets = array();
606 $handles = array();
607 $missing = array();
608 $seen = array();
609
610 foreach ( $deps as $handle ) {
611 $this->resolve_dependency_asset( $handle, $wp_scripts, $assets, $handles, $missing, $seen );
612 }
613
614 return array(
615 'assets' => $assets,
616 'handles' => array_values( array_unique( $handles ) ),
617 'missing' => array_values( array_unique( $missing ) ),
618 );
619 }
620
621 /**
622 * Resolve one script dependency handle.
623 *
624 * @param string $handle Script handle.
625 * @param WP_Scripts $wp_scripts Scripts registry.
626 * @param array $assets Resolved assets.
627 * @param array $handles Resolved handles.
628 * @param array $missing Missing handles.
629 * @param array $seen Handles already visited.
630 *
631 * @return void
632 */
633 private function resolve_dependency_asset( $handle, $wp_scripts, &$assets, &$handles, &$missing, &$seen ) {
634 if ( isset( $seen[ $handle ] ) ) {
635 return;
636 }
637
638 $seen[ $handle ] = true;
639 $handles[] = $handle;
640
641 if ( ! isset( $wp_scripts->registered[ $handle ] ) ) {
642 $missing[] = $handle;
643 return;
644 }
645
646 $registered = $wp_scripts->registered[ $handle ];
647
648 if ( ! empty( $registered->deps ) ) {
649 foreach ( $registered->deps as $dependency ) {
650 $this->resolve_dependency_asset( $dependency, $wp_scripts, $assets, $handles, $missing, $seen );
651 }
652 }
653
654 if ( empty( $registered->src ) ) {
655 return;
656 }
657
658 $assets[] = array(
659 'handle' => $handle,
660 'src' => $this->script_src( $registered, $wp_scripts ),
661 );
662 }
663
664 /**
665 * Build a script URL from a registered script object.
666 *
667 * @param _WP_Dependency $registered Registered script.
668 * @param WP_Scripts $wp_scripts Scripts registry.
669 *
670 * @return string
671 */
672 private function script_src( $registered, $wp_scripts ) {
673 $src = $registered->src;
674
675 if ( ! preg_match( '|^(https?:)?//|', $src ) ) {
676 if ( 0 === strpos( $src, '/' ) ) {
677 $src = site_url( $src );
678 } else {
679 $src = $wp_scripts->base_url . $src;
680 }
681 }
682
683 if ( null === $registered->ver ) {
684 return $src;
685 }
686
687 $ver = $registered->ver ? $registered->ver : $wp_scripts->default_version;
688 if ( $ver ) {
689 $src = add_query_arg( 'ver', $ver, $src );
690 }
691
692 return $src;
693 }
694
695 /**
696 * Check if the current request can safely print a delayed frontend loader.
697 *
698 * @return bool
699 */
700 private function is_frontend_request() {
701 if ( is_admin() ) {
702 return false;
703 }
704
705 if ( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() ) {
706 return false;
707 }
708
709 if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
710 return false;
711 }
712
713 if ( function_exists( 'wp_is_json_request' ) && wp_is_json_request() ) {
714 return false;
715 }
716
717 if ( defined( 'WP_CLI' ) && WP_CLI ) {
718 return false;
719 }
720
721 if ( function_exists( 'is_feed' ) && did_action( 'wp' ) && is_feed() ) {
722 return false;
723 }
724
725 return true;
726 }
727
728 /**
729 * Check if the current gallery is using legacy placeholder lazy loading.
730 *
731 * @param FooGallery|null $gallery The current gallery.
732 *
733 * @return bool
734 */
735 public function gallery_uses_legacy_lazyload( $gallery ) {
736 if ( ! is_object( $gallery ) ) {
737 return false;
738 }
739
740 if ( ! isset( $gallery->lazyload_support ) || true !== $gallery->lazyload_support ) {
741 return false;
742 }
743
744 if ( empty( $gallery->lazyload_enabled ) || ! empty( $gallery->lazyload_forced_disabled ) ) {
745 return false;
746 }
747
748 $legacy_mode = class_exists( 'FooGallery_LazyLoad' ) ? FooGallery_LazyLoad::MODE_LEGACY : 'legacy';
749 $mode = isset( $gallery->lazyload_mode ) ? $gallery->lazyload_mode : foogallery_get_setting( 'lazy_loading_mode', '' );
750
751 return $legacy_mode === $mode;
752 }
753
754 /**
755 * Normalize dependency handles.
756 *
757 * @param mixed $deps Dependency handles.
758 *
759 * @return array
760 */
761 private function normalize_dependencies( $deps ) {
762 if ( ! is_array( $deps ) ) {
763 $deps = array();
764 }
765
766 $normalized = array();
767 foreach ( $deps as $dep ) {
768 if ( is_string( $dep ) && '' !== $dep ) {
769 $normalized[] = $dep;
770 }
771 }
772
773 return array_values( array_unique( $normalized ) );
774 }
775
776 /**
777 * Check if a script handle has already printed.
778 *
779 * @param string $handle Script handle.
780 *
781 * @return bool
782 */
783 private function script_handle_is_done( $handle ) {
784 $wp_scripts = wp_scripts();
785
786 return is_array( $wp_scripts->done ) && in_array( $handle, $wp_scripts->done, true );
787 }
788 }
789 }
790