PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 11.0.0-beta.1
WooCommerce v11.0.0-beta.1
11.0.0-beta.1 10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / src / Blocks / AssetsController.php
woocommerce / src / Blocks Last commit date
AI 1 year ago AIContent 1 year ago Assets 3 days ago BlockTypes 3 days ago Domain 3 days ago Images 1 year ago Integrations 2 years ago Patterns 3 days ago Payments 5 months ago Registry 2 years ago SharedStores 2 months ago Shipping 3 days ago Templates 3 days ago Utils 3 days ago Assets.php 2 years ago AssetsController.php 3 days ago BlockPatterns.php 3 days ago BlockTemplatesController.php 7 months ago BlockTemplatesRegistry.php 10 months ago BlockTypesController.php 1 month ago DependencyDetection.php 3 days ago InboxNotifications.php 2 years ago Installer.php 2 months ago Library.php 2 years ago Options.php 2 years ago Package.php 1 year ago QueryFilters.php 3 days ago TemplateOptions.php 1 year ago
AssetsController.php
482 lines
1 <?php
2 declare( strict_types = 1 );
3
4 namespace Automattic\WooCommerce\Blocks;
5
6 use Automattic\Jetpack\Constants;
7 use Automattic\WooCommerce\Blocks\Assets\Api as AssetApi;
8 use Automattic\WooCommerce\Blocks\Utils\Utils;
9
10 /**
11 * AssetsController class.
12 *
13 * @since 5.0.0
14 * @internal
15 */
16 final class AssetsController {
17
18 /**
19 * Asset API interface for various asset registration.
20 *
21 * @var AssetApi
22 */
23 private $api;
24
25 /**
26 * Constructor.
27 *
28 * @param AssetApi $asset_api Asset API interface for various asset registration.
29 */
30 public function __construct( AssetApi $asset_api ) {
31 $this->api = $asset_api;
32 $this->init();
33 }
34
35 /**
36 * Initialize class features.
37 */
38 protected function init() { // phpcs:ignore WooCommerce.Functions.InternalInjectionMethod.MissingPublic
39 add_action( 'init', array( $this, 'register_assets' ) );
40 add_action( 'init', array( $this, 'register_script_modules' ) );
41 add_filter( 'wp_resource_hints', array( $this, 'add_resource_hints' ), 10, 2 );
42 add_action( 'body_class', array( $this, 'add_theme_body_class' ), 1 );
43 add_action( 'admin_body_class', array( $this, 'add_theme_body_class' ), 1 );
44 add_action( 'admin_enqueue_scripts', array( $this, 'update_block_style_dependencies' ), 20 );
45 add_action( 'wp_enqueue_scripts', array( $this, 'update_block_settings_dependencies' ), 100 );
46 add_action( 'admin_enqueue_scripts', array( $this, 'update_block_settings_dependencies' ), 100 );
47 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_wc_entities' ), 100 );
48 add_filter( 'js_do_concat', array( $this, 'skip_boost_minification_for_cart_checkout' ), 10, 2 );
49 }
50
51 /**
52 * Register script modules.
53 */
54 public function register_script_modules() {
55 // Right now we only have one script modules build for supported interactivity API powered block front-ends.
56 // We generate a combined asset file for that via DependencyExtractionWebpackPlugin to make registration more
57 // efficient.
58 $asset_data = $this->api->get_asset_data(
59 $this->api->get_block_asset_build_path( 'interactivity-blocks-frontend-assets', 'php' )
60 );
61
62 foreach ( $asset_data as $handle => $data ) {
63 $handle_without_js = str_replace( '.js', '', $handle );
64 wp_register_script_module( $handle_without_js, plugins_url( $this->api->get_block_asset_build_path( $handle_without_js ), dirname( __DIR__ ) ), $data['dependencies'], $data['version'] );
65 }
66 }
67
68 /**
69 * Register block scripts & styles.
70 */
71 public function register_assets() {
72 $this->register_style( 'wc-blocks-packages-style', plugins_url( $this->api->get_block_asset_build_path( 'packages-style', 'css' ), dirname( __DIR__ ) ), array(), 'all', true );
73 $this->register_style( 'wc-blocks-style', plugins_url( $this->api->get_block_asset_build_path( 'wc-blocks', 'css' ), dirname( __DIR__ ) ), array(), 'all', true );
74 $this->register_style( 'wc-blocks-editor-style', plugins_url( $this->api->get_block_asset_build_path( 'wc-blocks-editor-style', 'css' ), dirname( __DIR__ ) ), array( 'wp-edit-blocks' ), 'all', true );
75
76 $this->api->register_script( 'wc-types', $this->api->get_block_asset_build_path( 'wc-types' ), array(), false );
77 $this->api->register_script( 'wc-entities', 'assets/client/blocks/wc-entities.js', array(), false );
78 $this->api->register_script( 'wc-blocks-middleware', 'assets/client/blocks/wc-blocks-middleware.js', array(), false );
79 $this->api->register_script( 'wc-blocks-data-store', 'assets/client/blocks/wc-blocks-data.js', array( 'wc-blocks-middleware' ) );
80 $this->api->register_script( 'wc-blocks-vendors', $this->api->get_block_asset_build_path( 'wc-blocks-vendors' ), array(), false );
81 $this->api->register_script( 'wc-blocks-registry', 'assets/client/blocks/wc-blocks-registry.js', array(), false );
82 $this->api->register_script( 'wc-blocks', $this->api->get_block_asset_build_path( 'wc-blocks' ), array( 'wc-blocks-vendors' ), false );
83 $this->api->register_script( 'wc-blocks-shared-context', 'assets/client/blocks/wc-blocks-shared-context.js' );
84 $this->api->register_script( 'wc-blocks-shared-hocs', 'assets/client/blocks/wc-blocks-shared-hocs.js', array(), false );
85
86 // The price package is shared externally so has no blocks prefix.
87 $this->api->register_script( 'wc-price-format', 'assets/client/blocks/price-format.js', array(), false );
88
89 // Vendor scripts for blocks frontends (not including cart and checkout).
90 $this->api->register_script( 'wc-blocks-frontend-vendors', $this->api->get_block_asset_build_path( 'wc-blocks-frontend-vendors-frontend' ), array(), true );
91
92 // Cart and checkout frontend scripts.
93 $this->api->register_script( 'wc-cart-checkout-vendors', $this->api->get_block_asset_build_path( 'wc-cart-checkout-vendors-frontend' ), array(), true );
94 $this->api->register_script( 'wc-cart-checkout-base', $this->api->get_block_asset_build_path( 'wc-cart-checkout-base-frontend' ), array(), true );
95 $this->api->register_script( 'wc-blocks-checkout', 'assets/client/blocks/blocks-checkout.js' );
96 $this->api->register_script( 'wc-blocks-checkout-events', 'assets/client/blocks/blocks-checkout-events.js' );
97 $this->api->register_script( 'wc-blocks-components', 'assets/client/blocks/blocks-components.js' );
98 $this->api->register_script( 'wc-schema-parser', 'assets/client/blocks/wc-schema-parser.js', array(), false );
99
100 // Sanitize.
101 $this->api->register_script(
102 'wc-sanitize',
103 'assets/client/admin/sanitize/index.js',
104 array()
105 );
106
107 wp_add_inline_script(
108 'wc-blocks-middleware',
109 "
110 var wcBlocksMiddlewareConfig = {
111 storeApiNonce: '" . esc_js( wp_create_nonce( 'wc_store_api' ) ) . "',
112 wcStoreApiNonceTimestamp: '" . esc_js( time() ) . "'
113 };
114 ",
115 'before'
116 );
117 }
118
119 /**
120 * Defines resource hints to help speed up the loading of some critical blocks.
121 *
122 * These will not impact page loading times negatively because they are loaded once the current page is idle.
123 *
124 * @param array $urls URLs to print for resource hints. Each URL is an array of resource attributes, or a URL string.
125 * @param string $relation_type The relation type the URLs are printed. Possible values: preconnect, dns-prefetch, prefetch, prerender.
126 * @return array URLs to print for resource hints.
127 */
128 public function add_resource_hints( $urls, $relation_type ) {
129 if ( ! in_array( $relation_type, array( 'prefetch', 'prerender' ), true ) || is_admin() ) {
130 return $urls;
131 }
132
133 // We only need to prefetch when the cart has contents.
134 $cart = wc()->cart;
135
136 if ( ! $cart instanceof \WC_Cart || 0 === $cart->get_cart_contents_count() ) {
137 return $urls;
138 }
139
140 if ( 'prefetch' === $relation_type ) {
141 $urls = array_merge(
142 $urls,
143 $this->get_prefetch_resource_hints()
144 );
145 }
146
147 if ( 'prerender' === $relation_type ) {
148 $urls = array_merge(
149 $urls,
150 $this->get_prerender_resource_hints()
151 );
152 }
153
154 return $urls;
155 }
156
157 /**
158 * Get resource hints during prefetch requests.
159 *
160 * @return array Array of URLs.
161 */
162 private function get_prefetch_resource_hints() {
163 $urls = array();
164
165 // Core page IDs.
166 $cart_page_id = wc_get_page_id( 'cart' );
167 $checkout_page_id = wc_get_page_id( 'checkout' );
168
169 // Checks a specific page (by ID) to see if it contains the named block.
170 $has_block_cart = $cart_page_id && has_block( 'woocommerce/cart', $cart_page_id );
171 $has_block_checkout = $checkout_page_id && has_block( 'woocommerce/checkout', $checkout_page_id );
172
173 // Checks the current page to see if it contains the named block.
174 $is_block_cart = has_block( 'woocommerce/cart' );
175 $is_block_checkout = has_block( 'woocommerce/checkout' );
176
177 if ( $has_block_cart && ! $is_block_cart ) {
178 $urls = array_merge( $urls, $this->get_block_asset_resource_hints( 'cart-frontend' ) );
179 }
180
181 if ( $has_block_checkout && ! $is_block_checkout ) {
182 $urls = array_merge( $urls, $this->get_block_asset_resource_hints( 'checkout-frontend' ) );
183 }
184
185 return $urls;
186 }
187
188 /**
189 * Get resource hints during prerender requests.
190 *
191 * @return array Array of URLs.
192 */
193 private function get_prerender_resource_hints() {
194 $urls = array();
195 $is_block_cart = has_block( 'woocommerce/cart' );
196
197 if ( ! $is_block_cart ) {
198 return $urls;
199 }
200
201 $checkout_page_id = wc_get_page_id( 'checkout' );
202 $checkout_page_url = $checkout_page_id ? get_permalink( $checkout_page_id ) : '';
203
204 if ( $checkout_page_url ) {
205 $urls[] = $checkout_page_url;
206 }
207
208 return $urls;
209 }
210
211 /**
212 * Get the block asset resource hints in the cache or null if not found.
213 *
214 * @return array|null Array of resource hints.
215 */
216 private function get_block_asset_resource_hints_cache() {
217 if ( wp_is_development_mode( 'plugin' ) ) {
218 return null;
219 }
220
221 $cache = get_transient( 'woocommerce_block_asset_resource_hints' );
222
223 $current_version = array(
224 'woocommerce' => Constants::get_constant( 'WC_VERSION' ),
225 'wordpress' => get_bloginfo( 'version' ),
226 'site_url' => site_url(),
227 );
228
229 if ( isset( $cache['version'] ) && $cache['version'] === $current_version ) {
230 return $cache['files'];
231 }
232
233 return null;
234 }
235
236 /**
237 * Set the block asset resource hints in the cache.
238 *
239 * @param string $filename File name.
240 * @param array $data Array of resource hints.
241 */
242 private function set_block_asset_resource_hints_cache( $filename, $data ) {
243 $cache = $this->get_block_asset_resource_hints_cache();
244 $updated = array(
245 'files' => $cache ?? array(),
246 'version' => array(
247 'woocommerce' => Constants::get_constant( 'WC_VERSION' ),
248 'wordpress' => get_bloginfo( 'version' ),
249 'site_url' => site_url(),
250 ),
251 );
252
253 $updated['files'][ $filename ] = $data;
254 set_transient( 'woocommerce_block_asset_resource_hints', $updated, WEEK_IN_SECONDS );
255 }
256
257 /**
258 * Get resource hint for a block by name.
259 *
260 * @param string $filename Block filename.
261 * @return array
262 */
263 private function get_block_asset_resource_hints( $filename = '' ) {
264 if ( ! $filename ) {
265 return array();
266 }
267
268 $cached = $this->get_block_asset_resource_hints_cache();
269
270 if ( isset( $cached[ $filename ] ) ) {
271 return $cached[ $filename ];
272 }
273
274 $script_data = $this->api->get_script_data(
275 $this->api->get_block_asset_build_path( $filename )
276 );
277 $resources = array_merge(
278 array( esc_url( add_query_arg( 'ver', $script_data['version'], $script_data['src'] ) ) ),
279 $this->get_script_dependency_src_array( $script_data['dependencies'] )
280 );
281
282 $data = array_map(
283 function ( $src ) {
284 return array(
285 'href' => $src,
286 'as' => 'script',
287 );
288 },
289 array_unique( array_filter( $resources ) )
290 );
291
292 $this->set_block_asset_resource_hints_cache( $filename, $data );
293
294 return $data;
295 }
296
297 /**
298 * Get the src of all script dependencies (handles).
299 *
300 * @param array $dependencies Array of dependency handles.
301 * @return string[] Array of src strings.
302 */
303 private function get_script_dependency_src_array( array $dependencies ) {
304 $wp_scripts = wp_scripts();
305
306 $found_dependencies = array();
307 $this->gather_script_dependency_handles( $dependencies, $wp_scripts, $found_dependencies );
308
309 $src = array();
310 foreach ( $found_dependencies as $handle => $unused ) {
311 $script_src = $wp_scripts->registered[ $handle ]->src;
312 if ( ! is_string( $script_src ) ) {
313 // Skip srcless dependencies (e.g. meta-packages), which have no URL to hint.
314 continue;
315 }
316 $src[] = esc_url( add_query_arg( 'ver', $wp_scripts->registered[ $handle ]->ver, Utils::get_absolute_script_url( $script_src ) ) );
317 }
318 return $src;
319 }
320
321 /**
322 * Recursively gather all unique script dependency handles from a starting list.
323 *
324 * Traverses the dependency graph for each input handle, collecting any found handles
325 * and their nested dependencies in the provided array. Used internally to build a
326 * complete, deduplicated set of handles for further processing (e.g., mapping to src URLs).
327 *
328 * @param array $dependencies Array of initial script handles to process.
329 * @param \WP_Scripts $wp_scripts WP_Scripts instance containing all registered scripts.
330 * @param array $found_dependencies Reference to array in which discovered handles are stored.
331 *
332 * @return void
333 */
334 private function gather_script_dependency_handles( array $dependencies, \WP_Scripts $wp_scripts, &$found_dependencies = array() ) {
335 foreach ( $dependencies as $handle ) {
336 if ( isset( $wp_scripts->registered[ $handle ] ) && ! isset( $found_dependencies[ $handle ] ) ) {
337 $found_dependencies[ $handle ] = true;
338 if ( ! empty( $wp_scripts->registered[ $handle ]->deps ) ) {
339 $this->gather_script_dependency_handles( $wp_scripts->registered[ $handle ]->deps, $wp_scripts, $found_dependencies );
340 }
341 }
342 }
343 }
344
345 /**
346 * Skip Jetpack Boost minification on older versions of Jetpack Boost where it causes issues.
347 *
348 * @param mixed $do_concat Whether to concatenate the script or not.
349 * @param mixed $handle The script handle.
350 * @return mixed
351 */
352 public function skip_boost_minification_for_cart_checkout( $do_concat, $handle ) {
353 $boost_is_outdated = defined( 'JETPACK_BOOST_VERSION' ) && version_compare( JETPACK_BOOST_VERSION, '3.4.2', '<' );
354 $scripts_to_ignore = array(
355 'wc-cart-checkout-vendors',
356 'wc-cart-checkout-base',
357 );
358
359 return $boost_is_outdated && in_array( $handle, $scripts_to_ignore, true ) ? false : $do_concat;
360 }
361
362 /**
363 * Add body classes to the frontend and within admin.
364 *
365 * @param string|array $classes Array or string of CSS classnames.
366 * @return string|array Modified classnames.
367 */
368 public function add_theme_body_class( $classes ) {
369 $class = 'theme-' . get_template();
370
371 if ( is_array( $classes ) ) {
372 $classes[] = $class;
373 } else {
374 $classes .= ' ' . $class . ' ';
375 }
376
377 return $classes;
378 }
379
380 /**
381 * Get the file modified time as a cache buster if we're in dev mode.
382 *
383 * @param string $file Local path to the file.
384 * @return string The cache buster value to use for the given file.
385 */
386 protected function get_file_version( $file ) {
387 if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG && file_exists( \Automattic\WooCommerce\Blocks\Package::get_path() . $file ) ) {
388 return filemtime( \Automattic\WooCommerce\Blocks\Package::get_path() . $file );
389 }
390 return $this->api->wc_version;
391 }
392
393 /**
394 * Registers a style according to `wp_register_style`.
395 *
396 * @param string $handle Name of the stylesheet. Should be unique.
397 * @param string $src Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory.
398 * @param array $deps Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array.
399 * @param string $media Optional. The media for which this stylesheet has been defined. Default 'all'. Accepts media types like
400 * 'all', 'print' and 'screen', or media queries like '(orientation: portrait)' and '(max-width: 640px)'.
401 * @param boolean $rtl Optional. Whether or not to register RTL styles.
402 */
403 protected function register_style( $handle, $src, $deps = array(), $media = 'all', $rtl = false ) {
404 $filename = str_replace( plugins_url( '/', dirname( __DIR__ ) ), '', $src );
405 $ver = self::get_file_version( $filename );
406
407 wp_register_style( $handle, $src, $deps, $ver, $media );
408
409 if ( $rtl ) {
410 wp_style_add_data( $handle, 'rtl', 'replace' );
411 }
412 }
413
414 /**
415 * Update block style dependencies after they have been registered.
416 */
417 public function update_block_style_dependencies() {
418 $wp_styles = wp_styles();
419 $style = $wp_styles->query( 'wc-blocks-style', 'registered' );
420
421 if ( ! $style ) {
422 return;
423 }
424
425 // In WC < 5.5, `woocommerce-general` is not registered in block editor
426 // screens, so we don't add it as a dependency if it's not registered.
427 // In WC >= 5.5, `woocommerce-general` is registered on `admin_enqueue_scripts`,
428 // so we need to check if it's registered here instead of on `init`.
429 if (
430 wp_style_is( 'woocommerce-general', 'registered' ) &&
431 ! in_array( 'woocommerce-general', $style->deps, true )
432 ) {
433 $style->deps[] = 'woocommerce-general';
434 }
435 }
436
437 /**
438 * Fix scripts with wc-settings dependency.
439 *
440 * The wc-settings script only works correctly when enqueued in the footer. This is to give blocks etc time to
441 * register their settings data before it's printed.
442 *
443 * This code will look at registered scripts, and if they have a wc-settings dependency, force them to print in the
444 * footer instead of the header.
445 *
446 * This only supports packages known to require wc-settings!
447 *
448 * @see https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues/5052
449 */
450 public function update_block_settings_dependencies() {
451 $wp_scripts = wp_scripts();
452 $known_packages = array( 'wc-settings', 'wc-blocks-checkout', 'wc-price-format' );
453
454 foreach ( $wp_scripts->registered as $handle => $script ) {
455 // scripts that are loaded in the footer has extra->group = 1.
456 if ( array_intersect( $known_packages, $script->deps ) && ! isset( $script->extra['group'] ) ) {
457 // Append the script to footer.
458 $wp_scripts->add_data( $handle, 'group', 1 );
459 // Show a warning.
460 $error_handle = 'wc-settings-dep-in-header';
461 $used_deps = implode( ', ', array_intersect( $known_packages, $script->deps ) );
462 $error_message = "Scripts that have a dependency on [$used_deps] must be loaded in the footer, {$handle} was registered to load in the header, but has been switched to load in the footer instead. See https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5059";
463 // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NotInFooter,WordPress.WP.EnqueuedResourceParameters.MissingVersion
464 wp_register_script( $error_handle, '' );
465 wp_enqueue_script( $error_handle );
466 wp_add_inline_script(
467 $error_handle,
468 sprintf( 'console.warn( "%s" );', $error_message )
469 );
470
471 }
472 }
473 }
474
475 /**
476 * Enqueue the wc-entities script.
477 */
478 public function enqueue_wc_entities() {
479 wp_enqueue_script( 'wc-entities' );
480 }
481 }
482