PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.7.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.7.0
1.7.0 1.6.6 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 All 50 releases
← All changes | api/StoreSettings.php +229 -29 1.6.5 → 1.7.0 View file →
@@ -82,9 +82,10 @@
82 82 'show_cart_icon_in_body' => 'yes',
83 83 'additional_address_field' => 'yes',
84 84 'hide_coupon_field' => 'no',
85 85 'user_account_creation_mode' => 'all',
86 - 'auto_login_after_account_creation' => 'no',
86 + 'auto_login_after_account_creation' => 'yes',
87 + 'require_customer_email_verification' => 'no',
87 88 'checkout_page_id' => '',
88 89 'custom_payment_page_id' => '',
89 90 'registration_page_id' => '',
90 91 'login_page_id' => '',
@@ -89,8 +90,9 @@
89 90 'registration_page_id' => '',
90 91 'login_page_id' => '',
91 92 'cart_page_id' => '',
92 93 'receipt_page_id' => '',
94 + 'order_review_page_id' => '',
93 95 'shop_page_id' => '',
94 96 'customer_profile_page_id' => '',
95 97 'customer_profile_page_slug' => '',
96 98 'currency' => 'USD',
@@ -101,8 +103,11 @@
101 103 'store_postcode' => '',
102 104 'store_state' => '',
103 105 'show_relevant_product_in_single_page' => 'yes',
104 106 'show_relevant_product_in_modal' => '',
107 + 'show_reviews_in_single_page' => 'yes',
108 + 'show_rating_in_shop' => 'yes',
109 + 'show_rating_in_relevant' => 'yes',
105 110 'order_mode' => 'test',
106 111 'subscription_mode_guard' => 'yes',
107 112 'variation_view' => 'both',
108 113 'variation_columns' => 'masonry',
@@ -143,9 +148,10 @@
143 148 'shop_page_id' => $this->getShopPage(),
144 149 'customer_profile_page_id' => $this->getCustomerProfilePage(),
145 150 'cart_page_id' => $this->getCartPage(),
146 151 'checkout_page_id' => $this->getCheckoutPage(),
147 - 'receipt_page_id' => $this->getReceiptPage()
152 + 'receipt_page_id' => $this->getReceiptPage(),
153 + 'order_review_page_id' => $this->getOrderReviewPage()
148 154 ];
149 155 $isProActive = App::isProActive();
150 156 $proFeatureIcon = Vite::getAssetUrl('images/crown.svg');
151 157
@@ -892,8 +898,45 @@
892 898 ],
893 899 ]
894 900 ],
895 901
902 + 'hr_order_review' => [
903 + 'type' => 'html',
904 + 'value' => '<hr class="settings-divider">'
905 + ],
906 +
907 + 'order_review_page_grid' => [
908 + 'type' => 'grid',
909 + 'columns' => [
910 + 'default' => 1,
911 + 'md' => 3
912 + ],
913 + 'disable_nesting' => true,
914 + 'schema' => [
915 + 'label' => [
916 + 'type' => 'html',
917 + 'value' => '<span class="setting-label">' . __('Select Order Review Page', 'fluent-cart') . '</span>
918 + <div class="form-note">' . __("Select the page where customers will review the products they bought, from the link in their order email.", 'fluent-cart') . '</div>'
919 + ],
920 + 'order_review_page_id' => [
921 + 'wrapperClass' => 'col-span-2',
922 + 'label' => false,
923 + 'page_title' => __('Review Your Order', 'fluent-cart'),
924 + 'type' => 'component',
925 + 'component' => 'StoreSettings/PageSelector',
926 + 'page_key' => 'order_review_page_id',
927 + 'preview_link' => $previewLinks['order_review_page_id'],
928 + 'hide_note' => true,
929 + 'options' => $pages,
930 + 'value' => '',
931 + 'note' => \FluentCart\App\Helpers\Helper::getShortcodeInstructionString(
932 + '[fluent_cart_order_review]',
933 + __('Review Your Order', 'fluent-cart')
934 + ),
935 + ],
936 + ]
937 + ],
938 +
896 939 'hr4' => [
897 940 'type' => 'html',
898 941 'value' => '<hr class="settings-divider">'
899 942 ],
@@ -951,9 +994,9 @@
951 994 'schema' => [
952 995 'label' => [
953 996 'type' => 'html',
954 997 'value' => '<span class="setting-label">' . __('Single Product Setup', 'fluent-cart') . '</span>
955 - <div class="form-note">' . __("Control the display of relevant information.", 'fluent-cart') . '</div>'
998 + <div class="form-note">' . __("Choose which sections to display on the single product page.", 'fluent-cart') . '</div>'
956 999 ],
957 1000 'fields' => [
958 1001 'type' => 'grid',
959 1002 'columns' => [
@@ -971,8 +1014,17 @@
971 1014 "label" => __('Show Relevant In Product Modal', 'fluent-cart'),
972 1015 "type" => "checkbox",
973 1016 "value" => "no"
974 1017 ],
1018 + "show_reviews_in_single_page" => [
1019 + "label" => __('Show Reviews In Single Page', 'fluent-cart'),
1020 + "type" => "checkbox",
1021 + "value" => "yes"
1022 + ],
1023 + "show_reviews_note" => [
1024 + "type" => "html",
1025 + "value" => '<div class="form-note">' . __('For block themes, add the Product Reviews block to your Single Product template to display reviews on your product page.', 'fluent-cart') . '</div>'
1026 + ],
975 1027 ]
976 1028 ]
977 1029
978 1030 ]
@@ -1134,8 +1186,53 @@
1134 1186 ],
1135 1187
1136 1188 ]
1137 1189 ],
1190 +
1191 + 'hr_product_slug' => [
1192 + 'type' => 'html',
1193 + 'value' => '<hr class="settings-divider">'
1194 + ],
1195 +
1196 + 'product_rating_grid' => [
1197 + 'type' => 'grid',
1198 + 'columns' => [
1199 + 'default' => 1,
1200 + 'md' => 3
1201 + ],
1202 + 'disable_nesting' => true,
1203 + 'schema' => [
1204 + 'label' => [
1205 + 'type' => 'html',
1206 + 'value' => sprintf(
1207 + '<span class="setting-label">%1$s</span><div class="form-note">%2$s</div>',
1208 + __('Product Rating', 'fluent-cart'),
1209 + __('Show star ratings when reviews are enabled.', 'fluent-cart')
1210 + )
1211 + ],
1212 + 'fields' => [
1213 + 'type' => 'grid',
1214 + 'columns' => [
1215 + 'default' => 1,
1216 + 'md' => 1
1217 + ],
1218 + 'disable_nesting' => true,
1219 + 'schema' => [
1220 + "show_rating_in_shop" => [
1221 + "label" => __('Show Rating in Shop', 'fluent-cart'),
1222 + "type" => "checkbox",
1223 + "value" => "yes"
1224 + ],
1225 + "show_rating_in_relevant" => [
1226 + "label" => __('Show Rating in Relevant Products', 'fluent-cart'),
1227 + "type" => "checkbox",
1228 + "value" => "yes"
1229 + ],
1230 + ]
1231 + ]
1232 +
1233 + ]
1234 + ],
1138 1235 ],
1139 1236 ],
1140 1237 'compliance' => [
1141 1238 'title' => __('Compliance', 'fluent-cart'),
@@ -1146,27 +1243,99 @@
1146 1243 'default' => 1,
1147 1244 'md' => 1,
1148 1245 ],
1149 1246 'schema' => [
1150 - 'auto_login_after_account_creation' => [
1151 - 'wrapperClass' => 'fct-compliance-auto-login',
1152 - 'label' => __('Login after account creation', 'fluent-cart'),
1153 - 'type' => 'radio',
1154 - 'value' => 'no',
1155 - 'attributes' => [
1156 - 'aria-label' => __('Login after account creation', 'fluent-cart'),
1247 + 'email_verification_grid' => [
1248 + 'type' => 'grid',
1249 + 'disable_nesting' => true,
1250 + 'columns' => ['default' => 1, 'md' => 3],
1251 + 'wrapperClass' => 'items-start',
1252 + 'schema' => [
1253 + 'label' => [
1254 + 'type' => 'html',
1255 + 'value' => sprintf(
1256 + '<span class="setting-label">%1$s</span><div class="form-note">%2$s</div>',
1257 + esc_html__('Customer email verification', 'fluent-cart'),
1258 + esc_html__('Confirm email ownership before customers access their portal and saved checkout addresses.', 'fluent-cart')
1259 + ),
1260 + ],
1261 + 'fields' => [
1262 + 'type' => 'grid',
1263 + 'disable_nesting' => true,
1264 + 'columns' => ['default' => 1],
1265 + 'wrapperClass' => 'md:col-span-2',
1266 + 'schema' => [
1267 + 'require_customer_email_verification' => [
1268 + 'wrapperClass' => 'fct-compliance-auto-login',
1269 + 'label' => false,
1270 + 'type' => 'radio',
1271 + 'value' => 'no',
1272 + 'attributes' => [
1273 + 'aria-label' => __('Customer email verification', 'fluent-cart'),
1274 + ],
1275 + 'options' => [
1276 + [
1277 + 'label' => __('Required', 'fluent-cart'),
1278 + 'value' => 'yes',
1279 + ],
1280 + [
1281 + 'label' => __('Not required', 'fluent-cart'),
1282 + 'value' => 'no',
1283 + ],
1284 + ],
1285 + 'note' => __('When not required, new checkout accounts are linked to their purchases immediately.', 'fluent-cart'),
1286 + ],
1287 + ],
1288 + ],
1157 1289 ],
1158 - 'options' => [
1159 - [
1160 - 'label' => __("Don't auto login after account creation", 'fluent-cart'),
1161 - 'value' => 'no',
1290 + ],
1291 + 'compliance_divider' => [
1292 + 'type' => 'html',
1293 + 'value' => '<hr class="settings-divider">',
1294 + ],
1295 + 'account_login_grid' => [
1296 + 'type' => 'grid',
1297 + 'disable_nesting' => true,
1298 + 'columns' => ['default' => 1, 'md' => 3],
1299 + 'wrapperClass' => 'items-start',
1300 + 'schema' => [
1301 + 'label' => [
1302 + 'type' => 'html',
1303 + 'value' => sprintf(
1304 + '<span class="setting-label">%1$s</span><div class="form-note">%2$s</div>',
1305 + esc_html__('Login after account creation', 'fluent-cart'),
1306 + esc_html__('Choose how customers sign in after registering or completing checkout.', 'fluent-cart')
1307 + ),
1162 1308 ],
1163 - [
1164 - 'label' => __('Enable auto login after account creation', 'fluent-cart'),
1165 - 'value' => 'yes',
1309 + 'fields' => [
1310 + 'type' => 'grid',
1311 + 'disable_nesting' => true,
1312 + 'columns' => ['default' => 1],
1313 + 'wrapperClass' => 'md:col-span-2',
1314 + 'schema' => [
1315 + 'auto_login_after_account_creation' => [
1316 + 'wrapperClass' => 'fct-compliance-auto-login',
1317 + 'label' => false,
1318 + 'type' => 'radio',
1319 + 'value' => 'yes',
1320 + 'attributes' => [
1321 + 'aria-label' => __('Login after account creation', 'fluent-cart'),
1322 + ],
1323 + 'options' => [
1324 + [
1325 + 'label' => __('Log in automatically', 'fluent-cart'),
1326 + 'value' => 'yes',
1327 + ],
1328 + [
1329 + 'label' => __('Let customers log in', 'fluent-cart'),
1330 + 'value' => 'no',
1331 + ],
1332 + ],
1333 + 'note' => __('Email verification still applies when required above.', 'fluent-cart'),
1334 + ],
1335 + ],
1166 1336 ],
1167 1337 ],
1168 - 'note' => __('Choose whether customers are logged in automatically when FluentCart creates their account during registration or after checkout.', 'fluent-cart'),
1169 1338 ],
1170 1339 ],
1171 1340 ],
1172 1341 'cart_and_checkout' => [
@@ -1542,8 +1711,17 @@
1542 1711 ]
1543 1712 ];
1544 1713 }
1545 1714
1715 + // Product Rating toggles only apply while the reviews module is
1716 + // active — hide the section (and its divider) otherwise.
1717 + if (!ModuleSettings::isActive('reviews')) {
1718 + unset(
1719 + $fields['setting_tabs']['schema']['single_product_setup']['schema']['hr_product_slug'],
1720 + $fields['setting_tabs']['schema']['single_product_setup']['schema']['product_rating_grid']
1721 + );
1722 + }
1723 +
1546 1724 return apply_filters("fluent_cart/store_settings/fields", $fields, []);
1547 1725 }
1548 1726
1549 1727 public function isModuleTabEnabled(): bool
@@ -1657,8 +1835,9 @@
1657 1835 'registration_page_id',
1658 1836 'login_page_id',
1659 1837 'cart_page_id',
1660 1838 'receipt_page_id',
1839 + 'order_review_page_id',
1661 1840 'shop_page_id',
1662 1841 'customer_profile_page_id',
1663 1842 'customer_profile_page_slug',
1664 1843 ]
@@ -1734,9 +1913,29 @@
1734 1913 }
1735 1914 return home_url();
1736 1915 }
1737 1916
1917 + public function getOrderReviewPageId()
1918 + {
1919 + return Arr::get($this->storeSettings, 'order_review_page_id');
1920 + }
1738 1921
1922 + /**
1923 + * The page hosting [fluent_cart_order_review], or home_url() when the store
1924 + * has not picked one — Order::getOrderReviewUrl() then falls back to the
1925 + * ?fluent-cart=order-review route, which needs no page at all.
1926 + */
1927 + public function getOrderReviewPage(): string
1928 + {
1929 + if ($pageId = $this->getOrderReviewPageId()) {
1930 + if (Pages::isPage($pageId)) {
1931 + return $this->getPageLink($pageId);
1932 + }
1933 + }
1934 + return home_url();
1935 + }
1936 +
1937 +
1739 1938 public function getBuyButtonText(): string
1740 1939 {
1741 1940 return esc_html(Arr::get($this->storeSettings, 'checkout_button_text', __('Buy now', 'fluent-cart')));
1742 1941 }
@@ -1905,13 +2104,9 @@
1905 2104 [
1906 2105 'label' => __('Inherit from the active theme', 'fluent-cart'),
1907 2106 'value' => ColorPalette::SOURCE_THEME,
1908 2107 'icon' => 'PaintLine',
1909 - 'note' => sprintf(
1910 - '%1$s %2$s',
1911 - __('The storefront palette is rebuilt from your theme, and follows it when the theme changes.', 'fluent-cart'),
1912 - ThemePalette::sourceLabel()
1913 - ),
2108 + 'note' => __('FluentCart uses your active theme\'s colors for the storefront. If they don\'t come through as expected, choose Customize to set them yourself.', 'fluent-cart'),
1914 2109 ],
1915 2110 [
1916 2111 'label' => __('Customize', 'fluent-cart'),
1917 2112 'value' => ColorPalette::SOURCE_CUSTOM,
@@ -2050,10 +2245,13 @@
2050 2245 if (!ThemePalette::hasUsableSource()) {
2051 2246 return __('The active theme publishes nothing to inherit, so the storefront keeps FluentCart\'s own colors.', 'fluent-cart');
2052 2247 }
2053 2248
2249 + // Only a colour with no hex anywhere is unpreviewable. A live
2250 + // reference with a hex fallback — what the theme-settings readers and
2251 + // Blocksy write — previews as that fallback.
2054 2252 foreach (ThemePalette::resolve() as $value) {
2055 - if (!sanitize_hex_color((string)$value)) {
2253 + if ((string)$value !== '' && ThemePalette::measurable((string)$value) === '') {
2056 2254 return __('This theme publishes its palette as CSS variables. The storefront reads them, but they cannot be resolved here — the preview shows FluentCart\'s colors in their place.', 'fluent-cart');
2057 2255 }
2058 2256 }
2059 2257
@@ -2079,13 +2277,15 @@
2079 2277
2080 2278 $roles = [];
2081 2279
2082 2280 foreach (ThemePalette::resolve() as $role => $value) {
2083 - // A theme that publishes `var(--x)` is written to the storefront
2084 - // verbatim and resolved by the browser there, but that property is
2085 - // not declared in wp-admin. Unpreviewable, so leave it out and let
2086 - // the slot fall back to its own default.
2087 - $hex = sanitize_hex_color((string)$value);
2281 + // A theme that publishes a bare `var(--x)` is written to the
2282 + // storefront verbatim and resolved by the browser there, but that
2283 + // property is not declared in wp-admin. Unpreviewable, so leave it
2284 + // out and let the slot fall back to its own default. A reference
2285 + // with a hex fallback (`var(--x, #hex)`) previews as that hex —
2286 + // the same colour the storefront measures it by.
2287 + $hex = ThemePalette::measurable((string)$value);
2088 2288
2089 2289 if ($hex) {
2090 2290 $roles[$role] = $hex;
2091 2291 }