$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 = '