PluginProbe
FluentAuth – The Ultimate Authorization & Security Plugin for WordPress / trunk
FluentAuth – The Ultimate Authorization & Security Plugin for WordPress vtrunk
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.1.0 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2
fluent-security / app / Http / Controllers / SystemEmailsController.php

SystemEmailsController.php in FluentAuth – The Ultimate Authorization & Security Plugin for WordPress trunk, at app/Http/Controllers/SystemEmailsController.php

307 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 FluentAuth\App\Http\Controllers;
4
5 use FluentAuth\App\Helpers\Arr;
6 use FluentAuth\App\Helpers\Helper;
7 use FluentAuth\App\Services\SmartCodeParser;
8 use FluentAuth\App\Services\SystemEmailService;
9
10 class SystemEmailsController
11 {
12 public static function getEmails(\WP_REST_Request $request)
13 {
14 return [
15 'emailIndexes' => array_values(SystemEmailService::getEmailIndexes()),
16 ];
17 }
18
19 public static function findEmail(\WP_REST_Request $request)
20 {
21 $remailId = $request->get_param('email_id');
22
23 if (!$remailId) {
24 return new \WP_Error('invalid_email_id', __('Email ID is required', 'fluent-security'), ['status' => 400]);
25 }
26
27 $emailIndexes = SystemEmailService::getEmailIndexes();
28
29 if (!isset($emailIndexes[$remailId])) {
30 return new \WP_Error('invalid_email_id', __('Email ID is invalid', 'fluent-security'), ['status' => 400]);
31 }
32
33 $emailSettings = SystemEmailService::getGlobalSettings();
34
35 $targetEmail = $emailIndexes[$remailId];
36
37 $contextSmartCodes = Arr::get($targetEmail, 'additional_smartcodes', []);
38
39 $userSmartCodes = [
40 '{{user.first_name}}' => __('First Name', 'fluent-security'),
41 '{{user.last_name}}' => __('Last Name', 'fluent-security'),
42 '{{user.display_name}}' => __('Display Name', 'fluent-security'),
43 '{{user.user_email}}' => __('Email', 'fluent-security'),
44 '{{user.user_login}}' => __('Username', 'fluent-security'),
45 '{{user.roles}}' => __('User Roles', 'fluent-security'),
46 ];
47
48 if ($contextSmartCodes) {
49 $userSmartCodes = array_merge($contextSmartCodes, $userSmartCodes);
50 }
51
52 $editorCodes = [
53 [
54 'key' => 'user',
55 'title' => __('User Data', 'fluent-security'),
56 'shortcodes' => apply_filters('fluentcrm_auth/email_smartcodes', $userSmartCodes)
57 ],
58 [
59 'key' => 'site',
60 'title' => __('Site Data', 'fluent-security'),
61 'shortcodes' => apply_filters('fluentcrm_auth/email_smartcodes', [
62 '{{site.name}}' => __('Site Title', 'fluent-security'),
63 '{{site.description}}' => __('Site tagline', 'fluent-security'),
64 '{{site.admin_email}}' => __('Admin Email', 'fluent-security'),
65 '##site.url##' => __('Site URL', 'fluent-security'),
66 '##site.login_url##' => __('Login Url', 'fluent-security'),
67 ])
68 ]
69 ];
70
71 if (!isset($emailSettings['emails'][$remailId])) {
72 return new \WP_Error('invalid_email_id', __('Email ID is invalid', 'fluent-security'), ['status' => 400]);
73 }
74
75 $defaultEmails = SystemEmailService::getEmailDefaults();
76
77 return [
78 'email' => $targetEmail,
79 'settings' => $emailSettings['emails'][$remailId],
80 'smartcodes' => $editorCodes,
81 'default_content' => Arr::get($defaultEmails, $remailId),
82 ];
83 }
84
85 public static function previewEmail(\WP_REST_Request $request)
86 {
87 $remailId = $request->get_param('email_id');
88
89 if (!$remailId) {
90 return new \WP_Error('invalid_email_id', __('Email ID is required', 'fluent-security'), ['status' => 400]);
91 }
92
93 $emailIndexes = SystemEmailService::getEmailIndexes();
94
95 if (!isset($emailIndexes[$remailId])) {
96 return new \WP_Error('invalid_email_id', __('Email ID is invalid', 'fluent-security'), ['status' => 400]);
97 }
98
99 $emailData = (array) $request->get_param('email_data');
100
101 if (empty($emailData['body']) || empty($emailData['body'])) {
102 return new \WP_Error('invalid_email_settings', __('Email subject and body are required', 'fluent-security'), ['status' => 400]);
103 }
104
105 $subject = sanitize_text_field(Arr::get($emailData, 'subject'));
106 $emailBody = wp_kses_post(Arr::get($emailData, 'body'));
107
108 if (!defined('FLUENTAUTH_PREVIEWING_EMAIL')) {
109 define('FLUENTAUTH_PREVIEWING_EMAIL', true);
110 }
111
112 $wpUser = get_user_by('ID', get_current_user_id());
113 $subject = (new SmartCodeParser())->parse($subject, $wpUser);
114 $body = (new SmartCodeParser())->parse($emailBody, $wpUser);
115 $body = SystemEmailService::withHtmlTemplate($body, null, $wpUser);
116
117 return [
118 'rendered_email' => [
119 'subject' => $subject,
120 'body' => $body,
121 ]
122 ];
123 }
124
125 public static function saveEmailSettings(\WP_REST_Request $request)
126 {
127 $emailId = $request->get_param('email_id');
128
129 if (!$emailId) {
130 return new \WP_Error('invalid_email_id', __('Email ID is required', 'fluent-security'), ['status' => 400]);
131 }
132
133 $emailIndexes = SystemEmailService::getEmailIndexes();
134
135 if (!isset($emailIndexes[$emailId])) {
136 return new \WP_Error('invalid_email_id', __('Email ID is invalid', 'fluent-security'), ['status' => 400]);
137 }
138
139 $allEmailSettings = SystemEmailService::getGlobalSettings();
140
141 $settings = (array) $request->get_param('settings');
142
143 if ($settings['status'] == 'active') {
144 $allEmailSettings['emails'][$emailId]['status'] = 'active';
145
146 $subject = sanitize_text_field(Arr::get($settings, 'email.subject'));
147 $emailBody = wp_kses_post(Arr::get($settings, 'email.body'));
148
149 if (!$subject || !$emailBody) {
150 return new \WP_Error('invalid_email_settings', __('Email subject and body are required', 'fluent-security'), ['status' => 400]);
151 }
152
153 $requiredSmartCodes = Arr::get($emailIndexes, $emailId . '.required_smartcodes', []);
154
155 if (!self::validateEmailBody($emailBody, $requiredSmartCodes)) {
156 return new \WP_Error('invalid_email_settings', __('Email body is not valid. Please check the smartcodes.', 'fluent-security'), [
157 'status' => 400,
158 'required_smartcodes' => $requiredSmartCodes
159 ]);
160 }
161
162 $allEmailSettings['emails'][$emailId]['email'] = [
163 'subject' => sanitize_text_field(Arr::get($settings, 'email.subject')),
164 'body' => $emailBody,
165 ];
166 } else if ($settings['status'] == 'disabled') {
167 $allEmailSettings['emails'][$emailId]['status'] = 'disabled';
168 $allEmailSettings['emails'][$emailId]['email'] = [
169 'subject' => sanitize_text_field(Arr::get($settings, 'email.subject')),
170 'body' => wp_kses_post(Arr::get($settings, 'email.body')),
171 ];
172 } else {
173 unset($allEmailSettings['emails'][$emailId]);
174 }
175
176 update_option('fa_system_email_settings', $allEmailSettings, false);
177
178 return [
179 'message' => __('Email settings has been succcesfully updated', 'fluent-security')
180 ];
181 }
182
183 public static function getTemplateSettings(\WP_REST_Request $request)
184 {
185 $globalSettings = SystemEmailService::getGlobalSettings();
186 $settings = Arr::get($globalSettings, 'template_settings', []);
187
188 $defaultContent = SystemEmailService::getDefaultEmailBody('user_registration_to_user');
189 $user = get_user_by('ID', get_current_user_id());
190
191 if (!defined('FLUENTAUTH_PREVIEWING_EMAIL')) {
192 define('FLUENTAUTH_PREVIEWING_EMAIL', true);
193 }
194
195 $emailFooter = SystemEmailService::getEmailFooter();
196
197 if (!$emailFooter) {
198 $emailFooter = 'Email Footer Placeholder';
199 }
200
201 $defaultContent = (new SmartCodeParser())->parse($defaultContent, $user);
202 $defaultContent = SystemEmailService::withHtmlTemplate($defaultContent, $emailFooter, $user);
203
204 return [
205 'settings' => $settings,
206 'default_content' => $defaultContent,
207 'default_colors' => [
208 'body_bg' => '#f3f4f6',
209 'content_bg' => '#ffffff',
210 'content_color' => '#374151',
211 'footer_content_color' => '#6b7280',
212 'highlight_bg' => 'rgb(249, 250, 251)',
213 'highlight_color' => '#374151',
214 ]
215 ];
216 }
217
218 public static function saveTemplateSettings(\WP_REST_Request $request)
219 {
220 $newSettings = (array) $request->get_param('settings');
221
222 $globalSettings = SystemEmailService::getGlobalSettings();
223 $settings = Arr::get($globalSettings, 'template_settings', []);
224 $newSettings = Arr::only($newSettings, array_keys($settings));
225 $newSettings['footer_text'] = wp_kses_post($newSettings['footer_text']);
226
227 // Sanitize color fields
228 $colorFields = ['body_bg', 'content_bg', 'content_color', 'footer_content_color', 'highlight_bg', 'highlight_color'];
229 foreach ($colorFields as $field) {
230 if (!empty($newSettings[$field])) {
231 $newSettings[$field] = self::sanitizeColorValue($newSettings[$field]);
232 }
233 }
234
235 // Sanitize remaining text fields
236 $textFields = ['font_family', 'template', 'logo', 'email_footer'];
237 foreach ($textFields as $field) {
238 if (isset($newSettings[$field])) {
239 $newSettings[$field] = sanitize_text_field($newSettings[$field]);
240 }
241 }
242
243 // Validate the data
244 if (!empty($newSettings['from_email'])) {
245 if (!is_email($newSettings['from_email'])) {
246 return new \WP_Error('invalid_email', __('From email is not valid', 'fluent-security'), ['status' => 400]);
247 }
248 }
249
250 if (!empty($newSettings['from_name'])) {
251 $newSettings['from_name'] = sanitize_text_field($newSettings['from_name']);
252 }
253
254 if (!empty($newSettings['reply_to_email'])) {
255 if (!is_email($newSettings['reply_to_email'])) {
256 return new \WP_Error('invalid_email', __('Reply to email is not valid', 'fluent-security'), ['status' => 400]);
257 }
258 }
259
260 if (!empty($newSettings['reply_to_name'])) {
261 $newSettings['reply_to_name'] = sanitize_text_field($newSettings['reply_to_name']);
262 }
263
264 $globalSettings['template_settings'] = $newSettings;
265
266 update_option('fa_system_email_settings', $globalSettings, false);
267
268 return [
269 'message' => __('Email template settings has been succcesfully updated', 'fluent-security')
270 ];
271 }
272
273 private static function sanitizeColorValue($value)
274 {
275 $value = trim($value);
276
277 // Allow hex colors: #fff, #ffffff, #ffffffff
278 if (preg_match('/^#[0-9a-fA-F]{3,8}$/', $value)) {
279 return $value;
280 }
281
282 // Allow rgb/rgba: rgb(0, 0, 0) or rgba(0, 0, 0, 0.5)
283 if (preg_match('/^rgba?\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*(,\s*(0|1|0?\.\d+))?\s*\)$/', $value)) {
284 return $value;
285 }
286
287 return '';
288 }
289
290 private static function validateEmailBody($emailBody, $smartCodes = [])
291 {
292 if (!$smartCodes) {
293 return true;
294 }
295
296 foreach ($smartCodes as $smartCode) {
297 $codes = ['{{' . $smartCode . '}}', '##' . $smartCode . '##'];
298 $hasCode = str_contains($emailBody, $codes[0]) || str_contains($emailBody, $codes[1]);
299 if (!$hasCode) {
300 return false;
301 }
302 }
303
304 return true;
305 }
306 }
307