PluginProbe
The Innovative Form Builder – IvyForms / 0.6.1-backup
The Innovative Form Builder – IvyForms v0.6.1-backup
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / backend / src / Services / Notification / NotificationService.php

NotificationService.php in The Innovative Form Builder – IvyForms 0.6.1-backup, at backend/src/Services/Notification/NotificationService.php

333 lines 10.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace IvyForms\Services\Notification;
4
5 // phpcs:disable PSR1.Files.SideEffects
6 if (!defined('ABSPATH')) {
7 exit; // Exit if accessed directly
8 }
9
10 use IvyForms\Common\Exceptions\InvalidArgumentException;
11 use IvyForms\Common\Exceptions\NotFoundException;
12 use IvyForms\Common\Exceptions\QueryExecutionException;
13 use IvyForms\Common\Sanitizer\Sanitizer;
14 use IvyForms\Entity\Notification\Notification;
15 use IvyForms\Factory\Notification\NotificationFactory;
16 use IvyForms\Repository\Notification\NotificationRepositoryInterface;
17 use IvyForms\Services\Placeholder\PlaceholderService;
18 use IvyForms\Services\Translations\BackendStrings;
19 use IvyForms\Services\Mailer\MailerService;
20
21 class NotificationService
22 {
23 private NotificationRepositoryInterface $notificationRepository;
24
25 // Constructor injection for the NotificationRepository via PHP-DI
26 public function __construct(NotificationRepositoryInterface $notificationRepository)
27 {
28 $this->notificationRepository = $notificationRepository;
29 }
30
31 /**
32 * Get all notifications from the repository.
33 *
34 * @return array<mixed>|null
35 */
36 public function getAllNotifications(): ?array
37 {
38 return $this->notificationRepository->getAll();
39 }
40
41 /**
42 * Create a new notification.
43 *
44 * @param Notification $notificationData
45 *
46 * @return int Notification ID
47 */
48 public function createNotification(Notification $notificationData): int
49 {
50 // Create notification via repository and return new notification ID
51 return $this->notificationRepository->add($notificationData);
52 }
53
54 /**
55 * Get a specific notification by its ID.
56 *
57 * @param int $notificationId
58 *
59 * @return object NotificationEntity
60 *
61 * @throws NotFoundException If the notification is not found
62 */
63 public function getNotificationById(int $notificationId): object
64 {
65 $notification = $this->notificationRepository->getById($notificationId);
66
67 if (!$notification) {
68 throw new NotFoundException(
69 BackendStrings::getExceptionStrings()['notification_not_found']
70 );
71 }
72
73 return $notification;
74 }
75
76 /**
77 * Update an existing notification.
78 *
79 * @param int $notificationId
80 * @param Notification $notificationData
81 *
82 * @return bool
83 */
84 public function updateNotification(int $notificationId, Notification $notificationData): bool
85 {
86 // Validate notification data before updating
87
88 return $this->notificationRepository->update($notificationId, $notificationData);
89 }
90
91 /**
92 * Delete a notification by its ID.
93 *
94 * @param int $notificationId
95 *
96 * @return int
97 */
98 public function deleteNotification(int $notificationId): int
99 {
100 return $this->notificationRepository->delete($notificationId);
101 }
102
103 /**
104 * Delete multiple notifications by their IDs.
105 *
106 * @param array<int> $notificationIds
107 *
108 * @return int Number of deleted notifications
109 */
110 public function deleteNotifications(array $notificationIds): int
111 {
112 return $this->notificationRepository->deleteMany($notificationIds);
113 }
114
115 /**
116 * Get notifications by form ID.
117 *
118 * @param int $formId
119 *
120 * @return array<Notification>
121 *
122 * @throws NotFoundException If no notifications are found
123 */
124 public function getNotificationsByFormId(int $formId): array
125 {
126 $notification = $this->notificationRepository->getAllById($formId);
127
128 if (!$notification) {
129 throw new NotFoundException(
130 BackendStrings::getExceptionStrings()['notification_not_found']
131 );
132 }
133
134 return $notification;
135 }
136
137 /**
138 * Get active notifications by form ID.
139 *
140 * @param int $formId
141 *
142 * @return array<Notification>
143 *
144 */
145 public function getActiveNotificationsByFormId(int $formId): array
146 {
147 $notification = $this->notificationRepository->getAllActiveById($formId);
148
149 // TODO Implement handling no notifications found, but do not return an error to the user
150 // For now, log the error if WP_DEBUG is enabled
151 if (!$notification && defined('WP_DEBUG') && WP_DEBUG) {
152 error_log(BackendStrings::getExceptionStrings()['active_notif_not_found']);
153 }
154
155 return $notification;
156 }
157
158 /**
159 * Delete notifications by multiple form IDs.
160 *
161 * @param array<int> $formIds
162 *
163 * @return int Number of deleted notifications
164 * @throws InvalidArgumentException If no form IDs are provided
165 */
166 public function deleteNotificationsByFormIds(array $formIds): int
167 {
168 if (empty($formIds)) {
169 throw new InvalidArgumentException(
170 BackendStrings::getExceptionStrings()['no_form_ids_provided']
171 );
172 }
173
174 return $this->notificationRepository->deleteManyByForeignKeyValues($formIds);
175 }
176
177 /**
178 * Duplicate notifications from one form to another.
179 *
180 * @param int $originalFormId
181 * @param int $newFormId
182 *
183 * @return void
184 * @throws NotFoundException
185 * @throws InvalidArgumentException
186 */
187 public function duplicateNotifications(int $originalFormId, int $newFormId): void
188 {
189 $notifications = $this->getNotificationsByFormId($originalFormId);
190 foreach ($notifications as $notification) {
191 $notificationData = $notification->toArray();
192 unset($notificationData['id']);
193 $notificationData['formId'] = $newFormId;
194
195 $this->createNotification(NotificationFactory::create($notificationData));
196 }
197 }
198
199 /**
200 * Search notifications with pagination and sorting
201 *
202 * @param array<string, mixed> $params
203 *
204 * @return array<string, mixed>
205 */
206 public function searchNotifications(array $params): array
207 {
208 return $this->notificationRepository->search($params);
209 }
210
211 /**
212 * Create a default notification for a form.
213 *
214 * @param int $formId
215 * @param string $formName
216 * @param string $adminEmail
217 *
218 * @return void
219 * @throws InvalidArgumentException|QueryExecutionException
220 */
221 public function createDefaultNotificationForForm(int $formId, string $formName, string $adminEmail): void
222 {
223 $defaultNotification = [
224 'formId' => $formId,
225 'name' => BackendStrings::getAllFormsStrings()['admin_notification_email'],
226 'sender' => $adminEmail,
227 'receiver' => $adminEmail,
228 'enabled' => 1,
229 'subject' => $formName,
230 'message' => '{{all_data}}',
231 'smartLogic' => 0,
232 ];
233 $notification = NotificationFactory::create($defaultNotification);
234 $notificationId = $this->createNotification($notification);
235 if (!$notificationId) {
236 throw new QueryExecutionException(
237 BackendStrings::getSettingsFormBuilderStrings()['failed_to_create_default_notification']
238 );
239 }
240 $notification->setId($notificationId);
241 }
242
243 /**
244 * Process notifications for the form.
245 *
246 * @param int $formId
247 * @param array<mixed> $submissionData
248 * @param array<string, mixed> $fieldData
249 * @param array<string, mixed> $generalData
250 * @param MailerService $mailerService
251 * @param array<string, string> $fieldLabels
252 * @return bool
253 * @throws NotFoundException
254 */
255 public function processNotifications(
256 int $formId,
257 array $submissionData,
258 array $fieldData,
259 array $generalData,
260 MailerService $mailerService,
261 array $fieldLabels = []
262 ): bool {
263 $activeNotifications = $this->getActiveNotificationsByFormId($formId);
264 $exceptionStrings = BackendStrings::getExceptionStrings();
265 foreach ($activeNotifications as $notification) {
266 if (empty($notification->getReceiver())) {
267 continue;
268 }
269 $sender = Sanitizer::isValidEmail(
270 PlaceholderService::replacePlaceholders(
271 $notification->getSender(),
272 $fieldData,
273 $generalData,
274 $fieldLabels
275 )
276 )
277 ? PlaceholderService::replacePlaceholders(
278 $notification->getSender(),
279 $fieldData,
280 $generalData,
281 $fieldLabels
282 )
283 : '';
284 $receiver = Sanitizer::isValidEmail(
285 PlaceholderService::replacePlaceholders(
286 $notification->getReceiver(),
287 $fieldData,
288 $generalData,
289 $fieldLabels
290 )
291 )
292 ? PlaceholderService::replacePlaceholders(
293 $notification->getReceiver(),
294 $fieldData,
295 $generalData,
296 $fieldLabels
297 )
298 : '';
299 $subject = PlaceholderService::replacePlaceholders(
300 $notification->getSubject(),
301 $fieldData,
302 $generalData,
303 $fieldLabels
304 );
305 $message = PlaceholderService::replacePlaceholders(
306 $notification->getMessage(),
307 $fieldData,
308 $generalData,
309 $fieldLabels
310 );
311
312 // Sanitize notification message HTML to allow signature images with data: URIs
313 $safeMessage = Sanitizer::sanitizeHtmlContent($message);
314
315 if (empty($sender) || empty($receiver)) {
316 error_log(
317 $exceptionStrings['error_log_invalid_email'] . $sender . ' ' . $receiver
318 );
319 return false;
320 }
321 $notification->setSender($sender);
322 $notification->setReceiver($receiver);
323 $notification->setSubject($subject);
324 $notification->setMessage($safeMessage);
325 $sent = $mailerService->sendEmail($notification, $submissionData);
326 if (!$sent) {
327 error_log($exceptionStrings['error_log_failed_send'] . ' ' . $formId);
328 }
329 }
330 return true;
331 }
332 }
333