PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.9.19.4
Pods – Custom Content Types and Fields v2.9.19.4
2.7.31.4 2.8.23.5 2.9.19.5 3.0.10.5 3.1.4.3 3.2.8.4 3.3.9.2 2.8.23.4 2.9.19.4 3.0.10.4 3.1.4.2 3.2.8.3 3.3.9.1 trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / tribe-common / src / Tribe / Assets.php
pods / tribe-common / src / Tribe Last commit date
Admin 2 weeks ago Ajax 2 weeks ago Asset 2 weeks ago Context 2 weeks ago Customizer 2 weeks ago Debug_Bar 2 weeks ago Dialog 2 weeks ago Documentation 2 weeks ago Duplicate 2 weeks ago Editor 2 weeks ago Image 2 weeks ago JSON_LD 2 weeks ago Languages 2 weeks ago Log 2 weeks ago Meta 2 weeks ago Models 2 weeks ago PUE 2 weeks ago Process 2 weeks ago Promoter 2 weeks ago REST 2 weeks ago Repository 2 weeks ago Service_Providers 2 weeks ago Shortcode 2 weeks ago Support 2 weeks ago Tabbed_View 2 weeks ago Tooltip 2 weeks ago Traits 2 weeks ago Utils 2 weeks ago Validator 2 weeks ago Widget 2 weeks ago Abstract_Deactivation.php 2 weeks ago Abstract_Plugin_Register.php 2 weeks ago App_Shop.php 2 weeks ago Assets.php 2 weeks ago Assets_Pipeline.php 2 weeks ago Autoloader.php 2 weeks ago Cache.php 2 weeks ago Cache_Listener.php 2 weeks ago Changelog_Reader.php 2 weeks ago Container.php 2 weeks ago Context.php 2 weeks ago Cost_Utils.php 2 weeks ago Credits.php 2 weeks ago Customizer.php 2 weeks ago DB_Lock.php 2 weeks ago Data.php 2 weeks ago Date_Utils.php 2 weeks ago Db.php 2 weeks ago Debug.php 2 weeks ago Dependency.php 2 weeks ago Deprecation.php 2 weeks ago Editor.php 2 weeks ago Error.php 2 weeks ago Exception.php 2 weeks ago Extension.php 2 weeks ago Extension_Loader.php 2 weeks ago Feature_Detection.php 2 weeks ago Field.php 2 weeks ago Field_Conditional.php 2 weeks ago Freemius.php 2 weeks ago Log.php 2 weeks ago Main.php 2 weeks ago Notices.php 2 weeks ago Plugin_Meta_Links.php 2 weeks ago Plugins.php 2 weeks ago Plugins_API.php 2 weeks ago Post_History.php 2 weeks ago Post_Transient.php 2 weeks ago Promise.php 2 weeks ago Repository.php 2 weeks ago Rewrite.php 2 weeks ago Settings.php 2 weeks ago Settings_Manager.php 2 weeks ago Settings_Tab.php 2 weeks ago Simple_Table.php 2 weeks ago Support.php 2 weeks ago Tabbed_View.php 2 weeks ago Template.php 2 weeks ago Template_Factory.php 2 weeks ago Template_Part_Cache.php 2 weeks ago Templates.php 2 weeks ago Terms.php 2 weeks ago Timezones.php 2 weeks ago Tracker.php 2 weeks ago Updater.php 2 weeks ago Validate.php 2 weeks ago View_Helpers.php 2 weeks ago
Assets.php
841 lines
1 <?php
2 /**
3 * Class used to register and enqueue assets across our plugins.
4 *
5 * @since 4.3
6 */
7 class Tribe__Assets {
8 /**
9 * Stores all the Assets and it's configurations.
10 *
11 * @var array
12 */
13 protected $assets = [];
14
15 /**
16 * Stores the localized scripts for reference.
17 *
18 * @var array
19 */
20 private $localized = [];
21
22 /**
23 * Static Singleton Factory Method.
24 *
25 * @since 4.3
26 *
27 * @return self
28 */
29 public static function instance() {
30 return tribe( 'assets' );
31 }
32
33 /**
34 * Register the Methods in the correct places.
35 *
36 * @since 4.3
37 */
38 public function __construct() {
39 // Hook the actual registering of.
40 add_action( 'init', [ $this, 'register_in_wp' ], 1, 0 );
41 add_filter( 'script_loader_tag', [ $this, 'filter_tag_async_defer' ], 50, 2 );
42
43 // Enqueue late.
44 add_filter( 'script_loader_tag', [ $this, 'filter_add_localization_data' ], 500, 2 );
45 }
46
47 /**
48 * Handles adding localization data, when attached to `script_loader_tag` which allows dependencies to load in their
49 * localization data as well.
50 *
51 * @since 4.13.0
52 *
53 * @param string $tag Tag we are filtering.
54 * @param string $handle Which is the ID/Handle of the tag we are about to print.
55 *
56 * @return string Script tag with the localization variable HTML attached to it.
57 */
58 public function filter_add_localization_data( $tag, $handle ) {
59 // Only filter for own own filters.
60 if ( ! $asset = $this->get( $handle ) ) {
61 return $tag;
62 }
63
64 // Bail when not dealing with JS assets.
65 if ( 'js' !== $asset->type ) {
66 return $tag;
67 }
68
69 // Only localize on JS and if we have data.
70 if ( empty( $asset->localize ) ) {
71 return $tag;
72 }
73
74 global $wp_scripts;
75
76 // Makes sure we have an Array of Localize data.
77 if ( is_object( $asset->localize ) ) {
78 $localization = [ $asset->localize ];
79 } else {
80 $localization = (array) $asset->localize;
81 }
82
83 /**
84 * Check to ensure we haven't already localized it before.
85 *
86 * @since 4.5.8
87 */
88 foreach ( $localization as $localize ) {
89 if ( in_array( $localize->name, $this->localized ) ) {
90 continue;
91 }
92
93 // If we have a Callable as the Localize data we execute it.
94 if ( is_callable( $localize->data ) ) {
95 $localize->data = call_user_func( $localize->data, $asset );
96 }
97
98 wp_localize_script( $asset->slug, $localize->name, $localize->data );
99
100 $this->localized[] = $localize->name;
101 }
102
103 // Fetch the HTML for all the localized data.
104 ob_start();
105 $wp_scripts->print_extra_script( $asset->slug, true );
106 $localization_html = ob_get_clean();
107
108 // After printing it remove data;|
109 $wp_scripts->add_data( $asset->slug, 'data', '' );
110
111 return $localization_html . $tag;
112 }
113
114 /**
115 * Filters the Script tags to attach Async and/or Defer based on the rules we set in our Asset class.
116 *
117 * @since 4.13.0
118 *
119 * @param string $tag Tag we are filtering.
120 * @param string $handle Which is the ID/Handle of the tag we are about to print.
121 *
122 * @return string Script tag with the defer and/or async attached.
123 */
124 public function filter_tag_async_defer( $tag, $handle ) {
125 // Only filter for own own filters.
126 if ( ! $asset = $this->get( $handle ) ) {
127 return $tag;
128 }
129
130 // Bail when not dealing with JS assets.
131 if ( 'js' !== $asset->type ) {
132 return $tag;
133 }
134
135 // When async and defer are false we bail with the tag.
136 if ( ! $asset->defer && ! $asset->async ) {
137 return $tag;
138 }
139
140 $tag_has_async = false !== strpos( $tag, ' async ' );
141 $tag_has_defer = false !== strpos( $tag, ' defer ' );
142 $replacement = '<script ';
143
144 if ( $asset->async && ! $tag_has_async ) {
145 $replacement .= 'async ';
146 }
147
148 if ( $asset->defer && ! $tag_has_defer ) {
149 $replacement .= 'defer ';
150 }
151
152 $replacement_src = $replacement . 'src=';
153 $replacement_type = $replacement . 'type=';
154
155 return str_replace( [ '<script src=', '<script type=' ], [ $replacement_src, $replacement_type ], $tag );
156 }
157
158 /**
159 * Register the Assets on the correct hooks.
160 *
161 * @since 4.3
162 *
163 * @return void
164 */
165 public function register_in_wp( $assets = null ) {
166 if ( is_null( $assets ) ) {
167 $assets = $this->get();
168 }
169
170 if ( ! is_array( $assets ) ) {
171 $assets = [ $assets ];
172 }
173
174 foreach ( $assets as $asset ) {
175 // Asset is already registered.
176 if ( $asset->is_registered ) {
177 continue;
178 }
179
180 if ( 'js' === $asset->type ) {
181 // Script is already registered.
182 if ( wp_script_is( $asset->slug, 'registered' ) ) {
183 continue;
184 }
185
186 wp_register_script( $asset->slug, $asset->url, $asset->deps, $asset->version, $asset->in_footer );
187
188 // Register that this asset is actually registered on the WP methods.
189 $asset->is_registered = wp_script_is( $asset->slug, 'registered' );
190 } else {
191 // Style is already registered.
192 if ( wp_style_is( $asset->slug, 'registered' ) ) {
193 continue;
194 }
195
196 wp_register_style( $asset->slug, $asset->url, $asset->deps, $asset->version, $asset->media );
197
198 // Register that this asset is actually registered on the WP methods.
199 $asset->is_registered = wp_style_is( $asset->slug, 'registered' );
200 }
201
202 // If we don't have an action we don't even register the action to enqueue.
203 if ( empty( $asset->action ) ) {
204 continue;
205 }
206
207 // Now add an action to enqueue the registered assets.
208 foreach ( (array) $asset->action as $action ) {
209 // Enqueue the registered assets at the appropriate time.
210 if ( did_action( $action ) > 0 ) {
211 $this->enqueue();
212 } else {
213 add_action( $action, [ $this, 'enqueue' ], $asset->priority, 0 );
214 }
215 }
216 }
217 }
218
219 /**
220 * Enqueues registered assets based on their groups.
221 *
222 * @since 4.7
223 *
224 * @uses Tribe__Assets::enqueue()
225 *
226 * @param string|array $groups Which groups will be enqueued.
227 */
228 public function enqueue_group( $groups ) {
229 $assets = $this->get( null, false );
230 $enqueue = [];
231
232 foreach ( $assets as $asset ) {
233 if ( empty( $asset->groups ) ) {
234 continue;
235 }
236
237 $intersect = array_intersect( (array) $groups, $asset->groups );
238
239 if ( empty( $intersect ) ) {
240 continue;
241 }
242 $enqueue[] = $asset->slug;
243 }
244
245 $this->enqueue( $enqueue );
246 }
247
248 /**
249 * Enqueues registered assets.
250 *
251 * This method is called on whichever action (if any) was declared during registration.
252 *
253 * It can also be called directly with a list of asset slugs to forcibly enqueue, which may be
254 * useful where an asset is required in a situation not anticipated when it was originally
255 * registered.
256 *
257 * @since 4.3
258 *
259 * @param string|array $forcibly_enqueue
260 */
261 public function enqueue( $forcibly_enqueue = null ) {
262 $forcibly_enqueue = array_filter( (array) $forcibly_enqueue );
263 if ( ! empty( $forcibly_enqueue ) ) {
264 $assets = (array) $this->get( $forcibly_enqueue );
265 } else {
266 $assets = $this->get();
267 }
268
269 foreach ( $assets as $asset ) {
270 // Should this asset be enqueued regardless of the current filter/any conditional requirements?
271 $must_enqueue = in_array( $asset->slug, $forcibly_enqueue );
272 $in_filter = in_array( current_filter(), (array) $asset->action );
273
274 // Skip if we are not on the correct filter (unless we are forcibly enqueuing).
275 if ( ! $in_filter && ! $must_enqueue ) {
276 continue;
277 }
278
279 // If any single conditional returns true, then we need to enqueue the asset.
280 if ( empty( $asset->action ) && ! $must_enqueue ) {
281 continue;
282 }
283
284 // If this asset was late called
285 if ( ! $asset->is_registered ) {
286 $this->register_in_wp( $asset );
287 }
288
289 // Default to enqueuing the asset if there are no conditionals,
290 // and default to not enqueuing it if there *are* conditionals.
291 $enqueue = empty( $asset->conditionals );
292
293 if ( ! $enqueue ) {
294 // Reset Enqueue.
295 $enqueue = [];
296
297 // Which is the operator?
298 $conditional_operator = Tribe__Utils__Array::get( $asset->conditionals, 'operator', 'OR' );
299
300 // If we have a set of conditionals we loop on then and get if they are true.
301 foreach ( $asset->conditionals as $key => $conditional ) {
302 // Avoid doing anything to the operator
303 if ( 'operator' === $key ) {
304 continue;
305 }
306
307 $enqueue[] = call_user_func( $conditional );
308 }
309
310 // By default we use OR for backwards compatibility.
311 if ( 'OR' === $conditional_operator ) {
312 $enqueue = in_array( true, $enqueue );
313 } else {
314 $enqueue = ! in_array( false, $enqueue );
315 }
316 }
317
318 /**
319 * Allows developers to hook-in and prevent an asset from being loaded.
320 *
321 * @since 4.3
322 *
323 * @param bool $enqueue If we should enqueue or not a given asset.
324 * @param object $asset Which asset we are dealing with.
325 */
326 $enqueue = apply_filters( 'tribe_asset_enqueue', $enqueue, $asset );
327
328 /**
329 * Allows developers to hook-in and prevent an asset from being loaded.
330 *
331 * @since 4.3
332 *
333 * @param bool $enqueue If we should enqueue or not a given asset.
334 * @param object $asset Which asset we are dealing with.
335 */
336 $enqueue = apply_filters( "tribe_asset_enqueue_{$asset->slug}", $enqueue, $asset );
337
338 if ( ! $enqueue && ! $must_enqueue ) {
339 continue;
340 }
341
342 if ( 'js' === $asset->type ) {
343 if ( $asset->print && ! $asset->already_printed ) {
344 $asset->already_printed = true;
345 wp_print_scripts( [ $asset->slug ] );
346 }
347 // We print first, and tell the system it was enqueued, WP is smart not to do it twice.
348 wp_enqueue_script( $asset->slug );
349
350 // If available, load the script translations.
351 if ( isset( $asset->translations['domain'], $asset->translations['path'] ) && function_exists( 'wp_set_script_translations' ) ) {
352 wp_set_script_translations( $asset->slug, $asset->translations['domain'], $asset->translations['path'] );
353 }
354 } else {
355 if ( $asset->print && ! $asset->already_printed ) {
356 $asset->already_printed = true;
357 wp_print_styles( [ $asset->slug ] );
358 }
359 // We print first, and tell the system it was enqueued, WP is smart not to do it twice.
360 wp_enqueue_style( $asset->slug );
361 }
362
363 if ( ! empty( $asset->after_enqueue ) && is_callable( $asset->after_enqueue ) ) {
364 call_user_func_array( $asset->after_enqueue, [ $asset ] );
365 }
366
367 $asset->already_enqueued = true;
368 }
369 }
370
371 /**
372 * Returns the path to a minified version of a js or css file, if it exists.
373 * If the file does not exist, returns false.
374 *
375 * @since 4.3
376 * @since 4.5.10 Removed ability to pass a filepath as $url
377 *
378 * @param string $url The absolute URL to the un-minified file.
379 *
380 * @return string|false The url to the minified version or false, if file not found.
381 */
382 public static function maybe_get_min_file( $url ) {
383 static $wpmu_plugin_url;
384 static $wp_plugin_url;
385 static $wp_content_url;
386 static $plugins_url;
387 static $base_dirs;
388
389 $urls = [];
390 if ( ! isset( $wpmu_plugin_url ) ) {
391 $wpmu_plugin_url = set_url_scheme( WPMU_PLUGIN_URL );
392 }
393
394 if ( ! isset( $wp_plugin_url ) ) {
395 $wp_plugin_url = set_url_scheme( WP_PLUGIN_URL );
396 }
397
398 if ( ! isset( $wp_content_url ) ) {
399 $wp_content_url = set_url_scheme( WP_CONTENT_URL );
400 }
401
402 if ( ! isset( $plugins_url ) ) {
403 $plugins_url = plugins_url();
404 }
405
406 if ( ! isset( $base_dirs ) ) {
407 $base_dirs[ WPMU_PLUGIN_DIR ] = wp_normalize_path( WPMU_PLUGIN_DIR );
408 $base_dirs[ WP_PLUGIN_DIR ] = wp_normalize_path( WP_PLUGIN_DIR );
409 $base_dirs[ WP_CONTENT_DIR ] = wp_normalize_path( WP_CONTENT_DIR );
410 }
411
412 if ( 0 === strpos( $url, $wpmu_plugin_url ) ) {
413 // URL inside WPMU plugin dir.
414 $base_dir = $base_dirs[ WPMU_PLUGIN_DIR ];
415 $base_url = $wpmu_plugin_url;
416 } elseif ( 0 === strpos( $url, $wp_plugin_url ) ) {
417 // URL inside WP plugin dir.
418 $base_dir = $base_dirs[ WP_PLUGIN_DIR ];
419 $base_url = $wp_plugin_url;
420 } elseif ( 0 === strpos( $url, $wp_content_url ) ) {
421 // URL inside WP content dir.
422 $base_dir = $base_dirs[ WP_CONTENT_DIR ];
423 $base_url = $wp_content_url;
424 } elseif ( 0 === strpos( $url, $plugins_url ) ) {
425 $base_dir = $base_dirs[ WP_PLUGIN_DIR ];
426 $base_url = $plugins_url;
427 } else {
428 // Resource needs to be inside wp-content or a plugins dir.
429 return false;
430 }
431
432 $script_debug = defined( 'SCRIPT_DEBUG' ) && tribe_is_truthy( SCRIPT_DEBUG );
433
434 // Strip the plugin URL and make this relative.
435 $relative_location = str_replace( $base_url, '', $url );
436
437 if ( $script_debug ) {
438 // Add the actual url after having the min file added.
439 $urls[] = $relative_location;
440 }
441
442 // If needed add the Min Files.
443 if ( substr( $relative_location, -3, 3 ) === '.js' ) {
444 $urls[] = substr_replace( $relative_location, '.min', - 3, 0 );
445 } elseif ( substr( $relative_location, -4, 4 ) === '.css' ) {
446 $urls[] = substr_replace( $relative_location, '.min', - 4, 0 );
447 }
448
449 if ( ! $script_debug ) {
450 // Add the actual url after having the min file added.
451 $urls[] = $relative_location;
452 }
453
454 // Check for all Urls added to the array.
455 foreach ( $urls as $partial_path ) {
456 $file_path = wp_normalize_path( $base_dir . $partial_path );
457 $file_url = $base_url . $partial_path;
458
459 if ( file_exists( $file_path ) ) {
460 return $file_url;
461 }
462 }
463
464 // If we don't have any real file return false.
465 return false;
466 }
467
468 /**
469 * Register an Asset and attach a callback to the required action to display it correctly.
470 *
471 * @since 4.3
472 *
473 * @param object $origin The main object for the plugin you are enqueueing the asset for.
474 * @param string $slug Slug to save the asset - passes through `sanitize_title_with_dashes()`.
475 * @param string $file The asset file to load (CSS or JS), including non-minified file extension.
476 * @param array $deps The list of dependencies.
477 * @param string|array|null $action The WordPress action(s) to enqueue on, such as `wp_enqueue_scripts`,
478 * `admin_enqueue_scripts`, or `login_enqueue_scripts`.
479 * @param string|array $arguments {
480 * Optional. Array or string of parameters for this asset.
481 *
482 * @type array|string|null $action The WordPress action(s) this asset will be enqueued on.
483 * @type int $priority Priority in which this asset will be loaded on the WordPress action.
484 * @type string $file The relative path to the File that will be enqueued, uses the $origin to get the full path.
485 * @type string $type Asset Type, `js` or `css`.
486 * @type array $deps An array of other asset as dependencies.
487 * @type string $version Version number, used for cache expiring.
488 * @type string $media Used only for CSS, when to load the file.
489 * @type bool $in_footer A boolean determining if the javascript should be loaded on the footer.
490 * @type array|object $localize {
491 * Variables needed on the JavaScript side.
492 *
493 * @type string $name Name of the JS variable.
494 * @type string|array $data Contents of the JS variable.
495 * }
496 * @type callable[] $conditionals An callable method or an array of them, that will determine if the asset is loaded or not.
497 * }
498 *
499 * @return object|false The registered object or false on error.
500 */
501 public function register( $origin, $slug, $file, $deps = [], $action = null, $arguments = [] ) {
502 // Prevent weird stuff here.
503 $slug = sanitize_title_with_dashes( $slug );
504
505 if ( $this->exists( $slug ) ) {
506 return $this->get( $slug );
507 }
508
509 if ( is_string( $origin ) ) {
510 // Origin needs to be a class with a `instance` method and a Version constant.
511 if ( class_exists( $origin ) && method_exists( $origin, 'instance' ) && defined( $origin . '::VERSION' ) ) {
512 $origin = call_user_func( [ $origin, 'instance' ] );
513 }
514 }
515
516 if ( is_object( $origin ) ) {
517 $origin_name = get_class( $origin );
518
519 if ( ! defined( $origin_name . '::VERSION' ) ) {
520 // If we have a Object and we don't have instance or version.
521 return false;
522 }
523 } else {
524 return false;
525 }
526
527 // Fetches the version on the Origin Version constant.
528 $version = constant( $origin_name . '::VERSION' );
529
530 // Default variables to prevent notices.
531 $defaults = [
532 'slug' => null,
533 'file' => false,
534 'url' => false,
535 'action' => null,
536 'priority' => 10,
537 'type' => null,
538 'deps' => [],
539 'groups' => [],
540 'version' => $version,
541 'media' => 'all',
542
543 'print' => false,
544
545 'async' => false,
546 'defer' => false,
547
548 'in_footer' => true,
549 'is_registered' => false,
550
551 // Origin related params
552 'origin_path' => null,
553 'origin_url' => null,
554 'origin_name' => null,
555
556 // Bigger Variables at the end.
557 'localize' => [],
558 'conditionals' => [],
559
560 // Used to handle Translations handled in the JavaScript side of the Assets.
561 'translations' => [],
562
563 // Execute after the asset is enqueued.
564 'after_enqueue' => null,
565 'already_enqueued' => false,
566 'already_printed' => false,
567 ];
568
569 // Merge Arguments.
570 $asset = (object) wp_parse_args( $arguments, $defaults );
571
572 // Enforce these one.
573 $asset->slug = $slug;
574 $asset->file = $file;
575 $asset->deps = $deps;
576 $asset->action = $action;
577 $asset->origin_path = trailingslashit( ! empty( $origin->plugin_path ) ? $origin->plugin_path : $origin->pluginPath );
578 $asset->origin_name = $origin_name;
579
580 // Origin URL might throw notices so we double check.
581 $asset->origin_url = ! empty( $origin->plugin_url ) ? $origin->plugin_url : null;
582 $asset->origin_url = ! empty( $origin->pluginUrl ) ? $origin->pluginUrl : null;
583 if ( ! empty( $asset->origin_url ) ) {
584 $asset->origin_url = trailingslashit( $asset->origin_url );
585 }
586
587 // If we don't have a type on the arguments we grab from the File path.
588 if ( is_null( $asset->type ) ) {
589 if ( substr( $asset->file, -3, 3 ) === '.js' ) {
590 $asset->type = 'js';
591 } elseif ( substr( $asset->file, -4, 4 ) === '.css' ) {
592 $asset->type = 'css';
593 }
594 }
595
596 // If asset type is wrong don't register.
597 if ( ! in_array( $asset->type, [ 'js', 'css' ], true ) ) {
598 return false;
599 }
600
601 /**
602 * Filter to change version number on assets.
603 *
604 * @since 4.3
605 *
606 * @param string $version
607 * @param object $asset
608 */
609 $asset->version = apply_filters( 'tribe_asset_version', $asset->version, $asset );
610
611 // Clean these
612 $asset->priority = absint( $asset->priority );
613 $asset->in_footer = (bool) $asset->in_footer;
614 $asset->media = esc_attr( $asset->media );
615
616 // Ensures that we have a priority over 1.
617 if ( $asset->priority < 1 ) {
618 $asset->priority = 1;
619 }
620
621 $is_vendor = strpos( $asset->file, 'vendor/' ) !== false || strpos( $asset->file, 'node_modules/' ) !== false ? true : false;
622
623 // Setup the actual URL.
624 if ( filter_var( $asset->file, FILTER_VALIDATE_URL ) ) {
625 $asset->url = $asset->file;
626 } else {
627 $asset->url = $this->maybe_get_min_file( tribe_resource_url( $asset->file, false, ( $is_vendor ? '' : null ), $origin ) );
628 }
629
630 // Parse the Localize asset arguments.
631 $asset = $this->parse_argument_localize( $asset );
632
633 // Looks for a single conditional callable and places it in an Array.
634 if ( ! empty( $asset->conditionals ) && is_callable( $asset->conditionals ) ) {
635 $asset->conditionals = [ $asset->conditionals ];
636 }
637
638 // Groups is always an array of unique strings.
639 if ( ! empty( $asset->groups ) ) {
640 $asset->groups = (array) $asset->groups;
641 $asset->groups = array_filter( $asset->groups, 'is_string' );
642 $asset->groups = array_unique( $asset->groups );
643 }
644
645 if ( isset( $arguments['translations']['domain'], $arguments['translations']['path'] ) ) {
646 $asset->translations['domain'] = $arguments['translations']['domain'];
647 $asset->translations['path'] = $arguments['translations']['path'];
648 }
649
650 /**
651 * Filter an Asset loading variables.
652 *
653 * @since 4.3
654 *
655 * @param object $asset
656 */
657 $asset = apply_filters( 'tribe_asset_pre_register', $asset );
658
659 // Set the Asset on the array of notices.
660 $this->assets[ $slug ] = $asset;
661
662 // Return the Slug because it might be modified.
663 return $asset;
664 }
665
666 /**
667 * Parse the localize argument for a given asset object.
668 *
669 * @since 4.9.12
670 *
671 * @param stdClass $asset Argument that set that asset.
672 *
673 * @return stdClass
674 */
675 public function parse_argument_localize( stdClass $asset ) {
676 if ( empty( $asset->localize ) ) {
677 return $asset;
678 }
679
680 if ( ! is_array( $asset->localize ) && ! is_object( $asset->localize ) ) {
681 return $asset;
682 }
683
684 // Cast to array for safety.
685 $asset->localize = (array) $asset->localize;
686
687 // Allow passing of a single instance.
688 if ( ! empty( $asset->localize['name'] ) ) {
689 // Reset to empty when name was not empty data was not set.
690 $asset->localize = ! isset( $asset->localize['data'] ) ? [] : [ (object) $asset->localize ];
691 }
692
693 // Cast all instances as object.
694 $asset->localize = array_map( function( $values ) {
695 return (object) $values;
696 }, $asset->localize );
697
698 return $asset;
699 }
700
701 /**
702 * Removes an Asset from been registered and enqueue.
703 *
704 * @since 4.3
705 *
706 * @param string $slug Slug of the Asset.
707 *
708 * @return bool
709 */
710 public function remove( $slug ) {
711 if ( ! $this->exists( $slug ) ) {
712 return false;
713 }
714
715 unset( $this->assets[ $slug ] );
716 return true;
717 }
718
719 /**
720 * Get the Asset Object configuration.
721 *
722 * @since 4.3
723 * @since 4.11.0 Added $sort param.
724 *
725 * @param string|array $slug Slug of the Asset.
726 * @param boolean $sort If we should do any sorting before returning.
727 *
728 * @return array|object|null Array of asset objects, single asset object, or null if looking for a single asset but
729 * it was not in the array of objects.
730 */
731 public function get( $slug = null, $sort = true ) {
732 if ( is_null( $slug ) ) {
733 if ( $sort ) {
734 $cache_key_count = __METHOD__ . ':count';
735 // Sorts by priority.
736 $cache_count = tribe_get_var( $cache_key_count, 0 );
737 $count = count( $this->assets );
738
739 if ( $count !== $cache_count ) {
740 uasort( $this->assets, 'tribe_sort_by_priority' );
741 tribe_set_var( $cache_key_count, $count );
742 }
743 }
744 return $this->assets;
745 }
746
747 // If slug is an array we return all of those.
748 if ( is_array( $slug ) ) {
749 $assets = [];
750 foreach ( $slug as $asset_slug ) {
751 $asset_slug = sanitize_title_with_dashes( $asset_slug );
752 // Skip empty assets.
753 if ( empty( $this->assets[ $asset_slug ] ) ) {
754 continue;
755 }
756
757 $assets[ $asset_slug ] = $this->assets[ $asset_slug ];
758 }
759
760 if ( empty( $assets ) ) {
761 return null;
762 }
763
764 if ( $sort ) {
765 // Sorts by priority.
766 uasort( $assets, 'tribe_sort_by_priority' );
767 }
768
769 return $assets;
770 }
771
772 // Prevent weird stuff here.
773 $slug = sanitize_title_with_dashes( $slug );
774
775 if ( ! empty( $this->assets[ $slug ] ) ) {
776 return $this->assets[ $slug ];
777 }
778
779 return null;
780 }
781
782 /**
783 * Checks if an Asset exists.
784 *
785 * @param string|array $slug Slug of the Asset.
786 *
787 * @return bool
788 */
789 public function exists( $slug ) {
790 return is_object( $this->get( $slug ) ) ? true : false;
791 }
792
793 /**
794 * Prints the `script` (JS) and `link` (CSS) HTML tags associated with one or more assets groups.
795 *
796 * The method will force the scripts and styles to print overriding their registration and conditional.
797 *
798 * @since 4.12.6
799 *
800 * @param string|array $group Which group(s) should be enqueued.
801 * @param bool $echo Whether to print the group(s) tag(s) to the page or not; default to `true` to
802 * print the HTML `script` (JS) and `link` (CSS) tags to the page.
803 *
804 * @return string The `script` and `link` HTML tags produced for the group(s).
805 */
806 public function print_group( $group, $echo = true ) {
807 $all_assets = $this->get();
808 $groups = (array) $group;
809 $to_print = array_filter( $all_assets, static function ( $asset ) use ( $groups ) {
810 return isset( $asset->groups ) && array_intersect( $asset->groups, $groups );
811 } );
812 $by_type = array_reduce( $to_print, static function ( array $acc, \stdClass $asset ) {
813 $acc[ $asset->type ][] = $asset->slug;
814
815 return $acc;
816 }, [ 'css' => [], 'js' => [] ] );
817
818
819 // Make sure each script is registered.
820 foreach ( $to_print as $slug => $data ){
821 if ( $data->is_registered ){
822 continue;
823 }
824 'js' === $data->type
825 ? wp_register_script( $slug, $data->file, $data->deps, $data->version )
826 : wp_register_style( $slug, $data->file, $data->deps, $data->version );
827 }
828
829 ob_start();
830 wp_scripts()->do_items( $by_type['js'] );
831 wp_styles()->do_items( $by_type['css'] );
832 $tags = ob_get_clean();
833
834 if ( $echo ) {
835 echo $tags;
836 }
837
838 return $tags;
839 }
840 }
841