PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk 1.2.0 All 47 releases
fluent-cart / app / Modules / Templating / AssetLoader.php

AssetLoader.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at app/Modules/Templating/AssetLoader.php

640 lines 23.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Modules\Templating;
4
5 use FluentCart\Api\CurrencySettings;
6 use FluentCart\Api\StoreSettings;
7 use FluentCart\App\App;
8 use FluentCart\App\Helpers\CartHelper;
9 use FluentCart\App\Helpers\Helper;
10 use FluentCart\App\Helpers\UtmHelper;
11 use FluentCart\App\Hooks\Cart\CartLoader;
12 use FluentCart\App\Hooks\Handlers\ShortCodes\CustomerProfileHandler;
13 use FluentCart\App\Models\Cart;
14 use FluentCart\App\Modules\Tax\TaxModule;
15 use FluentCart\App\Services\Localization\LocalizationManager;
16 use FluentCart\App\Services\Renderer\ProductFilterRender;
17 use FluentCart\App\Services\TemplateService;
18 use FluentCart\App\Services\Translations\TransStrings;
19 use FluentCart\App\Services\URL;
20 use FluentCart\App\Vite;
21 use FluentCart\App\Services\Renderer\CartRenderer;
22 use FluentCart\Framework\Support\Arr;
23 use FluentCart\Api\Resource\FrontendResource\CartResource;
24
25 class AssetLoader
26 {
27 static $loadedAssets = [];
28 protected static bool $frontendAssetsRequired = false;
29
30 public static function markFrontendAssetsRequired(): void
31 {
32 self::$frontendAssetsRequired = true;
33 }
34
35 public static function isFrontendAssetsMarked(): bool
36 {
37 return self::$frontendAssetsRequired;
38 }
39
40 public static function shouldLoadGlobalFrontendAssets(): bool
41 {
42 $shouldLoad = true;
43
44 return (bool) apply_filters('fluent_cart/frontend_assets/should_load_global', $shouldLoad, [
45 'page_type' => TemplateService::getCurrentFcPageType(),
46 'is_marked' => self::isFrontendAssetsMarked(),
47 'is_fluentcart_context' => self::isFluentCartContext(),
48 'is_instant_checkout' => (bool) App::request()->get(Helper::INSTANT_CHECKOUT_URL_PARAM),
49 'is_modal_checkout' => App::request()->get('fluent-cart') === 'modal_checkout',
50 ]);
51 }
52
53 public static function isFluentCartContext(): bool
54 {
55 if (self::isFrontendAssetsMarked()) {
56 return true;
57 }
58
59 $pageType = TemplateService::getCurrentFcPageType();
60 if (in_array($pageType, [
61 'single_product',
62 'product_taxonomy',
63 'shop',
64 'cart',
65 'checkout',
66 'registration',
67 'login'
68 ], true)) {
69 return true;
70 }
71
72 if (App::request()->get(Helper::INSTANT_CHECKOUT_URL_PARAM)) {
73 return true;
74 }
75
76 return App::request()->get('fluent-cart') === 'modal_checkout';
77 }
78
79 public static function register()
80 {
81 add_action('wp_enqueue_scripts', [self::class, 'enqueueAssets']);
82 }
83
84 public static function enqueueAssets()
85 {
86 $pageType = TemplateService::getCurrentFcPageType();
87
88 switch ($pageType) {
89 case 'single_product':
90 self::loadSingleProductAssets();
91 break;
92 case 'product_taxonomy':
93 case 'shop':
94 self::loadProductArchiveAssets();
95 break;
96 case 'customer_dashboard':
97 self::loadCustomerDashboardGlobalAssets();
98 break;
99 case 'cart':
100 self::loadCartAssets();
101 break;
102 case 'checkout':
103 self::loadCheckoutAssets();
104 break;
105 default:
106 return;
107 }
108 }
109
110 public static function loadSingleProductAssets()
111 {
112 self::markFrontendAssetsRequired();
113 static $isLoaded = false;
114 if ($isLoaded) {
115 return;
116 }
117 self::loadProductCardAssets();
118 $isLoaded = true;
119 $singlePageScripts = [
120 [
121 'source' => 'public/single-product/xzoom/xzoom.js',
122 'dependencies' => [],
123 'inFooter' => true,
124 ],
125 [
126 'source' => 'public/single-product/SingleProduct.js',
127 'dependencies' => [],
128 'inFooter' => true
129 ]
130 ];
131 $localizeData = [
132 'fluentcart_single_product_vars' => [
133 'trans' => TransStrings::singleProductPageString(),
134 'cart_button_text' => apply_filters('fluent_cart/product/add_to_cart_text', __('Add To Cart', 'fluent-cart'), []),
135 // App::storeSettings()->get('cart_button_text', __('Add to Cart', 'fluent-cart')),
136 'out_of_stock_button_text' => apply_filters('fluent_cart/product/out_of_stock_text', __('Not Available', 'fluent-cart'), []),
137
138 'buy_now_button_text' => apply_filters('fluent_cart/product/buy_now_button_text', __('Buy Now', 'fluent-cart'), []),
139 'in_stock_status' => Helper::IN_STOCK,
140 'out_of_stock_status' => Helper::OUT_OF_STOCK,
141 'enable_image_zoom' => (new StoreSettings())->get('enable_image_zoom_in_single_product'),
142 'enable_image_zoom_in_modal' => (new StoreSettings())->get('enable_image_zoom_in_modal')
143 ]
144 ];
145 Vite::enqueueAllScripts($singlePageScripts, 'fluent-cart-single-product-page', $localizeData);
146
147 $singlePageStyles = [
148 'public/single-product/single-product.scss',
149 'public/single-product/similar-product.scss',
150 'public/product-card/style/product-card.scss',
151 'public/single-product/xzoom/xzoom.css',
152 'public/buttons/add-to-cart/style/style.scss',
153 'public/buttons/direct-checkout/style/style.scss'
154 ];
155
156 Vite::enqueueAllStyles($singlePageStyles, 'fluent-cart-single-product-page');
157
158
159 }
160
161 public static function loadAddToCartCss()
162 {
163 self::markFrontendAssetsRequired();
164 $singlePageStyles = [
165 'public/buttons/add-to-cart/style/style.scss',
166 ];
167
168 Vite::enqueueAllStyles($singlePageStyles, 'fluent-cart-add-to-cart');
169 }
170
171 public static function loadModalCheckoutAssets()
172 {
173 static $isLoaded = false;
174 if ($isLoaded) {
175 return;
176 }
177
178 $isLoaded = true;
179
180 // $scripts = [
181 // 'source' => 'public/checkout/ModalCheckoutHandler.js',
182 // 'dependencies' => [],
183 // 'inFooter' => true
184 // ];
185
186 Vite::enqueueStyle(
187 'fluentcart-modal-checkout-css',
188 'public/checkout/style/modal-checkout.scss'
189 );
190
191 // Vite::enqueueAllScripts($scripts, 'fluent-cart-modal-checkout');
192 }
193
194 public static function loadProductCardAssets()
195 {
196 self::markFrontendAssetsRequired();
197 static $isLoaded = false;
198 if ($isLoaded) {
199 return;
200 }
201 $isLoaded = true;
202 $singlePageStyles = [
203 'public/product-card/style/product-card.scss',
204 ];
205 Vite::enqueueAllStyles($singlePageStyles, 'fluent-cart-product-card-page');
206 Vite::enqueueStyle(
207 'fluent-cart-sold-out-badge',
208 'admin/BlockEditor/SoldOutBadge/style/sold-out-badge-block-editor.scss'
209 );
210 Vite::enqueueStyle(
211 'fluent-cart-sale-badge',
212 'admin/BlockEditor/SaleBadge/style/sale-badge-block-editor.scss'
213 );
214 Vite::enqueueScript(
215 'fluent-cart-product-card-js',
216 'public/product-card/product-card.js',
217 [],
218 null,
219 true
220 );
221 }
222
223 public static function loadProductArchiveAssets()
224 {
225 self::markFrontendAssetsRequired();
226 static $isLoaded = false;
227 if ($isLoaded) {
228 return;
229 }
230 $isLoaded = true;
231 static::loadProductCardAssets();
232
233 $app = App::getInstance();
234 $slug = $app->config->get('app.slug');
235 Vite::enqueueStyle(
236 'fluentcart-product-card-page-css',
237 'public/product-card/style/product-card.scss'
238 );
239
240 Vite::enqueueStyle(
241 'fluentcart-single-product-css',
242 'public/single-product/single-product.scss'
243 );
244 Vite::enqueueStyle(
245 'fluentcart-similar-product-css',
246 'public/single-product/similar-product.scss'
247 );
248 Vite::enqueueStyle(
249 'fluentcart-add-to-cart-btn-css',
250 'public/buttons/add-to-cart/style/style.scss'
251 );
252 Vite::enqueueStyle(
253 'fluentcart-direct-checkout-btn-css',
254 'public/buttons/direct-checkout/style/style.scss'
255 );
256 Vite::enqueueStyle(
257 $slug . '-fluentcart-product-page-css',
258 'public/product-page/style/shop-app.scss',
259 );
260 Vite::enqueueStaticStyle(
261 $slug . '-fluentcart-product-filter-slider-css',
262 'public/lib/nouislider/nouislider-15.7.1.css',
263 );
264
265
266 ob_start();
267 ProductFilterRender::renderResponsiveFilter();
268 $responsiveFilterWrapper = ob_get_clean();
269
270 $assetsPath = $app['url.assets'];
271
272
273 Vite::enqueueScript(
274 $slug . '-fluentcart-product-page-js',
275 'public/product-page/ShopApp.js',
276 []
277 )->with([
278 'fluentcart_shop_vars' => [
279 'rest' => Helper::getRestInfo(),
280 'shop' => Helper::shopConfig(),
281 'currency_settings' => CurrencySettings::get(),
282 'checkout_page' => (new StoreSettings)->getCheckoutPage(),
283 'cart_image' => $assetsPath . 'images/cart.svg',
284 'cart_driver' => Helper::getCartDriver(),
285 'responsive_filter_wrapper' => $responsiveFilterWrapper,
286 'is_admin_bar_showing' => is_admin_bar_showing(),
287 'responsive_filter_breakpoint' => apply_filters('shop_app_responsive_filter_breakpoint', 768)
288 ],
289 'fluentCartRestVars' => [
290 'rest' => Helper::getRestInfo(),
291 'ajaxurl' => admin_url('admin-ajax.php')
292 ]
293 ]);
294 Vite::enqueueStaticScript(
295 $slug . '-fluentcart-product-filter-slider',
296 'public/lib/nouislider/nouislider-15.7.1.min.js',
297 [$slug . '-fluentcart-product-page-js']
298 );
299 Vite::enqueueScript(
300 'fluentcart-zoom-js',
301 'public/single-product/xzoom/xzoom.js',
302 []
303 );
304
305 Vite::enqueueScript(
306 'fluentcart-single-product-js',
307 'public/single-product/SingleProduct.js',
308 []
309 )->with([
310 'fluentcart_single_product_vars' => [
311 'trans' => TransStrings::singleProductPageString(),
312 'cart_button_text' => apply_filters('fluent_cart/product/add_to_cart_text', __('Add To Cart', 'fluent-cart'), []),
313 // App::storeSettings()->get('cart_button_text', __('Add to Cart', 'fluent-cart')),
314 'out_of_stock_button_text' => apply_filters('fluent_cart/product/out_of_stock_button_text', __('Not Available', 'fluent-cart'), []),
315 'buy_now_button_text' => apply_filters('fluent_cart/product/buy_now_button_text', __('Buy Now', 'fluent-cart'), []),
316 'in_stock_status' => Helper::IN_STOCK,
317 'out_of_stock_status' => Helper::OUT_OF_STOCK,
318 'enable_image_zoom' => (new StoreSettings())->get('enable_image_zoom_in_single_product')
319 ]
320 ]);
321 }
322
323 public static function loadCustomerDashboardGlobalAssets()
324 {
325 static $isLoaded = false;
326 if ($isLoaded) {
327 return;
328 }
329 $isLoaded = true;
330 Vite::enqueueStyle('fluent-cart-customer-profile-global',
331 'public/customer-profile/style/customer-profile-global.scss',
332 );
333 }
334
335 public static function loadCustomerDashboardAssets()
336 {
337 static $isLoaded = false;
338 if ($isLoaded) {
339 return;
340 }
341 $isLoaded = true;
342 Vite::enqueueStyle('fluentcart-customer-css',
343 'public/customer-profile/style/customer-profile.scss'
344 );
345
346 // wp-i18n: this bundle pulls in the admin translator transitively
347 // (Start.js -> @/Bits/common.js -> @/utils/translator/Translator.js),
348 // which resolves strings through window.wp.i18n.
349 Vite::enqueueScript(
350 'fluentcart-customer-js',
351 'public/customer-profile/Start.js',
352 ['wp-i18n']
353 )->with(CustomerProfileHandler::getLocalizationData());
354
355 /**
356 * Enqueue additional customer-dashboard assets — the hook an add-on
357 * uses to ship the JS backing a portal section it registers through
358 * `fluent_cart/customer_portal/profile_sections`.
359 */
360 do_action('fluent_cart/customer_dashboard/enqueue_assets');
361 }
362
363 public static function loadCartAssets()
364 {
365 self::markFrontendAssetsRequired();
366 static $isLoaded = false;
367 if ($isLoaded) {
368 return;
369 }
370 $isLoaded = true;
371 $app = fluentCart();
372 $slug = $app->config->get('app.slug');
373 Vite::enqueueStaticScript(
374 $slug . '-fluentcart-toastify-notify-style',
375 'public/lib/toastify/toastify-js-1.12.0.js',
376 [$slug . '-app',]
377 );
378
379 Vite::enqueueStaticStyle(
380 $slug . '-fluentcart-toastify-notify-js',
381 'public/lib/toastify/toastify.min-1.12.0.css',
382 );
383
384 $cart = CartHelper::getCart(null, false);
385
386 $isInstantCheckout = (bool) App::request()->get(Helper::INSTANT_CHECKOUT_URL_PARAM);
387
388 $cartItemLayout = '';
389 $emptyCartLayout = '';
390
391 if (!App::request()->get(Helper::INSTANT_CHECKOUT_URL_PARAM)) {
392 $cartItems = Arr::get(CartResource::getStatus(), 'cart_data', []);
393 $cartRenderer = new CartRenderer($cartItems);
394
395 ob_start();
396 $cartRenderer->renderDummyItems();
397 $cartItemLayout = ob_get_clean();
398 ob_start();
399
400 $cartRenderer->renderEmpty();
401
402 $emptyCartLayout = ob_get_clean();
403 }
404
405 Vite::enqueueScript(
406 $slug . '-app',
407 'public/globals/FluentCartApp.js',
408 []
409 )->with([
410 'fluentCartRestVars' => [
411 'rest' => Helper::getRestInfo(),
412 'ajaxurl' => admin_url('admin-ajax.php'),
413 ],
414 'fluentcart_drawer_vars' => [
415 'placeholder_image' => Vite::getAssetUrl('images/placeholder.svg'),
416 'cart_item_layout' => $cartItemLayout,
417 'empty_cart_layout' => $emptyCartLayout,
418 'cart_driver' => Helper::getCartDriver(),
419 'cart_image' => Vite::getAssetUrl('images/cart.svg'),
420 'currency_settings' => CurrencySettings::get(),
421 'has_active_cart' => !!$cart,
422 'is_drawer_hidden' => CartLoader::shouldHideCartDrawer(),
423 'is_admin_bar_showing' => is_admin_bar_showing(),
424 'cart_item_count' => $isInstantCheckout ? 0 : ($cart ? count($cart->cart_data ?? []) : 0),
425 'cart_total_quantity' => $isInstantCheckout ? 0 : ($cart ? array_sum(array_map(function ($item) { return (int) ($item['quantity'] ?? 1); }, $cart->cart_data ?? [])) : 0),
426 ],
427 'fluentcart_utm_vars' => [
428 'allowed_keys' => UtmHelper::allowedUtmParameterKey(),
429 'internal_domains' => UtmHelper::getInternalDomains()
430 ]
431 ]);
432
433 Vite::enqueueStyle(
434 $slug . '-fluentcart-drawer',
435 'public/cart-drawer/cart-drawer.scss',
436 );
437
438 Vite::enqueueStyle(
439 $slug . '-global-styles',
440 'public/globals/style.scss',
441 );
442 }
443
444 public static function loadCheckoutAssets($cart = null)
445 {
446 self::markFrontendAssetsRequired();
447
448 static $isLoaded = false;
449 if ($isLoaded) {
450 return;
451 }
452 $isLoaded = true;
453 if (!$cart) {
454 $cart = CartHelper::getCart();
455 }
456
457 static::loadCartAssets();
458
459 if (!$cart) {
460 return;
461 }
462
463 static $alreadyLoaded = false;
464 if ($alreadyLoaded) {
465 return;
466 }
467
468 $alreadyLoaded = true;
469
470 Vite::enqueueAllStyles(
471 [
472 [
473 'source' => 'public/checkout/style/checkout.scss',
474 ],
475 [
476 'source' => 'public/components/select/style/style.scss',
477 ]
478 ],
479 'checkout-page'
480 );
481 $scripts = [
482 [
483 'source' => 'public/checkout/FluentCartCheckout.js',
484 'dependencies' => ['fluent-cart-app'],
485 'inFooter' => true,
486 'handle' => 'fct-checkout'
487 ],
488 [
489 'source' => 'public/orderbump/orderbump.js',
490 'dependencies' => ['fluent-cart-app'],
491 'inFooter' => true,
492 'handle' => 'fct-orderbump'
493 ]
494 ];
495 Vite::enqueueAllScripts($scripts, 'fct-checkout');
496
497 self::localizeCheckoutData($cart);
498 }
499
500 private static function localizeCheckoutData(Cart $cart)
501 {
502 static $isLoaded = false;
503 if ($isLoaded) {
504 return;
505 }
506 $isLoaded = true;
507 $countryCode = (string)Arr::get($cart->checkout_data, 'form_data.billing_country');
508 $countryInfo = [];
509 if (!empty($countryCode)) {
510 $countryInfo[$countryCode] = LocalizationManager::getCountryInfoFromRequest(null, $countryCode);
511 $shippingCountryCode = (string)Arr::get($cart->checkout_data, 'form_data.shipping_country');
512 if (Arr::get($cart->checkout_data, 'form_data.ship_to_different') === 'yes' && $shippingCountryCode !== $countryCode) {
513 $countryInfo[$shippingCountryCode] = LocalizationManager::getCountryInfoFromRequest(null, $shippingCountryCode);
514 }
515 }
516
517
518 //if url has cart hash then it's an instant checkout
519 $hasInstantCheckout = App::request()->get(Helper::INSTANT_CHECKOUT_URL_PARAM);
520 $hasModalCheckout = App::request()->get('fluent-cart') === 'modal_checkout';
521 $isInstantCheckout = 'no';
522 if ($hasInstantCheckout || $hasModalCheckout) {
523 $isInstantCheckout = 'yes';
524 }
525
526 $checkoutErrorNotices = Arr::get($cart->checkout_data, '__checkout_error_notices', []);
527 if ($checkoutErrorNotices) {
528 $checkoutData = is_array($cart->checkout_data) ? $cart->checkout_data : [];
529 unset($checkoutData['__checkout_error_notices']);
530 $cart->checkout_data = $checkoutData;
531 $cart->save();
532 }
533
534 $data = [
535 'fluentcart_checkout_vars' => [
536 'rest' => Helper::getRestInfo(),
537 'ajaxurl' => admin_url('admin-ajax.php'),
538 'is_all_digital' => !$cart->requireShipping(),
539 'is_cart_locked' => $cart->checkout_data['is_locked'] ?? 'no',
540 'disable_coupons' => $cart->checkout_data['disable_coupons'] ?? 'no',
541 'notices' => array_values($checkoutErrorNotices),
542 'payment_methods_with_custom_checkout_buttons' => apply_filters('fluent_cart/payment_methods_with_custom_checkout_buttons', []),
543 'tax_settings' => (new TaxModule())->getSettings(),
544 'submit_button' => [
545 'text' => __('Place Order', 'fluent-cart'),
546 ],
547 'trans' => TransStrings::checkoutPageString(),
548 'payments_trans' => TransStrings::paymentsString(),
549 'cart_hash' => $cart->cart_hash,
550 'is_instant_checkout' => $isInstantCheckout,
551 'is_modal_checkout' => $hasModalCheckout ? 'yes' : 'no',
552
553 ],
554 'fluentcart_checkout_info' => [
555 'baseUrl' => site_url(),
556 'rest_url' => Helper::getRestInfo()['url'],
557 'checkout_nonce' => wp_create_nonce('fluentcart'),
558 'ajax_url' => admin_url('admin-ajax.php'),
559 'is_user_logged_in' => is_user_logged_in(),
560 'is_admin' => current_user_can('manage_options'),
561 'has_subscription' => $cart->hasSubscription(),
562 'rest' => Helper::getRestInfo(),
563 'order_confirmation_url' => admin_url('admin-ajax.php?action=fluent_cart_place_order'),
564 'order_information_url' => URL::getApiUrl('/checkout/get-order-info'),
565 'custom_checkout_url' => URL::getApiUrl('/checkout'),
566 'redirect_url' => (new StoreSettings())->getCheckoutPage(),
567 'store_country' => (new StoreSettings())->get('store_country'),
568 'country_info' => $countryInfo,
569 'is_zero_payment' => $cart->isZeroPayment() ? 'yes' : 'no'
570 ]
571 ];
572
573 // Apply filters to allow modules to modify localized data
574 $data = apply_filters('fluent_cart/checkout/localize_data', $data, $cart);
575
576 foreach ($data as $key => $datum) {
577 wp_localize_script('fct-checkout', $key, $datum);
578 }
579 }
580
581 private static function markAssetLoaded($handle)
582 {
583 self::$loadedAssets[$handle] = true;
584 }
585
586 public static function enqueueProductInfoFrontendStyles()
587 {
588 self::markFrontendAssetsRequired();
589 static $isLoaded = false;
590 if ($isLoaded) {
591 return;
592 }
593 $isLoaded = true;
594 // Enqueue frontend styles for the product info block
595 Vite::enqueueStyle(
596 'fluentcart-single-product',
597 'public/single-product/single-product.scss'
598 );
599
600 // Enqueue related component styles
601 Vite::enqueueStyle(
602 'fluentcart-add-to-cart-btn-css',
603 'public/buttons/add-to-cart/style/style.scss'
604 );
605
606 Vite::enqueueStyle(
607 'fluentcart-direct-checkout-btn-css',
608 'public/buttons/direct-checkout/style/style.scss'
609 );
610 }
611
612
613 public static function enqueueThankYouPageAssets()
614 {
615 Vite::enqueueStyle(
616 'fluentcart-thank-you-css',
617 'public/receipt/style/thank_you.scss',
618 );
619 }
620
621 public static function loadMiniCartAssets()
622 {
623 self::markFrontendAssetsRequired();
624 static $isLoaded = false;
625 if ($isLoaded) {
626 return;
627 }
628 $isLoaded = true;
629
630 $app = fluentCart();
631 $slug = $app->config->get('app.slug');
632
633 Vite::enqueueStyle(
634 $slug . '-mini-cart',
635 'public/cart-drawer/mini-cart.scss',
636 );
637 }
638
639 }
640