$after = '';
$print_after = $asset->get_print_after();
if ( ! empty( $print_after ) ) {
$after = (string) ( is_callable( $print_after ) ? call_user_func( $print_after, $asset ) : $print_after );
}
$tag = $before . (string) $tag . $after;
return $tag;
}
/**
* Get the Asset Object configuration.
*
* @param string|array $slug Slug of the Asset.
* @param boolean $sort If we should do any sorting before returning.
*
* @return array|Asset Array of asset objects, single asset object, or null if looking for a single asset but
* it was not in the array of objects.
* @since 1.0.0
*
*/
public function get( $slug = null, $sort = true ) {
$obj = $this;
if ( is_null( $slug ) ) {
if ( $sort ) {
$cache_key_count = __METHOD__ . ':count';
// Sorts by priority.
$cache_count = $this->get_var( $cache_key_count, 0 );
$count = count( $this->assets );
if ( $count !== $cache_count ) {
uasort( $this->assets, static function ( $a, $b ) use ( $obj ) {
return $obj->sort_by_priority( $a, $b, 'get_priority' );
} );
$this->set_var( $cache_key_count, $count );
}
}
return $this->assets;
}
// If slug is an array we return all of those.
if ( is_array( $slug ) ) {
$assets = [];
foreach ( $slug as $asset_slug ) {
$asset_slug = sanitize_key( $asset_slug );
// Skip empty assets.
if ( empty( $this->assets[ $asset_slug ] ) ) {
continue;
}
$assets[ $asset_slug ] = $this->assets[ $asset_slug ];
}
if ( empty( $assets ) ) {
return [];
}
if ( $sort ) {
// Sorts by priority.
uasort( $assets, static function ( $a, $b ) use ( $obj ) {
return $obj->sort_by_priority( $a, $b, 'get_priority' );
} );
}
return $assets;
}
// Prevent weird stuff here.
$slug = sanitize_key( $slug );
if ( ! empty( $this->assets[ $slug ] ) ) {
return $this->assets[ $slug ];
}
return [];
}
/**
* Gets a memoized value.
*
* @param string $var Var name.
* @param mixed|null $default Default value.
*
* @return mixed|null
*/
public function get_var( string $var, $default = null ) {
return $this->memoized[ $var ] ?? $default;
}
/**
* Sorting function based on Priority
*
* @param object|array $b Second subject to compare.
* @param object|array $a First Subject to compare.
* @param string $method Method to use for sorting.
*
* @return int
* @since 1.0.0
*
*/
public function sort_by_priority( $a, $b, $method = null ) {
if ( is_array( $a ) ) {
$a_priority = $a['priority'];
} else {
$a_priority = $method ? $a->$method() : $a->priority;
}
if ( is_array( $b ) ) {
$b_priority = $b['priority'];
} else {
$b_priority = $method ? $b->$method() : $b->priority;
}
if ( (int) $a_priority === (int) $b_priority ) {
return 0;
}
return (int) $a_priority > (int) $b_priority ? 1 : - 1;
}
/**
* Sets a memoized value.
*
* @param string $var Var name.
* @param mixed|null $value The value.
*/
public function set_var( string $var, $value = null ) {
$this->memoized[ $var ] = $value;
}
/**
* Handles adding localization data, when attached to `script_loader_tag` which allows dependencies to load in their
* localization data as well.
*
* @param string $tag Tag we are filtering.
* @param string $handle Which is the ID/Handle of the tag we are about to print.
*
* @return string Script tag with the localization variable HTML attached to it.
* @since 1.0.0
*
*/
public function filter_add_localization_data( $tag, $handle ) {
// Only filter for own filters.
if ( ! $asset = $this->get( $handle ) ) {
return $tag;
}
// Bail when not dealing with JS assets.
if ( 'js' !== $asset->get_type() ) {
return $tag;
}
$localize_scripts = $asset->get_localize_scripts();
$custom_localize_scripts = $asset->get_custom_localize_scripts();
// Only localize on JS and if we have data.
if ( empty( $localize_scripts ) && empty( $custom_localize_scripts ) ) {
return $tag;
}
$localization_html = '';
if ( count( $localize_scripts ) ) {
global $wp_scripts;
$localization = $localize_scripts;
/**
* Check to ensure we haven't already localized it before.
*
* @since 1.0.0
*/
foreach ( $localization as $key => $localize ) {
if ( in_array( $key, $this->localized ) ) {
continue;
}
// If we have a Callable as the Localize data we execute it.
if ( is_callable( $localize ) ) {
$localize = $localize( $asset );
}
wp_localize_script( $asset->get_slug(), $key, $localize );
$this->localized[] = $key;
}
// Fetch the HTML for all the localized data.
ob_start();
$wp_scripts->print_extra_script( $asset->get_slug(), true );
$localization_html = ob_get_clean();
// After printing it remove data;|
$wp_scripts->add_data( $asset->get_slug(), 'data', '' );
}
/*
* Print the dot.notation namespaced objects for the asset.
*/
foreach ( $custom_localize_scripts as [$object_name, $data] ) {
// If we have a Callable as the Localize data we execute it.
if ( is_callable( $data ) ) {
$data = $data( $asset );
}
$localized_key = "{$asset->get_slug()}::{$object_name}";
if ( in_array( $localized_key, $this->localized, true ) ) {
continue;
}
$frags = explode( '.', $object_name );
$js_data = '';
$var_name = '';
foreach ( $frags as $i => $frag ) {
$var_name = ltrim( $var_name . '.' . $frag, '.' );
if ( isset( $frags[ $i + 1 ] ) ) {
$js_data .= PHP_EOL . sprintf( 'window.%1$s = window.%1$s || {};', $var_name );
} else {
$json_data = wp_json_encode( $data );
$js_data .= PHP_EOL . sprintf( 'window.%1$s = Object.assign(window.%1$s || {}, %2$s);', $var_name, $json_data );
}
}
$localization_html .= sprintf(
'',
$asset->get_slug(),
$js_data
);
$this->localized[] = $localized_key;
}
return $localization_html . $tag;
}
/**
* Filters the Script tags to attach Async and/or Defer based on the rules we set in our Asset class.
*
* @param string $tag Tag we are filtering.
* @param string $handle Which is the ID/Handle of the tag we are about to print.
*
* @return string Script tag with the defer and/or async attached.
* @since 1.0.0
*
*/
public function filter_tag_async_defer( $tag, $handle ) {
// Only filter for our own filters.
if ( ! $asset = $this->get( $handle ) ) {
return $tag;
}
// Bail when not dealing with JS assets.
if ( 'js' !== $asset->get_type() ) {
return $tag;
}
// When async and defer are false we bail with the tag.
if ( ! $asset->is_deferred() && ! $asset->is_async() ) {
return $tag;
}
$tag_has_async = false !== strpos( $tag, ' async ' );
$tag_has_defer = false !== strpos( $tag, ' defer ' );
$replacement = '