From 509841344fbff5de155a6d2ccfea3e1def1fd24d Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 19 Oct 2022 16:47:56 +0300 Subject: [PATCH] ref --- .../Crm/Business/Event/Invitations.php | 9 - .../Espo/Modules/Crm/Controllers/Call.php | 34 ++-- .../Espo/Modules/Crm/Controllers/Meeting.php | 36 ++-- .../Espo/Modules/Crm/Services/Meeting.php | 104 +--------- .../Crm/Tools/Meeting/InvitationService.php | 191 ++++++++++++++++++ 5 files changed, 225 insertions(+), 149 deletions(-) create mode 100644 application/Espo/Modules/Crm/Tools/Meeting/InvitationService.php diff --git a/application/Espo/Modules/Crm/Business/Event/Invitations.php b/application/Espo/Modules/Crm/Business/Event/Invitations.php index a77149b407..a101b687fc 100644 --- a/application/Espo/Modules/Crm/Business/Event/Invitations.php +++ b/application/Espo/Modules/Crm/Business/Event/Invitations.php @@ -55,23 +55,14 @@ use DateTime; class Invitations { private $smtpParams; - private $entityManager; - private $emailSender; - private $config; - private $dateTime; /** @phpstan-ignore-line */ - private $language; - private $number; /** @phpstan-ignore-line */ - private $templateFileManager; - private $fileManager; /** @phpstan-ignore-line */ - private $htmlizerFactory; /** diff --git a/application/Espo/Modules/Crm/Controllers/Call.php b/application/Espo/Modules/Crm/Controllers/Call.php index 0e4cb2211b..cd16fe47c2 100644 --- a/application/Espo/Modules/Crm/Controllers/Call.php +++ b/application/Espo/Modules/Crm/Controllers/Call.php @@ -31,38 +31,34 @@ namespace Espo\Modules\Crm\Controllers; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; +use Espo\Core\Exceptions\ForbiddenSilent; use Espo\Core\Exceptions\NotFound; - use Espo\Core\Api\Request; - +use Espo\Modules\Crm\Entities\Call as CallEntity; use Espo\Modules\Crm\Services\Call as Service; +use Espo\Modules\Crm\Tools\Meeting\InvitationService; class Call extends \Espo\Core\Controllers\Record { + /** + * @throws BadRequest + * @throws Forbidden + * @throws ForbiddenSilent + * @throws NotFound + */ public function postActionSendInvitations(Request $request): bool { - $data = $request->getParsedBody(); + $id = $request->getParsedBody()->id ?? null; - if (empty($data->id)) { + if (!$id) { throw new BadRequest(); } - /** @var \Espo\Modules\Crm\Entities\Call|null $entity */ - $entity = $this->getCallService()->getEntity($data->id); + $resultList = $this->injectableFactory + ->create(InvitationService::class) + ->send(CallEntity::ENTITY_TYPE, $id); - if (!$entity) { - throw new NotFound(); - } - - if (!$this->getAcl()->check($entity, 'edit')) { - throw new Forbidden(); - } - - if (!$this->getAcl()->checkScope('Email', 'create')) { - throw new Forbidden(); - } - - return $this->getCallService()->sendInvitations($entity); + return $resultList !== 0; } public function postActionMassSetHeld(Request $request): bool diff --git a/application/Espo/Modules/Crm/Controllers/Meeting.php b/application/Espo/Modules/Crm/Controllers/Meeting.php index 7003226fc4..8e32fa916a 100644 --- a/application/Espo/Modules/Crm/Controllers/Meeting.php +++ b/application/Espo/Modules/Crm/Controllers/Meeting.php @@ -29,40 +29,40 @@ namespace Espo\Modules\Crm\Controllers; +use Espo\Core\Acl\Table; +use Espo\Core\Controllers\Record; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; +use Espo\Core\Exceptions\ForbiddenSilent; use Espo\Core\Exceptions\NotFound; use Espo\Core\Api\Request; +use Espo\Modules\Crm\Entities\Meeting as MeetingEntity; use Espo\Modules\Crm\Services\Meeting as Service; +use Espo\Modules\Crm\Tools\Meeting\InvitationService; -class Meeting extends \Espo\Core\Controllers\Record +class Meeting extends Record { + /** + * @throws BadRequest + * @throws Forbidden + * @throws ForbiddenSilent + * @throws NotFound + */ public function postActionSendInvitations(Request $request): bool { - $data = $request->getParsedBody(); + $id = $request->getParsedBody()->id ?? null; - if (empty($data->id)) { + if (!$id) { throw new BadRequest(); } - /** @var \Espo\Modules\Crm\Entities\Meeting|null $entity */ - $entity = $this->getMeetingService()->getEntity($data->id); + $resultList = $this->injectableFactory + ->create(InvitationService::class) + ->send(MeetingEntity::ENTITY_TYPE, $id); - if (!$entity) { - throw new NotFound(); - } - - if (!$this->getAcl()->check($entity, 'edit')) { - throw new Forbidden(); - } - - if (!$this->getAcl()->checkScope('Email', 'create')) { - throw new Forbidden(); - } - - return $this->getMeetingService()->sendInvitations($entity); + return $resultList !== 0; } public function postActionMassSetHeld(Request $request): bool diff --git a/application/Espo/Modules/Crm/Services/Meeting.php b/application/Espo/Modules/Crm/Services/Meeting.php index 181d19d3c5..66410a5bd2 100644 --- a/application/Espo/Modules/Crm/Services/Meeting.php +++ b/application/Espo/Modules/Crm/Services/Meeting.php @@ -29,21 +29,15 @@ namespace Espo\Modules\Crm\Services; -use Espo\Core\Binding\BindingContainerBuilder; -use Espo\Core\Mail\SmtpParams; use Espo\Entities\User; use Espo\Modules\Crm\Entities\Meeting as MeetingEntity; use Espo\ORM\Entity; -use Espo\Modules\Crm\Business\Event\Invitations; use Espo\Services\Record; - use Espo\Core\ORM\Entity as CoreEntity; - use Espo\Core\Exceptions\NotFound; use Espo\Core\Exceptions\BadRequest; use Espo\Core\Di; -use Espo\Tools\Email\SendService; /** * @extends Record @@ -114,7 +108,7 @@ class Meeting extends Record implements } foreach ($newIdList as $userId) { - if (!$this->getAcl()->checkAssignmentPermission($userId)) { + if (!$this->acl->checkAssignmentPermission($userId)) { return false; } } @@ -122,97 +116,6 @@ class Meeting extends Record implements return true; } - protected function getInvitationManager(bool $useUserSmtp = true): Invitations - { - $smtpParams = null; - - if ($useUserSmtp) { - $smtpParams = $this->getEmailSendService()->getUserSmtpParams($this->user->getId()); - } - - $builder = BindingContainerBuilder::create(); - - if ($smtpParams) { - $builder->bindInstance(SmtpParams::class, $smtpParams); - } - - return $this->injectableFactory->createWithBinding(Invitations::class, $builder->build()); - } - - public function sendInvitations(CoreEntity $entity, bool $useUserSmtp = true): bool - { - $invitationManager = $this->getInvitationManager($useUserSmtp); - - $emailHash = []; - - $sentCount = 0; - - $users = $this->entityManager - ->getRDBRepository($entity->getEntityType()) - ->getRelation($entity, 'users') - ->find(); - - foreach ($users as $user) { - if ( - $user->getId() === $this->user->getId() && - $entity->getLinkMultipleColumn('users', 'status', $user->getId()) === - MeetingEntity::ATTENDEE_STATUS_ACCEPTED - ) { - continue; - } - - if ($user->get('emailAddress') && !array_key_exists($user->get('emailAddress'), $emailHash)) { - $invitationManager->sendInvitation($entity, $user, 'users'); - - $emailHash[$user->get('emailAddress')] = true; - - $sentCount ++; - } - } - - $contacts = $this->entityManager - ->getRDBRepository($entity->getEntityType()) - ->getRelation($entity, 'contacts') - ->find(); - - foreach ($contacts as $contact) { - if ( - $contact->get('emailAddress') && - !array_key_exists($contact->get('emailAddress'), $emailHash) - ) { - $invitationManager->sendInvitation($entity, $contact, 'contacts'); - - $emailHash[$contact->get('emailAddress')] = true; - - $sentCount ++; - } - } - - $leads = $this->entityManager - ->getRDBRepository($entity->getEntityType()) - ->getRelation($entity, 'leads') - ->find(); - - foreach ($leads as $lead) { - if ( - $lead->get('emailAddress') && - !array_key_exists($lead->get('emailAddress'), $emailHash) - ) { - $invitationManager->sendInvitation($entity, $lead, 'leads'); - - $emailHash[$lead->get('emailAddress')] = true; - - $sentCount ++; - } - } - - if (!$sentCount) { - return false; - } - - return true; - } - /** * @param string[] $ids */ @@ -302,9 +205,4 @@ class Meeting extends Record implements return true; } - - private function getEmailSendService(): SendService - { - return $this->injectableFactory->create(SendService::class); - } } diff --git a/application/Espo/Modules/Crm/Tools/Meeting/InvitationService.php b/application/Espo/Modules/Crm/Tools/Meeting/InvitationService.php new file mode 100644 index 0000000000..9f3f978156 --- /dev/null +++ b/application/Espo/Modules/Crm/Tools/Meeting/InvitationService.php @@ -0,0 +1,191 @@ +recordServiceContainer = $recordServiceContainer; + $this->sendService = $sendService; + $this->user = $user; + $this->injectableFactory = $injectableFactory; + $this->acl = $acl; + $this->entityManager = $entityManager; + } + + /** + * Send invitations for a meeting (or call). Checks access. Uses user's SMTP if available. + * + * @return Entity[] Entities an invitation was sent to. + * + * @throws Forbidden + * @throws NotFound + */ + public function send(string $entityType, string $id): array + { + $entity = $this->recordServiceContainer + ->get($entityType) + ->getEntity($id); + + if (!$entity) { + throw new NotFound(); + } + + if (!$this->acl->checkEntityEdit($entity)) { + throw new Forbidden("No edit access."); + } + + if (!$this->acl->checkScope(Email::ENTITY_TYPE, Table::ACTION_CREATE)) { + throw new Forbidden("No email create access."); + } + + $sender = $this->getSender(); + + $sentAddressList = []; + $resultEntityList = []; + + foreach ($this->getUsers($entity) as $user) { + $emailAddress = $user->getEmailAddress(); + + if ($emailAddress) { + $sender->sendInvitation($entity, $user, 'users'); + + $sentAddressList[] = $emailAddress; + $resultEntityList[] = $user; + } + } + + /** @var Collection $contacts */ + $contacts = $this->entityManager + ->getRDBRepository($entity->getEntityType()) + ->getRelation($entity, 'contacts') + ->find(); + + /** @var Collection $leads */ + $leads = $this->entityManager + ->getRDBRepository($entity->getEntityType()) + ->getRelation($entity, 'leads') + ->find(); + + foreach ($contacts as $contact) { + $emailAddress = $contact->getEmailAddress(); + + if ($emailAddress && !in_array($emailAddress, $sentAddressList)) { + $sender->sendInvitation($entity, $contact, 'contacts'); + + $sentAddressList[] = $emailAddress; + $resultEntityList[] = $contact; + } + } + + foreach ($leads as $lead) { + $emailAddress = $lead->getEmailAddress(); + + if ($emailAddress && !in_array($emailAddress, $sentAddressList)) { + $sender->sendInvitation($entity, $lead, 'leads'); + + $sentAddressList[] = $emailAddress; + $resultEntityList[] = $lead; + } + } + + return $resultEntityList; + } + + /** + * @return Collection + */ + private function getUsers(Entity $entity): Collection + { + /** @var Collection */ + return $this->entityManager + ->getRDBRepository($entity->getEntityType()) + ->getRelation($entity, 'users') + ->where([ + 'OR' => [ + [ + 'id=' => $this->user->getId(), + '@relation.status!=' => Meeting::ATTENDEE_STATUS_ACCEPTED, + ], + [ + 'id!=' => $this->user->getId(), + ] + ] + ]) + ->find(); + } + + private function getSender(): Invitations + { + $smtpParams = $this->sendService->getUserSmtpParams($this->user->getId()); + + $builder = BindingContainerBuilder::create(); + + if ($smtpParams) { + $builder->bindInstance(SmtpParams::class, $smtpParams); + } + + return $this->injectableFactory->createWithBinding(Invitations::class, $builder->build()); + } +}