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 / ModuleSettingsController.php

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

331 lines 13.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\App\Http\Controllers;
4
5 use FluentCart\Api\ModuleSettings;
6 use FluentCart\Api\Sanitizer\Sanitizer;
7 use FluentCart\App\Services\PluginInstaller\AddonManager;
8 use FluentCart\App\Vite;
9 use FluentCart\Framework\Http\Request\Request;
10 use FluentCart\Framework\Support\Arr;
11
12 class ModuleSettingsController extends Controller
13 {
14 public function getSettings(): \WP_REST_Response
15 {
16 $fields = ModuleSettings::fileds();
17 $values = ModuleSettings::getAllSettings();
18
19 return $this->sendSuccess([
20 'fields' => [
21 'modules_settings' => [
22 'title' => __('Features & addon', 'fluent-cart'),
23 'type' => 'section',
24 'class' => 'no-padding',
25 'disable_nesting' => true,
26 'columns' => [
27 'default' => 1,
28 'md' => 1
29 ],
30 'schema' => $fields
31 ]
32 ],
33 'settings' => $values
34 ]);
35 }
36
37 public function saveSettings(Request $request)
38 {
39 $prevSettings = ModuleSettings::getAllSettings(false);
40
41 $data = $request->only(
42 ModuleSettings::validKeys()
43 );
44
45 $data = Sanitizer::sanitize($data);
46
47 ModuleSettings::saveSettings($data);
48
49 foreach ($data as $moduleKey => $moduleData) {
50 $prevStatus = Arr::get($prevSettings, $moduleKey . '.active', 'no');
51 $newStatus = Arr::get($moduleData, 'active', 'no');
52
53 if ($prevStatus === 'yes' && $newStatus === 'no') {
54 // Module deactivated
55 do_action('fluent_cart/module/deactivated/' . $moduleKey, $moduleData, $prevSettings[$moduleKey] ?? []);
56 } elseif ($prevStatus === 'no' && $newStatus === 'yes') {
57 // Module activated
58 do_action('fluent_cart/module/activated/' . $moduleKey, $moduleData, $prevSettings[$moduleKey] ?? []);
59 } elseif ($newStatus === 'yes') {
60 // Module is active — fire activation hook if any child settings changed
61 $hasChanged = $this->hasModuleSettingsChanged($moduleData, $prevSettings[$moduleKey] ?? []);
62 if ($hasChanged) {
63 do_action('fluent_cart/module/activated/' . $moduleKey, $moduleData, $prevSettings[$moduleKey] ?? []);
64 }
65 }
66 }
67
68 return $this->sendSuccess([
69 'message' => __('Settings saved successfully', 'fluent-cart')
70 ]);
71 }
72
73 private function hasModuleSettingsChanged($newData, $oldData)
74 {
75 if (!is_array($newData) || !is_array($oldData)) {
76 return true;
77 }
78
79 foreach ($newData as $key => $value) {
80 if ($key === 'active') {
81 continue;
82 }
83
84 $oldValue = Arr::get($oldData, $key);
85 if ($oldValue !== $value) {
86 return true;
87 }
88 }
89
90 return false;
91 }
92
93 public function getPluginAddons(): \WP_REST_Response
94 {
95 $addons = $this->getRegisteredPluginAddons();
96
97 // Add installation status for each addon
98 foreach ($addons as $key => &$addon) {
99 $isUpcoming = Arr::get($addon, 'upcoming', false);
100 if($isUpcoming){
101 $addon['is_installed'] = false;
102 $addon['is_active'] = false;
103 $addon['plugin_file'] = '';
104 $addon['source_link'] = '';
105 $addon['source_type'] = '';
106 continue;
107 }
108 if (!empty($addon['plugin_file']) && !empty($addon['plugin_slug'])) {
109 $status = (new AddonManager())->getAddonStatus($addon['plugin_slug'], $addon['plugin_file']);
110 $addon['is_installed'] = $status['is_installed'];
111 $addon['is_active'] = $status['is_active'];
112 } else {
113 $addon['is_installed'] = false;
114 $addon['is_active'] = false;
115 }
116 }
117
118 return $this->sendSuccess([
119 'addons' => $addons,
120 ]);
121 }
122
123 public function installPluginAddon(Request $request): \WP_REST_Response
124 {
125 $pluginSlug = $request->getSafe('plugin_slug', 'sanitize_text_field');
126 $sourceType = $request->getSafe('source_type', 'sanitize_text_field', 'wordpress');
127 $sourceLink = $request->getSafe('source_link', 'sanitize_url', '');
128 $assetPath = $request->getSafe('asset_path', 'sanitize_text_field', '');
129 $assetPath = trim($assetPath);
130 if(empty($assetPath)){
131 $assetPath = 'zipball_url';
132 }
133
134
135 if (!$pluginSlug) {
136 return $this->sendError([
137 'message' => __('Plugin slug is required.', 'fluent-cart')
138 ]);
139 }
140
141 // Validate the addon is in the allowed list
142 $registeredAddons = $this->getRegisteredPluginAddons();
143 $allowedAddon = null;
144
145 foreach ($registeredAddons as $addon) {
146 if ($addon['plugin_slug'] === $pluginSlug) {
147 $allowedAddon = $addon;
148 break;
149 }
150 }
151
152 if (!$allowedAddon) {
153 return $this->sendError([
154 'message' => __('This addon cannot be installed.', 'fluent-cart')
155 ]);
156 }
157
158 // Use source from registered addon if not provided
159 if (empty($sourceType) && !empty($allowedAddon['source_type'])) {
160 $sourceType = $allowedAddon['source_type'];
161 }
162 if (empty($sourceLink) && !empty($allowedAddon['source_link'])) {
163 $sourceLink = $allowedAddon['source_link'];
164 }
165
166 $addonManager = new AddonManager();
167 $result = $addonManager->installAddon($sourceType, $sourceLink, $pluginSlug, $assetPath);
168
169 if (is_wp_error($result)) {
170 return $this->sendError([
171 'message' => $result->get_error_message()
172 ]);
173 }
174
175 return $this->sendSuccess($result);
176 }
177
178 public function activatePluginAddon(Request $request): \WP_REST_Response
179 {
180 $pluginFile = $request->getSafe('plugin_file', 'sanitize_text_field');
181
182 if (!$pluginFile) {
183 return $this->sendError([
184 'message' => __('Plugin file is required.', 'fluent-cart')
185 ]);
186 }
187
188
189 $addonManager = new AddonManager();
190 $result = $addonManager->activateAddon($pluginFile);
191
192 if (is_wp_error($result)) {
193 return $this->sendError([
194 'message' => $result->get_error_message()
195 ]);
196 }
197
198 return $this->sendSuccess([
199 'message' => __('Addon activated successfully.', 'fluent-cart')
200 ]);
201 }
202
203 public function verifyTurnstileKeys(Request $request): \WP_REST_Response
204 {
205 $siteKey = $request->getSafe('site_key', 'sanitize_text_field');
206 $secretKey = $request->getSafe('secret_key', 'sanitize_text_field');
207
208 $token = $request->getSafe('token', 'sanitize_text_field');
209
210 if (empty($siteKey) || empty($secretKey)) {
211 return $this->sendError([
212 'message' => __('Both Site Key and Secret Key are required.', 'fluent-cart')
213 ]);
214 }
215
216 if (empty($token)) {
217 return $this->sendError([
218 'message' => __('Could not get a Turnstile token. Please check your Site Key and ensure this domain is allowed in Cloudflare.', 'fluent-cart')
219 ]);
220 }
221
222 $response = wp_remote_post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
223 'body' => [
224 'secret' => $secretKey,
225 'response' => $token,
226 ],
227 'timeout' => 10
228 ]);
229
230 if (is_wp_error($response)) {
231 return $this->sendError([
232 'message' => __('Could not connect to Cloudflare. Please try again.', 'fluent-cart')
233 ]);
234 }
235
236 $body = wp_remote_retrieve_body($response);
237 $result = json_decode($body, true);
238
239 if (!empty($result['success'])) {
240 return $this->sendSuccess([
241 'message' => __('Turnstile keys are valid and working.', 'fluent-cart')
242 ]);
243 }
244
245 $errorCodes = Arr::get($result, 'error-codes', []);
246 $errorMessage = __('Invalid Turnstile keys. Please check your Site Key and Secret Key.', 'fluent-cart');
247
248 if (in_array('invalid-input-secret', $errorCodes)) {
249 $errorMessage = __('The Secret Key is invalid. Please check it in your Cloudflare Dashboard.', 'fluent-cart');
250 }
251
252 return $this->sendError([
253 'message' => $errorMessage
254 ]);
255 }
256
257 private function getRegisteredPluginAddons(): array
258 {
259 $addons = [
260 'elementor-block' => [
261 'title' => __('Elementor Blocks', 'fluent-cart'),
262 'description' => __('Enable to get Elementor Blocks for FluentCart. Minimum Requirement: Elementor V3.34', 'fluent-cart'),
263 'logo' => Vite::getAssetUrl('images/elementor/black.svg'),
264 'dark_logo' => Vite::getAssetUrl('images/elementor/white.svg'),
265 'plugin_slug' => 'fluent-cart-elementor-blocks',
266 'plugin_file' => 'fluent-cart-elementor-blocks/fluent-cart-elementor-blocks.php',
267 'source_type' => 'cdn',
268 'source_link' => 'https://addons-cdn.fluentcart.com/fluent-cart-elementor-blocks.zip',
269 'upcoming' => false,
270 'repo_link' => 'https://fluentcart.com/fluentcart-addons/'
271 ],
272 'fluent-cart-bricks-blocks' => [
273 'title' => __('FluentCart Bricks Blocks', 'fluent-cart'),
274 'description' => __('Enable to get Bricks Builder elements for FluentCart. Requires the Bricks theme.', 'fluent-cart'),
275 'logo' => Vite::getAssetUrl('images/bricks/logo.png'),
276 'plugin_slug' => 'fluent-cart-bricks-blocks',
277 'plugin_file' => 'fluent-cart-bricks-blocks/fluent-cart-bricks-blocks.php',
278 'source_type' => 'cdn',
279 'upcoming' => false,
280 'repo_link' => 'https://fluentcart.com/fluentcart-addons/'
281 ],
282 'fluent-cart-divi-modules' => [
283 'title' => __('FluentCart Divi Modules', 'fluent-cart'),
284 'description' => __('Native Divi 5 modules for FluentCart products, cart, and checkout. Requires Divi 5.0+ and FluentCart 1.3.4+.', 'fluent-cart'),
285 'logo' => Vite::getAssetUrl('images/divi/black.svg'),
286 'dark_logo' => Vite::getAssetUrl('images/divi/white.svg'),
287 'plugin_slug' => 'fluent-cart-divi-modules',
288 'plugin_file' => 'fluent-cart-divi-modules/fluent-cart-divi-modules.php',
289 'source_type' => 'cdn',
290 'source_link' => 'https://addons-cdn.fluentcart.com/fluent-cart-divi-modules.zip',
291 'upcoming' => false,
292 'repo_link' => 'https://fluentcart.com/fluentcart-addons/'
293 ],
294 'fluent-pdf' => [
295 'title' => __('Fluent PDF', 'fluent-cart'),
296 'description' => __('Generate PDF receipts and attach them to email notifications.', 'fluent-cart'),
297 'logo' => Vite::getAssetUrl('images/fluent-pdf/black.svg'),
298 'dark_logo' => Vite::getAssetUrl('images/fluent-pdf/white.svg'),
299 'plugin_slug' => 'fluentforms-pdf',
300 'plugin_file' => 'fluentforms-pdf/fluentforms-pdf.php',
301 'source_type' => 'wordpress',
302 'upcoming' => false,
303 ],
304 'fluent-cart-migrator' => [
305 'title' => __('FluentCart Migrator', 'fluent-cart'),
306 'description' => __('Migrate your store data to FluentCart from other eCommerce platforms.', 'fluent-cart'),
307 'logo' => Vite::getAssetUrl('images/logo.svg'),
308 'plugin_slug' => 'fluent-cart-migrator',
309 'plugin_file' => 'fluent-cart-migrator/fluent-cart-migrator.php',
310 'source_type' => 'cdn',
311 'source_link' => 'https://addons-cdn.fluentcart.com/fluent-cart-migrator.zip',
312 'upcoming' => false,
313 'repo_link' => 'https://fluentcart.com/fluentcart-addons/?3181_search=Migrator'
314 ],
315 'fluent-cart-customer-rights' => [
316 'title' => __('FluentCart Customer Rights', 'fluent-cart'),
317 'description' => __('Manage customer withdrawal, refund, return, and cancellation requests with dedicated forms, workflows, notifications, and admin tools. Includes support for the German Withdrawal Button requirement under § 356a BGB.', 'fluent-cart'),
318 'logo' => Vite::getAssetUrl('images/fluent-cart-resolution/logo.svg'),
319 'plugin_slug' => 'fluent-cart-customer-rights',
320 'plugin_file' => 'fluent-cart-customer-rights/fluent-cart-customer-rights.php',
321 'source_type' => 'cdn',
322 'upcoming' => false,
323 'repo_link' => 'https://fluentcart.com/fluentcart-addons/'
324 ],
325 ];
326
327 // Allow other modules/plugins to register their addons
328 return apply_filters('fluent_cart/module_settings/plugin_addons', $addons);
329 }
330 }
331