PluginProbe
Block Animations, Motion & Scroll Effects – Ghost Kit / trunk
Block Animations, Motion & Scroll Effects – Ghost Kit vtrunk
3.7.1 3.7.0 3.6.1 trunk 1.6.3 2.25.0 3.3.0 3.3.1 3.3.2 3.3.3 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.6.0
ghostkit / classes / class-assets.php

class-assets.php in Block Animations, Motion & Scroll Effects – Ghost Kit trunk, at classes/class-assets.php

849 lines 25.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Assets static and dynamic.
4 *
5 * @package ghostkit
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Class GhostKit_Assets
14 */
15 class GhostKit_Assets {
16 /**
17 * List with stored assets.
18 *
19 * @var array
20 */
21 private static $stored_assets = array(
22 'script' => array(),
23 'style' => array(),
24 'custom-css' => array(),
25 );
26
27 /**
28 * Already added custom assets in head.
29 *
30 * @var boolean
31 */
32 private static $already_added_custom_assets = false;
33
34 /**
35 * Already add styles.
36 *
37 * @var array
38 */
39 private static $already_added_styles = array();
40
41 /**
42 * List with assets to skip from Autoptimize when CSS generated.
43 *
44 * @var array
45 */
46 protected static $skip_from_autoptimize = array(
47 'ghostkit-blocks-content-custom-css',
48 'ghostkit-blocks-widget-custom-css',
49 );
50
51 /**
52 * GhostKit_Assets constructor.
53 */
54 public function __construct() {
55 add_action( 'init', array( $this, 'register_scripts' ) );
56 add_filter( 'render_block', array( $this, 'render_block_enqueue_assets' ), 9, 2 );
57 add_action( 'plugins_loaded', array( $this, 'enqueue_scripts_action' ), 11 );
58 add_action( 'ghostkit_parse_blocks', array( $this, 'maybe_enqueue_blocks_assets' ), 11, 2 );
59 add_action( 'wp_enqueue_scripts', array( $this, 'add_custom_assets' ), 100 );
60
61 add_action( 'autoptimize_filter_css_exclude', 'GhostKit_Assets::autoptimize_filter_css_exclude' );
62
63 // enqueue runtime.
64 add_action( 'enqueue_block_editor_assets', 'GhostKit_Assets::enqueue_runtime', 11 );
65 add_action( 'wp_enqueue_scripts', 'GhostKit_Assets::enqueue_runtime', 8 );
66 }
67
68 /**
69 * Check if Webpack HMR file available.
70 *
71 * @return boolean
72 */
73 public static function is_webpack_hmr_support() {
74 return file_exists( ghostkit()->plugin_path . 'build/runtime.js' );
75 }
76
77 /**
78 * Enqueue runtime script.
79 */
80 public static function enqueue_runtime() {
81 // HMR Webpack.
82 if ( self::is_webpack_hmr_support() ) {
83 self::enqueue_script( 'ghostkit-runtime', 'build/runtime', array(), null, false );
84 }
85 }
86
87 /**
88 * Get .asset.php file data.
89 *
90 * @param string $filepath asset file path.
91 * @param string $filetype asset file type [style|script].
92 *
93 * @return array
94 */
95 public static function get_asset_file( $filepath, $filetype = '' ) {
96 $asset_path = ghostkit()->plugin_path . str_replace( '.min', '', $filepath ) . '.asset.php';
97
98 if ( file_exists( $asset_path ) ) {
99 // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude.FileIncludeFound
100 return include $asset_path;
101 } elseif ( ! empty( $filetype ) ) {
102 $file_ext = 'style' === $filetype ? 'css' : 'js';
103 $full_file_path = ghostkit()->plugin_path . $filepath . '.' . $file_ext;
104 $file_version = file_exists( $full_file_path ) ? filemtime( $full_file_path ) : null;
105 }
106
107 return array(
108 'dependencies' => array(),
109 'version' => $file_version ?? GHOSTKIT_VERSION,
110 );
111 }
112
113 /**
114 * Register script.
115 *
116 * @param string $name asset name.
117 * @param string $path file path.
118 * @param array $dependencies asset dependencies.
119 * @param string $version asset version.
120 * @param boolean $in_footer render in footer.
121 */
122 public static function register_script( $name, $path, $dependencies = array(), $version = null, $in_footer = true ) {
123 global $current_screen;
124
125 $script_data = self::get_asset_file( $path, 'script' );
126
127 if ( ! empty( $dependencies ) ) {
128 $script_data['dependencies'] = array_unique(
129 array_merge(
130 $script_data['dependencies'],
131 $dependencies
132 )
133 );
134 }
135
136 // Fix for Widgets screen.
137 if ( isset( $current_screen->id ) && 'widgets' === $current_screen->id ) {
138 foreach ( array( 'wp-edit-post', 'wp-editor' ) as $skip ) {
139 $key = array_search( $skip, $script_data['dependencies'], true );
140
141 if ( false !== $key ) {
142 unset( $script_data['dependencies'][ $key ] );
143 }
144 }
145 }
146
147 wp_register_script(
148 $name,
149 ghostkit()->plugin_url . $path . '.js',
150 $script_data['dependencies'],
151 $version ?? $script_data['version'],
152 $in_footer
153 );
154 }
155
156 /**
157 * Enqueue script.
158 *
159 * @param string $name asset name.
160 * @param string $path file path.
161 * @param array $dependencies asset dependencies.
162 * @param string $version asset version.
163 * @param boolean $in_footer render in footer.
164 */
165 public static function enqueue_script( $name, $path, $dependencies = array(), $version = null, $in_footer = true ) {
166 self::register_script( $name, $path, $dependencies, $version, $in_footer );
167
168 wp_enqueue_script( $name );
169 }
170
171 /**
172 * Register style
173 *
174 * @param string $name asset name.
175 * @param string $path file path.
176 * @param array $dependencies asset dependencies.
177 * @param string $version asset version.
178 */
179 public static function register_style( $name, $path, $dependencies = array(), $version = null ) {
180 $style_data = self::get_asset_file( $path, 'style' );
181
182 wp_register_style(
183 $name,
184 ghostkit()->plugin_url . $path . '.css',
185 $dependencies,
186 $version ?? $style_data['version']
187 );
188 }
189
190 /**
191 * Enqueue style
192 *
193 * @param string $name asset name.
194 * @param string $path file path.
195 * @param array $dependencies asset dependencies.
196 * @param string $version asset version.
197 */
198 public static function enqueue_style( $name, $path, $dependencies = array(), $version = null ) {
199 self::register_style( $name, $path, $dependencies, $version );
200
201 wp_enqueue_style( $name );
202 }
203
204 /**
205 * Store used assets, so we can enqueue it later.
206 *
207 * @param string $name - asset name.
208 * @param bool|string $value - just enqueue flag or url to asset.
209 * @param string $type - assets type [script|style|custom-css].
210 * @param int $priority - asset enqueue priority.
211 */
212 public static function store_used_assets( $name, $value = true, $type = 'script', $priority = 10 ) {
213 if ( ! isset( self::$stored_assets[ $type ] ) ) {
214 return;
215 }
216
217 // We need to check for duplicate assets, which may be added because of custom locations.
218 // Sometimes custom CSS is duplicated in Astra or Blocksy themes.
219 if ( 'custom-css' === $type ) {
220 if ( in_array( $value, self::$already_added_styles, true ) ) {
221 return;
222 }
223 self::$already_added_styles[] = $value;
224 }
225
226 if ( isset( self::$stored_assets[ $type ][ $name ] ) ) {
227 if ( 'custom-css' === $type ) {
228 if ( ! self::$stored_assets[ $type ][ $name ]['value'] ) {
229 self::$stored_assets[ $type ][ $name ]['value'] = '';
230 }
231
232 self::$stored_assets[ $type ][ $name ]['value'] .= $value;
233 }
234
235 do_action( 'gkt_assets_store', $name, $value, $type, $priority );
236
237 return;
238 }
239
240 self::$stored_assets[ $type ][ $name ] = array(
241 'value' => $value,
242 'priority' => $priority,
243 );
244
245 do_action( 'gkt_assets_store', $name, $value, $type, $priority );
246 }
247
248 /**
249 * Enqueue stored assets.
250 *
251 * @param string $type - assets type [script|style|custom-css].
252 */
253 public static function enqueue_stored_assets( $type = 'script' ) {
254 if ( ! isset( self::$stored_assets[ $type ] ) || empty( self::$stored_assets[ $type ] ) ) {
255 return;
256 }
257
258 uasort(
259 self::$stored_assets[ $type ],
260 function ( $a, $b ) {
261 if ( $a === $b ) {
262 return 0;
263 }
264
265 if ( isset( $a['priority'] ) && isset( $b['priority'] ) ) {
266 return $a['priority'] < $b['priority'] ? -1 : 1;
267 }
268
269 return 0;
270 }
271 );
272
273 foreach ( self::$stored_assets[ $type ] as $name => $data ) {
274 if ( isset( $data['value'] ) && $data['value'] ) {
275 if ( 'script' === $type ) {
276 wp_enqueue_script( $name );
277 } elseif ( 'style' === $type ) {
278 wp_enqueue_style( $name );
279 } elseif ( 'custom-css' === $type ) {
280 self::add_custom_css( $name, $data['value'] );
281 }
282
283 self::$stored_assets[ $type ][ $name ]['value'] = false;
284 }
285 }
286 }
287
288 /**
289 * Enqueue assets for blocks.
290 *
291 * @param array $blocks - blocks array.
292 * @param string $location - blocks location [content,widget].
293 */
294 public static function enqueue( $blocks = array(), $location = 'content' ) {
295 if ( ! empty( $blocks ) && is_array( $blocks ) ) {
296 $detected_assets = GhostKit_Assets_Detector::detect_from_blocks( $blocks, 'parse' );
297 GhostKit_Assets_Detector::store_detected_assets( $detected_assets );
298 }
299
300 $blocks_css = '';
301
302 // Prepare blocks assets.
303 foreach ( $blocks as $block ) {
304 // Filter blocks custom CSS.
305 if ( isset( $block['blockName'] ) ) {
306 $custom_styles = apply_filters( 'gkt_block_custom_styles', '', $block );
307
308 if ( ! empty( $custom_styles ) ) {
309 if ( ! empty( $blocks_css ) ) {
310 $blocks_css .= ' ';
311 }
312
313 $blocks_css .= $custom_styles;
314 }
315 }
316 }
317
318 // Store custom CSS.
319 if ( ! empty( $blocks_css ) && $blocks_css ) {
320 self::store_used_assets( 'ghostkit-blocks-' . $location . '-custom-css', ghostkit()->replace_vars( $blocks_css ), 'custom-css' );
321 }
322 }
323
324 /**
325 * Enqueue extension, style-variant, and attr-based assets during block render.
326 *
327 * Block.json handles are detected at parse-time only; this callback covers
328 * attrs and rendered HTML markers (e.g. effects, list style variants).
329 *
330 * @param string $block_content rendered block content.
331 * @param array $block block data.
332 *
333 * @return string
334 */
335 public function render_block_enqueue_assets( $block_content, $block ) {
336 if ( ! is_array( $block ) ) {
337 return $block_content;
338 }
339
340 $content = is_string( $block_content ) ? $block_content : '';
341
342 $detected_assets = GhostKit_Assets_Detector::detect_from_block( $block, 'render', $content );
343 GhostKit_Assets_Detector::enqueue_detected_assets( $detected_assets );
344
345 return $block_content;
346 }
347
348 /**
349 * Enqueue scripts and styles actions.
350 * We need this to be used inside 'plugins_loaded' action to prevent conflicts with plugins and themes.
351 *
352 * 1. Enqueue plugins assets
353 * 2. Enqueue Ghost Kit assets
354 * 3. Enqueue theme assets
355 * 4. Enqueue Ghost Kit custom css
356 */
357 public function enqueue_scripts_action() {
358 add_action( 'wp_enqueue_scripts', array( $this, 'wp_enqueue_head_assets' ) );
359 add_action( 'wp_footer', array( $this, 'wp_enqueue_foot_assets' ) );
360
361 // Custom css with higher priority to overwrite theme styles.
362 add_action( 'wp_enqueue_scripts', array( $this, 'wp_enqueue_head_custom_assets' ), 11 );
363 add_action( 'wp_footer', array( $this, 'wp_enqueue_foot_custom_assets' ), 11 );
364 }
365
366 /**
367 * Register scripts that will be used in the future when portfolio will be printed.
368 */
369 public function register_scripts() {
370 $css_deps = array();
371 $js_deps = array( 'ghostkit-helper', 'ghostkit-event-fallbacks' );
372
373 do_action( 'gkt_before_assets_register' );
374
375 // Motion.
376 if ( apply_filters( 'gkt_enqueue_plugin_motion', true ) ) {
377 self::register_script( 'motion', 'assets/vendor/motion/dist/motion.min', array(), '11.15.0' );
378
379 $js_deps[] = 'motion';
380 }
381
382 // Ivent.
383 if ( apply_filters( 'gkt_enqueue_plugin_ivent', true ) ) {
384 self::register_script( 'ivent', 'assets/vendor/ivent/dist/ivent.min', array(), '0.2.0' );
385 }
386
387 // Jarallax.
388 if ( apply_filters( 'gkt_enqueue_plugin_jarallax', true ) ) {
389 self::register_script( 'jarallax', 'assets/vendor/jarallax/dist/jarallax.min', array(), '3.1.0' );
390 self::register_script( 'jarallax-video', 'assets/vendor/jarallax/dist/jarallax-video.min', array( 'jarallax' ), '3.1.0' );
391 }
392
393 // Swiper.
394 if ( apply_filters( 'gkt_enqueue_plugin_swiper', true ) ) {
395 // Add legacy swiper version in order to support Elementor plugin.
396 // https://wordpress.org/support/topic/visual-portfolio-elementor-issue/.
397 if ( class_exists( '\Elementor\Plugin' ) ) {
398 self::register_style( 'swiper', 'assets/vendor/swiper-5-4-5/swiper.min', array(), '5.4.5' );
399 self::register_script( 'swiper', 'assets/vendor/swiper-5-4-5/swiper.min', array(), '5.4.5' );
400 } else {
401 self::register_style( 'swiper', 'assets/vendor/swiper/swiper-bundle.min', array(), '8.4.6' );
402 self::register_script( 'swiper', 'assets/vendor/swiper/swiper-bundle.min', array(), '8.4.6' );
403 }
404 }
405
406 // Luxon.
407 if ( apply_filters( 'gkt_enqueue_plugin_luxon', true ) ) {
408 self::register_script( 'luxon', 'assets/vendor/luxon/build/global/luxon.min', array(), '3.3.0' );
409 }
410
411 // Lottie Player.
412 if ( apply_filters( 'gkt_enqueue_plugin_lottie_player', true ) ) {
413 self::register_script( 'lottie-player', 'assets/vendor/lottie-player/dist/lottie-player', array(), '2.0.12' );
414 wp_script_add_data( 'lottie-player', 'async', true );
415 }
416
417 // GistEmbed.
418 if ( apply_filters( 'gkt_enqueue_plugin_gist_simple', true ) ) {
419 self::register_style( 'gist-simple', 'assets/vendor/gist-simple/dist/gist-simple', array(), '2.1.0' );
420 self::register_script( 'gist-simple', 'assets/vendor/gist-simple/dist/gist-simple.min', array(), '2.1.0' );
421 }
422
423 // Google reCaptcha.
424 $recaptcha_site_key = get_option( 'ghostkit_google_recaptcha_api_site_key' );
425 $recaptcha_secret_key = get_option( 'ghostkit_google_recaptcha_api_secret_key' );
426
427 if ( apply_filters( 'gkt_enqueue_google_recaptcha', true ) && $recaptcha_site_key && $recaptcha_secret_key ) {
428 wp_register_script( 'google-recaptcha', 'https://www.google.com/recaptcha/api.js?render=' . esc_attr( $recaptcha_site_key ), array(), '3.0.0', true );
429 }
430
431 // Get all sidebars.
432 $sidebars = array();
433 if ( ! empty( $GLOBALS['wp_registered_sidebars'] ) ) {
434 foreach ( $GLOBALS['wp_registered_sidebars'] as $k => $sidebar ) {
435 $sidebars[ $k ] = array(
436 'id' => $sidebar['id'],
437 'name' => $sidebar['name'],
438 );
439 }
440 }
441
442 // helper script.
443 self::register_script(
444 'ghostkit-helper',
445 'build/assets/js/helper',
446 array( 'ivent' )
447 );
448
449 // Google Maps prepare localization as in WordPress settings.
450 $gmaps_locale = get_locale();
451 $gmaps_suffix = '.com';
452 switch ( $gmaps_locale ) {
453 case 'he_IL':
454 // Hebrew correction.
455 $gmaps_locale = 'iw';
456 break;
457 case 'zh_CN':
458 // Chinese integration.
459 $gmaps_suffix = '.cn';
460 break;
461 }
462 $gmaps_locale = substr( $gmaps_locale, 0, 2 );
463
464 $theme_data = wp_get_theme( get_template() );
465
466 $breakpoints = GhostKit_Breakpoints::get_breakpoints();
467
468 $timezone = wp_timezone_string();
469
470 if ( substr( $timezone, 0, 1 ) === '+' || substr( $timezone, 0, 1 ) === '-' ) {
471 $timezone = 'UTC' . $timezone;
472 }
473
474 $global_data = array(
475 'version' => GHOSTKIT_VERSION,
476 'pro' => false,
477
478 'themeName' => $theme_data->get( 'Name' ),
479 'settings' => get_option( 'ghostkit_settings', array() ),
480 'disabledBlocks' => get_option( 'ghostkit_disabled_blocks', array() ),
481
482 // TODO: Due to different formats in scss and assets there is an offset.
483 'media_sizes' => array(
484 'sm' => $breakpoints['xs'],
485 'md' => $breakpoints['sm'],
486 'lg' => $breakpoints['md'],
487 'xl' => $breakpoints['lg'],
488 ),
489 'timezone' => $timezone,
490 'googleMapsAPIKey' => get_option( 'ghostkit_google_maps_api_key' ),
491 'googleMapsAPIUrl' => 'https://maps.googleapis' . $gmaps_suffix . '/maps/api/js?v=3.exp&language=' . esc_attr( $gmaps_locale ),
492 'googleReCaptchaAPISiteKey' => $recaptcha_site_key,
493 'googleReCaptchaAPISecretKey' => is_admin() ? $recaptcha_secret_key : '',
494 'sidebars' => $sidebars,
495 'icons' => is_admin() ? apply_filters( 'gkt_icons_list', array() ) : array(),
496 'shapes' => is_admin() ? apply_filters( 'gkt_shapes_list', array() ) : array(),
497 'fonts' => is_admin() ? apply_filters( 'gkt_fonts_list', array() ) : array(),
498 'customTypographyList' => is_admin() ? apply_filters( 'gkt_custom_typography', array() ) : array(),
499 'admin_url' => admin_url(),
500 'admin_templates_url' => admin_url( 'edit.php?post_type=ghostkit_template' ),
501 );
502
503 $global_data = apply_filters( 'gkt_global_data', $global_data );
504
505 wp_localize_script(
506 'ghostkit-helper',
507 'ghostkitVariables',
508 $global_data
509 );
510
511 // events fallback script.
512 self::register_script(
513 'ghostkit-event-fallbacks',
514 'build/assets/js/event-fallbacks',
515 array( 'ghostkit-helper' )
516 );
517
518 // Fallback for classic themes.
519 if ( ! wp_is_block_theme() ) {
520 self::register_style(
521 'ghostkit-classic-theme-fallback',
522 'assets/css/fallback-classic-theme'
523 );
524 $css_deps[] = 'ghostkit-classic-theme-fallback';
525 }
526
527 // Ghost Kit.
528 self::register_style(
529 'ghostkit',
530 'build/gutenberg/style',
531 $css_deps
532 );
533 wp_style_add_data( 'ghostkit', 'rtl', 'replace' );
534 wp_style_add_data( 'ghostkit', 'suffix', '.min' );
535
536 self::register_script(
537 'ghostkit',
538 'build/assets/js/main',
539 $js_deps
540 );
541
542 // Extensions.
543 foreach ( glob( ghostkit()->plugin_path . 'build/gutenberg/extend/*/frontend.js' ) as $file ) {
544 $ext_name = basename( dirname( $file ) );
545 $ext_script_url = 'build/gutenberg/extend/' . $ext_name . '/frontend';
546 $ext_js_deps = array( 'ghostkit' );
547
548 switch ( $ext_name ) {
549 case 'effects':
550 $ext_js_deps[] = 'motion';
551 break;
552 }
553
554 self::register_script(
555 'ghostkit-extension-' . $ext_name,
556 $ext_script_url,
557 array_unique( $ext_js_deps )
558 );
559 }
560
561 // Style Variants.
562 foreach ( glob( ghostkit()->plugin_path . 'build/gutenberg/style-variants/*/frontend.js' ) as $template ) {
563 $ext_name = basename( dirname( $template ) );
564 $ext_script_url = 'build/gutenberg/style-variants/' . $ext_name . '/frontend';
565 $ext_js_deps = array( 'ghostkit' );
566
567 self::register_script(
568 'ghostkit-style-variant-' . $ext_name,
569 $ext_script_url,
570 array_unique( $ext_js_deps )
571 );
572 }
573
574 // Blocks.
575 foreach ( glob( ghostkit()->plugin_path . 'build/gutenberg/blocks/*/frontend.js' ) as $file ) {
576 $block_name = basename( dirname( $file ) );
577 $block_script_url = 'build/gutenberg/blocks/' . $block_name . '/frontend';
578 $block_js_deps = array( 'ghostkit' );
579
580 switch ( $block_name ) {
581 case 'accordion':
582 case 'alert':
583 $block_js_deps[] = 'motion';
584 break;
585 case 'grid':
586 case 'grid-column':
587 if ( wp_script_is( 'jarallax-video' ) || wp_script_is( 'jarallax-video', 'registered' ) ) {
588 $block_js_deps[] = 'jarallax-video';
589 }
590 if ( wp_script_is( 'jarallax' ) || wp_script_is( 'jarallax', 'registered' ) ) {
591 $block_js_deps[] = 'jarallax';
592 }
593 break;
594 case 'video':
595 if ( wp_script_is( 'jarallax-video' ) || wp_script_is( 'jarallax-video', 'registered' ) ) {
596 $block_js_deps[] = 'jarallax-video';
597 }
598 break;
599 case 'gist':
600 if ( wp_script_is( 'gist-simple' ) || wp_script_is( 'gist-simple', 'registered' ) ) {
601 $block_js_deps[] = 'gist-simple';
602 }
603 break;
604 case 'carousel':
605 if ( wp_script_is( 'swiper' ) || wp_script_is( 'swiper', 'registered' ) ) {
606 $block_js_deps[] = 'swiper';
607 }
608 break;
609 case 'countdown':
610 $block_js_deps[] = 'luxon';
611 break;
612 case 'form':
613 if ( wp_script_is( 'google-recaptcha' ) || wp_script_is( 'google-recaptcha', 'registered' ) ) {
614 $block_js_deps[] = 'google-recaptcha';
615 }
616 $block_js_deps[] = 'wp-i18n';
617 break;
618 case 'lottie':
619 $block_js_deps[] = 'motion';
620 $block_js_deps[] = 'lottie-player';
621 break;
622 case 'tabs':
623 $block_name = 'tabs-v2';
624 break;
625 }
626
627 self::register_script(
628 'ghostkit-block-' . $block_name,
629 $block_script_url,
630 array_unique( $block_js_deps )
631 );
632 }
633 foreach ( glob( ghostkit()->plugin_path . 'build/gutenberg/blocks/*/styles/style.css' ) as $file ) {
634 $block_name = basename( dirname( $file, 2 ) );
635 $block_style_url = 'build/gutenberg/blocks/' . $block_name . '/styles/style';
636 $block_css_deps = array( 'ghostkit' );
637
638 switch ( $block_name ) {
639 case 'gist':
640 $block_css_deps[] = 'gist-simple';
641 break;
642 case 'carousel':
643 $block_css_deps[] = 'swiper';
644 break;
645 case 'tabs':
646 $block_name = 'tabs-v2';
647 break;
648 }
649
650 self::register_style(
651 'ghostkit-block-' . $block_name,
652 $block_style_url,
653 array_unique( $block_css_deps )
654 );
655 wp_style_add_data( 'ghostkit-block-' . $block_name, 'rtl', 'replace' );
656 wp_style_add_data( 'ghostkit-block-' . $block_name, 'suffix', '.min' );
657 }
658
659 do_action( 'gkt_after_assets_register' );
660 }
661
662 /**
663 * Enqueue styles in head.
664 */
665 public function wp_enqueue_head_assets() {
666 self::enqueue_stored_assets( 'style' );
667 self::enqueue_stored_assets( 'script' );
668 }
669
670 /**
671 * Enqueue custom styles in head.
672 */
673 public function wp_enqueue_head_custom_assets() {
674 self::enqueue_stored_assets( 'custom-css' );
675 }
676
677 /**
678 * Enqueue scripts and styles in foot.
679 */
680 public function wp_enqueue_foot_assets() {
681 self::enqueue_stored_assets( 'style' );
682 self::enqueue_stored_assets( 'script' );
683 }
684
685 /**
686 * Enqueue custom styles in foot.
687 */
688 public function wp_enqueue_foot_custom_assets() {
689 self::enqueue_stored_assets( 'custom-css' );
690 }
691
692 /**
693 * Enqueue blocks assets.
694 *
695 * @param array $blocks - blocks array.
696 * @param array $location - blocks location [content,widget].
697 */
698 public function maybe_enqueue_blocks_assets( $blocks, $location ) {
699 if ( self::$already_added_custom_assets ) {
700 $location = 'widget';
701 }
702
703 self::enqueue( $blocks, $location );
704 }
705
706 /**
707 * Add styles from blocks to the head section.
708 *
709 * @param int $post_id - current post id.
710 */
711 public function add_custom_assets( $post_id ) {
712 $global_code = get_option( 'ghostkit_custom_code', array() );
713
714 if ( is_singular() && ! $post_id ) {
715 $post_id = get_the_ID();
716 }
717
718 $is_single = is_singular() && $post_id;
719
720 // Global custom CSS.
721 if ( $global_code && isset( $global_code['ghostkit_custom_css'] ) && $global_code['ghostkit_custom_css'] ) {
722 self::add_custom_css( 'ghostkit-global-custom-css', $global_code['ghostkit_custom_css'] );
723 }
724
725 // Local custom CSS.
726 if ( $is_single ) {
727 $meta_css = get_post_meta( $post_id, 'ghostkit_custom_css', true );
728
729 if ( ! empty( $meta_css ) ) {
730 self::add_custom_css( 'ghostkit-custom-css', $meta_css );
731 }
732 }
733
734 // Global custom JS head.
735 if ( $global_code && isset( $global_code['ghostkit_custom_js_head'] ) && $global_code['ghostkit_custom_js_head'] ) {
736 self::add_custom_js( 'ghostkit-global-custom-js-head', $global_code['ghostkit_custom_js_head'] );
737 }
738
739 // Local custom JS head.
740 if ( $is_single ) {
741 $meta_js_head = get_post_meta( $post_id, 'ghostkit_custom_js_head', true );
742
743 if ( ! empty( $meta_js_head ) ) {
744 self::add_custom_js( 'ghostkit-custom-js-head', $meta_js_head );
745 }
746 }
747
748 // Global custom JS foot.
749 if ( $global_code && isset( $global_code['ghostkit_custom_js_foot'] ) && $global_code['ghostkit_custom_js_foot'] ) {
750 self::add_custom_js( 'ghostkit-global-custom-js-foot', $global_code['ghostkit_custom_js_foot'], true );
751 }
752
753 // Local custom JS foot.
754 if ( $is_single ) {
755 $meta_js_foot = get_post_meta( $post_id, 'ghostkit_custom_js_foot', true );
756
757 if ( ! empty( $meta_js_foot ) ) {
758 self::add_custom_js( 'ghostkit-custom-js-foot', $meta_js_foot, true );
759 }
760 }
761
762 self::$already_added_custom_assets = true;
763 }
764
765 /**
766 * Skip custom styles from Autoptimize.
767 * We need this since generated CSS with custom breakpoints are excluded
768 * from Autoptimize by default and this cause conflicts.
769 *
770 * @param string $result - allowed list.
771 * @return string
772 */
773 public static function autoptimize_filter_css_exclude( $result ) {
774 $upload_dir = defined( 'UPLOADS' ) ? UPLOADS : 'wp-content/uploads/';
775
776 // By default in Autoptimize excluded folder `wp-content/uploads/`.
777 // We need to check, if this folder is not excluded, then we
778 // don't need to use our hack.
779 if ( $result && strpos( $result, $upload_dir ) === false ) {
780 return $result;
781 }
782
783 foreach ( self::$skip_from_autoptimize as $name ) {
784 if ( $result ) {
785 $result .= ',';
786 } else {
787 $result = '';
788 }
789
790 $result .= $name;
791 }
792
793 return $result;
794 }
795
796 /**
797 * Add custom CSS.
798 *
799 * @param string $name - handle name.
800 * @param string $css - code.
801 */
802 public static function add_custom_css( $name, $css ) {
803 if ( ! wp_style_is( $name, 'enqueued' ) ) {
804 $css = wp_kses( $css, array( '\'', '\"' ) );
805 $css = str_replace( '&gt;', '>', $css );
806
807 $allow_js_fallback = apply_filters( 'gkt_custom_css_allow_js_fallback', self::$already_added_custom_assets, $name, $css );
808
809 // Enqueue custom CSS.
810 if ( ! $allow_js_fallback ) {
811 wp_register_style( $name, false, array(), GHOSTKIT_VERSION );
812 wp_enqueue_style( $name );
813 wp_add_inline_style( $name, $css );
814
815 // Enqueue JS instead of CSS when rendering in <body> to prevent W3C errors.
816 } elseif ( ! wp_script_is( $name, 'enqueued' ) ) {
817 wp_register_script( $name, false, array(), GHOSTKIT_VERSION, true );
818 wp_enqueue_script( $name );
819 wp_add_inline_script(
820 $name,
821 '(function(){
822 var styleTag = document.createElement("style");
823 styleTag.id = "' . esc_attr( $name ) . '-inline-css";
824 styleTag.innerHTML = ' . wp_json_encode( $css ) . ';
825 document.body.appendChild(styleTag);
826 }());'
827 );
828 }
829 }
830
831 self::$stored_assets[] = $name;
832 }
833
834 /**
835 * Add custom JS.
836 *
837 * @param string $name - handle name.
838 * @param string $js - code.
839 * @param boolean $footer - print in footer.
840 */
841 public static function add_custom_js( $name, $js, $footer = false ) {
842 wp_register_script( $name, '', array(), GHOSTKIT_VERSION, $footer );
843 wp_enqueue_script( $name );
844 wp_add_inline_script( $name, $js );
845 }
846 }
847
848 new GhostKit_Assets();
849