src/EventSubscriber/NotificationSubscriber.php line 65

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Entity\Adult;
  4. use App\Entity\Notification;
  5. use App\Entity\NotificationMessage;
  6. use App\Entity\NotificationReceipt;
  7. use App\Entity\Referral;
  8. use App\Entity\User;
  9. use App\Event\NotificationEvent;
  10. use App\Event\ReferralEvent;
  11. use App\Event\UserEvent;
  12. use App\Service\SESService;
  13. use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
  14. use Doctrine\Persistence\ManagerRegistry;
  15. use Psr\Log\LoggerInterface;
  16. use Symfony\Component\PropertyAccess\PropertyAccess;
  17. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  18. use Symfony\Component\Routing\RouterInterface;
  19. use Twig\Environment;
  20. class NotificationSubscriber implements EventSubscriberInterface
  21. {
  22. protected $accessor;
  23. /** @var ManagerRegistry*/
  24. protected $doctrine;
  25. /** @var LoggerInterface */
  26. protected $logger;
  27. /** @var SESService */
  28. protected $sesService;
  29. /** @var Environment */
  30. protected $twig;
  31. /** @var RouterInterface */
  32. protected $router;
  33. protected $resetTtl;
  34. public function __construct(LoggerInterface $logger, SESService $sesService, ManagerRegistry $doctrine, Environment $twig, RouterInterface $router, $resetTtl)
  35. {
  36. $this->accessor = PropertyAccess::createPropertyAccessor();
  37. $this->doctrine = $doctrine;
  38. $this->logger = $logger;
  39. $this->sesService = $sesService;
  40. $this->twig = $twig;
  41. $this->router = $router;
  42. $this->resetTtl = $resetTtl;
  43. }
  44. public function getSubscribedEvents()
  45. {
  46. return [
  47. UserEvent::class => 'onUserEvent',
  48. ReferralEvent::class => 'onReferralEvent'
  49. ];
  50. }
  51. public function onUserEvent(UserEvent $event)
  52. {
  53. $notifications = $this->getNotifications($event);
  54. $this->logger->debug("****** NotificationSubscriber onUserEvent " . $event->getTimestamp()->format('Y-m-d H:i:s'));
  55. foreach($notifications as $notification) {
  56. /** @var Notification $notification */
  57. $messages = $notification->getNotificationMessages();
  58. $this->logger->debug("****** Found notification: " . $notification->getId());
  59. // Create NotificationReceipts for each Targeted User
  60. foreach ($messages as $message) {
  61. $this->logger->debug("****** Found notification message: " . $message->getId());
  62. switch ($message->getTarget()) {
  63. case NotificationMessage::TARGET_USER_SELF:
  64. $user = $event->getEntity();
  65. $this->createNotificationReceipt($notification, $message, [
  66. 'target' => $this->getTargetContextUser($user),
  67. 'properties' => $event->getAdditionalContext()
  68. ], $user);
  69. break;
  70. default:
  71. $this->logger->error("Invalid target '" . $message->getTarget() . "' for notification with id: " . $notification->getId());
  72. continue 2;
  73. }
  74. }
  75. }
  76. }
  77. public function onReferralEvent(ReferralEvent $event)
  78. {
  79. $notifications = $this->getNotifications($event);
  80. $this->logger->debug("****** NotificationSubscriber onReferralEvent");
  81. foreach($notifications as $notification) {
  82. /** @var Notification $notification */
  83. $messages = $notification->getNotificationMessages();
  84. $this->logger->debug("****** Found notification: " . $notification->getId());
  85. // Create NotificationReceipts for each Targeted User
  86. foreach ($messages as $message) {
  87. $this->logger->debug("****** Found notification message: " . $message->getId());
  88. switch ($message->getTarget()) {
  89. case NotificationMessage::TARGET_REFERRAL_AUTHOR:
  90. $referral = $event->getReferral();
  91. $user = $referral->getCreatedBy();
  92. $this->createNotificationReceipt($notification, $message, [
  93. 'target' => $this->getTargetContextUser($user),
  94. 'properties' => $event->getAdditionalContext()
  95. ], $user);
  96. break;
  97. case NotificationMessage::TARGET_REFERRAL_PARENTS:
  98. $referral = $event->getReferral();
  99. /** @var Adult $adult */
  100. foreach ( $referral->getAdults() as $adult ) {
  101. $this->createNotificationReceipt($notification, $message, [
  102. 'target' => $this->getTargetContextAdult($adult),
  103. 'properties' => $event->getAdditionalContext()
  104. ], null);
  105. }
  106. break;
  107. default:
  108. $this->logger->error("Invalid target '" . $message->getTarget() . "' for notification with id: " . $notification->getId());
  109. continue 2;
  110. }
  111. }
  112. }
  113. }
  114. protected function createNotificationReceipt(Notification $notification, NotificationMessage $message, array $context, ?User $user) {
  115. $this->logger->debug("****** NotificationSubscriber createNotificationReceipt(" . $notification->getId() . ", " . $message->getId() . ", " . $context['target']['email'] . ")");
  116. $receipt = new NotificationReceipt();
  117. $receipt->setNotificationMessage($message);
  118. $receipt->setRecipient($user);
  119. $receipt->setCreatedAt(new \DateTime());
  120. $receipt->setContext($context);
  121. $this->doctrine->getManager()->persist($receipt);
  122. if ( $message->getEmailEnabled() ) {
  123. $this->logger->debug("****** NotificationSubscriber creating template from variables: " . json_encode($context));
  124. $subject = $message->getEmailSubject();
  125. $body = $message->getEmailBody();
  126. $template = $this->twig->createTemplate($body);
  127. $body = $template->render($context);
  128. $this->logger->debug("****** TEST createNotificationReceipt(" . $notification->getId() . ", " . $message->getId() . ", " . $context['target']['email'] . ") attempting to send email (" . $subject . " => " . $body . ")");
  129. try {
  130. $this->sesService->send($user->getEmail(), $subject, $body);
  131. } catch ( \Exception $ex ) {
  132. $this->logger->error("NotificationSubscriber.createNotificationReceipt receieved an error when attempting to send an email: " . $ex->getMessage());
  133. }
  134. }
  135. if ( $message->getSmsEnabled() ) {
  136. // TODO: Implement SMS handling
  137. }
  138. if ( $message->getAlertEnabled() ) {
  139. // TODO: Implement in-app alert handling
  140. }
  141. }
  142. protected function getTargetContext($entity) {
  143. switch (get_class($entity)) {
  144. case User::class:
  145. return $this->getTargetContextUser($entity);
  146. case Adult::class:
  147. return $this->getTargetContextAdult($entity);
  148. default:
  149. return [];
  150. }
  151. }
  152. protected function getTargetContextUser(User $user)
  153. {
  154. // User $user
  155. $token = $user->getConfirmationToken() ?: '';
  156. // RouterInterface $router
  157. $confirmationUrl = str_replace('http:', 'https:', $this->router->generate('app_confirm_user', [
  158. 'token' => $token
  159. ], UrlGeneratorInterface::ABSOLUTE_URL));
  160. $resetUrl = str_replace('http:', 'https:', $this->router->generate('app_reset_user', [
  161. 'token' => $token
  162. ], UrlGeneratorInterface::ABSOLUTE_URL));
  163. // int $resetTtl
  164. $passwordExpiresAt = (new \DateTime())->add(\DateInterval::createFromDateString($this->resetTtl . ' seconds'));
  165. date_timezone_set($passwordExpiresAt, timezone_open('America/New_York'));
  166. return [
  167. 'id' => $user->getId(),
  168. 'type' => 'User',
  169. 'prefix' => ($user->prefix) ? $user->prefix->getDescription() : '',
  170. 'prefixES' => ($user->prefix) ? $user->prefix->getDescriptionEs() : '',
  171. 'firstName' => $user->firstName,
  172. 'lastName' => $user->lastName,
  173. 'suffix' => ($user->suffix) ? $user->suffix->getDescription() : '',
  174. 'suffixES' => ($user->suffix) ? $user->suffix->getDescriptionEs() : '',
  175. 'homePhone' => ($user->homePhoneNumber) ? implode("-", [$user->homePhoneNumber->getAreaCode(), $user->homePhoneNumber->getPrefix(), $user->homePhoneNumber->getSuffix()]) : '',
  176. 'mobilePhone' => ($user->mobilePhoneNumber) ? implode("-", [$user->mobilePhoneNumber->getAreaCode(), $user->mobilePhoneNumber->getPrefix(), $user->mobilePhoneNumber->getSuffix()]) : '',
  177. 'workPhone' => ($user->workPhoneNumber) ? implode("-", [$user->workPhoneNumber->getAreaCode(), $user->workPhoneNumber->getPrefix(), $user->workPhoneNumber->getSuffix()]) : '',
  178. 'email' => $user->getEmail(),
  179. 'confirmationUrl' => $confirmationUrl,
  180. 'resetUrl' => $resetUrl,
  181. 'expirationTimeUS' => $passwordExpiresAt->format('m-d-Y g:ia'),
  182. 'expirationTimeSTD' => $passwordExpiresAt->format('d-m-Y g:ia')
  183. ];
  184. }
  185. protected function getTargetContextAdult(Adult $adult) {
  186. return [
  187. 'id' => $adult->getId(),
  188. 'type' => 'Adult',
  189. 'firstName' => $adult->getFirstName(),
  190. 'lastName' => $adult->getLastName(),
  191. 'homePhone' => ($adult->getHomePhoneNumber()) ? implode("-", [$adult->getHomePhoneNumber()->getAreaCode(), $adult->getHomePhoneNumber()->getPrefix(), $adult->getHomePhoneNumber()->getSuffix()]) : '',
  192. 'mobilePhone' => ($adult->getMobilePhoneNumber()) ? implode("-", [$adult->getMobilePhoneNumber()->getAreaCode(), $adult->getMobilePhoneNumber()->getPrefix(), $adult->getMobilePhoneNumber()->getSuffix()]) : '',
  193. 'workPhone' => ($adult->getWorkPhoneNumber()) ? implode("-", [$adult->getWorkPhoneNumber()->getAreaCode(), $adult->getWorkPhoneNumber()->getPrefix(), $adult->getWorkPhoneNumber()->getSuffix()]) : '',
  194. 'email' => $adult->getEmail(),
  195. ];
  196. }
  197. protected function getNotifications(NotificationEvent $event) : array {
  198. $notificationRepository = $this->doctrine->getRepository(Notification::class);
  199. $notifications = $notificationRepository->findBy([
  200. 'entity' => $event->getEntityType(),
  201. 'field' => $event->getField(),
  202. 'checkLogic' => $event->getCheck()
  203. ]);
  204. $this->logger->debug("****** searching for notifications matching: " . json_encode([
  205. 'entity' => $event->getEntityType(),
  206. 'field' => $event->getField(),
  207. 'checkLogic' => $event->getCheck()
  208. ]));
  209. $resultList = [];
  210. $this->logger->debug("****** found notifications: " . count($notifications));
  211. foreach($notifications as $notification) {
  212. /** @var Notification $notification */
  213. if ($notification->getDisabled()) {
  214. continue;
  215. }
  216. if ($notification->getCheckValue() !== Notification::VALUE_ANY) {
  217. if ($this->accessor->getValue($event->getEntity(), $notification->getField()) !== $notification->getCheckValue()) {
  218. continue;
  219. };
  220. }
  221. $resultList []= $notification;
  222. }
  223. return $resultList;
  224. }
  225. }