$instance pairs. * * @since 1.0.0 * @var array */ private $assets = array(); /** * Constructor. * * @since 1.0.0 * * @param Context $context Plugin context. */ public function __construct( Context $context ) { $this->context = $context; } /** * Registers functionality through WordPress hooks. * * @since 1.0.0 */ public function register() { $register_callback = function() { if ( ! is_admin() ) { return; } $this->register_assets(); }; add_action( 'admin_enqueue_scripts', $register_callback ); add_action( 'wp_enqueue_scripts', $register_callback ); add_action( 'admin_enqueue_scripts', function() { $this->enqueue_minimal_admin_script(); } ); add_filter( 'script_loader_tag', function( $tag, $handle ) { return $this->add_async_defer_attribute( $tag, $handle ); }, 10, 2 ); } /** * Enqueues the given plugin asset (script or stylesheet). * * The asset must already be registered in order to be enqueued. * * @since 1.0.0 * * @param string $handle Asset handle. */ public function enqueue_asset( $handle ) { // Register assets on-the-fly if necessary (currently the case for admin bar in frontend). static $assets_registered = false; if ( ! $assets_registered ) { $assets_registered = true; $this->register_assets(); } $assets = $this->get_assets(); if ( empty( $assets[ $handle ] ) ) { return; } $assets[ $handle ]->enqueue(); } /** * Enqueues Google fonts. * * @since 1.0.0 */ public function enqueue_fonts() { static $enqueued = false; if ( $enqueued ) { return; } $font_families = array( 'Google+Sans:300,300i,400,400i,500,500i,700,700i', 'Roboto:300,300i,400,400i,500,500i,700,700i', ); if ( $this->context->is_amp() ) { $fonts_url = add_query_arg( array( 'family' => implode( '|', $font_families ), 'subset' => 'latin-ext', 'display' => 'fallback', ), 'https://fonts.googleapis.com/css' ); wp_enqueue_style( // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion 'googlesitekit-fonts', $fonts_url, array(), null ); return; } $action = current_action(); if ( strpos( $action, '_enqueue_scripts' ) ) { // Make sure we hook into the right `..._head` action if known. $action = str_replace( '_enqueue_scripts', '_head', $action ); } else { // Or fall back to `wp_head`. $action = 'wp_head'; } add_action( $action, function() use ( $font_families ) { ?> '', 'role' => 'img', 'height' => '25', 'width' => '25', ) ); $href = $this->context->url( 'dist/assets/svg/svg.svg' ) . '#' . $name; $label = 'aria-label="' . ( empty( $args['label'] ) ? esc_attr( $name ) : esc_attr( $args['label'] ) ) . '"'; $label = 'presentation' === $args['role'] ? '' : $label; return sprintf( '', esc_attr( $args['role'] ), esc_attr( 'svg googlesitekit-svg-' . $name ), $label, esc_attr( $args['height'] ), esc_attr( $args['width'] ), esc_url( $href ) ); } /** * Registers all plugin assets. * * @since 1.0.0 */ private function register_assets() { $assets = $this->get_assets(); foreach ( $assets as $asset ) { $asset->register(); } } /** * Enqueues the minimal admin script for the entire admin. * * @since 1.0.0 */ private function enqueue_minimal_admin_script() { $this->enqueue_asset( 'googlesitekit_admin' ); } /** * Gets all plugin assets. * * The method will lazy-load assets in an internal property so that the processing only happens once. * * @since 1.0.0 * * @return array Associative array of asset $handle => $instance pairs. */ private function get_assets() { if ( $this->assets ) { return $this->assets; } $base_url = $this->context->url( 'dist/assets/' ); $dependencies = array(); $external_assets = $this->get_external_assets(); foreach ( $external_assets as $asset ) { $dependencies[] = $asset->get_handle(); } $dependencies[] = 'sitekit-vendor'; $dependencies[] = 'sitekit-commons'; // Register plugin scripts. $assets = array( new Script( 'sitekit-vendor', array( 'src' => $base_url . 'js/vendor.js', ) ), new Script( 'sitekit-commons', array( 'src' => $base_url . 'js/commons.js', 'dependencies' => array( 'sitekit-vendor' ), 'post_register' => function( $handle ) use ( $base_url ) { $url_polyfill = ( '( typeof URL === \'function\') || ' . 'document.write( \'):', " $script_execution", $tag, 1 ); } return $tag; } /** * Gets all external assets. * * This method should only be called once as it will create a new instance for each asset. * * @since 1.0.0 * * @return array List of Asset instances. */ private function get_external_assets() { $base_url = $this->context->url( 'dist/assets/' ); $script_debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; $suffix = $script_debug ? '' : '.min'; $react_suffix = ( $script_debug ? '.development' : '.production' ) . $suffix; return array( new Script( 'lodash', array( 'src' => $base_url . 'vendor/lodash' . $suffix . '.js', 'version' => '4.17.11', 'fallback' => true, 'post_register' => function( $handle ) { wp_add_inline_script( $handle, 'window.lodash = window.lodash || _.noConflict(); window.lodash_load = true;' ); }, ) ), new Script( 'moment', array( 'src' => $base_url . 'vendor/moment' . $suffix . '.js', 'version' => '2.22.2', 'fallback' => true, ) ), new Script( 'react', array( 'src' => $base_url . 'vendor/react' . $react_suffix . '.js', 'version' => '16.8.5', 'fallback' => true, ) ), new Script( 'react-dom', array( 'src' => $base_url . 'vendor/react-dom' . $react_suffix . '.js', 'version' => '16.8.5', 'fallback' => true, ) ), new Script( 'wp-polyfill', array( 'src' => $base_url . 'js/externals/wp-polyfill.js', 'version' => '7.4.0', 'fallback' => true, // Note: For whatever reason, PHPCS reports weird errors here although everything is right. 'post_register' => function( $handle ) use ( $base_url ) { $inline_polyfill_tests = array( '\'fetch\' in window' => $base_url . 'js/externals/wp-polyfill-fetch.js', // phpcs:ignore WordPress.Arrays.MultipleStatementAlignment 'document.contains' => $base_url . 'js/externals/wp-polyfill-node-contains.js', // phpcs:ignore WordPress.Arrays.MultipleStatementAlignment 'window.FormData && window.FormData.prototype.keys' => $base_url . 'js/externals/wp-polyfill-formdata.js', // phpcs:ignore WordPress.Arrays.MultipleStatementAlignment 'Element.prototype.matches && Element.prototype.closest' => $base_url . 'js/externals/wp-polyfill-element-closest.js', // phpcs:ignore WordPress.Arrays.MultipleStatementAlignment ); $polyfill_scripts = ''; foreach ( $inline_polyfill_tests as $test => $script ) { // phpcs:ignore Generic.WhiteSpace.ScopeIndent.IncorrectExact $polyfill_scripts .= ( '( ' . $test . ' ) || ' . 'document.write( \'