PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.15
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.15
6.2.15 6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 All 197 releases
fluentform / app / Services / FormBuilder / Notifications / EmailNotificationActions.php

EmailNotificationActions.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.15, at app/Services/FormBuilder/Notifications/EmailNotificationActions.php

252 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\App\Services\FormBuilder\Notifications;
4
5 defined('ABSPATH') or die;
6
7 use FluentForm\App\Helpers\Helper;
8 use FluentForm\App\Services\FormBuilder\ShortCodeParser;
9 use FluentForm\Framework\Foundation\Application;
10 use FluentForm\Framework\Helpers\ArrayHelper;
11
12 class EmailNotificationActions
13 {
14 protected $app = null;
15
16 public function __construct(Application $app)
17 {
18 $this->app = $app;
19 }
20
21 public function register()
22 {
23 add_filter('fluentform/notifying_async_email_notifications', '__return_false', 9);
24 add_filter('fluentform/notifying_async_notifications', '__return_false', 9);
25
26 add_filter('fluentform/global_notification_active_types', function ($types) {
27 $types['notifications'] = 'email_notifications';
28 return $types;
29 });
30
31 add_action('fluentform/integration_notify_notifications', [$this, 'notify'], 10, 4);
32
33 add_action('fluentform/notify_on_form_submit', [$this, 'notifyOnSubmitPaymentForm'], 10, 3);
34 }
35
36 public function notifyOnSubmitPaymentForm($submissionId, $submissionData, $form)
37 {
38 $emailFeeds = wpFluent()->table('fluentform_form_meta')
39 ->where('form_id', $form->id)
40 ->where('meta_key', 'notifications')
41 ->get();
42
43 if (count($emailFeeds) === 0) {
44 return;
45 }
46
47 $formData = $this->getFormData($submissionId);
48 $notificationManager = new \FluentForm\App\Services\Integrations\GlobalNotificationManager(wpFluentForm());
49
50 $activeEmailFeeds = $notificationManager->getEnabledFeeds($emailFeeds, $formData, $submissionId);
51 if (! $activeEmailFeeds) {
52 return;
53 }
54
55 $onSubmitEmailFeeds = array_filter($activeEmailFeeds, function ($feed) {
56 return 'payment_form_submit' == ArrayHelper::get($feed, 'settings.feed_trigger_event');
57 });
58
59 if (! $onSubmitEmailFeeds || 'yes' === Helper::getSubmissionMeta($submissionId, '_ff_on_submit_email_sent')) {
60 return;
61 }
62
63 $entry = $this->getEntry($submissionId);
64
65 foreach ($onSubmitEmailFeeds as $feed) {
66 $processedValues = $feed['settings'];
67 unset($processedValues['conditionals']);
68
69 $processedValues = ShortCodeParser::parse(
70 $processedValues,
71 $submissionId,
72 $formData,
73 $form,
74 false,
75 $feed['meta_key']
76 );
77 $feed['processedValues'] = $processedValues;
78
79 $this->notify($feed, $formData, $entry, $form);
80 }
81
82 Helper::setSubmissionMeta($submissionId, '_ff_on_submit_email_sent', 'yes', $form->id);
83 }
84
85 public function notify($feed, $formData, $entry, $form)
86 {
87 // A payment_success email asserts a settled charge, so gate it on the payment status
88 // for every payment form -- not only those with a Payment Method field.
89 $isTriggerOnPaymentSuccess = ArrayHelper::get($feed, 'processedValues.feed_trigger_event') === 'payment_success';
90 if (!empty($form->has_payment) && $isTriggerOnPaymentSuccess && !$this->paymentSucceeded($entry, $form)) {
91 return;
92 }
93
94 $notifier = $this->app->make(
95 'FluentForm\App\Services\FormBuilder\Notifications\EmailNotification'
96 );
97
98 $emailData = $feed['processedValues'];
99 $emailAttachments = $this->getAttachments($emailData, $formData, $entry, $form);
100 if ($emailAttachments) {
101 $emailData['attachments'] = $emailAttachments;
102 }
103
104 $notifier->notify($emailData, $formData, $form, $entry->id);
105 }
106
107 // Whether a payment_success trigger may fire for this entry.
108 protected function paymentSucceeded($entry, $form)
109 {
110 $paymentStatus = is_null($entry->payment_status ?? null) ? '' : (string) $entry->payment_status;
111
112 // Settled → a custom/settled status a gateway registered still fires; it is only the
113 // known-unsettled ones that defer.
114 if ('' !== $paymentStatus) {
115 $unsettledStatuses = apply_filters('fluentform/unsettled_payment_statuses', [
116 'pending', 'failed', 'requires_review', 'cancelled', 'refunded', 'partially-refunded',
117 ]);
118 return !in_array($paymentStatus, $unsettledStatuses, true);
119 }
120
121 // Empty status is a $0 order: fulfil a coupon-zeroed purchase, not an omitted or zeroed input.
122 $isFreeOrder = 'yes' === Helper::getSubmissionMeta($entry->id, '_ff_zero_total_free_order');
123
124 return (bool) apply_filters('fluentform/send_payment_success_on_zero_total', $isFreeOrder, $entry, $form);
125 }
126
127 /**
128 * @param $emailData
129 * @param $formData
130 * @param $entry
131 * @param $form
132 *
133 * @return array
134 */
135 private function getAttachments($emailData, $formData, $entry, $form)
136 {
137 $emailAttachments = [];
138
139 $uploadDir = wp_upload_dir();
140
141 if (!empty($emailData['attachments']) && is_array($emailData['attachments'])) {
142 $attachments = [];
143 foreach ($emailData['attachments'] as $name) {
144 $fileUrls = ArrayHelper::get($formData, $name);
145 if ($fileUrls && is_array($fileUrls)) {
146 foreach ($fileUrls as $url) {
147 $filePath = $this->resolveUploadAttachmentPath($url, $uploadDir);
148 if ($filePath) {
149 $attachments[] = $filePath;
150 }
151 }
152 }
153 }
154 $emailAttachments = $attachments;
155 }
156 $mediaAttachments = ArrayHelper::get($emailData, 'media_attachments');
157 if (!empty($mediaAttachments) && is_array($mediaAttachments)) {
158 $attachments = [];
159 foreach ($mediaAttachments as $file) {
160 $fileUrl = ArrayHelper::get($file, 'url');
161 $filePath = $this->resolveUploadAttachmentPath($fileUrl, $uploadDir);
162 if ($filePath) {
163 $attachments[] = $filePath;
164 }
165 }
166 $emailAttachments = array_merge($emailAttachments, $attachments);
167 }
168
169 $emailAttachments = apply_filters_deprecated(
170 'fluentform_email_attachments',
171 [
172 $emailAttachments,
173 $emailData,
174 $formData,
175 $entry,
176 $form
177 ],
178 FLUENTFORM_FRAMEWORK_UPGRADE,
179 'fluentform/email_attachments',
180 'Use fluentform/email_attachments instead of fluentform_email_attachments.'
181 );
182 // let others to apply attachments
183 $emailAttachments = apply_filters(
184 'fluentform/email_attachments',
185 $emailAttachments,
186 $emailData,
187 $formData,
188 $entry,
189 $form
190 );
191 return $emailAttachments;
192 }
193
194 private function resolveUploadAttachmentPath($fileUrl, $uploadDir)
195 {
196 if (!$fileUrl || empty($uploadDir['baseurl']) || empty($uploadDir['basedir'])) {
197 return null;
198 }
199
200 $normalizedUrl = strtok($fileUrl, '?#');
201 if (strpos($normalizedUrl, $uploadDir['baseurl']) !== 0) {
202 return null;
203 }
204
205 $relativePath = rawurldecode(str_replace($uploadDir['baseurl'], '', $normalizedUrl));
206 $relativePath = ltrim(wp_normalize_path($relativePath), '/');
207
208 if (!$relativePath || strpos($relativePath, '../') !== false) {
209 return null;
210 }
211
212 $uploadsBaseDir = realpath($uploadDir['basedir']);
213 if (!$uploadsBaseDir) {
214 return null;
215 }
216
217 $uploadsBaseDir = trailingslashit(wp_normalize_path($uploadsBaseDir));
218 $resolvedPath = realpath($uploadsBaseDir . $relativePath);
219
220 if (!$resolvedPath) {
221 return null;
222 }
223
224 $resolvedPath = wp_normalize_path($resolvedPath);
225 if (strpos($resolvedPath, $uploadsBaseDir) !== 0 || !is_file($resolvedPath)) {
226 return null;
227 }
228
229 return $resolvedPath;
230 }
231
232 public function getFormData($submissionId)
233 {
234 $submission = wpFluent()->table('fluentform_submissions')
235 ->where('id', $submissionId)
236 ->first();
237
238 if (! $submission) {
239 return false;
240 }
241
242 return json_decode($submission->response, true);
243 }
244
245 public function getEntry($submissionId)
246 {
247 return wpFluent()->table('fluentform_submissions')
248 ->where('id', $submissionId)
249 ->first();
250 }
251 }
252