PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
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 1.2.0 All 47 releases
fluent-cart / app / Http / Controllers / OnboardingController.php

OnboardingController.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at app/Http/Controllers/OnboardingController.php

308 lines 11.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Http\Controllers;
4
5 use FluentCart\Api\CurrencySettings;
6 use FluentCart\Api\Invokable\DummyProduct;
7 use FluentCart\Api\StoreSettings;
8 use FluentCart\App\CPT\Pages;
9 use FluentCart\App\Helpers\Helper as HelperService;
10 use FluentCart\App\Http\Requests\CreatePageRequest;
11 use FluentCart\App\Models\Meta;
12 use FluentCart\App\Modules\Tax\TaxModule;
13 use FluentCart\App\Services\Localization\LocalizationManager;
14 use FluentCart\App\Services\Tax\TaxManager;
15 use FluentCart\Framework\Foundation\Async;
16 use FluentCart\Framework\Http\Request\Request;
17 use FluentCart\Framework\Support\Arr;
18 use FluentCart\Framework\Support\Str;
19
20 class OnboardingController extends Controller
21 {
22 public function index(Request $request): \WP_REST_Response
23 {
24 $defaultSettings = (new StoreSettings())->toArray();
25
26 $pages = new Pages();
27
28 foreach ($pages->getGeneratablePage(true) as $pageName => $page) {
29
30 if (empty(Arr::get($defaultSettings, "{$pageName}_page_id"))) {
31 Arr::set(
32 $defaultSettings,
33 "{$pageName}_page_id",
34 Arr::get($page, 'page_id')
35 );
36 }
37
38 }
39
40 $taxSettings = (new TaxModule())->getSettings();
41 $euVatSettings = Arr::get($taxSettings, 'eu_vat_settings', []);
42 $euMethod = Arr::get($euVatSettings, 'method', 'oss');
43 $storeCountry = strtoupper(Arr::get($defaultSettings, 'store_country', ''));
44 $isEuCountry = !empty($storeCountry) && (new LocalizationManager())->isEuTaxCountry($storeCountry);
45
46 if ($isEuCountry) {
47 $vatNumber = $euMethod === 'oss'
48 ? Arr::get($euVatSettings, 'oss_vat', '')
49 : Arr::get($euVatSettings, 'home_vat', '');
50 } elseif (!empty($storeCountry)) {
51 $nonEuMeta = Meta::query()
52 ->where('meta_key', 'fluent_cart_tax_id_' . $storeCountry)
53 ->where('object_type', 'tax')
54 ->first();
55 $vatNumber = $nonEuMeta ? Arr::get((array) $nonEuMeta->meta_value, 'tax_id', '') : '';
56 } else {
57 $vatNumber = '';
58 }
59
60 return $this->response->sendSuccess([
61 'pages' => Pages::getPages('', true),
62 'currencies' => CurrencySettings::getFormattedCurrencies(),
63 'default_settings' => $defaultSettings,
64 'tax_settings' => [
65 'enable_tax' => Arr::get($taxSettings, 'enable_tax', 'no'),
66 'tax_inclusion' => Arr::get($taxSettings, 'tax_inclusion', 'excluded'),
67 'eu_method' => $euMethod,
68 'vat_number' => $vatNumber,
69 ],
70 ]);
71 }
72
73 public function createPages(Request $request): \WP_REST_Response
74 {
75 $excluded = [];
76 $pages = new Pages();
77 $storeSettings = new StoreSettings();
78
79 foreach ($pages->getGeneratablePage() as $pageName => $page) {
80 $pageId = $storeSettings->get("{$pageName}_page_id");
81 if (!empty($pageId) && !Pages::isPage($pageId)) {
82 $excluded[] = $pageName;
83 }
84 }
85
86 $pages->createPages($excluded);
87
88 return $this->index($request);
89 }
90
91 public function createPage(CreatePageRequest $request): \WP_REST_Response
92 {
93 $content = sanitize_text_field($request->get('content'));
94 $pageKey = $content;
95 $content = Str::of($content)->replaceFirst('_page_id', '')->toString();
96 $saveSettings = filter_var($request->get('save_settings'), FILTER_VALIDATE_BOOLEAN);
97
98 $generateablePages = (new Pages())->getGeneratablePage();
99 $pageData = Arr::get($generateablePages, $content, null);
100
101 if (!empty($pageData)) {
102 $page = [
103 'post_type' => 'page',
104 'post_title' => sanitize_text_field($request->get('page_name')),
105 'post_content' => $pageData['content'],
106 'post_status' => 'publish'
107 ];
108
109 $pageId = (string)wp_insert_post($page);
110
111 if ($saveSettings) {
112 (new StoreSettings())->save([
113 $pageKey => $pageId
114 ]);
115
116 flush_rewrite_rules(true);
117 delete_option('rewrite_rules');
118 }
119
120 return $this->response->sendSuccess([
121 'page_id' => $pageId,
122 'page_name' => $pageData['title'],
123 'link' => get_page_link($pageId)
124 ]);
125 }
126
127 return $this->response->sendError([
128 'message' => __('Unable to create page', 'fluent-cart')
129 ]);
130 }
131
132 public function saveTaxSettings(Request $request): \WP_REST_Response
133 {
134 $enableTax = sanitize_text_field($request->get('enable_tax', 'no'));
135
136 if (!in_array($enableTax, ['yes', 'no'], true)) {
137 return $this->response->sendError([
138 'message' => __('Invalid enable_tax value', 'fluent-cart')
139 ], 422);
140 }
141
142 if ($enableTax === 'no') {
143 $currentSettings = (new TaxModule())->getSettings();
144 $currentSettings['enable_tax'] = 'no';
145 update_option('fluent_cart_tax_configuration_settings', $currentSettings, true);
146
147 return $this->response->sendSuccess([
148 'data' => [
149 'tax_enabled' => false,
150 'classes_created' => false,
151 'eu_rates_imported' => false,
152 ],
153 'message' => __('Tax settings saved', 'fluent-cart')
154 ]);
155 }
156
157 $taxInclusion = sanitize_text_field($request->get('tax_inclusion', 'excluded'));
158 $storeCountry = strtoupper(sanitize_text_field($request->get('store_country', '')));
159
160 if (!empty($storeCountry) && (!ctype_alpha($storeCountry) || strlen($storeCountry) > 3)) {
161 return $this->response->sendError([
162 'message' => __('Invalid store_country value', 'fluent-cart')
163 ], 422);
164 }
165
166 $localization = new LocalizationManager();
167 $isEuCountry = !empty($storeCountry) && $localization->isEuTaxCountry($storeCountry);
168 $euMethod = sanitize_text_field($request->get('eu_method', 'oss'));
169 $vatNumber = substr(sanitize_text_field($request->get('vat_number', '')), 0, 50);
170
171 if (!in_array($taxInclusion, ['included', 'excluded'], true)) {
172 return $this->response->sendError([
173 'message' => __('Invalid tax_inclusion value', 'fluent-cart')
174 ], 422);
175 }
176
177 if ($isEuCountry && !in_array($euMethod, ['oss', 'home', 'specific'], true)) {
178 return $this->response->sendError([
179 'message' => __('Invalid eu_method value', 'fluent-cart')
180 ], 422);
181 }
182
183 $currentSettings = (new TaxModule())->getSettings();
184 $currentSettings['enable_tax'] = 'yes';
185 $currentSettings['tax_inclusion'] = $taxInclusion;
186
187 $classesCreated = true;
188 $euRatesImported = false;
189 $taxManager = TaxManager::getInstance();
190
191 if ($isEuCountry) {
192 $euVatSettings = Arr::get($currentSettings, 'eu_vat_settings', []);
193 $euVatSettings['method'] = $euMethod;
194 if ($euMethod === 'oss') {
195 $euVatSettings['oss_vat'] = $vatNumber;
196 $euVatSettings['oss_country'] = $storeCountry;
197 } else {
198 // home and specific both register the home country VAT
199 $euVatSettings['home_vat'] = $vatNumber;
200 $euVatSettings['home_country'] = $storeCountry;
201 }
202
203 // Upsert country_registrations so the VAT number appears in Tax → EU VAT settings
204 $rawRates = $taxManager->getEuTaxRatesFromPhp($storeCountry);
205 $ratesMap = [];
206 $standardRate = 0.0;
207 foreach ($rawRates as $rateEntry) {
208 $typeKey = isset($rateEntry['type']) ? $rateEntry['type'] : '';
209 if (!$typeKey) {
210 continue;
211 }
212 $ratesMap[$typeKey] = [
213 'rate' => (float) $rateEntry['rate'],
214 'label' => '',
215 ];
216 if ($typeKey === 'standard') {
217 $standardRate = (float) $rateEntry['rate'];
218 }
219 }
220
221 if (!empty($ratesMap)) {
222 $taxManager->saveEuVatRegistration($storeCountry, [
223 'country' => $storeCountry,
224 'vat' => $vatNumber,
225 'rate' => $standardRate,
226 'rates' => $ratesMap,
227 'tax_label' => '',
228 ]);
229 }
230
231 $currentSettings['eu_vat_settings'] = $euVatSettings;
232 }
233
234 // Direct update_option used here intentionally — TaxModule::getSettings() caches its result
235 // on the instance, so going through the module would return stale data on the same request.
236 update_option('fluent_cart_tax_configuration_settings', $currentSettings, true);
237
238 $euCountries = Arr::get($localization->taxContinents('EU'), 'countries', []);
239
240 try {
241 if ($isEuCountry) {
242 $taxManager->generateTaxClasses($euCountries);
243 $taxManager->setTaxEnabledForCountry($storeCountry, true);
244 $euRatesImported = true;
245 } else {
246 $taxManager->generateTaxClasses(!empty($storeCountry) ? [$storeCountry] : []);
247 if (!empty($storeCountry)) {
248 $taxManager->setTaxEnabledForCountry($storeCountry, true);
249 }
250 }
251 } catch (\Exception $e) {
252 $classesCreated = false;
253 }
254
255 if (!$isEuCountry && !empty($vatNumber) && !empty($storeCountry)) {
256 $meta = Meta::query()
257 ->where('meta_key', 'fluent_cart_tax_id_' . $storeCountry)
258 ->where('object_type', 'tax')
259 ->first();
260
261 if ($meta) {
262 $meta->meta_value = ['tax_id' => $vatNumber];
263 $meta->save();
264 } else {
265 Meta::query()->create([
266 //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
267 'meta_key' => 'fluent_cart_tax_id_' . $storeCountry,
268 //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
269 'meta_value' => ['tax_id' => $vatNumber],
270 'object_type' => 'tax'
271 ]);
272 }
273 }
274
275 return $this->response->sendSuccess([
276 'data' => [
277 'tax_enabled' => true,
278 'classes_created' => $classesCreated,
279 'eu_rates_imported' => $euRatesImported,
280 ],
281 'message' => __('Tax settings saved', 'fluent-cart')
282 ]);
283 }
284
285 public function saveSettings(Request $request)
286 {
287 $settings = array_merge((new StoreSettings())->toArray(), $request->all());
288
289 $savedStoreSettings = (new StoreSettings())->save(
290 Arr::except($settings, 'category')
291 );
292
293 if ($category = $request->get('category')) {
294 Async::call(DummyProduct::class, ['category' => $category]);
295 }
296
297 if ($savedStoreSettings) {
298 return $this->response->sendSuccess([
299 'message' => __('Store has been updated successfully', 'fluent-cart')
300 ]);
301 }
302
303 return $this->response->sendError([
304 'errors' => __('Failed to update!', 'fluent-cart')
305 ], 400);
306 }
307 }
308