PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
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
← All changes | app/Http/Controllers/EmailNotificationController.php +74 -0 1.3.26 → 1.6.5 View file →
@@ -9,8 +9,9 @@
9 9 use FluentCart\App\Http\Requests\EmailSettingsRequest;
10 10 use FluentCart\App\Http\Requests\SchedulingSettingsRequest;
11 11 use FluentCart\App\Services\Email\EmailNotificationMailer;
12 12 use FluentCart\App\Services\Email\EmailNotifications;
13 +use FluentCart\App\Services\Email\StoreDigestService;
13 14 use FluentCart\App\Services\PDF\ReceiptPdfTemplateService;
14 15 use FluentCart\App\Services\Reminders\ReminderService;
15 16 use FluentCart\App\Services\ShortCodeParser\ShortcodeTemplateBuilder;
16 17 use FluentCart\App\Services\Email\EmailPreviewService;
@@ -54,8 +55,12 @@
54 55 }
55 56
56 57 $pdfTemplates = $hasFluentPdf ? (new ReceiptPdfTemplateService())->getTemplateList() : [];
57 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 +
58 63 return $this->sendSuccess([
59 64 'data' => $notification,
60 65 'shortcodes' => EditorShortCodeHelper::getEmailNotificationShortcodes(),
61 66 'has_fluent_pdf' => $hasFluentPdf,
@@ -84,8 +89,12 @@
84 89 $settings = apply_filters('fluent_cart/prepare_email_template_data', $settingsWithoutTemplate, $settings);
85 90
86 91 $updated = EmailNotifications::updateNotification($notification, $settings);
87 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 +
88 97 return $this->sendSuccess([
89 98 'message' => __('Notification updated successfully', 'fluent-cart')
90 99 ]);
91 100 } else {
@@ -129,11 +138,33 @@
129 138
130 139 public function previewDefaultTemplate(Request $request)
131 140 {
132 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 +
133 156 $previewService = new EmailPreviewService();
134 157 $data = $previewService->getPreviewData($template);
135 158
159 + // Let add-ons adjust the preview data for their own templates — e.g. unset
160 + // `order` so an orderless notification (wishlist, withdrawal, …) previews
161 + // without the order header (emails.parts.order_header renders only when
162 + // $order is non-empty), or add the sample context their smartcodes need.
163 + // Core templates are untouched: no core listener changes $data. The context
164 + // is an array so more keys can be added later without changing the signature.
165 + $data = apply_filters('fluent_cart/email/preview_data', $data, ['template' => $template]);
166 +
136 167 $body = TemplateService::getTemplateByPathName($template, $data);
137 168
138 169 // Wrap in the same outer email template used by actual emails
139 170 $header = (string) App::make('view')->make('emails.parts.order_header', $data);
@@ -202,8 +233,51 @@
202 233 return $this->sendError([
203 234 'message' => __('Failed to save email settings', 'fluent-cart')
204 235 ]);
205 236 }
237 + }
238 +
239 + public function getDigestSettings(): \WP_REST_Response
240 + {
241 + return $this->sendSuccess([
242 + 'data' => StoreDigestService::getSettings(),
243 + ]);
244 + }
245 +
246 + public function saveDigestSettings(Request $request): \WP_REST_Response
247 + {
248 + $saved = StoreDigestService::saveSettings($request->all());
249 +
250 + return $this->sendSuccess([
251 + 'data' => $saved,
252 + 'message' => __('Store digest settings saved successfully', 'fluent-cart'),
253 + ]);
254 + }
255 +
256 + public function sendDigestTest(Request $request): \WP_REST_Response
257 + {
258 + $frequency = sanitize_text_field(Arr::get($request->all(), 'frequency', 'daily'));
259 + if (!in_array($frequency, StoreDigestService::CADENCES, true)) {
260 + $frequency = 'daily';
261 + }
262 +
263 + // Send the test to the configured recipients, falling back to the WP admin email.
264 + $recipients = StoreDigestService::getSettings('recipients');
265 + if (empty($recipients)) {
266 + $recipients = get_bloginfo('admin_email');
267 + }
268 +
269 + $sent = StoreDigestService::sendDigest($frequency, (string) $recipients);
270 +
271 + if ($sent) {
272 + return $this->sendSuccess([
273 + 'message' => __('Test digest email sent.', 'fluent-cart'),
274 + ]);
275 + }
276 +
277 + return $this->sendError([
278 + 'message' => __('Could not send the test email. Please check your mailing settings and recipients.', 'fluent-cart'),
279 + ]);
206 280 }
207 281
208 282 public function getSchedulingSettings(StoreSettings $storeSettings): array
209 283 {