PluginProbe
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More / 1.9.1
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More v1.9.1
2.3.0 2.2.0 2.1.1 2.1.0 2.0.0 1.10.0 1.9.1 1.9.0 1.2.1 1.2.2 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 All 59 releases
storeengine / includes / assets.php

assets.php in StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More 1.9.1, at includes/assets.php

531 lines 18.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace StoreEngine;
4
5 use StoreEngine\Admin\Notices;
6 use StoreEngine\Classes\Countries;
7 use StoreEngine\Classes\Product\VariableProduct;
8 use StoreEngine\Utils\ArrayUtil;
9 use StoreEngine\Utils\Formatting;
10 use StoreEngine\Utils\Helper;
11 use StoreEngine\Utils\PaymentUtil;
12 use StoreEngine\Utils\Pixel;
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit(); // Exit if accessed directly.
16 }
17
18 class Assets {
19
20 public static function init() {
21 $self = new self();
22 add_action( 'admin_enqueue_scripts', array( $self, 'enqueue_admin_menu_css' ) );
23 add_action( 'admin_enqueue_scripts', [ $self, 'backend_scripts' ] );
24 add_action( 'admin_enqueue_scripts', [ $self, 'backend_inline_style' ] );
25 add_action( 'wp_enqueue_scripts', [ $self, 'frontend_scripts' ] );
26 add_action( 'enqueue_block_editor_assets', [ $self, 'block_editor_assets' ] );
27 add_action( 'wp_footer', [ $self, 'display_price_placeholder' ] );
28 }
29
30 public function web_fonts_url( $font ): string {
31 $font_url = add_query_arg( 'family', rawurlencode( $font ), '//fonts.googleapis.com/css2' );
32
33 return add_query_arg( 'display', 'swap', $font_url );
34 }
35
36 public function enqueue_admin_menu_css( $hook ) {
37 wp_enqueue_style( 'storeengine-admin-menu', STOREENGINE_ASSETS_URI . 'css/menu.css', [], STOREENGINE_VERSION, 'all' );
38
39 if ( strpos( $hook, '_page_' . STOREENGINE_PLUGIN_SLUG ) !== false ) {
40 return;
41 }
42
43 Notices::init()->dispatch_notices();
44 if ( ! empty( Admin\Notices::get_notices() ) ) {
45 wp_enqueue_style( 'storeengine-admin-notice', STOREENGINE_ASSETS_URI . 'css/notices.css', [], STOREENGINE_VERSION, 'all' );
46 wp_add_inline_style( 'storeengine-admin-notice', $this->get_dynamic_css() );
47 wp_enqueue_style(
48 'storeengine-frontend-icon',
49 STOREENGINE_ASSETS_URI . 'library/icons/storeengine-icons.css',
50 [],
51 filemtime( STOREENGINE_ASSETS_DIR_PATH . 'library/icons/storeengine-icons.css' )
52 );
53 }
54 }
55
56 public function frontend_scripts() {
57 // Icon Library.
58 wp_enqueue_style(
59 'storeengine-frontend-icon',
60 STOREENGINE_ASSETS_URI . 'library/icons/storeengine-icons.css',
61 [ 'wp-components' ],
62 filemtime(
63 STOREENGINE_ASSETS_DIR_PATH .
64 'library/icons/storeengine-icons.css'
65 ),
66 'all'
67 );
68
69 // Main Stylesheet.
70 wp_enqueue_style(
71 'storeengine-frontend-style',
72 STOREENGINE_ASSETS_URI . 'build/frontend.css',
73 [],
74 filemtime( STOREENGINE_ASSETS_DIR_PATH . 'build/frontend.css' ),
75 'all'
76 );
77
78 // Add dynamic CSS variables.
79 wp_add_inline_style( 'storeengine-frontend-style', $this->get_dynamic_css() );
80
81 wp_enqueue_style( 'storeengine-web-font', $this->web_fonts_url( 'Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900' ) ); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
82
83 // Add Flickity CSS.
84 if ( Helper::is_product() ) {
85 wp_enqueue_style(
86 'flickity',
87 STOREENGINE_ASSETS_URI . 'library/flickity/flickity.min.css',
88 [],
89 STOREENGINE_VERSION,
90 null
91 );
92 }
93
94 // JS — use `include` (not `include_once`) so a second hook invocation in
95 // the same request still gets the array; `*_once` returns int(1) after
96 // the first include and breaks the array_merge below.
97 $asset_file = STOREENGINE_ASSETS_DIR_PATH . sprintf( 'build/frontend.%s.asset.php', STOREENGINE_VERSION );
98 $dependencies = is_file( $asset_file ) ? include $asset_file : null;
99 if ( ! is_array( $dependencies ) ) {
100 $dependencies = [ 'dependencies' => [], 'version' => STOREENGINE_VERSION ];
101 }
102
103 do_action( 'storeengine/enqueue_frontend_scripts' );
104
105 wp_enqueue_script(
106 'storeengine-frontend-scripts',
107 STOREENGINE_ASSETS_URI .
108 sprintf( 'build/frontend.%s.js', STOREENGINE_VERSION ),
109 array_merge( [ 'jquery', 'wp-util' ], (array) ( $dependencies['dependencies'] ?? [] ) ),
110 $dependencies['version'] ?? STOREENGINE_VERSION,
111 true
112 );
113
114 if ( Helper::is_product() ) {
115 global $product;
116
117 if ( $product instanceof VariableProduct && 'variable' === $product->get_type() ) {
118 wp_localize_script(
119 'storeengine-frontend-scripts',
120 'StoreEngineProductVariations',
121 self::get_product_variations( $product )
122 );
123 }
124
125 }
126
127 $analytics = (array) Helper::get_settings( 'analytics', [] );
128 if ( ArrayUtil::any( $analytics, fn( $stat ) => true === $stat ) ) {
129 $data = [];
130 if ( Helper::is_product() ) {
131 $data = Pixel::get_single_product_data();
132 }
133 if ( Helper::is_shop() ) {
134 $data = Pixel::get_product_archive_data();
135 }
136 if ( Helper::is_cart() || Helper::is_checkout() ) {
137 $data = [ 'cart_info' => Pixel::get_cart_info() ];
138 }
139 wp_localize_script(
140 'storeengine-frontend-scripts',
141 'SEPixelData',
142 array_merge(
143 [
144 'page_title' => wp_get_document_title(),
145 'currency' => Formatting::get_currency(),
146 ],
147 $data
148 )
149 );
150 }
151
152 wp_localize_script(
153 'storeengine-frontend-scripts',
154 'StoreEngineGlobal',
155 $this->get_frontend_script_data()
156 );
157
158 wp_set_script_translations(
159 'storeengine-frontend-scripts',
160 'storeengine',
161 STOREENGINE_ROOT_DIR_PATH . 'languages'
162 );
163
164 // Add Flickity JS
165 if ( Helper::is_product() ) {
166 wp_enqueue_script(
167 'flickity',
168 STOREENGINE_ASSETS_URI . 'library/flickity/flickity.pkgd.min.js',
169 [],
170 STOREENGINE_VERSION,
171 true
172 );
173 }
174
175 do_action( 'storeengine/assets/after_frontend_scripts' );
176 }
177
178 /**
179 * Enqueue Block Editor Assets
180 *
181 * @since 1.3.3
182 */
183 public function block_editor_assets() {
184 // Check if the aBlocks plugin is active before enqueuing styles.
185 if ( ! Helper::is_plugin_active( 'ablocks/ablocks.php' ) ) {
186 return;
187 }
188
189 // Icon Library.
190 wp_enqueue_style(
191 'storeengine-frontend-icon',
192 STOREENGINE_ASSETS_URI . 'library/icons/storeengine-icons.css',
193 [ 'wp-components' ],
194 filemtime(
195 STOREENGINE_ASSETS_DIR_PATH .
196 'library/icons/storeengine-icons.css'
197 ),
198 'all'
199 );
200
201 // Main Stylesheet.
202 wp_enqueue_style(
203 'storeengine-frontend-style',
204 STOREENGINE_ASSETS_URI . 'build/frontend.css',
205 [],
206 filemtime( STOREENGINE_ASSETS_DIR_PATH . 'build/frontend.css' ),
207 'all'
208 );
209
210 // Add dynamic CSS variables.
211 wp_add_inline_style( 'storeengine-frontend-style', $this->get_dynamic_css() );
212
213 wp_enqueue_style( 'storeengine-web-font', $this->web_fonts_url( 'Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900' ) ); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
214
215 // Add Flickity CSS.
216 wp_enqueue_style(
217 'flickity',
218 STOREENGINE_ASSETS_URI . 'library/flickity/flickity.min.css',
219 [],
220 STOREENGINE_VERSION,
221 null
222 );
223 }
224
225 public static function get_product_variations( VariableProduct $product ): array {
226 $pricing = [];
227 $taxonomies = [];
228 $variations = array_map( function ( $variant ) use ( &$taxonomies ) {
229 $attributes = [];
230 foreach ( $variant->get_attributes() as $attribute ) {
231 $attributes[ $attribute->taxonomy ] = $attribute->slug;
232 $taxonomies[] = $attribute->taxonomy;
233 }
234
235 return [
236 'id' => $variant->get_id(),
237 'name' => $variant->get_name(),
238 'price' => $variant->get_price(),
239 'sku' => $variant->get_sku(),
240 'pricing_id' => (int) $variant->get_pricing_id(),
241 'featured_image_url' => wp_get_attachment_image_url( $variant->get_featured_image() ),
242 'attributes' => $attributes,
243 ];
244 }, $product->get_available_variants() );
245
246 foreach ( $product->get_prices() as $price ) {
247 $pricing[ $price->get_id() ] = $price->get_price();
248 }
249
250 return [
251 'taxonomies' => array_values( array_unique( $taxonomies ) ),
252 'pricing' => $pricing,
253 'variations' => $variations,
254 ];
255 }
256
257 public function get_frontend_script_data() {
258 $data = [];
259
260 if ( Helper::is_checkout() || Helper::is_edit_address_page() ) {
261 $state_labels = array_filter( array_map( fn( $data ) => [
262 'label' => $data['state']['label'] ?? '',
263 'required' => $data['state']['required'] ?? false,
264 ], Countries::init()->get_country_locale() ) );
265 $states = array_merge( Countries::init()->get_allowed_country_states(), Countries::init()->get_shipping_country_states() );
266 $data = [
267 'states' => $states,
268 'state_labels' => $state_labels,
269 'state_label' => __( 'State / County', 'storeengine' ),
270 'is_required' => '&nbsp;<abbr class="storeengine-required" title="' . esc_attr__( 'Required', 'storeengine' ) . '">*</abbr>',
271 'i18n_select_state_text' => esc_attr__( 'Select an option&hellip;', 'storeengine' ),
272 'i18n_no_matches' => _x( 'No matches found', 'enhanced select', 'storeengine' ),
273 'i18n_ajax_error' => _x( 'Loading failed', 'enhanced select', 'storeengine' ),
274 'i18n_input_too_short_1' => _x( 'Please enter 1 or more characters', 'enhanced select', 'storeengine' ),
275 'i18n_input_too_short_n' => _x( 'Please enter %qty% or more characters', 'enhanced select', 'storeengine' ),
276 'i18n_input_too_long_1' => _x( 'Please delete 1 character', 'enhanced select', 'storeengine' ),
277 'i18n_input_too_long_n' => _x( 'Please delete %qty% characters', 'enhanced select', 'storeengine' ),
278 'i18n_selection_too_long_1' => _x( 'You can only select 1 item', 'enhanced select', 'storeengine' ),
279 'i18n_selection_too_long_n' => _x( 'You can only select %qty% items', 'enhanced select', 'storeengine' ),
280 'i18n_load_more' => _x( 'Loading more results&hellip;', 'enhanced select', 'storeengine' ),
281 'i18n_searching' => _x( 'Searching&hellip;', 'enhanced select', 'storeengine' ),
282 ];
283 }
284
285 $analytics = (array) Helper::get_settings( 'analytics', [] );
286 $hasAnalytics = ArrayUtil::any( $analytics, fn( $stat ) => true === $stat );
287
288 return apply_filters(
289 'storeengine/frontend_scripts_data',
290 array_merge(
291 $this->_get_script_data(),
292 [
293 'checkout_page_url' => esc_url( Helper::get_checkout_url() ),
294 'thankyou_page_url' => esc_url( Helper::get_thankyou_page_url() ),
295 'payment_gateways' => $this->get_payment_method_script_data(),
296 'payment_data' => [],
297 'checkout_with_order_pay' => Formatting::string_to_bool( get_query_var( 'order_pay' ) ),
298 'page' => [
299 'dashboard' => esc_url( Helper::get_dashboard_url() ),
300 'checkout' => esc_url( Helper::get_checkout_url() ),
301 'thankyou' => esc_url( Helper::get_thankyou_page_url() ),
302 'terms' => esc_url( Helper::get_terms_page_url() ),
303 'privacy' => esc_url( Helper::get_privacy_page_url() ),
304 ],
305 'is_page' => [
306 'is_product' => Helper::is_product(),
307 'is_shop' => Helper::is_shop(),
308 'is_cart' => Helper::is_cart(),
309 'is_dashboard' => Helper::is_dashboard_index(),
310 'is_address_edit' => Helper::is_edit_address_page(),
311 'is_checkout' => Helper::is_checkout(),
312 'is_order_pay' => Helper::is_checkout() && PaymentUtil::is_valid_order_pay_page(),
313 'is_add_payment_method' => Helper::is_add_payment_method_page(),
314 ],
315 'settings' => [
316 'analytics' => $hasAnalytics ? $analytics : false,
317 ]
318 ],
319 $data
320 )
321 );
322 }
323
324 public function _get_script_data(): array {
325 global $storeengine_addons;
326
327 $current_user = wp_get_current_user();
328 $user_name = ! is_email( $current_user->display_name ) ? $current_user->display_name : trim( $current_user->first_name . ' ' . $current_user->last_name );
329 $user_name = $user_name ?: $current_user->user_login;
330
331 return [
332 'is_admin' => is_admin(),
333 'nonce' => wp_create_nonce( 'wp_rest' ),
334 'storeengine_nonce' => wp_create_nonce( 'storeengine_nonce' ),
335 'rest_url' => esc_url_raw( rest_url() ),
336 'locale' => get_locale(),
337 'user_locale' => function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale(),
338 'namespace' => STOREENGINE_PLUGIN_SLUG . '/v1/',
339 'plugin_root_url' => STOREENGINE_PLUGIN_ROOT_URI,
340 'plugin_root_path' => STOREENGINE_ROOT_DIR_PATH,
341 'root_path' => STOREENGINE_ROOT_DIR_PATH,
342 'root_url' => STOREENGINE_PLUGIN_ROOT_URI,
343 'assets_url' => STOREENGINE_ASSETS_URI,
344 'ajaxurl' => esc_url( admin_url( 'admin-ajax.php' ) ),
345 'admin_url' => admin_url(),
346 'site_url' => site_url(),
347 'route_path' => wp_parse_url( admin_url(), PHP_URL_PATH ),
348 'admin_menu_lists' => wp_json_encode( Admin\Menu::get_menu_lists() ),
349 'current_user_id' => $current_user->ID,
350 'current_user_name' => $user_name,
351 'store_email' => Helper::get_settings( 'store_email' ),
352 'is_rtl' => is_rtl(),
353 'addons' => $storeengine_addons,
354 'timezone' => wp_timezone_string(),
355 'current_user_can' => [
356 'manage_options' => current_user_can( 'manage_options' ),
357 ],
358 'currency_options' => Helper::get_currency_options(),
359 'localeConv' => localeconv(),
360 'is_tax_enabled' => Helper::get_settings( 'enable_product_tax' ),
361 'enable_product_tax' => Helper::get_settings( 'enable_product_tax' ),
362 'is_pro' => Helper::is_active_storeengine_pro(),
363 'ablocks_status' => Helper::is_plugin_installed( 'ablocks/ablocks.php' ) ? ( Helper::is_plugin_active( 'ablocks/ablocks.php' ) ? 'active' : 'not-active' ) : 'not-installed',
364 ];
365 }
366
367 public function get_payment_method_script_data() {
368 $data = apply_filters( 'storeengine/frontend_scripts_payment_method_data', [] );
369
370 // Also walk every available gateway through the unified per-gateway
371 // data filter — `storeengine/checkout/gateway/{id}/data` — so third-
372 // party gateways that only hook the new public API still populate the
373 // legacy `payment_gateways.{id}` global that the /checkout/ page
374 // shells read from. The same filter feeds React Quick Checkout's
375 // snapshot, so one hook covers both surfaces.
376 try {
377 $gateways = Helper::get_payment_gateways()->get_available_payment_gateways();
378 } catch ( \Throwable $e ) {
379 $gateways = [];
380 }
381 foreach ( $gateways as $gateway ) {
382 $existing = isset( $data[ $gateway->id ] ) && is_array( $data[ $gateway->id ] ) ? $data[ $gateway->id ] : [];
383 $merged = apply_filters( "storeengine/checkout/gateway/{$gateway->id}/data", $existing, $gateway );
384 if ( is_array( $merged ) && ! empty( $merged ) ) {
385 $data[ $gateway->id ] = $merged;
386 }
387 }
388
389 return $data;
390 }
391
392 /**
393 * Enqueue Files on Start Plugin
394 *
395 * @param string $hook
396 *
397 * @function backend_scripts
398 */
399 public function backend_scripts( string $hook ) {
400 if ( ! strpos( $hook, '_page_' . STOREENGINE_PLUGIN_SLUG ) !== false ) {
401 return;
402 }
403
404 remove_all_actions( 'admin_notices' );
405
406 wp_enqueue_style(
407 'storeengine-admin-icon',
408 STOREENGINE_ASSETS_URI . 'library/icons/storeengine-icons.css',
409 [ 'wp-components' ],
410 filemtime(
411 STOREENGINE_ASSETS_DIR_PATH .
412 'library/icons/storeengine-icons.css'
413 ),
414 );
415
416 wp_enqueue_style(
417 'storeengine-admin-style',
418 STOREENGINE_ASSETS_URI . 'build/backend.css',
419 [ 'wp-components' ],
420 filemtime( STOREENGINE_ASSETS_DIR_PATH . 'build/backend.css' ),
421 'all'
422 );
423
424 wp_add_inline_style( 'storeengine-admin-style', $this->get_dynamic_css() );
425
426 if ( ! did_action( 'wp_enqueue_media' ) ) {
427 wp_enqueue_media();
428 }
429
430 // js — see note on the frontend equivalent above (use `include` so a
431 // second invocation in the same request still returns the array).
432 $asset_file = STOREENGINE_ASSETS_DIR_PATH . sprintf( 'build/backend.%s.asset.php', STOREENGINE_VERSION );
433 $dependencies = is_file( $asset_file ) ? include $asset_file : null;
434 if ( ! is_array( $dependencies ) ) {
435 $dependencies = [ 'dependencies' => [], 'version' => STOREENGINE_VERSION ];
436 }
437
438 wp_enqueue_script(
439 'storeengine-admin-scripts',
440 STOREENGINE_ASSETS_URI .
441 sprintf( 'build/backend.%s.js', STOREENGINE_VERSION ),
442 (array) ( $dependencies['dependencies'] ?? [] ),
443 $dependencies['version'] ?? STOREENGINE_VERSION,
444 true
445 );
446 wp_localize_script(
447 'storeengine-admin-scripts',
448 'StoreEngineGlobal',
449 $this->get_backend_script_data()
450 );
451 wp_set_script_translations(
452 'storeengine-admin-scripts',
453 'storeengine',
454 STOREENGINE_ROOT_DIR_PATH . 'i18n/languages'
455 );
456 }
457
458 public function get_backend_script_data(): array {
459 $currencies = [];
460
461 foreach ( Helper::get_currencies() as $code => $label ) {
462 $currencies[] = [
463 'code' => $code,
464 'name' => $label,
465 'symbol' => Helper::get_currency_symbol( $code ),
466 ];
467 }
468
469 return apply_filters(
470 'storeengine/backend_scripts_data',
471 array_merge(
472 $this->_get_script_data(),
473 [
474 'first_order' => Helper::get_first_order_date( 'Y-m-d' ),
475 'currency_options' => Helper::get_currency_options(),
476 'localeConv' => localeconv(),
477 'countries' => Countries::init()->get_countries(),
478 'currencies' => $currencies,
479 'enable_after_purchase_redirect' => Helper::get_settings( 'enable_after_purchase_redirect', false ),
480 'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG,
481 ]
482 )
483 );
484 }
485
486 public function get_dynamic_css(): string {
487 global $storeengine_settings;
488
489 /**
490 * Filter css properties
491 */
492 $css = apply_filters( 'storeengine/dynamic_css_root_properties', [
493 '--storeengine-primary-color' => esc_attr( $storeengine_settings->global_primary_color ?? '' ),
494 '--storeengine-secondary-color' => esc_attr( $storeengine_settings->global_secondary_color ?? '' ),
495 '--storeengine-text-color' => esc_attr( $storeengine_settings->global_text_color ?? '' ),
496 '--storeengine-subtitle-color' => esc_attr( $storeengine_settings->global_subtitle_color ?? '' ),
497 '--storeengine-input-text-color' => esc_attr( $storeengine_settings->global_input_text_color ?? '' ),
498 '--storeengine-placeholder-color' => esc_attr( $storeengine_settings->global_placeholder_color ?? '' ),
499 '--storeengine-border-color' => esc_attr( $storeengine_settings->global_border_color ?? '' ),
500 '--storeengine-background-color' => esc_attr( $storeengine_settings->global_background_color ?? '' ),
501 ] );
502
503 // Filter out empty values to avoid invalid CSS.
504 $filtered_css = array_filter( $css, fn( $value ) => trim( ltrim( rtrim( $value, ';' ), ':' ) ) !== '' );
505
506 return ':root {' . PHP_EOL . implode( PHP_EOL, array_map( fn( $key, $value ) => "\t$key:$value;", array_keys( $filtered_css ), $filtered_css ) ) . PHP_EOL . '}';
507 }
508
509 public function display_price_placeholder() {
510 ?>
511 <script type="text/html" id="tmpl-storeengine-price">
512 <p class="storeengine-product__price-amount">
513 {{{ data.price }}}
514 </p>
515 </script>
516 <?php
517 }
518
519 public function backend_inline_style() {
520 $custom_css = '
521 a[href*="page=storeengine-get-pro"] {
522 background: #FFA500 !important;
523 color: #000000 !important;
524 font-weight: 600;
525 box-shadow: none !important;
526 }
527 ';
528 wp_add_inline_style( 'admin-bar', $custom_css );
529 }
530 }
531