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

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