PluginProbe
WooCommerce / 11.1.0-rc.2
WooCommerce v11.1.0-rc.2
11.1.0 11.1.0-rc.2 11.1.0-rc.1 11.1.0-beta.2 11.1.0-beta.1 11.0.1 11.0.0 11.0.0-rc.3 11.0.0-rc.2 11.0.0-rc.1 11.0.0-beta.2 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 All 648 releases
woocommerce / includes / class-wc-frontend-scripts.php
class-wc-frontend-scripts.php
834 lines 34.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handle frontend scripts
4 *
5 * @package WooCommerce\Classes
6 * @version 3.9.0
7 * @since 2.3.0
8 */
9
10 // phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment
11
12 use Automattic\Jetpack\Constants;
13 use Automattic\WooCommerce\Admin\Features\Features;
14 use Automattic\WooCommerce\Enums\DefaultCustomerAddress;
15 use Automattic\WooCommerce\Internal\AddressProvider\AddressProviderController;
16
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit;
19 }
20
21 /**
22 * Frontend scripts class.
23 *
24 * These scripts are enqueued in the frontend of the store. The registered script handles in this class
25 * can be used to enqueue the scripts in the frontend by third party plugins and the handles will follow
26 * WooCommerce's L-1 support policy. Scripts registered outside of this class do not guarantee support
27 * and can be removed in future versions of WooCommerce.
28 */
29 class WC_Frontend_Scripts {
30
31 /**
32 * Contains an array of script handles registered by WC.
33 *
34 * @var array
35 */
36 private static $registered_scripts = array();
37
38 /**
39 * Contains an array of script handles registered by WC.
40 *
41 * @var array
42 */
43 private static $styles = array();
44
45 /**
46 * Contains an array of script handles localized by WC.
47 *
48 * @var array
49 */
50 private static $wp_localize_scripts = array();
51
52 /**
53 * Hook in methods.
54 */
55 public static function init() {
56 add_action( 'wp_enqueue_scripts', array( __CLASS__, 'load_scripts' ) );
57 add_action( 'wp_print_scripts', array( __CLASS__, 'localize_printed_scripts' ), 5 );
58 add_action( 'wp_print_footer_scripts', array( __CLASS__, 'localize_printed_scripts' ), 5 );
59 add_action( 'enqueue_block_assets', array( __CLASS__, 'enqueue_block_assets' ) );
60 }
61
62 /**
63 * Get styles for the frontend.
64 *
65 * @return array
66 */
67 public static function get_styles() {
68 $version = Constants::get_constant( 'WC_VERSION' );
69
70 /**
71 * Filter list of WooCommerce styles to enqueue.
72 *
73 * @since 2.1.0
74 * @param array List of default WooCommerce styles.
75 * @return array List of styles to enqueue.
76 */
77 $styles = apply_filters(
78 'woocommerce_enqueue_styles',
79 array(
80 'woocommerce-layout' => array(
81 'src' => self::get_asset_url( 'assets/css/woocommerce-layout.css' ),
82 'deps' => '',
83 'version' => $version,
84 'media' => 'all',
85 'has_rtl' => true,
86 ),
87 'woocommerce-smallscreen' => array(
88 'src' => self::get_asset_url( 'assets/css/woocommerce-smallscreen.css' ),
89 'deps' => 'woocommerce-layout',
90 'version' => $version,
91 'media' => 'only screen and (max-width: ' . apply_filters( 'woocommerce_style_smallscreen_breakpoint', '768px' ) . ')',
92 'has_rtl' => true,
93 ),
94 'woocommerce-general' => array(
95 'src' => self::get_asset_url( 'assets/css/woocommerce.css' ),
96 'deps' => '',
97 'version' => $version,
98 'media' => 'all',
99 'has_rtl' => true,
100 ),
101 )
102 );
103 return is_array( $styles ) ? array_filter( $styles ) : array();
104 }
105
106 /**
107 * Enqueue styles for block assets (both editor and frontend).
108 * This ensures compatibility with WordPress 6.9+ requirements.
109 */
110 public static function enqueue_block_assets() {
111 if ( ! wp_is_block_theme() ) {
112 return;
113 }
114
115 $version = Constants::get_constant( 'WC_VERSION' );
116
117 wp_enqueue_style(
118 'woocommerce-blocktheme',
119 self::get_asset_url( 'assets/css/woocommerce-blocktheme.css' ),
120 array(),
121 $version,
122 'all'
123 );
124
125 wp_style_add_data( 'woocommerce-blocktheme', 'rtl', 'replace' );
126 }
127
128 /**
129 * Return asset URL.
130 *
131 * @param string $path Assets path.
132 * @return string
133 */
134 private static function get_asset_url( $path ) {
135 return apply_filters( 'woocommerce_get_asset_url', plugins_url( $path, WC_PLUGIN_FILE ), $path );
136 }
137
138 /**
139 * Register a script for use.
140 *
141 * @uses wp_register_script()
142 * @param string $handle Name of the script. Should be unique.
143 * @param string $path Full URL of the script, or path of the script relative to the WordPress root directory.
144 * @param string[] $deps An array of registered script handles this script depends on.
145 * @param string $version String specifying script version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added.
146 * @param boolean|array $in_footer Whether to enqueue the script before </body>, or an array of loading strategy arguments as accepted by wp_register_script(). Default 'defer' strategy.
147 */
148 private static function register_script( $handle, $path, $deps = array( 'jquery' ), $version = WC_VERSION, $in_footer = array( 'strategy' => 'defer' ) ) {
149 self::$registered_scripts[] = $handle;
150 wp_register_script( $handle, $path, $deps, $version, $in_footer );
151 }
152
153 /**
154 * Register and enqueue a script for use.
155 *
156 * @uses wp_enqueue_script()
157 * @param string $handle Name of the script. Should be unique.
158 * @param string $path Full URL of the script, or path of the script relative to the WordPress root directory.
159 * @param string[] $deps An array of registered script handles this script depends on.
160 * @param string $version String specifying script version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added.
161 * @param boolean|array $in_footer Whether to enqueue the script before </body>, or an array of loading strategy arguments as accepted by wp_enqueue_script(). Default 'defer' strategy.
162 */
163 private static function enqueue_script( $handle, $path = '', $deps = array( 'jquery' ), $version = WC_VERSION, $in_footer = array( 'strategy' => 'defer' ) ) {
164 if ( ! in_array( $handle, self::$registered_scripts, true ) && $path ) {
165 self::register_script( $handle, $path, $deps, $version, $in_footer );
166 }
167 wp_enqueue_script( $handle );
168 }
169
170 /**
171 * Register a style for use.
172 *
173 * @uses wp_register_style()
174 * @param string $handle Name of the stylesheet. Should be unique.
175 * @param string $path Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory.
176 * @param string[] $deps An array of registered stylesheet handles this stylesheet depends on.
177 * @param string $version String specifying stylesheet version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added.
178 * @param string $media The media for which this stylesheet has been defined. Accepts media types like 'all', 'print' and 'screen', or media queries like '(orientation: portrait)' and '(max-width: 640px)'.
179 * @param boolean $has_rtl If has RTL version to load too.
180 */
181 private static function register_style( $handle, $path, $deps = array(), $version = WC_VERSION, $media = 'all', $has_rtl = false ) {
182 self::$styles[] = $handle;
183 wp_register_style( $handle, $path, $deps, $version, $media );
184
185 if ( $has_rtl ) {
186 wp_style_add_data( $handle, 'rtl', 'replace' );
187 }
188 }
189
190 /**
191 * Register and enqueue a styles for use.
192 *
193 * @uses wp_enqueue_style()
194 * @param string $handle Name of the stylesheet. Should be unique.
195 * @param string $path Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory.
196 * @param string[] $deps An array of registered stylesheet handles this stylesheet depends on.
197 * @param string $version String specifying stylesheet version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added.
198 * @param string $media The media for which this stylesheet has been defined. Accepts media types like 'all', 'print' and 'screen', or media queries like '(orientation: portrait)' and '(max-width: 640px)'.
199 * @param boolean $has_rtl If has RTL version to load too.
200 */
201 private static function enqueue_style( $handle, $path = '', $deps = array(), $version = WC_VERSION, $media = 'all', $has_rtl = false ) {
202 if ( ! in_array( $handle, self::$styles, true ) && $path ) {
203 self::register_style( $handle, $path, $deps, $version, $media, $has_rtl );
204 }
205 wp_enqueue_style( $handle );
206 }
207
208 /**
209 * Get scripts for the frontend.
210 *
211 * @return array
212 */
213 private static function get_scripts(): array {
214 $suffix = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
215 $version = Constants::get_constant( 'WC_VERSION' );
216
217 $scripts = array(
218 'selectWoo' => array(
219 'src' => self::get_asset_url( 'assets/js/selectWoo/selectWoo.full' . $suffix . '.js' ),
220 'deps' => array( 'jquery' ),
221 'version' => '1.0.9-wc.' . $version,
222 ),
223 'wc-account-i18n' => array(
224 'src' => self::get_asset_url( 'assets/js/frontend/account-i18n' . $suffix . '.js' ),
225 'deps' => array( 'jquery' ),
226 'version' => $version,
227 ),
228 'wc-add-payment-method' => array(
229 'src' => self::get_asset_url( 'assets/js/frontend/add-payment-method' . $suffix . '.js' ),
230 'deps' => array( 'jquery', 'woocommerce', 'wc-custom-place-order-button' ),
231 'version' => $version,
232 ),
233 'wc-add-to-cart' => array(
234 'src' => self::get_asset_url( 'assets/js/frontend/add-to-cart' . $suffix . '.js' ),
235 'deps' => array( 'jquery', 'wc-jquery-blockui' ),
236 'version' => $version,
237 ),
238 'wc-add-to-cart-variation' => array(
239 'src' => self::get_asset_url( 'assets/js/frontend/add-to-cart-variation' . $suffix . '.js' ),
240 'deps' => array( 'jquery', 'wp-util', 'wc-jquery-blockui' ),
241 'version' => $version,
242 ),
243 'wc-address-i18n' => array(
244 'src' => self::get_asset_url( 'assets/js/frontend/address-i18n' . $suffix . '.js' ),
245 'deps' => array( 'jquery', 'wc-country-select' ),
246 'version' => $version,
247 ),
248 'wc-back-in-stock-form' => array(
249 'src' => self::get_asset_url( 'assets/js/frontend/back-in-stock-form' . $suffix . '.js' ),
250 'deps' => array( 'jquery' ),
251 'version' => $version,
252 ),
253 'wc-cart' => array(
254 'src' => self::get_asset_url( 'assets/js/frontend/cart' . $suffix . '.js' ),
255 'deps' => array( 'jquery', 'woocommerce', 'wc-country-select', 'wc-address-i18n' ),
256 'version' => $version,
257 ),
258 'wc-cart-fragments' => array(
259 'src' => self::get_asset_url( 'assets/js/frontend/cart-fragments' . $suffix . '.js' ),
260 'deps' => array( 'jquery', 'wc-js-cookie' ),
261 'version' => $version,
262 ),
263 'wc-checkout' => array(
264 'src' => self::get_asset_url( 'assets/js/frontend/checkout' . $suffix . '.js' ),
265 'deps' => array(
266 'jquery',
267 'woocommerce',
268 'wc-country-select',
269 'wc-address-i18n',
270 'wc-custom-place-order-button',
271 ),
272 'version' => $version,
273 ),
274 'wc-country-select' => array(
275 'src' => self::get_asset_url( 'assets/js/frontend/country-select' . $suffix . '.js' ),
276 'deps' => array( 'jquery' ),
277 'version' => $version,
278 ),
279 'wc-credit-card-form' => array(
280 'src' => self::get_asset_url( 'assets/js/frontend/credit-card-form' . $suffix . '.js' ),
281 'deps' => array( 'jquery', 'wc-jquery-payment' ),
282 'version' => $version,
283 ),
284 'wc-custom-place-order-button' => array(
285 'src' => self::get_asset_url( 'assets/js/frontend/utils/custom-place-order-button' . $suffix . '.js' ),
286 'deps' => array( 'jquery' ),
287 'version' => $version,
288 ),
289 'wc-dompurify' => array(
290 'src' => self::get_asset_url( 'assets/js/dompurify/purify' . $suffix . '.js' ),
291 'deps' => array(),
292 'version' => $version,
293 ),
294 'wc-flexslider' => array(
295 'src' => self::get_asset_url( 'assets/js/flexslider/jquery.flexslider' . $suffix . '.js' ),
296 'deps' => array( 'jquery' ),
297 'version' => '2.7.2-wc.' . $version,
298 'legacy_handle' => 'flexslider',
299 ),
300 'wc-geolocation' => array(
301 'src' => self::get_asset_url( 'assets/js/frontend/geolocation' . $suffix . '.js' ),
302 'deps' => array( 'jquery' ),
303 'version' => $version,
304 ),
305 'wc-jquery-blockui' => array(
306 'src' => self::get_asset_url( 'assets/js/jquery-blockui/jquery.blockUI' . $suffix . '.js' ),
307 'deps' => array( 'jquery' ),
308 'version' => '2.7.0-wc.' . $version,
309 'legacy_handle' => 'jquery-blockui',
310 ),
311 'wc-jquery-cookie' => array(
312 'src' => self::get_asset_url( 'assets/js/jquery-cookie/jquery.cookie' . $suffix . '.js' ),
313 'deps' => array( 'jquery' ),
314 'version' => '1.4.1-wc.' . $version,
315 'legacy_handle' => 'jquery-cookie',
316 ),
317 'wc-jquery-payment' => array(
318 'src' => self::get_asset_url( 'assets/js/jquery-payment/jquery.payment' . $suffix . '.js' ),
319 'deps' => array( 'jquery' ),
320 'version' => '3.0.0-wc.' . $version,
321 'legacy_handle' => 'jquery-payment',
322 ),
323 'wc-jquery-tiptip' => array(
324 'src' => self::get_asset_url( 'assets/js/jquery-tiptip/jquery.tipTip' . $suffix . '.js' ),
325 'deps' => array( 'jquery', 'wc-dompurify' ),
326 'version' => $version,
327 'legacy_handle' => 'jquery-tiptip',
328 ),
329 'wc-js-cookie' => array(
330 'src' => self::get_asset_url( 'assets/js/js-cookie/js.cookie' . $suffix . '.js' ),
331 'deps' => array(),
332 'version' => '2.1.4-wc.' . $version,
333 'legacy_handle' => 'js-cookie',
334 ),
335 'wc-lost-password' => array(
336 'src' => self::get_asset_url( 'assets/js/frontend/lost-password' . $suffix . '.js' ),
337 'deps' => array( 'jquery', 'woocommerce' ),
338 'version' => $version,
339 ),
340 'wc-password-strength-meter' => array(
341 'src' => self::get_asset_url( 'assets/js/frontend/password-strength-meter' . $suffix . '.js' ),
342 'deps' => array( 'jquery', 'password-strength-meter' ),
343 'version' => $version,
344 ),
345 'wc-photoswipe' => array(
346 'src' => self::get_asset_url( 'assets/js/photoswipe/photoswipe' . $suffix . '.js' ),
347 'deps' => array(),
348 'version' => '4.1.1-wc.' . $version,
349 'legacy_handle' => 'photoswipe',
350 ),
351 'wc-photoswipe-ui-default' => array(
352 'src' => self::get_asset_url( 'assets/js/photoswipe/photoswipe-ui-default' . $suffix . '.js' ),
353 'deps' => array( 'wc-photoswipe' ),
354 'version' => '4.1.1-wc.' . $version,
355 'legacy_handle' => 'photoswipe-ui-default',
356 ),
357 'wc-prettyPhoto' => array( // deprecated.
358 'src' => self::get_asset_url( 'assets/js/prettyPhoto/jquery.prettyPhoto' . $suffix . '.js' ),
359 'deps' => array( 'jquery' ),
360 'version' => '3.1.6-wc.' . $version,
361 'legacy_handle' => 'prettyPhoto',
362 ),
363 'wc-prettyPhoto-init' => array( // deprecated.
364 'src' => self::get_asset_url( 'assets/js/prettyPhoto/jquery.prettyPhoto.init' . $suffix . '.js' ),
365 'deps' => array( 'jquery', 'wc-prettyPhoto' ),
366 'version' => $version,
367 'legacy_handle' => 'prettyPhoto-init',
368 ),
369 'wc-select2' => array(
370 'src' => self::get_asset_url( 'assets/js/select2/select2.full' . $suffix . '.js' ),
371 'deps' => array( 'jquery' ),
372 'version' => '4.0.3-wc.' . $version,
373 'legacy_handle' => 'select2',
374 ),
375 'wc-single-product' => array(
376 'src' => self::get_asset_url( 'assets/js/frontend/single-product' . $suffix . '.js' ),
377 'deps' => array( 'jquery' ),
378 'version' => $version,
379 ),
380 'wc-zoom' => array(
381 'src' => self::get_asset_url( 'assets/js/zoom/jquery.zoom' . $suffix . '.js' ),
382 'deps' => array( 'jquery' ),
383 'version' => '1.7.21-wc.' . $version,
384 'legacy_handle' => 'zoom',
385 ),
386 'woocommerce' => array(
387 'src' => self::get_asset_url( 'assets/js/frontend/woocommerce' . $suffix . '.js' ),
388 'deps' => array( 'jquery', 'wc-jquery-blockui', 'wc-js-cookie' ),
389 'version' => $version,
390 ),
391 );
392
393 if ( wc_string_to_bool( get_option( 'woocommerce_address_autocomplete_enabled', 'no' ) ) === true ) {
394 $scripts['wc-address-autocomplete-common'] = array(
395 'src' => self::get_asset_url( 'assets/js/frontend/utils/address-autocomplete-common' . $suffix . '.js' ),
396 'deps' => array(),
397 'version' => $version,
398 );
399
400 $scripts['wc-address-autocomplete'] = array(
401 'src' => self::get_asset_url( 'assets/js/frontend/address-autocomplete' . $suffix . '.js' ),
402 'deps' => array( 'wc-address-autocomplete-common', 'wc-dompurify' ),
403 'version' => $version,
404 );
405 }
406
407 return $scripts;
408 }
409
410 /**
411 * Register all WC scripts.
412 */
413 private static function register_scripts() {
414 $register_scripts = self::get_scripts();
415
416 foreach ( $register_scripts as $name => $props ) {
417 self::register_script( $name, $props['src'], $props['deps'], $props['version'] );
418
419 if ( isset( $props['legacy_handle'] ) ) {
420 self::register_script( $props['legacy_handle'], false, array( $name ), $props['version'], true );
421 }
422 }
423 }
424
425 /**
426 * Register all WC styles.
427 */
428 private static function register_styles() {
429 $version = Constants::get_constant( 'WC_VERSION' );
430
431 $register_styles = array(
432 'photoswipe' => array(
433 'src' => self::get_asset_url( 'assets/css/photoswipe/photoswipe.min.css' ),
434 'deps' => array(),
435 'version' => $version,
436 'has_rtl' => false,
437 ),
438 'photoswipe-default-skin' => array(
439 'src' => self::get_asset_url( 'assets/css/photoswipe/default-skin/default-skin.min.css' ),
440 'deps' => array( 'photoswipe' ),
441 'version' => $version,
442 'has_rtl' => false,
443 ),
444 'select2' => array(
445 'src' => self::get_asset_url( 'assets/css/select2.css' ),
446 'deps' => array(),
447 'version' => $version,
448 'has_rtl' => false,
449 ),
450 'woocommerce_prettyPhoto_css' => array( // deprecated.
451 'src' => self::get_asset_url( 'assets/css/prettyPhoto.css' ),
452 'deps' => array(),
453 'version' => $version,
454 'has_rtl' => true,
455 ),
456 );
457
458 if ( wc_string_to_bool( get_option( 'woocommerce_address_autocomplete_enabled', 'no' ) ) === true ) {
459 $register_styles['wc-address-autocomplete'] = array(
460 'src' => self::get_asset_url( 'assets/css/address-autocomplete.css' ),
461 'deps' => array(),
462 'version' => $version,
463 'has_rtl' => false,
464 );
465 }
466
467 foreach ( $register_styles as $name => $props ) {
468 self::register_style( $name, $props['src'], $props['deps'], $props['version'], 'all', $props['has_rtl'] );
469 }
470 }
471
472 /**
473 * Register/queue frontend scripts.
474 */
475 public static function load_scripts() {
476 global $post;
477
478 if ( ! did_action( 'before_woocommerce_init' ) ) {
479 return;
480 }
481
482 self::register_scripts();
483 self::register_styles();
484
485 if ( 'yes' === get_option( 'woocommerce_enable_ajax_add_to_cart' ) ) {
486 self::enqueue_script( 'wc-add-to-cart' );
487 }
488 if ( is_cart() ) {
489 self::enqueue_script( 'wc-cart' );
490 }
491 if ( is_cart() || is_checkout() || is_account_page() ) {
492 self::enqueue_script( 'selectWoo' );
493 self::enqueue_style( 'select2' );
494
495 // Password strength meter. Load in checkout, account login and edit account page.
496 if ( ( 'no' === get_option( 'woocommerce_registration_generate_password' ) && ! is_user_logged_in() ) || is_edit_account_page() || is_lost_password_page() ) {
497 self::enqueue_script( 'wc-password-strength-meter' );
498 }
499 }
500 if ( is_account_page() ) {
501 self::enqueue_script( 'wc-account-i18n' );
502 }
503 if ( is_checkout() ) {
504 self::enqueue_script( 'wc-checkout' );
505 }
506
507 if ( wc_string_to_bool( get_option( 'woocommerce_address_autocomplete_enabled', 'no' ) ) === true ) {
508 $address_provider_service = wc_get_container()->get( AddressProviderController::class );
509 if ( $address_provider_service && method_exists( $address_provider_service, 'get_providers' ) ) {
510 $registered_providers = $address_provider_service->get_providers();
511 if ( is_array( $registered_providers ) && count( $registered_providers ) > 0 ) {
512 // Always enqueue the common module if providers are registered.
513 self::enqueue_script( 'wc-address-autocomplete-common' );
514 self::enqueue_script( 'wc-address-autocomplete' );
515 self::enqueue_style( 'wc-address-autocomplete' );
516 }
517 }
518 }
519
520 if ( is_add_payment_method_page() ) {
521 self::enqueue_script( 'wc-add-payment-method' );
522 }
523 if ( is_lost_password_page() ) {
524 self::enqueue_script( 'wc-lost-password' );
525 }
526
527 // Load gallery scripts on product pages only if supported.
528 if ( ( is_product() && ! wp_is_block_theme() ) || ( ! empty( $post->post_content ) && strstr( $post->post_content, '[product_page' ) ) ) {
529 if ( current_theme_supports( 'wc-product-gallery-zoom' ) ) {
530 self::enqueue_script( 'wc-zoom' );
531 }
532 if ( current_theme_supports( 'wc-product-gallery-slider' ) ) {
533 self::enqueue_script( 'wc-flexslider' );
534 }
535 if ( current_theme_supports( 'wc-product-gallery-lightbox' ) ) {
536 self::enqueue_script( 'wc-photoswipe-ui-default' );
537 self::enqueue_style( 'photoswipe-default-skin' );
538 add_action( 'wp_footer', 'woocommerce_photoswipe' );
539 }
540
541 self::enqueue_script( 'wc-single-product' );
542 }
543
544 // Only enqueue the geolocation script if the Default Current Address is set to "Geolocate
545 // (with Page Caching Support) and outside of the cart, checkout, account and customizer preview.
546 if (
547 DefaultCustomerAddress::GEOLOCATION_AJAX === get_option( 'woocommerce_default_customer_address' )
548 && ! ( is_cart() || is_account_page() || is_checkout() || is_customize_preview() )
549 ) {
550 $ua = strtolower( wc_get_user_agent() ); // Exclude common bots from geolocation by user agent.
551
552 if ( ! strstr( $ua, 'bot' ) && ! strstr( $ua, 'spider' ) && ! strstr( $ua, 'crawl' ) ) {
553 self::enqueue_script( 'wc-geolocation' );
554 }
555 }
556
557 // Global frontend scripts.
558 self::enqueue_script( 'woocommerce' );
559
560 // CSS Styles.
561 $enqueue_styles = self::get_styles();
562 if ( $enqueue_styles ) {
563 foreach ( $enqueue_styles as $handle => $args ) {
564 if ( ! isset( $args['has_rtl'] ) ) {
565 $args['has_rtl'] = false;
566 }
567
568 self::enqueue_style( $handle, $args['src'], $args['deps'], $args['version'], $args['media'], $args['has_rtl'] );
569 }
570 }
571
572 // Placeholder style.
573 wp_register_style( 'woocommerce-inline', false ); // phpcs:ignore
574 wp_enqueue_style( 'woocommerce-inline' );
575
576 if ( true === wc_string_to_bool( get_option( 'woocommerce_checkout_highlight_required_fields', 'yes' ) ) ) {
577 wp_add_inline_style( 'woocommerce-inline', '.woocommerce form .form-row .required { visibility: visible; }' );
578 } else {
579 wp_add_inline_style( 'woocommerce-inline', '.woocommerce form .form-row .required { visibility: hidden; }' );
580 }
581 }
582
583 /**
584 * Localize a WC script once.
585 *
586 * @since 2.3.0 this needs less wp_script_is() calls due to https://core.trac.wordpress.org/ticket/28404 being added in WP 4.0.
587 * @param string $handle Script handle the data will be attached to.
588 */
589 private static function localize_script( $handle ) {
590 if ( ! in_array( $handle, self::$wp_localize_scripts, true ) && wp_script_is( $handle ) ) {
591 $data = self::get_script_data( $handle );
592
593 if ( ! $data ) {
594 return;
595 }
596
597 $name = str_replace( '-', '_', $handle ) . '_params';
598 self::$wp_localize_scripts[] = $handle;
599 wp_localize_script( $handle, $name, apply_filters( $name, $data ) );
600 }
601 }
602
603 /**
604 * Return data for script handles.
605 *
606 * @param string $handle Script handle the data will be attached to.
607 * @return array|bool
608 */
609 private static function get_script_data( $handle ) {
610 global $wp;
611
612 switch ( $handle ) {
613 case 'woocommerce':
614 $params = array(
615 'ajax_url' => WC()->ajax_url(),
616 'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
617 'i18n_password_show' => esc_attr__( 'Show password', 'woocommerce' ),
618 'i18n_password_hide' => esc_attr__( 'Hide password', 'woocommerce' ),
619 );
620 break;
621 case 'wc-geolocation':
622 $params = array(
623 'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
624 'home_url' => remove_query_arg( 'lang', home_url() ), // FIX for WPML compatibility.
625 );
626 break;
627 case 'wc-single-product':
628 $params = array(
629 'i18n_required_rating_text' => esc_attr__( 'Please select a rating', 'woocommerce' ),
630 'i18n_rating_options' => array(
631 esc_attr__( '1 of 5 stars', 'woocommerce' ),
632 esc_attr__( '2 of 5 stars', 'woocommerce' ),
633 esc_attr__( '3 of 5 stars', 'woocommerce' ),
634 esc_attr__( '4 of 5 stars', 'woocommerce' ),
635 esc_attr__( '5 of 5 stars', 'woocommerce' ),
636 ),
637 'i18n_product_gallery_trigger_text' => esc_attr__( 'View full-screen image gallery', 'woocommerce' ),
638 'review_rating_required' => wc_review_ratings_required() ? 'yes' : 'no',
639 'flexslider' => apply_filters(
640 'woocommerce_single_product_carousel_options',
641 array(
642 'rtl' => is_rtl(),
643 'animation' => 'slide',
644 'smoothHeight' => true,
645 'directionNav' => false,
646 'controlNav' => 'thumbnails',
647 'slideshow' => false,
648 'animationSpeed' => 500,
649 'animationLoop' => false, // Breaks photoswipe pagination if true.
650 'allowOneSlide' => false,
651 )
652 ),
653 'zoom_enabled' => apply_filters( 'woocommerce_single_product_zoom_enabled', get_theme_support( 'wc-product-gallery-zoom' ) ),
654 'zoom_options' => apply_filters( 'woocommerce_single_product_zoom_options', array() ),
655 'photoswipe_enabled' => apply_filters( 'woocommerce_single_product_photoswipe_enabled', get_theme_support( 'wc-product-gallery-lightbox' ) ),
656 'photoswipe_options' => apply_filters(
657 'woocommerce_single_product_photoswipe_options',
658 array(
659 'shareEl' => false,
660 'closeOnScroll' => false,
661 'history' => false,
662 'hideAnimationDuration' => 0,
663 'showAnimationDuration' => 0,
664 )
665 ),
666 'flexslider_enabled' => apply_filters( 'woocommerce_single_product_flexslider_enabled', get_theme_support( 'wc-product-gallery-slider' ) ),
667 );
668 break;
669 case 'wc-checkout':
670 $params = array(
671 'ajax_url' => WC()->ajax_url(),
672 'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
673 'update_order_review_nonce' => wp_create_nonce( 'update-order-review' ),
674 'apply_coupon_nonce' => wp_create_nonce( 'apply-coupon' ),
675 'remove_coupon_nonce' => wp_create_nonce( 'remove-coupon' ),
676 'option_guest_checkout' => get_option( 'woocommerce_enable_guest_checkout' ),
677 'checkout_url' => WC_AJAX::get_endpoint( 'checkout' ),
678 'is_checkout' => is_checkout() && empty( $wp->query_vars['order-pay'] ) && ! isset( $wp->query_vars['order-received'] ) ? 1 : 0,
679 'debug_mode' => Constants::is_true( 'WP_DEBUG' ),
680 /* translators: %s: Order history URL on My Account section */
681 'i18n_checkout_error' => sprintf( esc_attr__( 'There was an error processing your order. Please check for any charges in your payment method and review your <a href="%s">order history</a> before placing the order again.', 'woocommerce' ), esc_url( wc_get_account_endpoint_url( 'orders' ) ) ),
682 'gateways_with_custom_place_order_button' => self::get_gateways_with_custom_place_order_button(),
683 );
684 break;
685 case 'wc-address-autocomplete-common':
686 $providers = array();
687 try {
688 $providers = wc_get_container()->get( AddressProviderController::class )->get_providers();
689 } catch ( Throwable $e ) {
690 wc_get_logger()->error( 'Could not get address providers for wc-address-autocomplete script: ' . $e->getMessage(), array( 'source' => 'address-autocomplete' ) );
691 }
692 $params = array(
693 'address_providers' => wp_json_encode(
694 array_map(
695 function ( $provider ) {
696 // Escape provider data before sending to frontend.
697 return array(
698 'id' => $provider->id,
699 'name' => $provider->name,
700 'branding_html' => wp_kses(
701 trim( (string) ( $provider->branding_html ?? '' ) ),
702 'post'
703 ),
704 );
705 },
706 $providers
707 ),
708 JSON_HEX_TAG | JSON_UNESCAPED_SLASHES
709 ),
710 );
711 break;
712 case 'wc-address-i18n':
713 $params = array(
714 'locale' => wp_json_encode( WC()->countries->get_country_locale(), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
715 'locale_fields' => wp_json_encode( WC()->countries->get_country_locale_field_selectors(), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
716 'i18n_required_text' => esc_attr__( 'required', 'woocommerce' ),
717 'i18n_optional_text' => esc_html__( 'optional', 'woocommerce' ),
718 );
719 break;
720 case 'wc-cart':
721 $params = array(
722 'ajax_url' => WC()->ajax_url(),
723 'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
724 'update_shipping_method_nonce' => wp_create_nonce( 'update-shipping-method' ),
725 'apply_coupon_nonce' => wp_create_nonce( 'apply-coupon' ),
726 'remove_coupon_nonce' => wp_create_nonce( 'remove-coupon' ),
727 );
728 break;
729 case 'wc-cart-fragments':
730 $params = array(
731 'ajax_url' => WC()->ajax_url(),
732 'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
733 'cart_hash_key' => apply_filters( 'woocommerce_cart_hash_key', 'wc_cart_hash_' . md5( get_current_blog_id() . '_' . get_site_url( get_current_blog_id(), '/' ) . get_template() ) ),
734 'fragment_name' => apply_filters( 'woocommerce_cart_fragment_name', 'wc_fragments_' . md5( get_current_blog_id() . '_' . get_site_url( get_current_blog_id(), '/' ) . get_template() ) ),
735 'request_timeout' => 5000,
736 );
737 break;
738 case 'wc-add-to-cart':
739 $params = array(
740 'ajax_url' => WC()->ajax_url(),
741 'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
742 'i18n_view_cart' => esc_attr__( 'View cart', 'woocommerce' ),
743 'cart_url' => apply_filters( 'woocommerce_add_to_cart_redirect', wc_get_cart_url(), null ),
744 'is_cart' => is_cart(),
745 'cart_redirect_after_add' => get_option( 'woocommerce_cart_redirect_after_add' ),
746 );
747 break;
748 case 'wc-add-payment-method':
749 $params = array(
750 'gateways_with_custom_place_order_button' => self::get_gateways_with_custom_place_order_button(),
751 );
752 break;
753 case 'wc-add-to-cart-variation':
754 // We also need the wp.template for this script :).
755 wc_get_template( 'single-product/add-to-cart/variation.php' );
756
757 $params = array(
758 'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
759 'i18n_no_matching_variations_text' => esc_attr__( 'Sorry, no products matched your selection. Please choose a different combination.', 'woocommerce' ),
760 'i18n_make_a_selection_text' => esc_attr__( 'Please select some product options before adding this product to your cart.', 'woocommerce' ),
761 'i18n_unavailable_text' => esc_attr__( 'Sorry, this product is unavailable. Please choose a different combination.', 'woocommerce' ),
762 'i18n_reset_alert_text' => esc_attr__( 'Your selection has been reset. Please select some product options before adding this product to your cart.', 'woocommerce' ),
763 );
764 break;
765 case 'wc-country-select':
766 $params = array(
767 'countries' => wp_json_encode( array_merge( WC()->countries->get_allowed_country_states(), WC()->countries->get_shipping_country_states() ), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
768 'i18n_select_state_text' => esc_attr__( 'Select an option&hellip;', 'woocommerce' ),
769 'i18n_no_matches' => _x( 'No matches found', 'enhanced select', 'woocommerce' ),
770 'i18n_ajax_error' => _x( 'Loading failed', 'enhanced select', 'woocommerce' ),
771 'i18n_input_too_short_1' => _x( 'Please enter 1 or more characters', 'enhanced select', 'woocommerce' ),
772 'i18n_input_too_short_n' => _x( 'Please enter %qty% or more characters', 'enhanced select', 'woocommerce' ),
773 'i18n_input_too_long_1' => _x( 'Please delete 1 character', 'enhanced select', 'woocommerce' ),
774 'i18n_input_too_long_n' => _x( 'Please delete %qty% characters', 'enhanced select', 'woocommerce' ),
775 'i18n_selection_too_long_1' => _x( 'You can only select 1 item', 'enhanced select', 'woocommerce' ),
776 'i18n_selection_too_long_n' => _x( 'You can only select %qty% items', 'enhanced select', 'woocommerce' ),
777 'i18n_load_more' => _x( 'Loading more results&hellip;', 'enhanced select', 'woocommerce' ),
778 'i18n_searching' => _x( 'Searching&hellip;', 'enhanced select', 'woocommerce' ),
779 );
780 break;
781 case 'wc-password-strength-meter':
782 $params = array(
783 'min_password_strength' => apply_filters( 'woocommerce_min_password_strength', 3 ),
784 'stop_checkout' => apply_filters( 'woocommerce_enforce_password_strength_meter_on_checkout', false ),
785 'i18n_password_error' => esc_attr__( 'Please enter a stronger password.', 'woocommerce' ),
786 'i18n_password_hint' => esc_attr( wp_get_password_hint() ),
787 );
788 break;
789 default:
790 $params = false;
791 }
792
793 $params = apply_filters_deprecated( $handle . '_params', array( $params ), '3.0.0', 'woocommerce_get_script_data' );
794
795 return apply_filters( 'woocommerce_get_script_data', $params, $handle );
796 }
797
798 /**
799 * Get a list of payment gateway IDs that have custom place order buttons.
800 *
801 * @return array List of gateway IDs with custom place order buttons.
802 */
803 private static function get_gateways_with_custom_place_order_button() {
804 $gateways_with_custom_button = array();
805
806 if ( ! WC()->payment_gateways() ) {
807 return $gateways_with_custom_button;
808 }
809
810 $available_gateways = WC()->payment_gateways()->get_available_payment_gateways();
811
812 foreach ( $available_gateways as $gateway ) {
813 // phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- Type hint for PHPStan.
814 /* @var WC_Payment_Gateway $gateway */
815 if ( true === $gateway->has_custom_place_order_button ) {
816 $gateways_with_custom_button[] = $gateway->id;
817 }
818 }
819
820 return $gateways_with_custom_button;
821 }
822
823 /**
824 * Localize scripts only when enqueued.
825 */
826 public static function localize_printed_scripts() {
827 foreach ( self::$registered_scripts as $handle ) {
828 self::localize_script( $handle );
829 }
830 }
831 }
832
833 WC_Frontend_Scripts::init();
834