From 95122b8241b96667133b498f6ab691de535eec2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Stan=C4=9Bk?= Date: Wed, 11 Oct 2023 22:28:02 +0200 Subject: [PATCH] create mail commands --- .../Forms/MailingFormFactory.php | 2 - .../Forms/EditUserSeminarFormFactory.php | 4 +- .../MailingModule/Forms/SendFormFactory.php | 4 +- .../Presenters/MaturityPresenter.php | 8 +- app/Model/Mailing/Commands/CreateMail.php | 56 +++++++++++++ .../Mailing/Commands/CreateTemplateMail.php | 41 ++++++++++ .../Commands/Handlers/CreateMailHandler.php | 72 +++++++++++++++++ .../Handlers/CreateTemplateMailHandler.php | 81 +++++++++++++++++++ app/Model/Mailing/Mail.php | 66 +++++++++------ app/Model/Mailing/MailQueue.php | 50 ++++++++++-- .../Repositories/MailQueueRepository.php | 29 +++++++ .../ProgramRegisteredEventListener.php | 4 +- .../ProgramUnregisteredEventListener.php | 2 - app/Presenters/AuthPresenter.php | 8 +- .../AdditionalInformationFormFactory.php | 4 +- app/WebModule/Forms/ContactForm.php | 4 +- app/WebModule/Presenters/ProfilePresenter.php | 8 +- 17 files changed, 385 insertions(+), 58 deletions(-) create mode 100644 app/Model/Mailing/Commands/CreateMail.php create mode 100644 app/Model/Mailing/Commands/CreateTemplateMail.php create mode 100644 app/Model/Mailing/Commands/Handlers/CreateMailHandler.php create mode 100644 app/Model/Mailing/Commands/Handlers/CreateTemplateMailHandler.php create mode 100644 app/Model/Mailing/Repositories/MailQueueRepository.php diff --git a/app/AdminModule/ConfigurationModule/Forms/MailingFormFactory.php b/app/AdminModule/ConfigurationModule/Forms/MailingFormFactory.php index 976d41e59..bb272b0f3 100644 --- a/app/AdminModule/ConfigurationModule/Forms/MailingFormFactory.php +++ b/app/AdminModule/ConfigurationModule/Forms/MailingFormFactory.php @@ -15,7 +15,6 @@ use App\Model\Settings\Queries\SettingStringValueQuery; use App\Model\Settings\Settings; use App\Services\CommandBus; -use App\Services\IMailService; use App\Services\QueryBus; use App\Utils\Validators; use Doctrine\Common\Collections\ArrayCollection; @@ -48,7 +47,6 @@ public function __construct( private readonly BaseFormFactory $baseFormFactory, private readonly CommandBus $commandBus, private readonly QueryBus $queryBus, - private readonly IMailService $mailService, private readonly LinkGenerator $linkGenerator, private readonly Validators $validators, ) { diff --git a/app/AdminModule/Forms/EditUserSeminarFormFactory.php b/app/AdminModule/Forms/EditUserSeminarFormFactory.php index 34b8e2398..49e4c9941 100644 --- a/app/AdminModule/Forms/EditUserSeminarFormFactory.php +++ b/app/AdminModule/Forms/EditUserSeminarFormFactory.php @@ -30,8 +30,8 @@ use App\Model\User\User; use App\Services\AclService; use App\Services\ApplicationService; +use App\Services\CommandBus; use App\Services\FilesService; -use App\Services\IMailService; use App\Services\QueryBus; use App\Services\UserService; use App\Utils\Helpers; @@ -71,6 +71,7 @@ class EditUserSeminarFormFactory public function __construct( private readonly BaseFormFactory $baseFormFactory, + private readonly CommandBus $commandBus, private readonly QueryBus $queryBus, private readonly EntityManagerInterface $em, private readonly UserRepository $userRepository, @@ -80,7 +81,6 @@ public function __construct( private readonly ApplicationService $applicationService, private readonly Validators $validators, private readonly FilesService $filesService, - private readonly IMailService $mailService, private readonly AclService $aclService, private readonly UserService $userService, ) { diff --git a/app/AdminModule/MailingModule/Forms/SendFormFactory.php b/app/AdminModule/MailingModule/Forms/SendFormFactory.php index 80494cbcc..6b40939cd 100644 --- a/app/AdminModule/MailingModule/Forms/SendFormFactory.php +++ b/app/AdminModule/MailingModule/Forms/SendFormFactory.php @@ -10,7 +10,7 @@ use App\Model\Structure\Repositories\SubeventRepository; use App\Model\User\Repositories\UserRepository; use App\Services\AclService; -use App\Services\IMailService; +use App\Services\CommandBus; use App\Services\SubeventService; use Doctrine\Common\Collections\ArrayCollection; use Nette; @@ -35,7 +35,7 @@ class SendFormFactory public function __construct( private readonly BaseFormFactory $baseFormFactory, - private readonly IMailService $mailService, + private readonly CommandBus $commandBus, private readonly RoleRepository $roleRepository, private readonly UserRepository $userRepository, private readonly SubeventRepository $subeventRepository, diff --git a/app/ApiModule/Presenters/MaturityPresenter.php b/app/ApiModule/Presenters/MaturityPresenter.php index 31968c465..0c9c23065 100644 --- a/app/ApiModule/Presenters/MaturityPresenter.php +++ b/app/ApiModule/Presenters/MaturityPresenter.php @@ -14,7 +14,7 @@ use App\Model\Settings\Settings; use App\Model\User\Repositories\UserRepository; use App\Services\ApplicationService; -use App\Services\IMailService; +use App\Services\CommandBus; use App\Services\QueryBus; use App\Utils\Helpers; use DateTimeImmutable; @@ -29,6 +29,9 @@ */ class MaturityPresenter extends ApiBasePresenter { + #[Inject] + public CommandBus $commandBus; + #[Inject] public QueryBus $queryBus; @@ -41,9 +44,6 @@ class MaturityPresenter extends ApiBasePresenter #[Inject] public RoleRepository $roleRepository; - #[Inject] - public IMailService $mailService; - #[Inject] public ApplicationService $applicationService; diff --git a/app/Model/Mailing/Commands/CreateMail.php b/app/Model/Mailing/Commands/CreateMail.php new file mode 100644 index 000000000..3486d757b --- /dev/null +++ b/app/Model/Mailing/Commands/CreateMail.php @@ -0,0 +1,56 @@ +recipientRoles; + } + + public function getRecipientSubevents(): Collection|null + { + return $this->recipientSubevents; + } + + public function getRecipientUsers(): Collection|null + { + return $this->recipientUsers; + } + + public function getRecipientEmails(): Collection|null + { + return $this->recipientEmails; + } + + public function getSubject(): string + { + return $this->subject; + } + + public function getText(): string + { + return $this->text; + } + + public function isAutomatic(): bool + { + return $this->automatic; + } +} diff --git a/app/Model/Mailing/Commands/CreateTemplateMail.php b/app/Model/Mailing/Commands/CreateTemplateMail.php new file mode 100644 index 000000000..e7ce74cf9 --- /dev/null +++ b/app/Model/Mailing/Commands/CreateTemplateMail.php @@ -0,0 +1,41 @@ +recipientUsers; + } + + /** @return string[]|null */ + public function getRecipientEmails(): Collection|null + { + return $this->recipientEmails; + } + + public function getTemplate(): string + { + return $this->template; + } + + public function getParameters(): array + { + return $this->parameters; + } +} diff --git a/app/Model/Mailing/Commands/Handlers/CreateMailHandler.php b/app/Model/Mailing/Commands/Handlers/CreateMailHandler.php new file mode 100644 index 000000000..b9eab2056 --- /dev/null +++ b/app/Model/Mailing/Commands/Handlers/CreateMailHandler.php @@ -0,0 +1,72 @@ +em->wrapInTransaction(function () use ($command): void { + $mail = new Mail(); + $recipients = []; + + if ($command->getRecipientUsers() !== null) { + $mail->setRecipientUsers($command->getRecipientUsers()); + foreach ($command->getRecipientUsers() as $user) { + $recipients[] = $user->getEmail(); + } + } + + if ($command->getRecipientRoles() !== null) { + $mail->setRecipientRoles($command->getRecipientRoles()); + foreach ($command->getRecipientUsers() as $user) { //todo + $recipients[] = $user->getEmail(); + } + } + + if ($command->getRecipientSubevents() !== null) { + $mail->setRecipientSubevents($command->getRecipientSubevents()); + foreach ($command->getRecipientUsers() as $user) { //todo + $recipients[] = $user->getEmail(); + } + } + + if ($command->getRecipientEmails() !== null) { + $mail->setRecipientEmails($command->getRecipientEmails()->toArray()); + foreach ($command->getRecipientEmails() as $email) { + $recipients[] = $email; + } + } + + $mail->setSubject($command->getSubject()); + $mail->setText($command->getText()); + $mail->setDatetime(new DateTimeImmutable()); + $mail->setAutomatic($command->isAutomatic()); + + $this->mailRepository->save($mail); + + foreach (array_unique($recipients) as $recipient) { + $this->mailQueueRepository->save(new MailQueue($recipient, $mail, new DateTimeImmutable())); + } + }); + } +} diff --git a/app/Model/Mailing/Commands/Handlers/CreateTemplateMailHandler.php b/app/Model/Mailing/Commands/Handlers/CreateTemplateMailHandler.php new file mode 100644 index 000000000..f0eaef9e5 --- /dev/null +++ b/app/Model/Mailing/Commands/Handlers/CreateTemplateMailHandler.php @@ -0,0 +1,81 @@ +em->wrapInTransaction(function () use ($command): void { + $template = $this->templateRepository->findByType($command->getTemplate()); + + if (! $template->isActive()) { + return; + } + + $subject = $template->getSubject(); + $text = $template->getText(); + + foreach ($template->getVariables() as $variable) { + $variableName = '%' . $this->translator->translate('common.mailing.variable_name.' . $variable->getName()) . '%'; + $value = $command->getParameters()[$variable->getName()]; + + $subject = str_replace($variableName, strval($value), $subject); + $text = str_replace($variableName, strval($value), $text); + } + + $mail = new Mail(); + $recipients = []; + + if ($command->getRecipientUsers() !== null) { + $mail->setRecipientUsers($command->getRecipientUsers()); + foreach ($command->getRecipientUsers() as $user) { + $recipients[] = $user->getEmail(); + } + } + + if ($command->getRecipientEmails() !== null) { + $mail->setRecipientEmails($command->getRecipientEmails()->toArray()); + foreach ($command->getRecipientEmails() as $email) { + $recipients[] = $email; + } + } + + $mail->setSubject($subject); + $mail->setText($text); + $mail->setDatetime(new DateTimeImmutable()); + $mail->setAutomatic(true); + + $this->mailRepository->save($mail); + + foreach (array_unique($recipients) as $recipient) { + $this->mailQueueRepository->save(new MailQueue($recipient, $mail, new DateTimeImmutable())); + } + }); + } +} diff --git a/app/Model/Mailing/Mail.php b/app/Model/Mailing/Mail.php index dad31f9b8..aaca3a02a 100644 --- a/app/Model/Mailing/Mail.php +++ b/app/Model/Mailing/Mail.php @@ -27,7 +27,15 @@ class Mail private int|null $id = null; /** - * Role, kterým byl e-mail odeslán. + * Příjemci e-mailu - uživatelé. + * + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: User::class)] + protected Collection $recipientUsers; + + /** + * Příjemci e-mailu - uživatelé s rolemi. * * @var Collection */ @@ -35,7 +43,7 @@ class Mail protected Collection $recipientRoles; /** - * Podakce, jejichž účastníkům byl e-mail odeslán. + * Příjemci e-mailu - uživatelé s podakcemi. * * @var Collection */ @@ -43,12 +51,12 @@ class Mail protected Collection $recipientSubevents; /** - * Uživatelé, kterém byl e-mail odeslán. + * Příjemci e-mailu - e-maily. * - * @var Collection + * @var string[] */ - #[ORM\ManyToMany(targetEntity: User::class)] - protected Collection $recipientUsers; + #[ORM\Column(type: 'simple_array')] + protected array $recipientEmails = []; /** * Předmět e-mailu. @@ -76,9 +84,9 @@ class Mail public function __construct() { + $this->recipientUsers = new ArrayCollection(); $this->recipientRoles = new ArrayCollection(); $this->recipientSubevents = new ArrayCollection(); - $this->recipientUsers = new ArrayCollection(); } public function getId(): int|null @@ -86,6 +94,29 @@ public function getId(): int|null return $this->id; } + /** @return Collection */ + public function getRecipientUsers(): Collection + { + return $this->recipientUsers; + } + + /** @param Collection $recipientUsers */ + public function setRecipientUsers(Collection $recipientUsers): void + { + $this->recipientUsers->clear(); + foreach ($recipientUsers as $recipientUser) { + $this->recipientUsers->add($recipientUser); + } + } + + /** + * Vrací příjemce (uživatele) oddělené čárkou. + */ + public function getRecipientUsersText(): string + { + return implode(', ', $this->recipientUsers->map(static fn (User $user) => $user->getDisplayName())->toArray()); + } + /** @return Collection */ public function getRecipientRoles(): Collection { @@ -132,27 +163,14 @@ public function getRecipientSubeventsText(): string return implode(', ', $this->recipientSubevents->map(static fn (Subevent $subevent) => $subevent->getName())->toArray()); } - /** @return Collection */ - public function getRecipientUsers(): Collection - { - return $this->recipientUsers; - } - - /** @param Collection $recipientUsers */ - public function setRecipientUsers(Collection $recipientUsers): void + public function getRecipientEmails(): array { - $this->recipientUsers->clear(); - foreach ($recipientUsers as $recipientUser) { - $this->recipientUsers->add($recipientUser); - } + return $this->recipientEmails; } - /** - * Vrací příjemce (uživatele) oddělené čárkou. - */ - public function getRecipientUsersText(): string + public function setRecipientEmails(array $recipientEmails): void { - return implode(', ', $this->recipientUsers->map(static fn (User $user) => $user->getDisplayName())->toArray()); + $this->recipientEmails = $recipientEmails; } public function getSubject(): string diff --git a/app/Model/Mailing/MailQueue.php b/app/Model/Mailing/MailQueue.php index 597103aeb..0cdbfa1e8 100644 --- a/app/Model/Mailing/MailQueue.php +++ b/app/Model/Mailing/MailQueue.php @@ -4,16 +4,9 @@ namespace App\Model\Mailing; -use App\Model\Acl\Role; -use App\Model\Structure\Subevent; -use App\Model\User\User; use DateTimeImmutable; -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -use function implode; - /** * Entita položka fronty e-mailů. */ @@ -29,7 +22,7 @@ class MailQueue #[ORM\Column(type: 'string')] protected string $recipient; - + #[ORM\ManyToOne(targetEntity: Mail::class, cascade: ['persist'])] protected Mail $mail; #[ORM\Column(type: 'boolean')] @@ -47,9 +40,50 @@ class MailQueue #[ORM\Column(type: 'datetime_immutable')] protected DateTimeImmutable $sendDatetime; + public function __construct(string $recipient, Mail $mail, DateTimeImmutable $enqueueDatetime) + { + $this->recipient = $recipient; + $this->mail = $mail; + $this->enqueueDatetime = $enqueueDatetime; + } public function getId(): int|null { return $this->id; } + + public function getRecipient(): string + { + return $this->recipient; + } + + public function getMail(): Mail + { + return $this->mail; + } + + public function isSent(): bool + { + return $this->sent; + } + + public function setSent(bool $sent): void + { + $this->sent = $sent; + } + + public function getEnqueueDatetime(): DateTimeImmutable + { + return $this->enqueueDatetime; + } + + public function getSendDatetime(): DateTimeImmutable + { + return $this->sendDatetime; + } + + public function setSendDatetime(DateTimeImmutable $sendDatetime): void + { + $this->sendDatetime = $sendDatetime; + } } diff --git a/app/Model/Mailing/Repositories/MailQueueRepository.php b/app/Model/Mailing/Repositories/MailQueueRepository.php new file mode 100644 index 000000000..12f8508c3 --- /dev/null +++ b/app/Model/Mailing/Repositories/MailQueueRepository.php @@ -0,0 +1,29 @@ +em->persist($mailQueue); + $this->em->flush(); + } +} diff --git a/app/Model/User/Events/Subscribers/ProgramRegisteredEventListener.php b/app/Model/User/Events/Subscribers/ProgramRegisteredEventListener.php index 8f1f475f8..435c8cc6e 100644 --- a/app/Model/User/Events/Subscribers/ProgramRegisteredEventListener.php +++ b/app/Model/User/Events/Subscribers/ProgramRegisteredEventListener.php @@ -9,14 +9,14 @@ use App\Model\Settings\Queries\SettingStringValueQuery; use App\Model\Settings\Settings; use App\Model\User\Events\ProgramRegisteredEvent; -use App\Services\IMailService; +use App\Services\CommandBus; use App\Services\QueryBus; use Doctrine\Common\Collections\ArrayCollection; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; class ProgramRegisteredEventListener implements MessageHandlerInterface { - public function __construct(private readonly QueryBus $queryBus, private readonly IMailService $mailService) + public function __construct(private readonly CommandBus $commandBus, private readonly QueryBus $queryBus) { } diff --git a/app/Model/User/Events/Subscribers/ProgramUnregisteredEventListener.php b/app/Model/User/Events/Subscribers/ProgramUnregisteredEventListener.php index 90ada58cd..5142c95d1 100644 --- a/app/Model/User/Events/Subscribers/ProgramUnregisteredEventListener.php +++ b/app/Model/User/Events/Subscribers/ProgramUnregisteredEventListener.php @@ -12,7 +12,6 @@ use App\Model\User\Events\ProgramUnregisteredEvent; use App\Model\User\Repositories\UserRepository; use App\Services\CommandBus; -use App\Services\IMailService; use App\Services\QueryBus; use Doctrine\Common\Collections\ArrayCollection; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; @@ -23,7 +22,6 @@ public function __construct( private readonly CommandBus $commandBus, private readonly QueryBus $queryBus, private readonly UserRepository $userRepository, - private readonly IMailService $mailService, ) { } diff --git a/app/Presenters/AuthPresenter.php b/app/Presenters/AuthPresenter.php index 534a0ffd1..a7fac93bf 100644 --- a/app/Presenters/AuthPresenter.php +++ b/app/Presenters/AuthPresenter.php @@ -11,7 +11,7 @@ use App\Model\Settings\Settings; use App\Model\User\Repositories\UserRepository; use App\Model\User\User; -use App\Services\IMailService; +use App\Services\CommandBus; use App\Services\QueryBus; use App\Services\SkautIsService; use Doctrine\Common\Collections\ArrayCollection; @@ -30,6 +30,9 @@ */ class AuthPresenter extends BasePresenter { + #[Inject] + public CommandBus $commandBus; + #[Inject] public QueryBus $queryBus; @@ -39,9 +42,6 @@ class AuthPresenter extends BasePresenter #[Inject] public UserRepository $userRepository; - #[Inject] - public IMailService $mailService; - /** * Přesměruje na přihlašovací stránku skautIS, nastaví přihlášení. * diff --git a/app/WebModule/Forms/AdditionalInformationFormFactory.php b/app/WebModule/Forms/AdditionalInformationFormFactory.php index cf1f42dcd..f0a8e2420 100644 --- a/app/WebModule/Forms/AdditionalInformationFormFactory.php +++ b/app/WebModule/Forms/AdditionalInformationFormFactory.php @@ -28,8 +28,8 @@ use App\Model\User\Repositories\UserRepository; use App\Model\User\User; use App\Services\ApplicationService; +use App\Services\CommandBus; use App\Services\FilesService; -use App\Services\IMailService; use App\Services\QueryBus; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\EntityManagerInterface; @@ -64,6 +64,7 @@ class AdditionalInformationFormFactory public function __construct( private readonly BaseFormFactory $baseFormFactory, + private readonly CommandBus $commandBus, private readonly QueryBus $queryBus, private readonly EntityManagerInterface $em, private readonly UserRepository $userRepository, @@ -71,7 +72,6 @@ public function __construct( private readonly ApplicationService $applicationService, private readonly CustomInputValueRepository $customInputValueRepository, private readonly FilesService $filesService, - private readonly IMailService $mailService, ) { } diff --git a/app/WebModule/Forms/ContactForm.php b/app/WebModule/Forms/ContactForm.php index df79e56e3..09ee4654b 100644 --- a/app/WebModule/Forms/ContactForm.php +++ b/app/WebModule/Forms/ContactForm.php @@ -12,7 +12,7 @@ use App\Model\Settings\Settings; use App\Model\User\Repositories\UserRepository; use App\Model\User\User; -use App\Services\IMailService; +use App\Services\CommandBus; use App\Services\QueryBus; use Contributte\ReCaptcha\Forms\ReCaptchaField; use Contributte\ReCaptcha\ReCaptchaProvider; @@ -45,10 +45,10 @@ class ContactForm extends UI\Control public function __construct( private readonly BaseFormFactory $baseFormFactory, + private readonly CommandBus $commandBus, private readonly QueryBus $queryBus, private readonly UserRepository $userRepository, private readonly ReCaptchaProvider $recaptchaProvider, - private readonly IMailService $mailService, ) { } diff --git a/app/WebModule/Presenters/ProfilePresenter.php b/app/WebModule/Presenters/ProfilePresenter.php index 6cc98eb1b..dac90a649 100644 --- a/app/WebModule/Presenters/ProfilePresenter.php +++ b/app/WebModule/Presenters/ProfilePresenter.php @@ -12,8 +12,8 @@ use App\Model\User\Queries\UserAttendsProgramsQuery; use App\Services\ApplicationService; use App\Services\Authenticator; +use App\Services\CommandBus; use App\Services\ExcelExportService; -use App\Services\IMailService; use App\WebModule\Components\ApplicationsGridControl; use App\WebModule\Components\IApplicationsGridControlFactory; use App\WebModule\Forms\AdditionalInformationFormFactory; @@ -31,6 +31,9 @@ */ class ProfilePresenter extends WebBasePresenter { + #[Inject] + public CommandBus $commandBus; + #[Inject] public PersonalDetailsFormFactory $personalDetailsFormFactory; @@ -49,9 +52,6 @@ class ProfilePresenter extends WebBasePresenter #[Inject] public SubeventRepository $subeventRepository; - #[Inject] - public IMailService $mailService; - #[Inject] public ApplicationService $applicationService;