PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.1
1.6.5 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 All 48 releases
fluent-cart / app / Modules / Templating / AssetLoader.php

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

637 lines 22.9 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 Vite::enqueueScript(
347 'fluentcart-customer-js',
348 'public/customer-profile/Start.js',
349 []
350 )->with(CustomerProfileHandler::getLocalizationData());
351
352 /**
353 * Enqueue additional customer-dashboard assets — the hook an add-on
354 * uses to ship the JS backing a portal section it registers through
355 * `fluent_cart/customer_portal/profile_sections`.
356 */
357 do_action('fluent_cart/customer_dashboard/enqueue_assets');
358 }
359
360 public static function loadCartAssets()
361 {
362 self::markFrontendAssetsRequired();
363 static $isLoaded = false;
364 if ($isLoaded) {
365 return;
366 }
367 $isLoaded = true;
368 $app = fluentCart();
369 $slug = $app->config->get('app.slug');
370 Vite::enqueueStaticScript(
371 $slug . '-fluentcart-toastify-notify-style',
372 'public/lib/toastify/toastify-js-1.12.0.js',
373 [$slug . '-app',]
374 );
375
376 Vite::enqueueStaticStyle(
377 $slug . '-fluentcart-toastify-notify-js',
378 'public/lib/toastify/toastify.min-1.12.0.css',
379 );
380
381 $cart = CartHelper::getCart(null, false);
382
383 $isInstantCheckout = (bool) App::request()->get(Helper::INSTANT_CHECKOUT_URL_PARAM);
384
385 $cartItemLayout = '';
386 $emptyCartLayout = '';
387
388 if (!App::request()->get(Helper::INSTANT_CHECKOUT_URL_PARAM)) {
389 $cartItems = Arr::get(CartResource::getStatus(), 'cart_data', []);
390 $cartRenderer = new CartRenderer($cartItems);
391
392 ob_start();
393 $cartRenderer->renderDummyItems();
394 $cartItemLayout = ob_get_clean();
395 ob_start();
396
397 $cartRenderer->renderEmpty();
398
399 $emptyCartLayout = ob_get_clean();
400 }
401
402 Vite::enqueueScript(
403 $slug . '-app',
404 'public/globals/FluentCartApp.js',
405 []
406 )->with([
407 'fluentCartRestVars' => [
408 'rest' => Helper::getRestInfo(),
409 'ajaxurl' => admin_url('admin-ajax.php'),
410 ],
411 'fluentcart_drawer_vars' => [
412 'placeholder_image' => Vite::getAssetUrl('images/placeholder.svg'),
413 'cart_item_layout' => $cartItemLayout,
414 'empty_cart_layout' => $emptyCartLayout,
415 'cart_driver' => Helper::getCartDriver(),
416 'cart_image' => Vite::getAssetUrl('images/cart.svg'),
417 'currency_settings' => CurrencySettings::get(),
418 'has_active_cart' => !!$cart,
419 'is_drawer_hidden' => CartLoader::shouldHideCartDrawer(),
420 'is_admin_bar_showing' => is_admin_bar_showing(),
421 'cart_item_count' => $isInstantCheckout ? 0 : ($cart ? count($cart->cart_data ?? []) : 0),
422 'cart_total_quantity' => $isInstantCheckout ? 0 : ($cart ? array_sum(array_map(function ($item) { return (int) ($item['quantity'] ?? 1); }, $cart->cart_data ?? [])) : 0),
423 ],
424 'fluentcart_utm_vars' => [
425 'allowed_keys' => UtmHelper::allowedUtmParameterKey(),
426 'internal_domains' => UtmHelper::getInternalDomains()
427 ]
428 ]);
429
430 Vite::enqueueStyle(
431 $slug . '-fluentcart-drawer',
432 'public/cart-drawer/cart-drawer.scss',
433 );
434
435 Vite::enqueueStyle(
436 $slug . '-global-styles',
437 'public/globals/style.scss',
438 );
439 }
440
441 public static function loadCheckoutAssets($cart = null)
442 {
443 self::markFrontendAssetsRequired();
444
445 static $isLoaded = false;
446 if ($isLoaded) {
447 return;
448 }
449 $isLoaded = true;
450 if (!$cart) {
451 $cart = CartHelper::getCart();
452 }
453
454 static::loadCartAssets();
455
456 if (!$cart) {
457 return;
458 }
459
460 static $alreadyLoaded = false;
461 if ($alreadyLoaded) {
462 return;
463 }
464
465 $alreadyLoaded = true;
466
467 Vite::enqueueAllStyles(
468 [
469 [
470 'source' => 'public/checkout/style/checkout.scss',
471 ],
472 [
473 'source' => 'public/components/select/style/style.scss',
474 ]
475 ],
476 'checkout-page'
477 );
478 $scripts = [
479 [
480 'source' => 'public/checkout/FluentCartCheckout.js',
481 'dependencies' => ['fluent-cart-app'],
482 'inFooter' => true,
483 'handle' => 'fct-checkout'
484 ],
485 [
486 'source' => 'public/orderbump/orderbump.js',
487 'dependencies' => ['fluent-cart-app'],
488 'inFooter' => true,
489 'handle' => 'fct-orderbump'
490 ]
491 ];
492 Vite::enqueueAllScripts($scripts, 'fct-checkout');
493
494 self::localizeCheckoutData($cart);
495 }
496
497 private static function localizeCheckoutData(Cart $cart)
498 {
499 static $isLoaded = false;
500 if ($isLoaded) {
501 return;
502 }
503 $isLoaded = true;
504 $countryCode = (string)Arr::get($cart->checkout_data, 'form_data.billing_country');
505 $countryInfo = [];
506 if (!empty($countryCode)) {
507 $countryInfo[$countryCode] = LocalizationManager::getCountryInfoFromRequest(null, $countryCode);
508 $shippingCountryCode = (string)Arr::get($cart->checkout_data, 'form_data.shipping_country');
509 if (Arr::get($cart->checkout_data, 'form_data.ship_to_different') === 'yes' && $shippingCountryCode !== $countryCode) {
510 $countryInfo[$shippingCountryCode] = LocalizationManager::getCountryInfoFromRequest(null, $shippingCountryCode);
511 }
512 }
513
514
515 //if url has cart hash then it's an instant checkout
516 $hasInstantCheckout = App::request()->get(Helper::INSTANT_CHECKOUT_URL_PARAM);
517 $hasModalCheckout = App::request()->get('fluent-cart') === 'modal_checkout';
518 $isInstantCheckout = 'no';
519 if ($hasInstantCheckout || $hasModalCheckout) {
520 $isInstantCheckout = 'yes';
521 }
522
523 $checkoutErrorNotices = Arr::get($cart->checkout_data, '__checkout_error_notices', []);
524 if ($checkoutErrorNotices) {
525 $checkoutData = is_array($cart->checkout_data) ? $cart->checkout_data : [];
526 unset($checkoutData['__checkout_error_notices']);
527 $cart->checkout_data = $checkoutData;
528 $cart->save();
529 }
530
531 $data = [
532 'fluentcart_checkout_vars' => [
533 'rest' => Helper::getRestInfo(),
534 'ajaxurl' => admin_url('admin-ajax.php'),
535 'is_all_digital' => !$cart->requireShipping(),
536 'is_cart_locked' => $cart->checkout_data['is_locked'] ?? 'no',
537 'disable_coupons' => $cart->checkout_data['disable_coupons'] ?? 'no',
538 'notices' => array_values($checkoutErrorNotices),
539 'payment_methods_with_custom_checkout_buttons' => apply_filters('fluent_cart/payment_methods_with_custom_checkout_buttons', []),
540 'tax_settings' => (new TaxModule())->getSettings(),
541 'submit_button' => [
542 'text' => __('Place Order', 'fluent-cart'),
543 ],
544 'trans' => TransStrings::checkoutPageString(),
545 'payments_trans' => TransStrings::paymentsString(),
546 'cart_hash' => $cart->cart_hash,
547 'is_instant_checkout' => $isInstantCheckout,
548 'is_modal_checkout' => $hasModalCheckout ? 'yes' : 'no',
549
550 ],
551 'fluentcart_checkout_info' => [
552 'baseUrl' => site_url(),
553 'rest_url' => Helper::getRestInfo()['url'],
554 'checkout_nonce' => wp_create_nonce('fluentcart'),
555 'ajax_url' => admin_url('admin-ajax.php'),
556 'is_user_logged_in' => is_user_logged_in(),
557 'is_admin' => current_user_can('manage_options'),
558 'has_subscription' => $cart->hasSubscription(),
559 'rest' => Helper::getRestInfo(),
560 'order_confirmation_url' => admin_url('admin-ajax.php?action=fluent_cart_place_order'),
561 'order_information_url' => URL::getApiUrl('/checkout/get-order-info'),
562 'custom_checkout_url' => URL::getApiUrl('/checkout'),
563 'redirect_url' => (new StoreSettings())->getCheckoutPage(),
564 'store_country' => (new StoreSettings())->get('store_country'),
565 'country_info' => $countryInfo,
566 'is_zero_payment' => $cart->isZeroPayment() ? 'yes' : 'no'
567 ]
568 ];
569
570 // Apply filters to allow modules to modify localized data
571 $data = apply_filters('fluent_cart/checkout/localize_data', $data, $cart);
572
573 foreach ($data as $key => $datum) {
574 wp_localize_script('fct-checkout', $key, $datum);
575 }
576 }
577
578 private static function markAssetLoaded($handle)
579 {
580 self::$loadedAssets[$handle] = true;
581 }
582
583 public static function enqueueProductInfoFrontendStyles()
584 {
585 self::markFrontendAssetsRequired();
586 static $isLoaded = false;
587 if ($isLoaded) {
588 return;
589 }
590 $isLoaded = true;
591 // Enqueue frontend styles for the product info block
592 Vite::enqueueStyle(
593 'fluentcart-single-product',
594 'public/single-product/single-product.scss'
595 );
596
597 // Enqueue related component styles
598 Vite::enqueueStyle(
599 'fluentcart-add-to-cart-btn-css',
600 'public/buttons/add-to-cart/style/style.scss'
601 );
602
603 Vite::enqueueStyle(
604 'fluentcart-direct-checkout-btn-css',
605 'public/buttons/direct-checkout/style/style.scss'
606 );
607 }
608
609
610 public static function enqueueThankYouPageAssets()
611 {
612 Vite::enqueueStyle(
613 'fluentcart-thank-you-css',
614 'public/receipt/style/thank_you.scss',
615 );
616 }
617
618 public static function loadMiniCartAssets()
619 {
620 self::markFrontendAssetsRequired();
621 static $isLoaded = false;
622 if ($isLoaded) {
623 return;
624 }
625 $isLoaded = true;
626
627 $app = fluentCart();
628 $slug = $app->config->get('app.slug');
629
630 Vite::enqueueStyle(
631 $slug . '-mini-cart',
632 'public/cart-drawer/mini-cart.scss',
633 );
634 }
635
636 }
637