PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.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 1.3.19 All 49 releases
fluent-cart / app / Http / Controllers / EmailNotificationController.php

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

334 lines 11.7 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\App\App;
6 use FluentCart\Api\StoreSettings;
7 use FluentCart\App\Helpers\EditorShortCodeHelper;
8 use FluentCart\App\Http\Requests\EmailNotificationRequest;
9 use FluentCart\App\Http\Requests\EmailSettingsRequest;
10 use FluentCart\App\Http\Requests\SchedulingSettingsRequest;
11 use FluentCart\App\Services\Email\EmailNotificationMailer;
12 use FluentCart\App\Services\Email\EmailNotifications;
13 use FluentCart\App\Services\Email\StoreDigestService;
14 use FluentCart\App\Services\PDF\ReceiptPdfTemplateService;
15 use FluentCart\App\Services\Reminders\ReminderService;
16 use FluentCart\App\Services\ShortCodeParser\ShortcodeTemplateBuilder;
17 use FluentCart\App\Services\Email\EmailPreviewService;
18 use FluentCart\App\Services\TemplateService;
19 use FluentCart\Framework\Http\Request\Request;
20 use FluentCart\Framework\Support\Arr;
21 use FluentCart\Framework\Support\Str;
22
23 class EmailNotificationController extends Controller
24 {
25 public function index(Request $request): \WP_REST_Response
26 {
27
28 $getNotifications = EmailNotifications::getNotifications();
29
30 if ($getNotifications) {
31 return $this->sendSuccess([
32 'data' => $getNotifications
33 ]);
34 }
35 return $this->sendError([
36 'data' => []
37 ]);
38 }
39
40 public function find($notification): \WP_REST_Response
41 {
42 $name = sanitize_text_field($notification);
43 $notification = EmailNotifications::getNotification($name);
44
45
46 if ($notification) {
47 $hasFluentPdf = defined('FLUENT_PDF');
48 $fontsReady = false;
49 $setupUrl = '';
50
51 if ($hasFluentPdf && class_exists('FluentPdf\Classes\Controller\FontDownloader')) {
52 $fontDownloader = new \FluentPdf\Classes\Controller\FontDownloader();
53 $fontsReady = empty($fontDownloader->getDownloadableFonts());
54 $setupUrl = admin_url('admin.php?page=fluent_pdf.php');
55 }
56
57 $pdfTemplates = $hasFluentPdf ? (new ReceiptPdfTemplateService())->getTemplateList() : [];
58
59 // Let add-ons inject their custom field data (settings.extra / extra_fields)
60 // into the editor payload from their own storage.
61 $notification = apply_filters('fluent_cart/email_notification_data', $notification, $name);
62
63 return $this->sendSuccess([
64 'data' => $notification,
65 'shortcodes' => EditorShortCodeHelper::getEmailNotificationShortcodes(),
66 'has_fluent_pdf' => $hasFluentPdf,
67 'fonts_ready' => $fontsReady,
68 'setup_url' => $setupUrl,
69 'pdf_templates' => $pdfTemplates,
70 ]);
71 }
72
73 return $this->sendError([
74 'message' => __('Notification Details not found', 'fluent-cart')
75 ]);
76 }
77
78 public function update(EmailNotificationRequest $request, $notification): \WP_REST_Response
79 {
80 $data = $request->getSafe($request->sanitize());
81
82 $settings = Arr::get($data, 'settings', []);
83
84 // Strip custom template data in free; pro filter restores it
85 $settingsWithoutTemplate = $settings;
86 unset($settingsWithoutTemplate['email_body']);
87 $settingsWithoutTemplate['is_default_body'] = 'yes';
88
89 $settings = apply_filters('fluent_cart/prepare_email_template_data', $settingsWithoutTemplate, $settings);
90
91 $updated = EmailNotifications::updateNotification($notification, $settings);
92 if ($updated) {
93 // Core does not persist custom fields (settings.extra). It fires this after a
94 // successful update so add-ons can store their own data in their own storage.
95 do_action('fluent_cart/email_notification_updated', $notification, $settings);
96
97 return $this->sendSuccess([
98 'message' => __('Notification updated successfully', 'fluent-cart')
99 ]);
100 } else {
101 return $this->sendError([
102 'message' => __('Failed to update notification', 'fluent-cart')
103 ]);
104 }
105
106 }
107
108 public function enableNotification(Request $request, $name): \WP_REST_Response
109 {
110 $enabledValue = sanitize_text_field(Arr::get($request->all(), 'active'));
111
112 $notification = EmailNotifications::updateNotification(
113 $name,
114 ['active' => $enabledValue]
115 );
116
117 if ($notification) {
118 return $this->sendSuccess([
119 'message' => __('Notification updated successfully', 'fluent-cart')
120 ]);
121 }
122 return $this->sendError([
123 'message' => __('Failed to update notification', 'fluent-cart')
124 ]);
125
126 }
127
128 public function getShortCodes(Request $request): \WP_REST_Response
129 {
130 return $this->sendSuccess([
131 'data' => [
132 'email_templates' => $this->getTemplateFiles(),
133 'shortcodes' => EditorShortCodeHelper::getEmailNotificationShortcodes(),
134 'buttons' => EditorShortCodeHelper::getButtons()
135 ],
136 ]);
137 }
138
139 public function previewDefaultTemplate(Request $request)
140 {
141 $template = sanitize_text_field($request->get('template'));
142
143 // Validate the template against the known notification template paths so an
144 // invalid or missing value returns a clean REST error instead of an uncaught
145 // "view not found" fatal from the template renderer.
146 $validTemplates = array_filter(array_column(
147 EmailNotifications::getNotifications(), 'template_path'
148 ));
149
150 if (!$template || !in_array($template, $validTemplates, true)) {
151 return $this->sendError([
152 'message' => __('Invalid or missing "template" parameter.', 'fluent-cart')
153 ], 422);
154 }
155
156 $previewService = new EmailPreviewService();
157 $data = $previewService->getPreviewData($template);
158
159 $body = TemplateService::getTemplateByPathName($template, $data);
160
161 // Wrap in the same outer email template used by actual emails
162 $header = (string) App::make('view')->make('emails.parts.order_header', $data);
163 $mailer = new EmailNotificationMailer();
164 $view = (string) App::make('view')->make('emails.general_template', [
165 'emailBody' => $body,
166 'preheader' => '',
167 'header' => $header,
168 'emailFooter' => $mailer->getEmailFooter(),
169 ]);
170
171 // Resolve shortcodes (e.g., {{ settings.store_brand }}, {{order.created_at}})
172 $view = ShortcodeTemplateBuilder::make($view, $data);
173
174 // Disable all links/buttons in the preview so they are not clickable
175 $view .= '<style>a, button, [role="button"] { pointer-events: none !important; cursor: default !important; }</style>';
176
177 return $this->sendSuccess([
178 'data' => [
179 'content' => $view
180 ],
181 ]);
182 }
183
184 public function getTemplateFiles()
185 {
186 $defaultFilePath = FLUENTCART_PLUGIN_PATH . '/app/Views/emails';
187 $filesArray = [];
188 $files = scandir($defaultFilePath);
189 foreach ($files as $file) {
190 $filePath = $defaultFilePath . '/' . $file;
191 if (is_file($filePath)) {
192 $file = Str::of($file)->replace('.php', '');
193 $filesArray[] = [
194 'path' => $file,
195 'label' => Str::of($file)->replace('fluent_cart', '')->headline()
196 ];
197 }
198 }
199 return $filesArray;
200 }
201
202 public function getSettings(): \WP_REST_Response
203 {
204 return $this->sendSuccess([
205 'data' => EmailNotifications::getSettings(),
206 'shortcodes' => EditorShortCodeHelper::getEmailSettingsShortcodes(),
207 ]);
208 }
209
210 public function saveSettings(EmailSettingsRequest $request): \WP_REST_Response
211 {
212 $data = $request->getSafe($request->sanitize());
213
214 if (!App::isProActive()) {
215 $data['show_email_footer'] = 'yes';
216 }
217
218 $updated = EmailNotifications::updateSettings($data);
219
220 if ($updated) {
221 return $this->sendSuccess([
222 'message' => __('Email settings saved successfully', 'fluent-cart')
223 ]);
224 } else {
225 return $this->sendError([
226 'message' => __('Failed to save email settings', 'fluent-cart')
227 ]);
228 }
229 }
230
231 public function getDigestSettings(): \WP_REST_Response
232 {
233 return $this->sendSuccess([
234 'data' => StoreDigestService::getSettings(),
235 ]);
236 }
237
238 public function saveDigestSettings(Request $request): \WP_REST_Response
239 {
240 $saved = StoreDigestService::saveSettings($request->all());
241
242 return $this->sendSuccess([
243 'data' => $saved,
244 'message' => __('Store digest settings saved successfully', 'fluent-cart'),
245 ]);
246 }
247
248 public function sendDigestTest(Request $request): \WP_REST_Response
249 {
250 $frequency = sanitize_text_field(Arr::get($request->all(), 'frequency', 'daily'));
251 if (!in_array($frequency, StoreDigestService::CADENCES, true)) {
252 $frequency = 'daily';
253 }
254
255 // Send the test to the configured recipients, falling back to the WP admin email.
256 $recipients = StoreDigestService::getSettings('recipients');
257 if (empty($recipients)) {
258 $recipients = get_bloginfo('admin_email');
259 }
260
261 $sent = StoreDigestService::sendDigest($frequency, (string) $recipients);
262
263 if ($sent) {
264 return $this->sendSuccess([
265 'message' => __('Test digest email sent.', 'fluent-cart'),
266 ]);
267 }
268
269 return $this->sendError([
270 'message' => __('Could not send the test email. Please check your mailing settings and recipients.', 'fluent-cart'),
271 ]);
272 }
273
274 public function getSchedulingSettings(StoreSettings $storeSettings): array
275 {
276 $tab = 'reminders';
277 $currentTabFields = Arr::get($storeSettings->fields(), 'setting_tabs.schema.' . $tab);
278
279 return [
280 'settings' => $storeSettings->get(),
281 'fields' => [
282 $tab => $currentTabFields
283 ]
284 ];
285 }
286
287 public function saveSchedulingSettings(SchedulingSettingsRequest $request, StoreSettings $storeSettings): \WP_REST_Response
288 {
289 try {
290 $sanitizedData = $request->getSafe($request->sanitize());
291
292 $data = array_merge(
293 $storeSettings->get(),
294 $sanitizedData
295 );
296
297 $updated = $storeSettings->save($data);
298
299 return $this->sendSuccess([
300 'data' => $updated,
301 'message' => __('Scheduling settings saved successfully', 'fluent-cart')
302 ]);
303 } catch (\Throwable $e) {
304 return $this->sendError([
305 'message' => __('Failed to save scheduling settings', 'fluent-cart')
306 ], 423);
307 }
308 }
309
310 public function sendManualReminder(Request $request): \WP_REST_Response
311 {
312 $event = sanitize_text_field(Arr::get($request->all(), 'event', ''));
313 $entityId = absint(Arr::get($request->all(), 'entity_id', 0));
314
315 if (empty($event) || empty($entityId)) {
316 return $this->sendError([
317 'message' => __('Event type and entity ID are required', 'fluent-cart')
318 ]);
319 }
320
321 $result = (new ReminderService())->sendManualReminder($event, $entityId);
322
323 if ($result['success']) {
324 return $this->sendSuccess([
325 'message' => $result['message']
326 ]);
327 }
328
329 return $this->sendError([
330 'message' => $result['message']
331 ]);
332 }
333 }
334