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

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

320 lines 11.1 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 $previewService = new EmailPreviewService();
143 $data = $previewService->getPreviewData($template);
144
145 $body = TemplateService::getTemplateByPathName($template, $data);
146
147 // Wrap in the same outer email template used by actual emails
148 $header = (string) App::make('view')->make('emails.parts.order_header', $data);
149 $mailer = new EmailNotificationMailer();
150 $view = (string) App::make('view')->make('emails.general_template', [
151 'emailBody' => $body,
152 'preheader' => '',
153 'header' => $header,
154 'emailFooter' => $mailer->getEmailFooter(),
155 ]);
156
157 // Resolve shortcodes (e.g., {{ settings.store_brand }}, {{order.created_at}})
158 $view = ShortcodeTemplateBuilder::make($view, $data);
159
160 // Disable all links/buttons in the preview so they are not clickable
161 $view .= '<style>a, button, [role="button"] { pointer-events: none !important; cursor: default !important; }</style>';
162
163 return $this->sendSuccess([
164 'data' => [
165 'content' => $view
166 ],
167 ]);
168 }
169
170 public function getTemplateFiles()
171 {
172 $defaultFilePath = FLUENTCART_PLUGIN_PATH . '/app/Views/emails';
173 $filesArray = [];
174 $files = scandir($defaultFilePath);
175 foreach ($files as $file) {
176 $filePath = $defaultFilePath . '/' . $file;
177 if (is_file($filePath)) {
178 $file = Str::of($file)->replace('.php', '');
179 $filesArray[] = [
180 'path' => $file,
181 'label' => Str::of($file)->replace('fluent_cart', '')->headline()
182 ];
183 }
184 }
185 return $filesArray;
186 }
187
188 public function getSettings(): \WP_REST_Response
189 {
190 return $this->sendSuccess([
191 'data' => EmailNotifications::getSettings(),
192 'shortcodes' => EditorShortCodeHelper::getEmailSettingsShortcodes(),
193 ]);
194 }
195
196 public function saveSettings(EmailSettingsRequest $request): \WP_REST_Response
197 {
198 $data = $request->getSafe($request->sanitize());
199
200 if (!App::isProActive()) {
201 $data['show_email_footer'] = 'yes';
202 }
203
204 $updated = EmailNotifications::updateSettings($data);
205
206 if ($updated) {
207 return $this->sendSuccess([
208 'message' => __('Email settings saved successfully', 'fluent-cart')
209 ]);
210 } else {
211 return $this->sendError([
212 'message' => __('Failed to save email settings', 'fluent-cart')
213 ]);
214 }
215 }
216
217 public function getDigestSettings(): \WP_REST_Response
218 {
219 return $this->sendSuccess([
220 'data' => StoreDigestService::getSettings(),
221 ]);
222 }
223
224 public function saveDigestSettings(Request $request): \WP_REST_Response
225 {
226 $saved = StoreDigestService::saveSettings($request->all());
227
228 return $this->sendSuccess([
229 'data' => $saved,
230 'message' => __('Store digest settings saved successfully', 'fluent-cart'),
231 ]);
232 }
233
234 public function sendDigestTest(Request $request): \WP_REST_Response
235 {
236 $frequency = sanitize_text_field(Arr::get($request->all(), 'frequency', 'daily'));
237 if (!in_array($frequency, StoreDigestService::CADENCES, true)) {
238 $frequency = 'daily';
239 }
240
241 // Send the test to the configured recipients, falling back to the WP admin email.
242 $recipients = StoreDigestService::getSettings('recipients');
243 if (empty($recipients)) {
244 $recipients = get_bloginfo('admin_email');
245 }
246
247 $sent = StoreDigestService::sendDigest($frequency, (string) $recipients);
248
249 if ($sent) {
250 return $this->sendSuccess([
251 'message' => __('Test digest email sent.', 'fluent-cart'),
252 ]);
253 }
254
255 return $this->sendError([
256 'message' => __('Could not send the test email. Please check your mailing settings and recipients.', 'fluent-cart'),
257 ]);
258 }
259
260 public function getSchedulingSettings(StoreSettings $storeSettings): array
261 {
262 $tab = 'reminders';
263 $currentTabFields = Arr::get($storeSettings->fields(), 'setting_tabs.schema.' . $tab);
264
265 return [
266 'settings' => $storeSettings->get(),
267 'fields' => [
268 $tab => $currentTabFields
269 ]
270 ];
271 }
272
273 public function saveSchedulingSettings(SchedulingSettingsRequest $request, StoreSettings $storeSettings): \WP_REST_Response
274 {
275 try {
276 $sanitizedData = $request->getSafe($request->sanitize());
277
278 $data = array_merge(
279 $storeSettings->get(),
280 $sanitizedData
281 );
282
283 $updated = $storeSettings->save($data);
284
285 return $this->sendSuccess([
286 'data' => $updated,
287 'message' => __('Scheduling settings saved successfully', 'fluent-cart')
288 ]);
289 } catch (\Throwable $e) {
290 return $this->sendError([
291 'message' => __('Failed to save scheduling settings', 'fluent-cart')
292 ], 423);
293 }
294 }
295
296 public function sendManualReminder(Request $request): \WP_REST_Response
297 {
298 $event = sanitize_text_field(Arr::get($request->all(), 'event', ''));
299 $entityId = absint(Arr::get($request->all(), 'entity_id', 0));
300
301 if (empty($event) || empty($entityId)) {
302 return $this->sendError([
303 'message' => __('Event type and entity ID are required', 'fluent-cart')
304 ]);
305 }
306
307 $result = (new ReminderService())->sendManualReminder($event, $entityId);
308
309 if ($result['success']) {
310 return $this->sendSuccess([
311 'message' => $result['message']
312 ]);
313 }
314
315 return $this->sendError([
316 'message' => $result['message']
317 ]);
318 }
319 }
320