PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.3.25
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.3.25
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 / api / StoreSettings.php

StoreSettings.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.3.25, at api/StoreSettings.php

1,565 lines 78.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\Api;
4
5 use FluentCart\App\App;
6 use FluentCart\App\Vite;
7 use FluentCart\App\CPT\Pages;
8 use FluentCart\App\Helpers\AddressHelper;
9 use FluentCart\App\Helpers\CurrenciesHelper;
10 use FluentCart\App\Services\OrderService;
11 use FluentCart\Framework\Support\Arr;
12 use FluentCart\Framework\Support\ArrayableInterface;
13 use FluentCart\Framework\Support\Str;
14 use FluentCart\App\Services\Permission\PermissionManager;
15
16 class StoreSettings implements ArrayableInterface
17 {
18 /**
19 * @var string
20 *
21 * Store settings option name
22 */
23 protected string $optionKey = 'fluent_cart_store_settings';
24
25 /**
26 * @var array key value pair
27 *
28 * Store settings parsed from fields
29 */
30 protected array $storeSettings;
31
32 protected static $cachedStoreSettings = null;
33
34 public function __construct()
35 {
36 $defaultSettings = $this->getDefaultSettings();
37 $storeSettings = get_option($this->optionKey, []);
38 $settings = wp_parse_args($storeSettings, $defaultSettings);
39 $this->storeSettings = $settings;
40 }
41
42 protected function getDefaultSettings(): array
43 {
44 $defaultSettings = [
45 'store_name' => get_bloginfo('name'),
46 'note_for_user_account_creation' => __('An user account will be created', 'fluent-cart'),
47 'checkout_button_text' => __('Checkout', 'fluent-cart'),
48 'view_cart_button_text' => __('View Cart', 'fluent-cart'),
49 'cart_button_text' => __('Add To Cart', 'fluent-cart'),
50 'popup_button_text' => __('View Product', 'fluent-cart'),
51 'out_of_stock_button_text' => __('Not Available', 'fluent-cart'),
52 'currency_position' => 'before',
53 // 'thousand_separator' => 'comma',
54 'decimal_separator' => 'dot',
55 'checkout_method_style' => 'logo',
56 'enable_modal_checkout' => 'no',
57 'require_logged_in' => 'no',
58 'show_cart_icon_in_nav' => 'no',
59 'show_cart_icon_in_body' => 'yes',
60 'additional_address_field' => 'yes',
61 'hide_coupon_field' => 'no',
62 'user_account_creation_mode' => 'all',
63 'checkout_page_id' => '',
64 'custom_payment_page_id' => '',
65 'registration_page_id' => '',
66 'login_page_id' => '',
67 'cart_page_id' => '',
68 'receipt_page_id' => '',
69 'shop_page_id' => '',
70 'customer_profile_page_id' => '',
71 'customer_profile_page_slug' => '',
72 'currency' => 'USD',
73 'store_address1' => '',
74 'store_address2' => '',
75 'store_city' => '',
76 'store_country' => '',
77 'store_postcode' => '',
78 'store_state' => '',
79 'show_relevant_product_in_single_page' => 'yes',
80 'show_relevant_product_in_modal' => '',
81 'order_mode' => 'test',
82 'variation_view' => 'both',
83 'variation_columns' => 'masonry',
84 'enable_early_payment_for_installment' => 'yes',
85 'modules_settings' => [],
86 'min_receipt_number' => '1',
87 'inv_prefix' => 'INV-',
88 'weight_unit' => 'kg',
89 'dimension_unit' => 'cm'
90 ];
91
92 return apply_filters('fluent_cart/store_settings/values', $defaultSettings, []);
93 }
94
95 /**
96 * @return array
97 *
98 * Get all store settings fields
99 * @hook to use apply_filters("fluent_cart/store_setting_fields", $fields)
100 */
101 public function fields($params = []): array
102 {
103
104 $pages = Pages::getPages('');
105 $previewLinks = [
106 'shop_page_id' => $this->getShopPage(),
107 'customer_profile_page_id' => $this->getCustomerProfilePage(),
108 'cart_page_id' => $this->getCartPage(),
109 'checkout_page_id' => $this->getCheckoutPage(),
110 'receipt_page_id' => $this->getReceiptPage()
111 ];
112 $isProActive = App::isProActive();
113 $proFeatureIcon = Vite::getAssetUrl('images/crown.svg');
114
115
116 $fields = [
117 'setting_tabs' => [
118 'type' => 'section',
119 'disable_nesting' => true,
120 'default_tab' => 'store_setup',
121 'hide_tab_switch' => true,
122 'schema' => [
123 'store_setup' => [
124 'title' => __('Store Setup', 'fluent-cart'),
125 'show_title' => false,
126 'type' => 'section',
127 'disable_nesting' => true,
128 'columns' => [
129 'default' => 1,
130 'md' => 1
131 ],
132 'schema' => [
133 'name_grid' => [
134 'type' => 'grid',
135 'columns' => [
136 'default' => 1,
137 'md' => 3
138 ],
139 'disable_nesting' => true,
140 'schema' => [
141 'label' => [
142 'type' => 'html',
143 'value' => '<span class="setting-label">' . __('Store Name', 'fluent-cart') . '</span>
144 <div class="form-note">' . __('Enter the public name of your online store.', 'fluent-cart') . '</div>'
145 ],
146 "store_name" => [
147 'wrapperClass' => 'col-span-2 flex items-center',
148 "label" => '',
149 "type" => "input",
150 "value" => "",
151 ],
152 ]
153 ],
154
155 'hr' => [
156 'type' => 'html',
157 'value' => '<hr class="settings-divider">'
158 ],
159
160
161 'logo_grid' => [
162 'type' => 'grid',
163 'columns' => [
164 'default' => 1,
165 'md' => 3
166 ],
167 'disable_nesting' => true,
168 'schema' => [
169 'label' => [
170 'type' => 'html',
171 'value' => '<span class="setting-label">' . __('Store Logo', 'fluent-cart') . '</span>
172 <div class="form-note">' . __("Upload your brand's logo. Recommended width: 512 pixels minimum.", 'fluent-cart') . '</div>'
173 ],
174 "store_logo" => [
175 "label" => false,
176 "type" => "media",
177 "value" => "",
178 'multiple' => false,
179 // if `condition_type` not specified then all condition type will be `and`
180
181 // 'conditions' => [
182 // [
183 // 'key' => 'store_name',
184 // 'operator' => '==',
185 // 'value' => [
186 // 'accessor' => 'order_mode'
187 // ]
188 // ],
189 // ],
190
191 ],
192 ]
193 ],
194
195 'hr2' => [
196 'type' => 'html',
197 'value' => '<hr class="settings-divider">'
198 ],
199
200 'mode_grid' => [
201 'type' => 'grid',
202 'columns' => [
203 'default' => 1,
204 'md' => 3
205 ],
206 'disable_nesting' => true,
207 'schema' => [
208 'label' => [
209 'type' => 'html',
210 'value' => '<span class="setting-label">' . __('Store Mode', 'fluent-cart') . '</span>
211 <div class="form-note">' . __("Select your store's operating mode: `Test` for setup, `Live` for real transactions.", 'fluent-cart') . '</div>'
212 ],
213 'order_mode' => [
214 'wrapperClass' => 'col-span-2 flex items-center',
215 "label" => '',
216 "type" => "radio",
217 "options" => [
218 [
219 "label" => __('Live', 'fluent-cart'),
220 "value" => 'live',
221 ],
222 [
223 "label" => __('Test', 'fluent-cart'),
224 "value" => 'test',
225 ],
226 ],
227 "value" => "live"
228 ],
229 ]
230 ],
231
232 'settings_hr' => [
233 'type' => 'html',
234 'value' => '<hr class="settings-divider">'
235 ],
236
237 'address_grid' => [
238 'type' => 'grid',
239 'columns' => [
240 'default' => 1,
241 'md' => 3
242 ],
243 'disable_nesting' => true,
244 'schema' => [
245 'label' => [
246 'type' => 'html',
247 'value' => '<span class="setting-label">' . __('Store Address', 'fluent-cart') . '</span>
248 <div class="form-note">' . __("Provide your physical business address details.", 'fluent-cart') . '</div>'
249 ],
250 'address_input_grid' => [
251 'wrapperClass' => 'fct-compact-form',
252 'type' => 'grid',
253 'disable_nesting' => true,
254 'class' => 'col-span-2',
255 'schema' => [
256 'store_address_component' => [
257 'type' => 'component',
258 'component' => 'StoreSettings/AddressComponent',
259 'wrapperClass' => 'col-span-full'
260 ],
261 'store_address1' => [
262 'type' => 'hidden',
263 ],
264 'store_address2' => [
265 'type' => 'hidden',
266 ],
267 'store_city' => [
268 'type' => 'hidden',
269 ],
270 'store_postcode' => [
271 'type' => 'hidden',
272 ],
273 'store_country' => [
274 'type' => 'hidden',
275 ],
276 'store_state' => [
277 'type' => 'hidden',
278 ],
279 ]
280 ],
281 ]
282 ],
283
284
285 'settings_hr_2' => [
286 'type' => 'html',
287 'value' => '<hr class="settings-divider">'
288 ],
289
290 'currency_grid' => [
291 'type' => 'grid',
292 'columns' => [
293 'default' => 1,
294 'md' => 3
295 ],
296 'disable_nesting' => true,
297 'schema' => [
298 'label' => [
299 'type' => 'html',
300 'value' => '<span class="setting-label">' . __('Checkout Currency', 'fluent-cart') . '</span>
301 <div class="form-note">' . __("Select the primary currency for your store.", 'fluent-cart') . '</div>'
302 ],
303 "currency" => [
304 'wrapperClass' => 'col-span-2 flex items-center',
305 "label" => '',
306 "type" => "select",
307 'filterable' => true,
308 "options" => CurrencySettings::getFormattedCurrencies(),
309 "value" => "USD"
310 ],
311 ]
312 ],
313
314 'hr3' => [
315 'type' => 'html',
316 'value' => '<hr class="settings-divider">'
317 ],
318
319 'decimal_separator_grid' => [
320 'type' => 'grid',
321 'columns' => [
322 'default' => 1,
323 'md' => 3
324 ],
325 'disable_nesting' => true,
326 'schema' => [
327 'label' => [
328 'type' => 'html',
329 'value' => '<span class="setting-label">' . __('Number Format', 'fluent-cart') . '</span>
330 <div class="form-note">' . __("Select the character used to separate thousands or decimals in prices.", 'fluent-cart') . '</div>'
331 ],
332 'decimal_separator' => [
333 'wrapperClass' => 'col-span-2 flex items-start flex-col',
334 "label" => '',
335 "type" => "radio",
336 "options" => [
337 [
338 "label" => __('Comma & Dot (eg 10,000.00)', 'fluent-cart'),
339 "value" => 'dot'
340 ],
341 [
342 "label" => __('Dot & Comma (eg 10.000,00)', 'fluent-cart'),
343 "value" => 'comma'
344 ],
345 ],
346 "value" => "dot"
347 ],
348 ]
349 ],
350
351 'hr4' => [
352 'type' => 'html',
353 'value' => '<hr class="settings-divider">'
354 ],
355
356 'currency_position_grid' => [
357 'type' => 'grid',
358 'columns' => [
359 'default' => 1,
360 'md' => 3
361 ],
362 'disable_nesting' => true,
363 'schema' => [
364 'label' => [
365 'type' => 'html',
366 'value' => '<span class="setting-label">' . __('Currency Formatting', 'fluent-cart') . '</span>
367 <div class="form-note">' . __("Select how the currency should be formatted.", 'fluent-cart') . '</div>'
368 ],
369 'currency_position' => [
370 'wrapperClass' => 'col-span-2 flex items-center',
371 "label" => '',
372 "type" => "select",
373 "options" => [
374 [
375 "label" => __('Symbol before (eg: $100)', 'fluent-cart'),
376 "value" => 'before',
377 ],
378 [
379 "label" => __('Symbol after (eg: 100$)', 'fluent-cart'),
380 "value" => 'after',
381 ],
382 [
383 "label" => __('ISO before (eg: USD 100)', 'fluent-cart'),
384 "value" => 'iso_before',
385 ],
386 [
387 "label" => __('ISO after (eg: 100 USD)', 'fluent-cart'),
388 "value" => 'iso_after',
389 ],
390 [
391 "label" => __('Symbol & ISO (eg: $100 USD)', 'fluent-cart'),
392 "value" => 'symbool_before_iso',
393 ],
394 [
395 "label" => __('ISO & Symbol (eg: USD 100$)', 'fluent-cart'),
396 "value" => 'symbool_after_iso',
397 ],
398 [
399 "label" => __('ISO-Symbol (eg: USD $100)', 'fluent-cart'),
400 "value" => 'symbool_and_iso',
401 ],
402 ],
403 "value" => "before"
404 ],
405 ]
406 ],
407
408 'hr5' => [
409 'type' => 'html',
410 'value' => '<hr class="settings-divider">'
411 ],
412
413
414 'checkout_style_grid' => [
415 'type' => 'grid',
416 'columns' => [
417 'default' => 1,
418 'md' => 3
419 ],
420 'disable_nesting' => true,
421 'schema' => [
422 'label' => [
423 'type' => 'html',
424 'value' => '<span class="setting-label">' . __('Payment View', 'fluent-cart') . '</span>
425 <div class="form-note">' . __("Select how payment options are visually presented on checkout.", 'fluent-cart') . '</div>'
426 ],
427 "checkout_method_style" => [
428 'wrapperClass' => 'col-span-2 flex items-center',
429 "type" => "component",
430 'component' => 'PaymentView',
431 'label' => false,
432 "options" => [
433 [
434 "label" => '',
435 "value" => 'logo',
436 ],
437 [
438 "label" => __('Label Selector', 'fluent-cart'),
439 "value" => 'radio',
440 ],
441 ],
442 "value" => "logo"
443 ],
444 ]
445 ],
446
447 // 'settings_hr_modal' => [
448 // 'type' => 'html',
449 // 'value' => '<hr class="settings-divider">'
450 // ],
451 //
452 // 'modal_checkout_grid' => [
453 // 'type' => 'grid',
454 // 'columns' => [
455 // 'default' => 1,
456 // 'md' => 3
457 // ],
458 // 'disable_nesting' => true,
459 // 'schema' => [
460 // 'label' => [
461 // 'type' => 'html',
462 // 'value' => '<span class="setting-label">' . __('Buy Now Button Behavior', 'fluent-cart') . '</span>
463 // <div class="form-note">' . __("Choose how the Buy Now button behaves. Modal checkout provides a seamless experience without leaving the product page.", 'fluent-cart') . '</div>'
464 // ],
465 // "enable_modal_checkout" => [
466 // 'wrapperClass' => 'col-span-2 flex items-center',
467 // "label" => '',
468 // "type" => "radio",
469 // "options" => [
470 // [
471 // "label" => __('Redirect to Checkout Page', 'fluent-cart'),
472 // "value" => 'no',
473 // ],
474 // [
475 // "label" => __('Open Checkout in Modal', 'fluent-cart'),
476 // "value" => 'yes',
477 // ],
478 // ],
479 // "value" => "no"
480 // ],
481 // ]
482 // ],
483 ],
484 ],
485 // 'button_setup' => [
486 // 'title' => __('Button Setup', 'fluent-cart'),
487 // 'type' => 'tab-pane',
488 // 'disable_nesting' => true,
489 // 'schema' => [
490 // 'button_setup_settings' => [
491 // 'title' => __('Button Setup', 'fluent-cart'),
492 // 'type' => 'section',
493 // 'disable_nesting' => true,
494 // 'columns' => [
495 // 'default' => 1,
496 // 'md' => 2
497 // ],
498 // 'schema' => [
499 // "checkout_button_text" => [
500 // "label" => __('Checkout Button Text', 'fluent-cart'),
501 // "type" => "input",
502 // "value" => __('Buy now', 'fluent-cart')
503 // ],
504 // "cart_button_text" => [
505 // "label" => __('Cart Button Text', 'fluent-cart'),
506 // "type" => "input",
507 // "value" => __('Add to cart', 'fluent-cart')
508 // ],
509 //
510 // "popup_button_text" => [
511 // "label" => __('Popup Button Text', 'fluent-cart'),
512 // "type" => "input",
513 // "value" => __('View Product', 'fluent-cart')
514 // ],
515 // "out_of_stock_button_text" => [
516 // "label" => __('Out of Stock Button Text', 'fluent-cart'),
517 // "type" => "input",
518 // "value" => __('Out of stock', 'fluent-cart')
519 // ],
520 // "view_cart_button_text" => [
521 // "label" => __('View Cart Button Text', 'fluent-cart'),
522 // "type" => "input",
523 // "value" => __('View Cart', 'fluent-cart')
524 // ],
525 //
526 // "note_for_user_account_creation" => [
527 // "label" => __('Note for User Account Creation,', 'fluent-cart'),
528 // "type" => "input",
529 // "value" => __('You have subscription product in your cart, an account will be created', 'fluent-cart')
530 // ],
531 // ],
532 // ]
533 // ]
534 // ],
535 'pages_setup' => [
536 'title' => __('Pages Setup', 'fluent-cart'),
537 'show_title' => false,
538 'type' => 'section',
539 'disable_nesting' => true,
540 'columns' => [
541 'default' => 1,
542 'md' => 1
543 ],
544 'schema' => [
545
546 'shop_page_grid' => [
547 'type' => 'grid',
548 'columns' => [
549 'default' => 1,
550 'md' => 3,
551 ],
552 'disable_nesting' => true,
553 'schema' => [
554 'label' => [
555 'type' => 'html',
556 'value' => '<span class="setting-label">' . __('Select Shop Page', 'fluent-cart') . '</span>
557 <div class="form-note">' . __("Select the page that showcases all of your products.", 'fluent-cart') . '</div>'
558 ],
559 'shop_page_id' => [
560 'wrapperClass' => 'col-span-2',
561 'page_title' => __('Shop', 'fluent-cart'),
562 'type' => 'component',
563 'component' => 'StoreSettings/PageSelector',
564 'page_key' => 'shop_page_id',
565 'preview_link' => $previewLinks['shop_page_id'],
566 'options' => $pages,
567 'hide_note' => true,
568 'value' => '',
569 'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
570 '[fluent_cart_products]',
571 __('Products', 'fluent-cart')
572 ),
573 ],
574 ]
575 ],
576
577 'hr1' => [
578 'type' => 'html',
579 'value' => '<hr class="settings-divider">'
580 ],
581
582 'customer_profile_grid' => [
583 'type' => 'grid',
584 'columns' => [
585 'default' => 1,
586 'md' => 3
587 ],
588 'disable_nesting' => true,
589 'schema' => [
590 'label' => [
591 'type' => 'html',
592 'value' => '<span class="setting-label">' . __('Select Customer Profile Page', 'fluent-cart') . '</span>
593 <div class="form-note">' . __("Select the page where customers will manage their profile, orders, and downloads.", 'fluent-cart') . '</div>'
594 ],
595 'customer_profile_page_id' => [
596 'wrapperClass' => 'col-span-2',
597 'label' => false,
598 'page_title' => __('Account', 'fluent-cart'),
599 'type' => 'component',
600 'component' => 'StoreSettings/PageSelector',
601 'page_key' => 'customer_profile_page_id',
602 'preview_link' => $previewLinks['customer_profile_page_id'],
603 'hide_note' => true,
604 'options' => $pages,
605 'value' => '',
606 'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
607 '[fluent_cart_customer_profile]',
608 __('Account', 'fluent-cart')
609 ),
610 ],
611 ]
612 ],
613
614 'hr2' => [
615 'type' => 'html',
616 'value' => '<hr class="settings-divider">'
617 ],
618
619 'cart_page_grid' => [
620 'type' => 'grid',
621 'columns' => [
622 'default' => 1,
623 'md' => 3
624 ],
625 'disable_nesting' => true,
626 'schema' => [
627 'label' => [
628 'type' => 'html',
629 'value' => '<span class="setting-label">' . __('Select Cart Page', 'fluent-cart') . '</span>
630 <div class="form-note">' . __("Select the page that will display customer's current shopping cart.", 'fluent-cart') . '</div>'
631 ],
632 'cart_page_id' => [
633 'wrapperClass' => 'col-span-2',
634 'label' => false,
635 'page_title' => __('Cart', 'fluent-cart'),
636 'type' => 'component',
637 'component' => 'StoreSettings/PageSelector',
638 'page_key' => 'cart_page_id',
639 'preview_link' => $previewLinks['cart_page_id'],
640 'hide_note' => true,
641 'options' => $pages,
642 'value' => '',
643 'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
644 '[fluent_cart_cart]',
645 __('Cart', 'fluent-cart')
646 ),
647 ],
648 ]
649 ],
650
651 'hr3' => [
652 'type' => 'html',
653 'value' => '<hr class="settings-divider">'
654 ],
655
656 'receipt_page_grid' => [
657 'type' => 'grid',
658 'columns' => [
659 'default' => 1,
660 'md' => 3
661 ],
662 'disable_nesting' => true,
663 'schema' => [
664 'label' => [
665 'type' => 'html',
666 'value' => '<span class="setting-label">' . __('Select Receipt Page', 'fluent-cart') . '</span>
667 <div class="form-note">' . __("Select the page that will display order summary after a successful purchase.", 'fluent-cart') . '</div>'
668 ],
669 'receipt_page_id' => [
670 'wrapperClass' => 'col-span-2',
671 'label' => false,
672 'page_title' => __('Receipt', 'fluent-cart'),
673 'type' => 'component',
674 'component' => 'StoreSettings/PageSelector',
675 'page_key' => 'receipt_page_id',
676 'preview_link' => $previewLinks['receipt_page_id'],
677 'hide_note' => true,
678 'options' => $pages,
679 'value' => '',
680 'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
681 '[fluent_cart_receipt]',
682 __('Receipt', 'fluent-cart')
683 ),
684 ],
685 ]
686 ],
687
688 'hr4' => [
689 'type' => 'html',
690 'value' => '<hr class="settings-divider">'
691 ],
692
693 'checkout_page_grid' => [
694 'type' => 'grid',
695 'columns' => [
696 'default' => 1,
697 'md' => 3
698 ],
699 'disable_nesting' => true,
700 'schema' => [
701 'label' => [
702 'type' => 'html',
703 'value' => '<span class="setting-label">' . __('Select Checkout Page', 'fluent-cart') . '</span>
704 <div class="form-note">' . __("Select the page where customers will finalize their purchase.", 'fluent-cart') . '</div>'
705 ],
706 'checkout_page_id' => [
707 'wrapperClass' => 'col-span-2',
708 'label' => false,
709 'page_title' => __('Checkout', 'fluent-cart'),
710 'type' => 'component',
711 'component' => 'StoreSettings/PageSelector',
712 'page_key' => 'checkout_page_id',
713 'preview_link' => $previewLinks['checkout_page_id'],
714 'hide_note' => true,
715 'options' => $pages,
716 'value' => '',
717 'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
718 '[fluent_cart_checkout]',
719 __('Checkout', 'fluent-cart')
720 ),
721 ],
722 ]
723 ]
724 ]
725 ],
726 'single_product_setup' => [
727 'title' => __('Product Page', 'fluent-cart'),
728 'show_title' => false,
729 'type' => 'section',
730 'disable_nesting' => true,
731 'columns' => [
732 'default' => 1,
733 'md' => 1
734 ],
735 'schema' => [
736 'product_settings_grid' => [
737 'type' => 'grid',
738 'columns' => [
739 'default' => 1,
740 'md' => 3
741 ],
742 'disable_nesting' => true,
743 'schema' => [
744 'label' => [
745 'type' => 'html',
746 'value' => '<span class="setting-label">' . __('Single Product Setup', 'fluent-cart') . '</span>
747 <div class="form-note">' . __("Control the display of relevant information.", 'fluent-cart') . '</div>'
748 ],
749 'fields' => [
750 'type' => 'grid',
751 'columns' => [
752 'default' => 1,
753 'md' => 1
754 ],
755 'disable_nesting' => true,
756 'schema' => [
757 "show_relevant_product_in_single_page" => [
758 "label" => __('Show Relevant In Single Page', 'fluent-cart'),
759 "type" => "checkbox",
760 "value" => "yes"
761 ],
762 "show_relevant_product_in_modal" => [
763 "label" => __('Show Relevant In Product Modal', 'fluent-cart'),
764 "type" => "checkbox",
765 "value" => "no"
766 ],
767 ]
768 ]
769
770 ]
771 ],
772 'hr' => [
773 'type' => 'html',
774 'value' => '<hr class="settings-divider">'
775 ],
776
777 'image_zoom_grid' => [
778 'type' => 'grid',
779 'columns' => [
780 'default' => 1,
781 'md' => 3
782 ],
783 'disable_nesting' => true,
784 'schema' => [
785 'label' => [
786 'type' => 'html',
787 'value' => '<span class="setting-label">' . __('Image Zooming', 'fluent-cart') . '</span>
788 <div class="form-note">' . __("Enable Image zoom in single product.", 'fluent-cart') . '</div>'
789 ],
790 'fields' => [
791 'type' => 'grid',
792 'columns' => [
793 'default' => 1,
794 'md' => 1
795 ],
796 'disable_nesting' => true,
797 'schema' => [
798 "enable_image_zoom_in_single_product" => [
799 "label" => __('Enable Zoom in Single Product', 'fluent-cart'),
800 "type" => "checkbox",
801 "value" => "no"
802 ],
803 "enable_image_zoom_in_modal" => [
804 "label" => __('Enable Zoom in Modal', 'fluent-cart'),
805 "type" => "checkbox",
806 "value" => "no"
807 ],
808 ]
809 ]
810
811 ]
812 ],
813
814 'hr_image_zoom' => [
815 'type' => 'html',
816 'value' => '<hr class="settings-divider">'
817 ],
818
819 'variation_grid' => [
820 'type' => 'grid',
821 'columns' => [
822 'default' => 1,
823 'md' => 3
824 ],
825 'disable_nesting' => true,
826 'schema' => [
827 'label' => [
828 'type' => 'html',
829 'value' => '<span class="setting-label">' . __('Variation View', 'fluent-cart') . '</span>
830 <div class="form-note">' . __("Defines how product variations are visually presented to customers.", 'fluent-cart') . '</div>'
831 ],
832 "variation_view" => [
833 'wrapperClass' => 'col-span-2 flex items-center',
834 "label" => false,
835 "type" => "select",
836 "options" => [
837 [
838 "label" => __('Image', 'fluent-cart'),
839 "value" => 'image',
840 ],
841 [
842 "label" => __('Text', 'fluent-cart'),
843 "value" => 'text',
844 ],
845 [
846 "label" => __('Image with Text', 'fluent-cart'),
847 "value" => 'both',
848 ],
849 ],
850 "value" => ""
851 ],
852
853 ]
854 ],
855 'hr2' => [
856 'type' => 'html',
857 'value' => '<hr class="settings-divider">'
858 ],
859 'variation_column_grid' => [
860 'type' => 'grid',
861 'columns' => [
862 'default' => 1,
863 'md' => 3
864 ],
865 'disable_nesting' => true,
866 'schema' => [
867 'label' => [
868 'type' => 'html',
869 'value' => '<span class="setting-label">' . __('Variation Columns', 'fluent-cart') . '</span>
870 <div class="form-note">' . __("Set the column layout for how product variations are displayed within product sections.", 'fluent-cart') . '</div>'
871 ],
872 "variation_columns" => [
873 'wrapperClass' => 'col-span-2 flex items-center',
874 "label" => false,
875 "type" => "select",
876 "options" => [
877 [
878 "label" => __('One Column', 'fluent-cart'),
879 "value" => 'one',
880 ],
881 [
882 "label" => __('Two Columns', 'fluent-cart'),
883 "value" => 'two',
884 ],
885 [
886 "label" => __('Three Columns', 'fluent-cart'),
887 "value" => 'three',
888 ],
889 [
890 "label" => __('Four Columns', 'fluent-cart'),
891 "value" => 'four',
892 ],
893 [
894 "label" => __('Masonry', 'fluent-cart'),
895 "value" => 'masonry',
896 ],
897 ],
898 "value" => ""
899 ],
900
901 ]
902 ],
903
904 'hr3' => [
905 'type' => 'html',
906 'value' => '<hr class="settings-divider">'
907 ],
908 'product_slug_grid' => [
909 'type' => 'grid',
910 'columns' => [
911 'default' => 1,
912 'md' => 3
913 ],
914 'disable_nesting' => true,
915 'schema' => [
916 'label' => [
917 'type' => 'html',
918 'value' => '<span class="setting-label">' . __('Product Slug', 'fluent-cart') . '</span>
919 <div class="form-note">' . __("Set Product Slug.", 'fluent-cart') . '</div>'
920 ],
921 "product_slug" => [
922 'wrapperClass' => 'col-span-2 flex items-center',
923 "label" => false,
924 "type" => "input",
925 "value" => ""
926 ],
927
928 ]
929 ],
930 ],
931 ],
932 'cart_and_checkout' => [
933 'title' => __('Cart & checkout', 'fluent-cart'),
934 'show_title' => false,
935 'type' => 'section',
936 'disable_nesting' => true,
937 'columns' => [
938 'default' => 1,
939 'md' => 1
940 ],
941 'schema' => [
942 "show_cart_icon_in_body" => [
943 "label" => __('Cart Icon In Body', 'fluent-cart'),
944 "type" => "checkbox",
945 "value" => "yes",
946 'note' => sprintf(
947 /* translators: %1$s: Display instruction text, %2$s: "Use this" text, %3$s: Copy to clipboard tooltip, %4$s: CSS class name, %5$s: CSS class description text */
948 "<div class='pl-6'><p>%1\$s</p><p>%2\$s <code class='copyable-content' title='%3\$s'>%4\$s</code> %5\$s</p></div>",
949 __('Display the cart icon in the body of the website', 'fluent-cart'),
950 __('Use this', 'fluent-cart'),
951 __('Copy to clipboard', 'fluent-cart'),
952 'fcart-cart-toggle-button',
953 __('CSS class to display the cart link/icon anywhere else.', 'fluent-cart')
954 )
955 ],
956 'hr2' => [
957 'type' => 'html',
958 'value' => '<hr class="settings-divider">'
959 ],
960 "require_logged_in" => [
961 "label" => __('Require user to be logged in for checkout (Coming soon)', 'fluent-cart'),
962 "type" => "checkbox",
963 "value" => "no",
964 'note' => "<div class='pl-6'>" . __('Enforce that customers must be logged into their account to complete a purchase.', 'fluent-cart') . "</div>",
965 'wrapperClass' => 'disabled'
966 ],
967 'hr3' => [
968 'type' => 'html',
969 'value' => '<hr class="settings-divider">'
970 ],
971
972 'user_account_creation_mode_grid' => [
973 'type' => 'grid',
974 'columns' => [
975 'default' => 1,
976 'md' => 3
977 ],
978 'disable_nesting' => true,
979 'schema' => [
980 'label' => [
981 'type' => 'html',
982 'value' => '<span class="setting-label">' . __('User Account Creation Mode', 'fluent-cart') . '</span>
983 <div class="form-note">' . __("User account will be created regardless of the mode if the order has a subscription.", 'fluent-cart') . '</div>'
984 ],
985 'user_account_input_grid' => [
986 'type' => 'grid',
987 'disable_nesting' => true,
988 'class' => 'col-span-2',
989 'schema' => [
990 'user_account_creation_mode' => [
991 'wrapperClass' => 'col-span-2 flex items-center',
992 "label" => '',
993 "type" => "radio",
994 "options" => [
995 [
996 "label" => __('Create User Account Automatically after payment
997 ', 'fluent-cart'),
998 "value" => 'all',
999 'note' => "<div class='my-[2px] form-note'>" . __('User account will be created automatically after payment.', 'fluent-cart') . "</div>",
1000 'option_class' => 'mb-2.5'
1001 ],
1002 [
1003 "label" => __('Give checkbox to create account on checkout page', 'fluent-cart'),
1004 "value" => 'user_choice',
1005 'note' => "<div class='my-[2px] form-note'>" . __('User will have an option to create an account during checkout.', 'fluent-cart') . "</div>",
1006 'option_class' => 'mb-2.5'
1007 ],
1008 [
1009 "label" => __('No need to create account for onetime purchases', 'fluent-cart'),
1010 "value" => 'only_subscription',
1011 'note' => "<div class='my-[2px] form-note'>" . __('User account will not be created for onetime purchases.', 'fluent-cart') . "</div>",
1012 ],
1013 ],
1014 "value" => "all"
1015 ],
1016 ]
1017 ],
1018 ]
1019 ],
1020
1021
1022 // "allow_checkout_signup" => [
1023 // "label" => __('Allow customers to create account during one-time checkout', 'fluent-cart'),
1024 // "type" => "checkbox",
1025 // "value" => "no",
1026 // 'note' => "<div class='pl-6'>" . __('Provide an option for customers to create a user account during a single, non-recurring checkout process.', 'fluent-cart') . "</div>"
1027 // ],
1028 // "force_ssl" => [
1029 // "label" => __('Force page to SSL (https)', 'fluent-cart'),
1030 // "type" => "checkbox",
1031 // "value" => "no"
1032 // ],
1033 'hr5' => [
1034 'type' => 'html',
1035 'value' => '<hr class="settings-divider">'
1036 ],
1037 "hide_coupon_field" => [
1038 "label" => __('Hide coupon field on checkout', 'fluent-cart'),
1039 "type" => "checkbox",
1040 "value" => "no",
1041 'note' => "<div class='pl-6'>" . __('Hide the coupon code input field on the checkout page.', 'fluent-cart') . "</div>"
1042 ],
1043 'hr6' => [
1044 'type' => 'html',
1045 'value' => '<hr class="settings-divider">'
1046 ],
1047 'order_invoice_grid' => [
1048 'type' => 'grid',
1049 'columns' => [
1050 'default' => 1,
1051 'md' => 3
1052 ],
1053 'disable_nesting' => true,
1054 'schema' => [
1055 'label' => [
1056 'type' => 'html',
1057 'value' => '<span class="setting-label">' . __('Receipt Settings', 'fluent-cart') . '</span>
1058 <div class="form-note">' . __("Setup your receipt.", 'fluent-cart') . '</div>'
1059 ],
1060 'invoice_input_grid' => [
1061 'type' => 'grid',
1062 'disable_nesting' => true,
1063 'class' => 'col-span-2',
1064 'schema' => [
1065 "min_receipt_number" => [
1066 'wrapperClass' => 'col-span-2 flex flex-col',
1067 "label" => __('Minimum Receipt Number', 'fluent-cart'),
1068 "type" => "input",
1069 "value" => "",
1070 'note' => sprintf(
1071 "<div class=''>%s</div>",
1072 sprintf(
1073 /* translators: %s is the next receipt number */
1074 __('Next Receipt Number: %s', 'fluent-cart'),
1075 OrderService::getNextReceiptNumber()
1076 )
1077 ),
1078
1079 ],
1080 "inv_prefix" => [
1081 'wrapperClass' => 'col-span-2 flex flex-col',
1082 "label" => __('Receipt Prefix', 'fluent-cart'),
1083 "type" => "input",
1084 "value" => "",
1085 ],
1086 ]
1087 ],
1088 ]
1089 ],
1090 ]
1091 ],
1092 'subscriptions_setup' => [
1093 'title' => __('Subscriptions', 'fluent-cart'),
1094 'show_title' => false,
1095 'type' => 'section',
1096 'disable_nesting' => true,
1097 'columns' => [
1098 'default' => 1,
1099 'md' => 1
1100 ],
1101 'schema' => [
1102 'subscription_settings_grid' => [
1103 'type' => 'grid',
1104 'columns' => [
1105 'default' => 1,
1106 'md' => 3
1107 ],
1108 'disable_nesting' => true,
1109 'schema' => [
1110 'label' => [
1111 'type' => 'html',
1112 'value' => '<span class="setting-label">' . __('Subscription Settings', 'fluent-cart') . (!$isProActive ? ' <img src="' . esc_url($proFeatureIcon) . '" alt="' . esc_attr__('Pro feature', 'fluent-cart') . '" class="pro-feature-icon" style="margin-left: 6px; width: 14px; height: 14px; display: inline-block; vertical-align: text-top;" />' : '') . '</span>
1113 <div class="form-note">' . __('Configure how installment subscriptions can be paid early.', 'fluent-cart') . '</div>'
1114 ],
1115 'fields' => [
1116 'type' => 'grid',
1117 'columns' => [
1118 'default' => 1,
1119 'md' => 1
1120 ],
1121 'disable_nesting' => true,
1122 'class' => 'col-span-2',
1123 'schema' => [
1124 'enable_early_payment_for_installment' => [
1125 'label' => __('Enable early payment for installment', 'fluent-cart'),
1126 'type' => 'checkbox',
1127 'value' => 'yes',
1128 'disabled' => !$isProActive,
1129 'wrapperClass' => !$isProActive ? 'disabled' : '',
1130 'note' => !$isProActive
1131 ? "<div class='pl-6'>" . __('This is a FluentCart Pro feature.', 'fluent-cart') . "</div>"
1132 : "<div class='pl-6'>" . __('Allow customers to pay remaining installments early from subscription screens.', 'fluent-cart') . "</div>"
1133 ]
1134 ]
1135 ]
1136 ]
1137 ],
1138 ]
1139 ],
1140 ]
1141 ],
1142 ];
1143
1144
1145 // Only show weight/dimension unit fields to users with shipping-sensitive permission
1146 if (PermissionManager::hasPermission(['store/sensitive'])) {
1147 $storeSchema = &$fields['setting_tabs']['schema']['store_setup']['schema'];
1148 $storeSchema['weight_unit_grid'] = [
1149 'type' => 'grid',
1150 'columns' => ['default' => 1, 'md' => 3],
1151 'disable_nesting' => true,
1152 'schema' => [
1153 'label' => [
1154 'type' => 'html',
1155 'value' => '<span class="setting-label">' . __('Weight Unit', 'fluent-cart') . '</span>
1156 <div class="form-note">' . __('Unit used for product weight measurements.', 'fluent-cart') . '</div>'
1157 ],
1158 'weight_unit' => [
1159 'wrapperClass' => 'col-span-2 flex items-center',
1160 'label' => '',
1161 'type' => 'select',
1162 'options' => [
1163 ['label' => __('kg', 'fluent-cart'), 'value' => 'kg'],
1164 ['label' => __('g', 'fluent-cart'), 'value' => 'g'],
1165 ['label' => __('lbs', 'fluent-cart'), 'value' => 'lbs'],
1166 ['label' => __('oz', 'fluent-cart'), 'value' => 'oz'],
1167 ],
1168 'value' => 'kg'
1169 ],
1170 ]
1171 ];
1172 $storeSchema['dimension_unit_grid'] = [
1173 'type' => 'grid',
1174 'columns' => ['default' => 1, 'md' => 3],
1175 'disable_nesting' => true,
1176 'schema' => [
1177 'label' => [
1178 'type' => 'html',
1179 'value' => '<span class="setting-label">' . __('Dimension Unit', 'fluent-cart') . '</span>
1180 <div class="form-note">' . __('Unit used for product dimension measurements.', 'fluent-cart') . '</div>'
1181 ],
1182 'dimension_unit' => [
1183 'wrapperClass' => 'col-span-2 flex items-center',
1184 'label' => '',
1185 'type' => 'select',
1186 'options' => [
1187 ['label' => __('cm', 'fluent-cart'), 'value' => 'cm'],
1188 ['label' => __('mm', 'fluent-cart'), 'value' => 'mm'],
1189 ['label' => __('in', 'fluent-cart'), 'value' => 'in'],
1190 ['label' => __('m', 'fluent-cart'), 'value' => 'm'],
1191 ],
1192 'value' => 'cm'
1193 ],
1194 ]
1195 ];
1196 }
1197
1198 return apply_filters("fluent_cart/store_settings/fields", $fields, []);
1199 }
1200
1201 public function isModuleTabEnabled(): bool
1202 {
1203 $fields = $this->fields();
1204 return isset($fields['setting_tabs']['schema']['modules_tab']);
1205 }
1206
1207 /**
1208 * @param string|null $key like stripe or paypal
1209 * All store settings if key is not provided
1210 * @return mixed
1211 *
1212 */
1213
1214 public function get($key = null, $default = null)
1215 {
1216 if (empty($key)) {
1217 return $this->storeSettings;
1218 }
1219
1220 if (is_array($key)) {
1221 $data = Arr::only($this->storeSettings, $key);
1222 } else {
1223 $data = Arr::get($this->storeSettings, $key);
1224 }
1225
1226 return empty($data) ? $default : $data;
1227 }
1228
1229 public function moduleSettings(): array
1230 {
1231 $settings = $this->get('modules_settings', []);
1232 return Arr::wrap($settings);
1233 }
1234
1235 /**
1236 * @param array $settings like Stripe or PayPal settings array
1237 * Save store settings
1238 * @return array
1239 *
1240 */
1241 public function save(array $settings)
1242 {
1243 $prevSettings = get_option($this->optionKey, []);
1244 $prevSettings = wp_parse_args($prevSettings, $this->getDefaultSettings());
1245
1246 $settings = wp_parse_args($settings, $prevSettings);
1247
1248 $customerProfilePageId = Arr::get($settings, 'customer_profile_page_id', 0);
1249 if ($customerProfilePageId) {
1250 $settings['customer_profile_page_slug'] = $this->getCustomerDashboardPageSlug($customerProfilePageId, false);
1251 }
1252
1253 update_option($this->optionKey, $settings, true);
1254 $this->storeSettings = $settings;
1255
1256 $isSlugChanged = Arr::get($prevSettings, 'product_slug') !== Arr::get($settings, 'product_slug');
1257 $isAccountPageChanged = Arr::get($prevSettings, 'customer_profile_page_slug') !== Arr::get($settings, 'customer_profile_page_slug');
1258
1259 if ($isSlugChanged || $isAccountPageChanged) {
1260 flush_rewrite_rules();
1261 delete_option('rewrite_rules');
1262 }
1263
1264 return $this->storeSettings;
1265 }
1266
1267 public function set(string $key, $value)
1268 {
1269 return $this->save([
1270 $key => $value
1271 ]);
1272 }
1273
1274 public function getCurrency()
1275 {
1276 return $this->get('currency', 'USD');
1277 }
1278
1279 public function getCurrencySymbol()
1280 {
1281 $currency = $this->getCurrency();
1282 return CurrenciesHelper::getCurrencySign($currency);
1283 }
1284
1285 public function isCheckoutPage(): bool
1286 {
1287 global $post;
1288 $pageId = $this->getCheckoutPageId();
1289 return intval($pageId) === intval($post->ID);
1290 }
1291
1292 public function getCheckoutPageId()
1293 {
1294 return Arr::get($this->storeSettings, 'checkout_page_id');
1295 }
1296
1297 public function getPagesSettings(): array
1298 {
1299 return Arr::only(
1300 $this->storeSettings,
1301 [
1302 'checkout_page_id',
1303 'custom_payment_page_id',
1304 'registration_page_id',
1305 'login_page_id',
1306 'cart_page_id',
1307 'receipt_page_id',
1308 'shop_page_id',
1309 'customer_profile_page_id',
1310 'customer_profile_page_slug',
1311 ]
1312 );
1313 }
1314
1315 public function getCheckoutPage(): string
1316 {
1317 if ($pageID = $this->getCheckoutPageId()) {
1318 return $this->getPageLink($pageID);
1319 }
1320
1321 return '';
1322 }
1323
1324
1325 public function getCustomerProfilePageId()
1326 {
1327 return Arr::get($this->storeSettings, 'customer_profile_page_id');
1328 }
1329
1330 public function getCustomerProfilePage(): string
1331 {
1332 if ($pageId = $this->getCustomerProfilePageId()) {
1333 return $this->getPageLink($pageId);
1334 }
1335 return '';
1336 }
1337
1338
1339 public function getCartPageId()
1340 {
1341 return Arr::get($this->storeSettings, 'cart_page_id');
1342 }
1343
1344 public function getCartPage(): string
1345 {
1346 if ($pageId = $this->getCartPageId()) {
1347 if (Pages::isPage($pageId)) {
1348 return $this->getPageLink($pageId);
1349 }
1350 }
1351 return '';
1352 }
1353
1354 public function getShopPageId()
1355 {
1356 return Arr::get($this->storeSettings, 'shop_page_id');
1357 }
1358
1359 public function getShopPage(): string
1360 {
1361 if ($pageId = $this->getShopPageId()) {
1362 if (Pages::isPage($pageId)) {
1363 return $this->getPageLink($pageId);
1364 }
1365 }
1366
1367 return '';
1368 }
1369
1370 public function getReceiptPageId()
1371 {
1372 return Arr::get($this->storeSettings, 'receipt_page_id');
1373 }
1374
1375 public function getReceiptPage(): string
1376 {
1377 if ($pageId = $this->getReceiptPageId()) {
1378 if (Pages::isPage($pageId)) {
1379 return $this->getPageLink($pageId);
1380 }
1381 }
1382 return '';
1383 }
1384
1385
1386 public function getBuyButtonText(): string
1387 {
1388 return esc_html(Arr::get($this->storeSettings, 'checkout_button_text', __('Buy now', 'fluent-cart')));
1389 }
1390
1391 public function getViewCartButtonText(): string
1392 {
1393 return esc_html(Arr::get($this->storeSettings, 'view_cart_button_text', __('View Cart', 'fluent-cart')));
1394 }
1395
1396 /**
1397 * @return string
1398 *
1399 * Get cart button text
1400 */
1401 public function getCartButtonText(): string
1402 {
1403 return esc_html(Arr::get($this->storeSettings, 'cart_button_text', __('Add To Cart', 'fluent-cart')));
1404 }
1405
1406 public function toArray(): array
1407 {
1408 return $this->storeSettings;
1409 }
1410
1411 /**
1412 * @return string
1413 *
1414 * Get the base address1 for the store.
1415 */
1416 public function getBaseAddressLine1()
1417 {
1418 return Arr::get($this->storeSettings, 'store_address1');
1419 }
1420
1421 public function getFormattedFullAddress()
1422 {
1423 $addressParts = [
1424 trim(Arr::get($this->storeSettings, 'store_address1') ?? ''),
1425 trim(Arr::get($this->storeSettings, 'store_address2') ?? ''),
1426 trim(Arr::get($this->storeSettings, 'store_city') ?? ''),
1427 trim(AddressHelper::getStateNameByCode(
1428 Arr::get($this->storeSettings, 'store_state'),
1429 Arr::get($this->storeSettings, 'store_country')
1430 )),
1431 trim(Arr::get($this->storeSettings, 'store_postcode') ?? ''),
1432 trim(AddressHelper::getCountryNameByCode(Arr::get($this->storeSettings, 'store_country')))
1433 ];
1434
1435 // Filter out empty or null parts
1436 $addressParts = array_filter($addressParts, function ($part) {
1437 return $part !== '';
1438 });
1439
1440 // Join parts with comma and space
1441 $addressString = implode(', ', $addressParts);
1442 return $addressString;
1443 }
1444
1445 /**
1446 * @return string
1447 *
1448 * Get the base address2 for the store.
1449 */
1450 public function getBaseAddressLine2()
1451 {
1452 return Arr::get($this->storeSettings, 'store_address2');
1453 }
1454
1455 /**
1456 * @return string
1457 *
1458 * Get the base country for the store.
1459 */
1460 public function getBaseCountry()
1461 {
1462 return Arr::get($this->storeSettings, 'store_country');
1463 }
1464
1465 /**
1466 * @return string
1467 *
1468 * Get the base state for the store.
1469 */
1470 public function getBaseState()
1471 {
1472 return Arr::get($this->storeSettings, 'store_state');
1473 }
1474
1475 /**
1476 * @return string
1477 *
1478 * Get the base city for the store.
1479 */
1480 public function getBaseCity()
1481 {
1482 return Arr::get($this->storeSettings, 'store_city');
1483 }
1484
1485 /**
1486 * @return string
1487 *
1488 * Get the base postcode for the store.
1489 */
1490 public function getBasePostcode()
1491 {
1492 return Arr::get($this->storeSettings, 'store_postcode');
1493 }
1494
1495 public function getInvoicePrefix()
1496 {
1497 // @todo: make this dynamic from settings
1498 return $this->get('inv_prefix', '');
1499 }
1500
1501 public function getInvoiceSuffix(): string
1502 {
1503 return '';
1504 }
1505
1506 public function getCustomerDashboardPageSlug($pageId = null, $cached = true)
1507 {
1508 $slug = Arr::get($this->storeSettings, 'customer_profile_page_slug', '');
1509
1510 if ($cached && $slug) {
1511 return $slug;
1512 }
1513
1514 if (!$pageId) {
1515 $pageId = Arr::get($this->storeSettings, 'customer_profile_page_id');
1516 }
1517
1518 if (!$pageId) {
1519 return $slug;
1520 }
1521
1522 $url = get_page_link($pageId);
1523 $url = rtrim($url, '/');
1524
1525 if (!$url) {
1526 return $slug;
1527 }
1528
1529 return trim(str_replace(home_url('/'), '', $url), '/');
1530 }
1531
1532 /**
1533 * Get theme colors as CSS variable string.
1534 *
1535 * @return string
1536 */
1537 public function getThemeColors(): string
1538 {
1539 $themeSetup = $this->get('theme_setup');
1540 $colors = '';
1541
1542 if (!empty($themeSetup) && is_array($themeSetup)) {
1543 foreach ($themeSetup as $key => $value) {
1544 if (!empty($value)) {
1545 $safeKey = preg_replace('/[^a-zA-Z0-9\-_]/', '', $key);
1546 $safeValue = preg_replace('/[;\{\}]/', '', $value);
1547 $colors .= "$safeKey: $safeValue;";
1548 }
1549 }
1550 }
1551
1552 return $colors;
1553 }
1554
1555 public function getPageLink($pageId = null): string
1556 {
1557 $link = get_page_link($pageId);
1558
1559 if (!empty($link)) {
1560 return Str::endsWith($link, '/') ? $link : $link . '/';
1561 }
1562 return '';
1563 }
1564 }
1565