storeSettings = self::$cachedStoreSettings;
return;
}
$defaultSettings = $this->getDefaultSettings();
$storeSettings = get_option($this->optionKey, []);
$settings = wp_parse_args($storeSettings, $defaultSettings);
$this->storeSettings = $settings;
self::$cachedStoreSettings = $this->storeSettings;
}
protected function getDefaultSettings(): array
{
$defaultSettings = [
'store_name' => get_bloginfo('name'),
'company_name' => '',
'legal_registration_id' => '',
'seller_vat_id' => '',
'seller_tax_id' => '',
'note_for_user_account_creation' => __('An user account will be created', 'fluent-cart'),
'checkout_button_text' => __('Checkout', 'fluent-cart'),
'view_cart_button_text' => __('View Cart', 'fluent-cart'),
'cart_button_text' => __('Add To Cart', 'fluent-cart'),
'popup_button_text' => __('View Product', 'fluent-cart'),
'out_of_stock_button_text' => __('Not Available', 'fluent-cart'),
'currency_position' => 'before',
// 'thousand_separator' => 'comma',
'decimal_separator' => 'dot',
'checkout_method_style' => 'logo',
'enable_modal_checkout' => 'no',
'require_logged_in' => 'no',
'show_cart_icon_in_nav' => 'no',
'show_cart_icon_in_body' => 'yes',
'additional_address_field' => 'yes',
'hide_coupon_field' => 'no',
'user_account_creation_mode' => 'all',
'checkout_page_id' => '',
'custom_payment_page_id' => '',
'registration_page_id' => '',
'login_page_id' => '',
'cart_page_id' => '',
'receipt_page_id' => '',
'shop_page_id' => '',
'customer_profile_page_id' => '',
'customer_profile_page_slug' => '',
'currency' => 'USD',
'store_address1' => '',
'store_address2' => '',
'store_city' => '',
'store_country' => '',
'store_postcode' => '',
'store_state' => '',
'show_relevant_product_in_single_page' => 'yes',
'show_relevant_product_in_modal' => '',
'order_mode' => 'test',
'subscription_mode_guard' => 'yes',
'variation_view' => 'both',
'variation_columns' => 'masonry',
'enable_early_payment_for_installment' => 'yes',
'subscription_management_mode' => 'gateway_managed',
'subscription_system_charge' => 'no',
'modules_settings' => [],
'min_receipt_number' => '1',
'inv_prefix' => 'INV-',
'weight_unit' => 'kg',
'dimension_unit' => 'cm'
];
return apply_filters('fluent_cart/store_settings/values', $defaultSettings, []);
}
/**
* @return array
*
* Get all store settings fields
* @hook to use apply_filters("fluent_cart/store_setting_fields", $fields)
*/
public function fields($params = []): array
{
$pages = Pages::getPages('');
$previewLinks = [
'shop_page_id' => $this->getShopPage(),
'customer_profile_page_id' => $this->getCustomerProfilePage(),
'cart_page_id' => $this->getCartPage(),
'checkout_page_id' => $this->getCheckoutPage(),
'receipt_page_id' => $this->getReceiptPage()
];
$isProActive = App::isProActive();
$proFeatureIcon = Vite::getAssetUrl('images/crown.svg');
// Read-only schedule for store-managed subscription renewals. Pulled live
// from the same map the scheduler uses, so it stays accurate under the
// fluent_cart/renewal/advance_creation_days filter. No editable knob — the timing is
// deliberately built-in; developers tune it via that filter.
$invoiceScheduleMap = RenewalService::getAdvanceCreationDaysMap();
$invoiceScheduleLabels = [
'daily' => __('Daily', 'fluent-cart'),
'weekly' => __('Weekly', 'fluent-cart'),
'monthly' => __('Monthly', 'fluent-cart'),
'quarterly' => __('Quarterly', 'fluent-cart'),
'half_yearly' => __('Half-yearly', 'fluent-cart'),
'yearly' => __('Yearly', 'fluent-cart'),
];
// Structured renewal-order schedule for the SubscriptionModeManager
// component (status card + guarded edit dialog).
$invoiceScheduleList = [];
foreach ($invoiceScheduleLabels as $invoiceScheduleKey => $invoiceScheduleLabel) {
if (!isset($invoiceScheduleMap[$invoiceScheduleKey])) {
continue;
}
$invoiceScheduleDays = (int) $invoiceScheduleMap[$invoiceScheduleKey];
$invoiceScheduleList[] = [
'label' => $invoiceScheduleLabel,
'when' => $invoiceScheduleDays <= 0
? __('on the due date', 'fluent-cart')
/* translators: %d: number of days before the due date */
: sprintf(_n('%d day before due date', '%d days before due date', $invoiceScheduleDays, 'fluent-cart'), $invoiceScheduleDays),
];
}
// Gateways declaring `system_subscription` — the only ones
// subscription_system_charge can ever auto-charge.
$systemChargeGateways = [];
foreach (GatewayManager::getInstance()->all() as $systemChargeGateway) {
if (!$systemChargeGateway->has('system_subscription') || $systemChargeGateway->isUpcoming()) {
continue;
}
$systemChargeGatewayMeta = $systemChargeGateway->getMeta();
$systemChargeGateways[] = [
'label' => Arr::get($systemChargeGatewayMeta, 'admin_title')
?: Arr::get($systemChargeGatewayMeta, 'label')
?: Arr::get($systemChargeGatewayMeta, 'title'),
'active' => $systemChargeGateway->isEnabled(),
];
}
$fields = [
'setting_tabs' => [
'type' => 'section',
'disable_nesting' => true,
'default_tab' => 'store_setup',
'hide_tab_switch' => true,
'schema' => [
'store_setup' => [
'id' => '',
'title' => __('Store Setup', 'fluent-cart'),
'show_title' => false,
'type' => 'section',
'disable_nesting' => true,
'columns' => [
'default' => 1,
'md' => 1
],
'schema' => [
'name_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Store Name', 'fluent-cart') . '
' . __('Enter the public name of your online store.', 'fluent-cart') . '
'
],
"store_name" => [
'wrapperClass' => 'col-span-2 flex items-center',
"label" => '',
"type" => "input",
"value" => "",
],
]
],
'hr' => [
'type' => 'html',
'value' => '
'
],
'logo_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Store Logo', 'fluent-cart') . '
' . __("Upload your brand's logo. Recommended width: 512 pixels minimum.", 'fluent-cart') . '
'
],
"store_logo" => [
"label" => false,
"type" => "media",
"value" => "",
'multiple' => false,
// if `condition_type` not specified then all condition type will be `and`
// 'conditions' => [
// [
// 'key' => 'store_name',
// 'operator' => '==',
// 'value' => [
// 'accessor' => 'order_mode'
// ]
// ],
// ],
],
]
],
'hr2' => [
'type' => 'html',
'value' => '
'
],
'mode_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Store Mode', 'fluent-cart') . '
' . __("Select your store's operating mode: `Test` for setup, `Live` for real transactions.", 'fluent-cart') . '
'
],
'order_mode' => [
'wrapperClass' => 'col-span-2 flex items-center',
"label" => '',
"type" => "radio",
"options" => [
[
"label" => __('Live', 'fluent-cart'),
"value" => 'live',
],
[
"label" => __('Test', 'fluent-cart'),
"value" => 'test',
],
],
"value" => "live"
],
]
],
'settings_hr' => [
'type' => 'html',
'value' => '
'
],
'address_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Store Address', 'fluent-cart') . '
' . __("Provide your physical business address details.", 'fluent-cart') . '
'
],
'address_input_grid' => [
'wrapperClass' => 'fct-compact-form',
'type' => 'grid',
'disable_nesting' => true,
'class' => 'col-span-2',
'schema' => [
'store_address_component' => [
'type' => 'component',
'component' => 'StoreSettings/AddressComponent',
'wrapperClass' => 'col-span-full'
],
'store_address1' => [
'type' => 'hidden',
],
'store_address2' => [
'type' => 'hidden',
],
'store_city' => [
'type' => 'hidden',
],
'store_postcode' => [
'type' => 'hidden',
],
'store_country' => [
'type' => 'hidden',
],
'store_state' => [
'type' => 'hidden',
],
]
],
]
],
'settings_hr_2' => [
'type' => 'html',
'value' => '
'
],
'business_details_grid' => [
'type' => 'grid',
'id' => 'business_details',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Business Details', 'fluent-cart') . '
' . __('Add your legal business identity details used for store records and compliance.', 'fluent-cart') . '
'
],
'business_details_fields' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 2
],
'disable_nesting' => true,
'wrapperClass' => 'col-span-2',
'schema' => [
'company_name' => [
'label' => __('Company Name', 'fluent-cart'),
'type' => 'input',
'value' => '',
],
'legal_registration_id' => [
'label' => __('Legal Registration ID', 'fluent-cart'),
'type' => 'input',
'value' => '',
],
'seller_vat_id' => [
'label' => __('Seller VAT ID', 'fluent-cart'),
'type' => 'input',
'value' => '',
],
'seller_tax_id' => [
'label' => __('Seller Tax ID', 'fluent-cart'),
'type' => 'input',
'value' => '',
],
]
],
]
],
'settings_hr_3' => [
'type' => 'html',
'value' => '
'
],
'currency_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Checkout Currency', 'fluent-cart') . '
' . __("Select the primary currency for your store.", 'fluent-cart') . '
'
],
"currency" => [
'wrapperClass' => 'col-span-2 flex items-center',
"label" => '',
"type" => "select",
'filterable' => true,
"options" => CurrencySettings::getFormattedCurrencies(),
"value" => "USD"
],
]
],
'hr3' => [
'type' => 'html',
'value' => '
'
],
'decimal_separator_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Number Format', 'fluent-cart') . '
' . __("Select the character used to separate thousands or decimals in prices.", 'fluent-cart') . '
'
],
'decimal_separator' => [
'wrapperClass' => 'col-span-2 flex items-start flex-col',
"label" => '',
"type" => "radio",
"options" => [
[
"label" => __('Comma & Dot (eg 10,000.00)', 'fluent-cart'),
"value" => 'dot'
],
[
"label" => __('Dot & Comma (eg 10.000,00)', 'fluent-cart'),
"value" => 'comma'
],
],
"value" => "dot"
],
]
],
'hr4' => [
'type' => 'html',
'value' => '
'
],
'currency_position_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Currency Formatting', 'fluent-cart') . '
' . __("Select how the currency should be formatted.", 'fluent-cart') . '
'
],
'currency_position' => [
'wrapperClass' => 'col-span-2 flex items-center',
"label" => '',
"type" => "select",
"options" => [
[
"label" => __('Symbol before (eg: $100)', 'fluent-cart'),
"value" => 'before',
],
[
"label" => __('Symbol after (eg: 100$)', 'fluent-cart'),
"value" => 'after',
],
[
"label" => __('ISO before (eg: USD 100)', 'fluent-cart'),
"value" => 'iso_before',
],
[
"label" => __('ISO after (eg: 100 USD)', 'fluent-cart'),
"value" => 'iso_after',
],
[
"label" => __('Symbol & ISO (eg: $100 USD)', 'fluent-cart'),
"value" => 'symbool_before_iso',
],
[
"label" => __('ISO & Symbol (eg: USD 100$)', 'fluent-cart'),
"value" => 'symbool_after_iso',
],
[
"label" => __('ISO-Symbol (eg: USD $100)', 'fluent-cart'),
"value" => 'symbool_and_iso',
],
],
"value" => "before"
],
]
],
'hr5' => [
'type' => 'html',
'value' => '
'
],
'checkout_style_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Payment View', 'fluent-cart') . '
' . __("Select how payment options are visually presented on checkout.", 'fluent-cart') . '
'
],
"checkout_method_style" => [
'wrapperClass' => 'col-span-2 flex items-center',
"type" => "component",
'component' => 'PaymentView',
'label' => false,
"options" => [
[
"label" => '',
"value" => 'logo',
],
[
"label" => __('Label Selector', 'fluent-cart'),
"value" => 'radio',
],
],
"value" => "logo"
],
]
],
// 'settings_hr_modal' => [
// 'type' => 'html',
// 'value' => '
'
// ],
//
// 'modal_checkout_grid' => [
// 'type' => 'grid',
// 'columns' => [
// 'default' => 1,
// 'md' => 3
// ],
// 'disable_nesting' => true,
// 'schema' => [
// 'label' => [
// 'type' => 'html',
// 'value' => '' . __('Buy Now Button Behavior', 'fluent-cart') . '
// ' . __("Choose how the Buy Now button behaves. Modal checkout provides a seamless experience without leaving the product page.", 'fluent-cart') . '
'
// ],
// "enable_modal_checkout" => [
// 'wrapperClass' => 'col-span-2 flex items-center',
// "label" => '',
// "type" => "radio",
// "options" => [
// [
// "label" => __('Redirect to Checkout Page', 'fluent-cart'),
// "value" => 'no',
// ],
// [
// "label" => __('Open Checkout in Modal', 'fluent-cart'),
// "value" => 'yes',
// ],
// ],
// "value" => "no"
// ],
// ]
// ],
],
],
// 'button_setup' => [
// 'title' => __('Button Setup', 'fluent-cart'),
// 'type' => 'tab-pane',
// 'disable_nesting' => true,
// 'schema' => [
// 'button_setup_settings' => [
// 'title' => __('Button Setup', 'fluent-cart'),
// 'type' => 'section',
// 'disable_nesting' => true,
// 'columns' => [
// 'default' => 1,
// 'md' => 2
// ],
// 'schema' => [
// "checkout_button_text" => [
// "label" => __('Checkout Button Text', 'fluent-cart'),
// "type" => "input",
// "value" => __('Buy now', 'fluent-cart')
// ],
// "cart_button_text" => [
// "label" => __('Cart Button Text', 'fluent-cart'),
// "type" => "input",
// "value" => __('Add to cart', 'fluent-cart')
// ],
//
// "popup_button_text" => [
// "label" => __('Popup Button Text', 'fluent-cart'),
// "type" => "input",
// "value" => __('View Product', 'fluent-cart')
// ],
// "out_of_stock_button_text" => [
// "label" => __('Out of Stock Button Text', 'fluent-cart'),
// "type" => "input",
// "value" => __('Out of stock', 'fluent-cart')
// ],
// "view_cart_button_text" => [
// "label" => __('View Cart Button Text', 'fluent-cart'),
// "type" => "input",
// "value" => __('View Cart', 'fluent-cart')
// ],
//
// "note_for_user_account_creation" => [
// "label" => __('Note for User Account Creation,', 'fluent-cart'),
// "type" => "input",
// "value" => __('You have subscription product in your cart, an account will be created', 'fluent-cart')
// ],
// ],
// ]
// ]
// ],
'pages_setup' => [
'id' => '',
'title' => __('Pages Setup', 'fluent-cart'),
'show_title' => false,
'type' => 'section',
'disable_nesting' => true,
'columns' => [
'default' => 1,
'md' => 1
],
'schema' => [
'shop_page_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3,
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Select Shop Page', 'fluent-cart') . '
' . __("Select the page that showcases all of your products.", 'fluent-cart') . '
'
],
'shop_page_id' => [
'wrapperClass' => 'col-span-2',
'page_title' => __('Shop', 'fluent-cart'),
'type' => 'component',
'component' => 'StoreSettings/PageSelector',
'page_key' => 'shop_page_id',
'preview_link' => $previewLinks['shop_page_id'],
'options' => $pages,
'hide_note' => true,
'value' => '',
'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
'[fluent_cart_products]',
__('Products', 'fluent-cart')
),
],
]
],
'hr1' => [
'type' => 'html',
'value' => '
'
],
'customer_profile_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Select Customer Profile Page', 'fluent-cart') . '
' . __("Select the page where customers will manage their profile, orders, and downloads.", 'fluent-cart') . '
'
],
'customer_profile_page_id' => [
'wrapperClass' => 'col-span-2',
'label' => false,
'page_title' => __('Account', 'fluent-cart'),
'type' => 'component',
'component' => 'StoreSettings/PageSelector',
'page_key' => 'customer_profile_page_id',
'preview_link' => $previewLinks['customer_profile_page_id'],
'hide_note' => true,
'options' => $pages,
'value' => '',
'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
'[fluent_cart_customer_profile]',
__('Account', 'fluent-cart')
),
],
]
],
'hr2' => [
'type' => 'html',
'value' => '
'
],
'cart_page_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Select Cart Page', 'fluent-cart') . '
' . __("Select the page that will display customer's current shopping cart.", 'fluent-cart') . '
'
],
'cart_page_id' => [
'wrapperClass' => 'col-span-2',
'label' => false,
'page_title' => __('Cart', 'fluent-cart'),
'type' => 'component',
'component' => 'StoreSettings/PageSelector',
'page_key' => 'cart_page_id',
'preview_link' => $previewLinks['cart_page_id'],
'hide_note' => true,
'options' => $pages,
'value' => '',
'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
'[fluent_cart_cart]',
__('Cart', 'fluent-cart')
),
],
]
],
'hr3' => [
'type' => 'html',
'value' => '
'
],
'receipt_page_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Select Receipt Page', 'fluent-cart') . '
' . __("Select the page that will display order summary after a successful purchase.", 'fluent-cart') . '
'
],
'receipt_page_id' => [
'wrapperClass' => 'col-span-2',
'label' => false,
'page_title' => __('Receipt', 'fluent-cart'),
'type' => 'component',
'component' => 'StoreSettings/PageSelector',
'page_key' => 'receipt_page_id',
'preview_link' => $previewLinks['receipt_page_id'],
'hide_note' => true,
'options' => $pages,
'value' => '',
'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
'[fluent_cart_receipt]',
__('Receipt', 'fluent-cart')
),
],
]
],
'hr4' => [
'type' => 'html',
'value' => '
'
],
'checkout_page_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Select Checkout Page', 'fluent-cart') . '
' . __("Select the page where customers will finalize their purchase.", 'fluent-cart') . '
'
],
'checkout_page_id' => [
'wrapperClass' => 'col-span-2',
'label' => false,
'page_title' => __('Checkout', 'fluent-cart'),
'type' => 'component',
'component' => 'StoreSettings/PageSelector',
'page_key' => 'checkout_page_id',
'preview_link' => $previewLinks['checkout_page_id'],
'hide_note' => true,
'options' => $pages,
'value' => '',
'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
'[fluent_cart_checkout]',
__('Checkout', 'fluent-cart')
),
],
]
]
]
],
'single_product_setup' => [
'title' => __('Product Page', 'fluent-cart'),
'show_title' => false,
'type' => 'section',
'disable_nesting' => true,
'columns' => [
'default' => 1,
'md' => 1
],
'schema' => [
'product_settings_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Single Product Setup', 'fluent-cart') . '
' . __("Control the display of relevant information.", 'fluent-cart') . '
'
],
'fields' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 1
],
'disable_nesting' => true,
'schema' => [
"show_relevant_product_in_single_page" => [
"label" => __('Show Relevant In Single Page', 'fluent-cart'),
"type" => "checkbox",
"value" => "yes"
],
"show_relevant_product_in_modal" => [
"label" => __('Show Relevant In Product Modal', 'fluent-cart'),
"type" => "checkbox",
"value" => "no"
],
]
]
]
],
'hr' => [
'type' => 'html',
'value' => '
'
],
'image_zoom_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Image Zooming', 'fluent-cart') . '
' . __("Enable Image zoom in single product.", 'fluent-cart') . '
'
],
'fields' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 1
],
'disable_nesting' => true,
'schema' => [
"enable_image_zoom_in_single_product" => [
"label" => __('Enable Zoom in Single Product', 'fluent-cart'),
"type" => "checkbox",
"value" => "no"
],
"enable_image_zoom_in_modal" => [
"label" => __('Enable Zoom in Modal', 'fluent-cart'),
"type" => "checkbox",
"value" => "no"
],
]
]
]
],
'hr_image_zoom' => [
'type' => 'html',
'value' => '
'
],
'variation_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Variation View', 'fluent-cart') . '
' . __("Defines how product variations are visually presented to customers.", 'fluent-cart') . '
'
],
"variation_view" => [
'wrapperClass' => 'col-span-2 flex items-center',
"label" => false,
"type" => "select",
"options" => [
[
"label" => __('Image', 'fluent-cart'),
"value" => 'image',
],
[
"label" => __('Text', 'fluent-cart'),
"value" => 'text',
],
[
"label" => __('Image with Text', 'fluent-cart'),
"value" => 'both',
],
],
"value" => ""
],
]
],
'hr2' => [
'type' => 'html',
'value' => '
'
],
'variation_column_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Variation Columns', 'fluent-cart') . '
' . __("Set the column layout for how product variations are displayed within product sections.", 'fluent-cart') . '
'
],
"variation_columns" => [
'wrapperClass' => 'col-span-2 flex items-center',
"label" => false,
"type" => "select",
"options" => [
[
"label" => __('One Column', 'fluent-cart'),
"value" => 'one',
],
[
"label" => __('Two Columns', 'fluent-cart'),
"value" => 'two',
],
[
"label" => __('Three Columns', 'fluent-cart'),
"value" => 'three',
],
[
"label" => __('Four Columns', 'fluent-cart'),
"value" => 'four',
],
[
"label" => __('Masonry', 'fluent-cart'),
"value" => 'masonry',
],
],
"value" => ""
],
]
],
'hr3' => [
'type' => 'html',
'value' => '
'
],
'product_slug_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Product Slug', 'fluent-cart') . '
' . __("Set Product Slug.", 'fluent-cart') . '
'
],
"product_slug" => [
'wrapperClass' => 'col-span-2 flex items-center',
"label" => false,
"type" => "input",
"value" => ""
],
]
],
],
],
'cart_and_checkout' => [
'title' => __('Cart & checkout', 'fluent-cart'),
'show_title' => false,
'type' => 'section',
'disable_nesting' => true,
'columns' => [
'default' => 1,
'md' => 1
],
'schema' => [
"show_cart_icon_in_body" => [
"label" => __('Cart Icon In Body', 'fluent-cart'),
"type" => "checkbox",
"value" => "yes",
'note' => sprintf(
/* 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 */
"",
__('Display the cart icon in the body of the website', 'fluent-cart'),
__('Use this', 'fluent-cart'),
__('Copy to clipboard', 'fluent-cart'),
'fcart-cart-toggle-button',
__('CSS class to display the cart link/icon anywhere else.', 'fluent-cart')
)
],
'hr2' => [
'type' => 'html',
'value' => '
'
],
"require_logged_in" => [
"label" => __('Require user to be logged in for checkout (Coming soon)', 'fluent-cart'),
"type" => "checkbox",
"value" => "no",
'note' => "" . __('Enforce that customers must be logged into their account to complete a purchase.', 'fluent-cart') . "
",
'wrapperClass' => 'disabled'
],
'hr3' => [
'type' => 'html',
'value' => '
'
],
'user_account_creation_mode_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('User Account Creation Mode', 'fluent-cart') . '
' . __("User account will be created regardless of the mode if the order has a subscription.", 'fluent-cart') . '
'
],
'user_account_input_grid' => [
'type' => 'grid',
'disable_nesting' => true,
'class' => 'col-span-2',
'schema' => [
'user_account_creation_mode' => [
'wrapperClass' => 'col-span-2 flex items-center',
"label" => '',
"type" => "radio",
"options" => [
[
"label" => __('Create User Account Automatically after payment
', 'fluent-cart'),
"value" => 'all',
'note' => "" . __('User account will be created automatically after payment.', 'fluent-cart') . "
",
'option_class' => 'mb-2.5'
],
[
"label" => __('Give checkbox to create account on checkout page', 'fluent-cart'),
"value" => 'user_choice',
'note' => "" . __('User will have an option to create an account during checkout.', 'fluent-cart') . "
",
'option_class' => 'mb-2.5'
],
[
"label" => __('No need to create account for onetime purchases', 'fluent-cart'),
"value" => 'only_subscription',
'note' => "" . __('User account will not be created for onetime purchases.', 'fluent-cart') . "
",
],
],
"value" => "all"
],
]
],
]
],
// "allow_checkout_signup" => [
// "label" => __('Allow customers to create account during one-time checkout', 'fluent-cart'),
// "type" => "checkbox",
// "value" => "no",
// 'note' => "" . __('Provide an option for customers to create a user account during a single, non-recurring checkout process.', 'fluent-cart') . "
"
// ],
// "force_ssl" => [
// "label" => __('Force page to SSL (https)', 'fluent-cart'),
// "type" => "checkbox",
// "value" => "no"
// ],
'hr5' => [
'type' => 'html',
'value' => '
'
],
"hide_coupon_field" => [
"label" => __('Hide coupon field on checkout', 'fluent-cart'),
"type" => "checkbox",
"value" => "no",
'note' => "" . __('Hide the coupon code input field on the checkout page.', 'fluent-cart') . "
"
],
'hr6' => [
'type' => 'html',
'value' => '
'
],
'order_invoice_grid' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Receipt Settings', 'fluent-cart') . '
' . __("Setup your receipt.", 'fluent-cart') . '
'
],
'invoice_input_grid' => [
'type' => 'grid',
'disable_nesting' => true,
'class' => 'col-span-2',
'schema' => [
"min_receipt_number" => [
'wrapperClass' => 'col-span-2 flex flex-col',
"label" => __('Minimum Receipt Number', 'fluent-cart'),
"type" => "input",
"value" => "",
'note' => sprintf(
"%s
",
sprintf(
/* translators: %s is the next receipt number */
__('Next Receipt Number: %s', 'fluent-cart'),
OrderService::getNextReceiptNumber()
)
),
],
"inv_prefix" => [
'wrapperClass' => 'col-span-2 flex flex-col',
"label" => __('Receipt Prefix', 'fluent-cart'),
"type" => "input",
"value" => "",
],
]
],
]
],
]
],
'subscriptions_setup' => [
'title' => __('Subscriptions', 'fluent-cart'),
'show_title' => false,
'type' => 'section',
'disable_nesting' => true,
'columns' => [
'default' => 1,
'md' => 1
],
'schema' => [
'subscription_early_payment_grid' => [
'type' => 'grid',
'wrapperClass' => 'items-start mb-6',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Early Payment', 'fluent-cart') . (!$isProActive ? '
' : '') . '
' . __('Let customers pay remaining installments before their due date.', 'fluent-cart') . '
'
],
'fields' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 1
],
'disable_nesting' => true,
'class' => 'col-span-2',
'schema' => [
'enable_early_payment_for_installment' => [
'label' => __('Enable early payment for installment', 'fluent-cart'),
'type' => 'checkbox',
'value' => 'yes',
'disabled' => !$isProActive,
'wrapperClass' => !$isProActive ? 'disabled' : '',
'note' => !$isProActive
? "" . __('This is a FluentCart Pro feature.', 'fluent-cart') . "
"
: "" . __('Allow customers to pay remaining installments early from subscription screens.', 'fluent-cart') . "
"
]
]
]
]
],
'subscription_management_mode_grid' => [
'type' => 'grid',
'wrapperClass' => 'items-start',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => sprintf(
/* translators: 1: setting label, 2: setting description */
'%1$s
%2$s
',
__('Renewal Billing', 'fluent-cart'),
__('Choose how recurring subscription payments are collected.', 'fluent-cart')
)
],
'fields' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 1
],
'disable_nesting' => true,
'class' => 'col-span-2',
'schema' => [
// Compact, guarded control: shows only the CURRENT mode with a
// short how-it-works summary and a Change button. Editing goes
// through a disclaimer confirm + dialog so the store-wide
// billing decision can never be flipped by a stray click.
'subscription_management_mode' => [
'label' => false,
'component' => 'StoreSettings/SubscriptionModeManager',
'disable_nesting' => true,
'value' => 'gateway_managed',
// Read-only renewal-order schedule, built live from the
// same map the scheduler uses (filterable).
'schedule_items' => $invoiceScheduleList,
// Which gateways auto-charge is actually possible on.
'system_charge_gateways' => $systemChargeGateways,
],
// Keep these in the form payload — the component above writes
// them; without a schema entry the keys would drop out of the
// saved values.
'subscription_system_charge' => [
'type' => 'hidden',
'value' => 'no',
],
'subscription_manual_fallback' => [
'type' => 'hidden',
'value' => 'no',
],
]
]
]
],
'subscription_mode_guard_grid' => [
'type' => 'grid',
'wrapperClass' => 'items-start mt-6',
'columns' => [
'default' => 1,
'md' => 3
],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => sprintf(
/* translators: 1: setting label, 2: setting description */
'%1$s
%2$s
',
__('Staging Protection', 'fluent-cart'),
__('Prevent staging or test copies of your store from billing real customers.', 'fluent-cart')
)
],
'fields' => [
'type' => 'grid',
'columns' => [
'default' => 1,
'md' => 1
],
'disable_nesting' => true,
'class' => 'col-span-2',
'schema' => [
'subscription_mode_guard' => [
'label' => __('Don\'t bill live subscriptions from this site while it is in test mode', 'fluent-cart'),
'type' => 'checkbox',
'value' => 'yes',
'note' => sprintf(
/* translators: 1: the setting's explanatory note text */
"%1\$s
",
__('In test mode, this site won\'t invoice, charge, or email live subscriptions — so a staging copy can never double-bill customers. Billing from this site resumes when it is live again.', 'fluent-cart')
)
],
]
]
]
],
]
],
]
],
];
// Only show weight/dimension unit fields to users with shipping-sensitive permission
if (PermissionManager::hasPermission(['store/sensitive'])) {
$storeSchema = &$fields['setting_tabs']['schema']['store_setup']['schema'];
$storeSchema['weight_unit_grid'] = [
'type' => 'grid',
'columns' => ['default' => 1, 'md' => 3],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Weight Unit', 'fluent-cart') . '
' . __('Unit used for product weight measurements.', 'fluent-cart') . '
'
],
'weight_unit' => [
'wrapperClass' => 'col-span-2 flex items-center',
'label' => '',
'type' => 'select',
'options' => [
['label' => __('kg', 'fluent-cart'), 'value' => 'kg'],
['label' => __('g', 'fluent-cart'), 'value' => 'g'],
['label' => __('lbs', 'fluent-cart'), 'value' => 'lbs'],
['label' => __('oz', 'fluent-cart'), 'value' => 'oz'],
],
'value' => 'kg'
],
]
];
$storeSchema['dimension_unit_grid'] = [
'type' => 'grid',
'columns' => ['default' => 1, 'md' => 3],
'disable_nesting' => true,
'schema' => [
'label' => [
'type' => 'html',
'value' => '' . __('Dimension Unit', 'fluent-cart') . '
' . __('Unit used for product dimension measurements.', 'fluent-cart') . '
'
],
'dimension_unit' => [
'wrapperClass' => 'col-span-2 flex items-center',
'label' => '',
'type' => 'select',
'options' => [
['label' => __('cm', 'fluent-cart'), 'value' => 'cm'],
['label' => __('mm', 'fluent-cart'), 'value' => 'mm'],
['label' => __('in', 'fluent-cart'), 'value' => 'in'],
['label' => __('m', 'fluent-cart'), 'value' => 'm'],
],
'value' => 'cm'
],
]
];
}
return apply_filters("fluent_cart/store_settings/fields", $fields, []);
}
public function isModuleTabEnabled(): bool
{
$fields = $this->fields();
return isset($fields['setting_tabs']['schema']['modules_tab']);
}
/**
* @param string|null $key like stripe or paypal
* All store settings if key is not provided
* @return mixed
*
*/
public function get($key = null, $default = null)
{
if (empty($key)) {
return $this->storeSettings;
}
if (is_array($key)) {
$data = Arr::only($this->storeSettings, $key);
} else {
$data = Arr::get($this->storeSettings, $key);
}
return empty($data) ? $default : $data;
}
public function moduleSettings(): array
{
$settings = $this->get('modules_settings', []);
return Arr::wrap($settings);
}
/**
* @param array $settings like Stripe or PayPal settings array
* Save store settings
* @return array
*
*/
public function save(array $settings)
{
$prevSettings = get_option($this->optionKey, []);
$prevSettings = wp_parse_args($prevSettings, $this->getDefaultSettings());
$settings = wp_parse_args($settings, $prevSettings);
$customerProfilePageId = Arr::get($settings, 'customer_profile_page_id', 0);
if ($customerProfilePageId) {
$settings['customer_profile_page_slug'] = $this->getCustomerDashboardPageSlug($customerProfilePageId, false);
}
update_option($this->optionKey, $settings, true);
$this->storeSettings = $settings;
self::$cachedStoreSettings = $this->storeSettings;
wp_cache_delete(self::CACHE_KEY, self::CACHE_GROUP);
$isSlugChanged = Arr::get($prevSettings, 'product_slug') !== Arr::get($settings, 'product_slug');
$isAccountPageChanged = Arr::get($prevSettings, 'customer_profile_page_slug') !== Arr::get($settings, 'customer_profile_page_slug');
if ($isSlugChanged || $isAccountPageChanged) {
flush_rewrite_rules();
delete_option('rewrite_rules');
}
return $this->storeSettings;
}
public function set(string $key, $value)
{
return $this->save([
$key => $value
]);
}
public function getCurrency()
{
return $this->get('currency', 'USD');
}
public function getCurrencySymbol()
{
$currency = $this->getCurrency();
return CurrenciesHelper::getCurrencySign($currency);
}
public function isCheckoutPage(): bool
{
global $post;
$pageId = $this->getCheckoutPageId();
return intval($pageId) === intval($post->ID);
}
public function getCheckoutPageId()
{
return Arr::get($this->storeSettings, 'checkout_page_id');
}
public function getPagesSettings(): array
{
return Arr::only(
$this->storeSettings,
[
'checkout_page_id',
'custom_payment_page_id',
'registration_page_id',
'login_page_id',
'cart_page_id',
'receipt_page_id',
'shop_page_id',
'customer_profile_page_id',
'customer_profile_page_slug',
]
);
}
public function getCheckoutPage(): string
{
if ($pageID = $this->getCheckoutPageId()) {
return $this->getPageLink($pageID);
}
return '';
}
public function getCustomerProfilePageId()
{
return Arr::get($this->storeSettings, 'customer_profile_page_id');
}
public function getCustomerProfilePage(): string
{
if ($pageId = $this->getCustomerProfilePageId()) {
return $this->getPageLink($pageId);
}
return '';
}
public function getCartPageId()
{
return Arr::get($this->storeSettings, 'cart_page_id');
}
public function getCartPage(): string
{
if ($pageId = $this->getCartPageId()) {
if (Pages::isPage($pageId)) {
return $this->getPageLink($pageId);
}
}
return '';
}
public function getShopPageId()
{
return Arr::get($this->storeSettings, 'shop_page_id');
}
public function getShopPage(): string
{
if ($pageId = $this->getShopPageId()) {
if (Pages::isPage($pageId)) {
return $this->getPageLink($pageId);
}
}
return '';
}
public function getReceiptPageId()
{
return Arr::get($this->storeSettings, 'receipt_page_id');
}
public function getReceiptPage(): string
{
if ($pageId = $this->getReceiptPageId()) {
if (Pages::isPage($pageId)) {
return $this->getPageLink($pageId);
}
}
return home_url();
}
public function getBuyButtonText(): string
{
return esc_html(Arr::get($this->storeSettings, 'checkout_button_text', __('Buy now', 'fluent-cart')));
}
public function getViewCartButtonText(): string
{
return esc_html(Arr::get($this->storeSettings, 'view_cart_button_text', __('View Cart', 'fluent-cart')));
}
/**
* @return string
*
* Get cart button text
*/
public function getCartButtonText(): string
{
return esc_html(Arr::get($this->storeSettings, 'cart_button_text', __('Add To Cart', 'fluent-cart')));
}
public function toArray(): array
{
return $this->storeSettings;
}
/**
* @return string
*
* Get the base address1 for the store.
*/
public function getBaseAddressLine1()
{
return Arr::get($this->storeSettings, 'store_address1');
}
public function getFormattedFullAddress()
{
$addressParts = [
trim(Arr::get($this->storeSettings, 'store_address1') ?? ''),
trim(Arr::get($this->storeSettings, 'store_address2') ?? ''),
trim(Arr::get($this->storeSettings, 'store_city') ?? ''),
trim(AddressHelper::getStateNameByCode(
Arr::get($this->storeSettings, 'store_state'),
Arr::get($this->storeSettings, 'store_country')
)),
trim(Arr::get($this->storeSettings, 'store_postcode') ?? ''),
trim(AddressHelper::getCountryNameByCode(Arr::get($this->storeSettings, 'store_country')))
];
// Filter out empty or null parts
$addressParts = array_filter($addressParts, function ($part) {
return $part !== '';
});
// Join parts with comma and space
$addressString = implode(', ', $addressParts);
return $addressString;
}
/**
* @return string
*
* Get the base address2 for the store.
*/
public function getBaseAddressLine2()
{
return Arr::get($this->storeSettings, 'store_address2');
}
/**
* @return string
*
* Get the base country for the store.
*/
public function getBaseCountry()
{
return Arr::get($this->storeSettings, 'store_country');
}
/**
* @return string
*
* Get the base state for the store.
*/
public function getBaseState()
{
return Arr::get($this->storeSettings, 'store_state');
}
/**
* @return string
*
* Get the base city for the store.
*/
public function getBaseCity()
{
return Arr::get($this->storeSettings, 'store_city');
}
/**
* @return string
*
* Get the base postcode for the store.
*/
public function getBasePostcode()
{
return Arr::get($this->storeSettings, 'store_postcode');
}
public function getInvoicePrefix()
{
// @todo: make this dynamic from settings
return $this->get('inv_prefix', '');
}
public function getInvoiceSuffix(): string
{
return '';
}
public function getCustomerDashboardPageSlug($pageId = null, $cached = true)
{
$slug = Arr::get($this->storeSettings, 'customer_profile_page_slug', '');
if ($cached && $slug) {
return $slug;
}
if (!$pageId) {
$pageId = Arr::get($this->storeSettings, 'customer_profile_page_id');
}
if (!$pageId || !get_post($pageId)) {
return $slug;
}
$url = get_page_link($pageId);
$url = rtrim($url, '/');
if (!$url) {
return $slug;
}
return trim(str_replace(home_url('/'), '', $url), '/');
}
/**
* Get theme colors as CSS variable string.
*
* @return string
*/
public function getThemeColors(): string
{
$themeSetup = $this->get('theme_setup');
$colors = '';
if (!empty($themeSetup) && is_array($themeSetup)) {
foreach ($themeSetup as $key => $value) {
if (!empty($value)) {
$safeKey = preg_replace('/[^a-zA-Z0-9\-_]/', '', $key);
$safeValue = preg_replace('/[;\{\}]/', '', $value);
$colors .= "$safeKey: $safeValue;";
}
}
}
return $colors;
}
public function getPageLink($pageId = null): string
{
if (!$pageId || !get_post($pageId)) {
return '';
}
$link = get_page_link($pageId);
if (!empty($link)) {
return Str::endsWith($link, '/') ? $link : $link . '/';
}
return '';
}
}