PluginProbe
The Innovative Form Builder – IvyForms / 1.5.1
The Innovative Form Builder – IvyForms v1.5.1
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
← All changes | backend/src/Services/Notification/NotificationService.php +208 -70 1.4 → 1.5.1 View file →
@@ -14,8 +14,11 @@
14 14 use IvyForms\Services\Media\ImageService;
15 15 use IvyForms\Services\Translations\BackendStrings;
16 16 use IvyForms\Services\Mailer\MailerService;
17 17
18 +/**
19 + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
20 + */
18 21 class NotificationService
19 22 {
20 23 private NotificationRepositoryInterface $notificationRepository;
21 24 private ImageService $imageService;
@@ -132,22 +135,12 @@
132 135 *
133 136 * @param int $formId
134 137 *
135 138 * @return array<Notification>
136 - *
137 - * @throws NotFoundException If no notifications are found
138 139 */
139 140 public function getNotificationsByFormId(int $formId): array
140 141 {
141 - $notification = $this->notificationRepository->getAllById($formId);
142 -
143 - if (!$notification) {
144 - throw new NotFoundException(
145 - BackendStrings::getExceptionStrings()['notification_not_found']
146 - );
147 - }
148 -
149 - return $notification;
142 + return $this->notificationRepository->getAllById($formId);
150 143 }
151 144
152 145 /**
153 146 * Get active notifications by form ID.
@@ -280,10 +273,10 @@
280 273 MailerService $mailerService,
281 274 array $fieldLabels = []
282 275 ): bool {
283 276 $activeNotifications = $this->getActiveNotificationsByFormId($formId);
284 - $logicFormFields = $formFields;
285 277 $exceptionStrings = BackendStrings::getExceptionStrings();
278 +
286 279 foreach ($activeNotifications as $notification) {
287 280 if (empty($notification->getNotificationContact()->getReceiver())) {
288 281 continue;
289 282 }
@@ -292,9 +285,9 @@
292 285 'ivyforms/notification/should_send',
293 286 true,
294 287 $notification->getSmartLogic(),
295 288 $submissionData,
296 - $logicFormFields,
289 + $formFields,
297 290 $notification,
298 291 $formId
299 292 );
300 293
@@ -301,89 +294,234 @@
301 294 if (!$shouldSend) {
302 295 continue;
303 296 }
304 297
305 - // Resolve sender and receiver
306 - $sender = $this->resolveAddress(
307 - $notification->getNotificationContact()->getSender(),
298 + if (
299 + !$this->dispatchNotificationEmail(
300 + $notification,
301 + $formId,
302 + $submissionData,
303 + $formFields,
304 + $fieldData,
305 + $generalData,
306 + $mailerService,
307 + $fieldLabels,
308 + $exceptionStrings
309 + )
310 + ) {
311 + return false;
312 + }
313 + }
314 +
315 + return true;
316 + }
317 +
318 + /**
319 + * Resolve placeholders, apply attachments, and send one notification email.
320 + *
321 + * @param Notification $notification
322 + * @param int $formId
323 + * @param array<mixed> $submissionData
324 + * @param array<mixed> $formFields
325 + * @param array<string, mixed> $fieldData
326 + * @param array<string, mixed> $generalData
327 + * @param MailerService $mailerService
328 + * @param array<string, string> $fieldLabels
329 + * @param array<string, string> $exceptionStrings
330 + * @return bool False when sender/receiver are invalid; true otherwise (send failure is logged)
331 + */
332 + private function dispatchNotificationEmail(
333 + Notification $notification,
334 + int $formId,
335 + array $submissionData,
336 + array $formFields,
337 + array $fieldData,
338 + array $generalData,
339 + MailerService $mailerService,
340 + array $fieldLabels,
341 + array $exceptionStrings
342 + ): bool {
343 + if (
344 + !$this->hydrateNotificationForSend(
345 + $notification,
308 346 $fieldData,
309 347 $generalData,
310 - $fieldLabels
311 - );
348 + $fieldLabels,
349 + $exceptionStrings
350 + )
351 + ) {
352 + return false;
353 + }
312 354
313 - $receiver = $this->resolveAddress(
314 - $notification->getNotificationContact()->getReceiver(),
315 - $fieldData,
316 - $generalData,
317 - $fieldLabels
318 - );
355 + $this->sendHydratedNotificationEmail(
356 + $notification,
357 + $formId,
358 + $submissionData,
359 + $formFields,
360 + $fieldData,
361 + $mailerService,
362 + $exceptionStrings
363 + );
319 364
320 - $cc = $this->resolveAddressList(
321 - $notification->getNotificationContact()->getCc(),
322 - $fieldData,
323 - $generalData,
324 - $fieldLabels
325 - );
365 + return true;
366 + }
326 367
327 - $bcc = $this->resolveAddressList(
328 - $notification->getNotificationContact()->getBcc(),
329 - $fieldData,
330 - $generalData,
331 - $fieldLabels
368 + /**
369 + * Resolve and apply sender/receiver/replyTo/cc/bcc/subject/message onto the notification.
370 + *
371 + * @param Notification $notification
372 + * @param array<string, mixed> $fieldData
373 + * @param array<string, mixed> $generalData
374 + * @param array<string, string> $fieldLabels
375 + * @param array<string, string> $exceptionStrings
376 + */
377 + private function hydrateNotificationForSend(
378 + Notification $notification,
379 + array $fieldData,
380 + array $generalData,
381 + array $fieldLabels,
382 + array $exceptionStrings
383 + ): bool {
384 + $contact = $notification->getNotificationContact();
385 + $sender = $this->resolveAddress($contact->getSender(), $fieldData, $generalData, $fieldLabels);
386 + $receiver = $this->resolveAddress($contact->getReceiver(), $fieldData, $generalData, $fieldLabels);
387 +
388 + if ($sender === '' || $receiver === '') {
389 + error_log(
390 + $exceptionStrings['error_log_invalid_email'] . $sender . ' ' . $receiver
332 391 );
392 + return false;
393 + }
333 394
334 - // Build subject and sanitized message
335 - $subject = PlaceholderService::replacePlaceholders(
395 + $contact->setSender($sender);
396 + $contact->setReceiver($receiver);
397 + $contact->setReplyTo(
398 + $this->resolveReplyTo($contact->getReplyTo(), $sender, $fieldData, $generalData, $fieldLabels)
399 + );
400 + $contact->setCc(
401 + $this->resolveAddressList($contact->getCc(), $fieldData, $generalData, $fieldLabels)
402 + );
403 + $contact->setBcc(
404 + $this->resolveAddressList($contact->getBcc(), $fieldData, $generalData, $fieldLabels)
405 + );
406 + $notification->setSubject(
407 + PlaceholderService::replacePlaceholders(
336 408 $notification->getSubject(),
337 409 $fieldData,
338 410 $generalData,
339 411 $fieldLabels,
340 412 $notification
341 - );
342 -
343 - $safeMessage = $this->buildSafeMessage(
413 + )
414 + );
415 + $notification->setMessage(
416 + $this->buildSafeMessage(
344 417 $notification->getMessage(),
345 418 $fieldData,
346 419 $generalData,
347 420 $fieldLabels,
348 421 $notification
349 - );
422 + )
423 + );
350 424
351 - // Resolve replyTo and validate; fallback to sender if empty
352 - $replyTo = $this->resolveAddress(
353 - $notification->getNotificationContact()->getReplyTo(),
354 - $fieldData,
355 - $generalData,
356 - $fieldLabels
357 - );
358 - if (empty($replyTo) && !empty($sender)) {
359 - $replyTo = $sender;
360 - }
425 + return true;
426 + }
361 427
362 - if (empty($sender) || empty($receiver)) {
363 - error_log(
364 - $exceptionStrings['error_log_invalid_email'] . $sender . ' ' . $receiver
365 - );
366 - return false;
367 - }
428 + /**
429 + * @param Notification $notification
430 + * @param int $formId
431 + * @param array<mixed> $submissionData
432 + * @param array<mixed> $formFields
433 + * @param array<string, mixed> $fieldData
434 + * @param MailerService $mailerService
435 + * @param array<string, string> $exceptionStrings
436 + */
437 + private function sendHydratedNotificationEmail(
438 + Notification $notification,
439 + int $formId,
440 + array $submissionData,
441 + array $formFields,
442 + array $fieldData,
443 + MailerService $mailerService,
444 + array $exceptionStrings
445 + ): void {
446 + $sent = $mailerService->sendEmail(
447 + $notification,
448 + $submissionData,
449 + $this->resolveEmailAttachments($notification, $submissionData, $formFields, $fieldData)
450 + );
368 451
369 - // Apply resolved values back to the notification
370 - $notification->getNotificationContact()->setSender($sender);
371 - $notification->getNotificationContact()->setReceiver($receiver);
372 - $notification->getNotificationContact()->setReplyTo($replyTo);
373 - $notification->getNotificationContact()->setCc($cc);
374 - $notification->getNotificationContact()->setBcc($bcc);
375 - $notification->setSubject($subject);
376 - $notification->setMessage($safeMessage);
452 + if ($sent) {
453 + return;
454 + }
377 455
378 - // Send notification
379 - $sent = $mailerService->sendEmail($notification, $submissionData);
380 - if (!$sent) {
381 - error_log($exceptionStrings['error_log_failed_send'] . ' ' . $formId);
456 + error_log($exceptionStrings['error_log_failed_send'] . ' ' . $formId);
457 + }
458 +
459 + /**
460 + * @param string $template
461 + * @param string $sender
462 + * @param array<string, mixed> $fieldData
463 + * @param array<string, mixed> $generalData
464 + * @param array<string, string> $fieldLabels
465 + */
466 + private function resolveReplyTo(
467 + string $template,
468 + string $sender,
469 + array $fieldData,
470 + array $generalData,
471 + array $fieldLabels
472 + ): string {
473 + $replyTo = $this->resolveAddress($template, $fieldData, $generalData, $fieldLabels);
474 +
475 + return $replyTo !== '' ? $replyTo : $sender;
476 + }
477 +
478 + /**
479 + * @param Notification $notification
480 + * @param array<mixed> $submissionData
481 + * @param array<mixed> $formFields
482 + * @param array<string, mixed> $fieldData
483 + * @return string[]
484 + */
485 + private function resolveEmailAttachments(
486 + Notification $notification,
487 + array $submissionData,
488 + array $formFields,
489 + array $fieldData
490 + ): array {
491 + /**
492 + * Local file paths to attach to the notification email (Pro file attachments).
493 + *
494 + * @since 1.2.0
495 + *
496 + * @param mixed $attachments
497 + * @param \IvyForms\Entity\Notification\Notification $notification
498 + * @param array<string, mixed> $submissionData
499 + * @param array<int, mixed> $formFields
500 + * @param array<string, mixed> $fieldData
501 + */
502 + $attachments = apply_filters(
503 + 'ivyforms/notification/email_attachments',
504 + [],
505 + $notification,
506 + $submissionData,
507 + $formFields,
508 + $fieldData
509 + );
510 +
511 + if (!is_array($attachments)) {
512 + return [];
513 + }
514 +
515 + $paths = [];
516 + foreach ($attachments as $path) {
517 + if (!is_string($path) || $path === '') {
518 + continue;
382 519 }
520 + $paths[] = $path;
383 521 }
384 522
385 - return true;
523 + return $paths;
386 524 }
387 525
388 526 /**
389 527 * Resolve an email address template that may contain placeholders