diff --git a/application/Espo/Classes/AssignmentNotificators/Email.php b/application/Espo/Classes/AssignmentNotificators/Email.php index 916772b2a6..2a354f7d9c 100644 --- a/application/Espo/Classes/AssignmentNotificators/Email.php +++ b/application/Espo/Classes/AssignmentNotificators/Email.php @@ -29,60 +29,62 @@ namespace Espo\Classes\AssignmentNotificators; +use Espo\Entities\EmailAddress; +use Espo\Entities\EmailFolder; +use Espo\Modules\Crm\Entities\Account; +use Espo\Modules\Crm\Entities\Contact; +use Espo\Modules\Crm\Entities\Lead; use Espo\Tools\Stream\Service as StreamService; - use Espo\Core\Notification\AssignmentNotificator; use Espo\Core\Notification\AssignmentNotificator\Params; use Espo\Core\Notification\UserEnabledChecker; -use Espo\Core\InjectableFactory; use Espo\Core\AclManager; - use Espo\ORM\EntityManager; use Espo\ORM\Entity; - use Espo\Entities\User; use Espo\Entities\Notification; use Espo\Entities\Email as EmailEntity; - use Espo\Repositories\Email as EmailRepository; use Espo\Repositories\EmailAddress as EmailAddressRepository; - -use DateTime; use Espo\Tools\Email\Util; +use DateTime; use Exception; +/** + * @implements AssignmentNotificator + */ class Email implements AssignmentNotificator { private const DAYS_THRESHOLD = 2; - private ?StreamService $streamService = null; - private $user; - private $entityManager; - private $injectableFactory; - private $aclManager; - private $userChecker; + private User $user; + private EntityManager $entityManager; + private UserEnabledChecker $userChecker; + private AclManager $aclManager; + private StreamService $streamService; public function __construct( User $user, EntityManager $entityManager, UserEnabledChecker $userChecker, - InjectableFactory $injectableFactory, - AclManager $aclManager + AclManager $aclManager, + StreamService $streamService ) { $this->user = $user; $this->entityManager = $entityManager; $this->userChecker = $userChecker; - $this->injectableFactory = $injectableFactory; $this->aclManager = $aclManager; + $this->streamService = $streamService; } + /** + * @param EmailEntity $entity + */ public function process(Entity $entity, Params $params): void { - /** @var EmailEntity $entity */ - if ( !in_array( - $entity->get('status'), + $entity->getStatus(), [ EmailEntity::STATUS_ARCHIVED, EmailEntity::STATUS_SENT, @@ -141,13 +143,13 @@ class Email implements AssignmentNotificator $data = [ 'emailId' => $entity->getId(), - 'emailName' => $entity->get('name'), + 'emailName' => $entity->getSubject(), ]; /** @var EmailRepository $emailRepository */ - $emailRepository = $this->entityManager->getRepository('Email'); + $emailRepository = $this->entityManager->getRepository(EmailEntity::ENTITY_TYPE); /** @var EmailAddressRepository $emailAddressRepository */ - $emailAddressRepository = $this->entityManager->getRepository('EmailAddress'); + $emailAddressRepository = $this->entityManager->getRepository(EmailAddress::ENTITY_TYPE); if (!$entity->has('from')) { $emailRepository->loadFromField($entity); @@ -162,7 +164,11 @@ class Email implements AssignmentNotificator $from = $entity->get('from'); if ($from) { - $person = $emailAddressRepository->getEntityByAddress($from, null, ['User', 'Contact', 'Lead']); + $person = $emailAddressRepository->getEntityByAddress($from, null, [ + User::ENTITY_TYPE, + Contact::ENTITY_TYPE, + Lead::ENTITY_TYPE, + ]); if ($person) { $data['personEntityType'] = $person->getEntityType(); @@ -187,8 +193,8 @@ class Email implements AssignmentNotificator $parent = null; - $parentId = $entity->get('parentId'); - $parentType = $entity->get('parentType'); + $parentId = $entity->getParentId(); + $parentType = $entity->getParentType(); if ($parentType && $parentId) { $parent = $this->entityManager->getEntityById($parentType, $parentId); @@ -196,10 +202,10 @@ class Email implements AssignmentNotificator $account = null; - $accountId = $entity->get('accountId'); + $accountLink = $entity->getAccount(); - if ($accountId) { - $account = $this->entityManager->getEntityById('Account', $accountId); + if ($accountLink) { + $account = $this->entityManager->getEntityById(Account::ENTITY_TYPE, $accountLink->getId()); } foreach ($userIdList as $userId) { @@ -215,7 +221,7 @@ class Email implements AssignmentNotificator continue; } - if (!$this->userChecker->checkAssignment('Email', $userId)) { + if (!$this->userChecker->checkAssignment(EmailEntity::ENTITY_TYPE, $userId)) { continue; } @@ -228,7 +234,7 @@ class Email implements AssignmentNotificator if ($folderId) { if ( $this->entityManager - ->getRDBRepository('EmailFolder') + ->getRDBRepositoryByClass(EmailFolder::class) ->where([ 'id' => $folderId, 'skipNotifications' => true, @@ -241,7 +247,7 @@ class Email implements AssignmentNotificator } /** @var User|null $user */ - $user = $this->entityManager->getEntity('User', $userId); + $user = $this->entityManager->getEntityById(EmailEntity::ENTITY_TYPE, $userId); if (!$user) { continue; @@ -251,18 +257,18 @@ class Email implements AssignmentNotificator continue; } - if (!$this->aclManager->checkScope($user, 'Email')) { + if (!$this->aclManager->checkScope($user, EmailEntity::ENTITY_TYPE)) { continue; } $isArchivedOrBeingImported = - $entity->get('status') === EmailEntity::STATUS_ARCHIVED || + $entity->getStatus() === EmailEntity::STATUS_ARCHIVED || $params->getOption('isBeingImported'); if ( $isArchivedOrBeingImported && $parent && - $this->getStreamService()->checkIsFollowed($parent, $userId) + $this->streamService->checkIsFollowed($parent, $userId) ) { continue; } @@ -270,7 +276,7 @@ class Email implements AssignmentNotificator if ( $isArchivedOrBeingImported && $account && - $this->getStreamService()->checkIsFollowed($account, $userId) + $this->streamService->checkIsFollowed($account, $userId) ) { continue; } @@ -281,7 +287,7 @@ class Email implements AssignmentNotificator 'type' => Notification::TYPE_EMAIL_RECEIVED, 'userId' => $userId, 'relatedId' => $entity->getId(), - 'relatedType' => 'Email', + 'relatedType' => EmailEntity::ENTITY_TYPE, ]) ->select(['id']) ->findOne(); @@ -295,17 +301,8 @@ class Email implements AssignmentNotificator 'userId' => $userId, 'data' => $data, 'relatedId' => $entity->getId(), - 'relatedType' => 'Email', + 'relatedType' => EmailEntity::ENTITY_TYPE, ]); } } - - private function getStreamService(): StreamService - { - if (empty($this->streamService)) { - $this->streamService = $this->injectableFactory->create(StreamService::class); - } - - return $this->streamService; - } } diff --git a/application/Espo/Core/Mail/Importer.php b/application/Espo/Core/Mail/Importer.php index 0f8407ba57..826b034586 100644 --- a/application/Espo/Core/Mail/Importer.php +++ b/application/Espo/Core/Mail/Importer.php @@ -70,6 +70,7 @@ class Importer private EntityManager $entityManager; private Config $config; + /** @var AssignmentNotificator */ private AssignmentNotificator $notificator; private FiltersMatcher $filtersMatcher; private ParserFactory $parserFactory; @@ -93,7 +94,7 @@ class Importer $this->duplicateFinder = $duplicateFinder; $this->jobSchedulerFactory = $jobSchedulerFactory; - $this->notificator = $notificatorFactory->create(Email::ENTITY_TYPE); + $this->notificator = $notificatorFactory->createByClass(Email::class); $this->filtersMatcher = new FiltersMatcher(); } diff --git a/application/Espo/Core/Notification/AssignmentNotificator.php b/application/Espo/Core/Notification/AssignmentNotificator.php index 53a74971e3..4fe7d409c2 100644 --- a/application/Espo/Core/Notification/AssignmentNotificator.php +++ b/application/Espo/Core/Notification/AssignmentNotificator.php @@ -30,11 +30,12 @@ namespace Espo\Core\Notification; use Espo\ORM\Entity; - use Espo\Core\Notification\AssignmentNotificator\Params; /** * Processes assignment notifications. Called after entity is saved. + * + * @template TEntity of Entity */ interface AssignmentNotificator { diff --git a/application/Espo/Core/Notification/AssignmentNotificatorFactory.php b/application/Espo/Core/Notification/AssignmentNotificatorFactory.php index 356174ac6f..735586d8a6 100644 --- a/application/Espo/Core/Notification/AssignmentNotificatorFactory.php +++ b/application/Espo/Core/Notification/AssignmentNotificatorFactory.php @@ -29,25 +29,19 @@ namespace Espo\Core\Notification; -use Espo\Core\{ - InjectableFactory, - Utils\ClassFinder, - Utils\Metadata, - Notification\DefaultAssignmentNotificator, - Notification\AssignmentNotificator, -}; +use Espo\Core\InjectableFactory; +use Espo\Core\Utils\ClassFinder; +use Espo\Core\Utils\Metadata; +use Espo\ORM\Entity; +use Espo\ORM\Repository\Util as RepositoryUtil; class AssignmentNotificatorFactory { - /** - * @var class-string - */ + /** @var class-string> */ protected string $defaultClassName = DefaultAssignmentNotificator::class; private InjectableFactory $injectableFactory; - private ClassFinder $classFinder; - private Metadata $metadata; public function __construct(InjectableFactory $injectableFactory, ClassFinder $classFinder, Metadata $metadata) @@ -57,10 +51,23 @@ class AssignmentNotificatorFactory $this->metadata = $metadata; } + /** + * @template T of Entity + * @param class-string $className An entity class name. + * @return AssignmentNotificator + */ + public function createByClass(string $className): AssignmentNotificator + { + $entityType = RepositoryUtil::getEntityTypeByClass($className); + + /** @var AssignmentNotificator */ + return $this->create($entityType); + } + /** * @todo Change return type to AssignmentNotificator. * - * @return AssignmentNotificator + * @return AssignmentNotificator */ public function create(string $entityType): object // AssignmentNotificator { @@ -70,11 +77,11 @@ class AssignmentNotificatorFactory } /** - * @return class-string + * @return class-string> */ private function getClassName(string $entityType): string { - /** @var ?class-string $className1 */ + /** @var ?class-string> $className1 */ $className1 = $this->metadata->get(['notificationDefs', $entityType, 'assignmentNotificatorClassName']); if ($className1) { @@ -82,7 +89,7 @@ class AssignmentNotificatorFactory } /* For backward compatibility. */ - /** @var ?class-string $className2 */ + /** @var ?class-string> $className2 */ $className2 = $this->classFinder->find('Notificators', $entityType); if ($className2) { diff --git a/application/Espo/Core/Notification/DefaultAssignmentNotificator.php b/application/Espo/Core/Notification/DefaultAssignmentNotificator.php index 04c63295b7..8c7ef37d20 100644 --- a/application/Espo/Core/Notification/DefaultAssignmentNotificator.php +++ b/application/Espo/Core/Notification/DefaultAssignmentNotificator.php @@ -30,31 +30,20 @@ namespace Espo\Core\Notification; use Espo\Core\ORM\Entity as CoreEntity; - use Espo\ORM\Entity; use Espo\ORM\EntityManager; - use Espo\Entities\User; use Espo\Entities\Notification; - use Espo\Core\Notification\AssignmentNotificator\Params; +/** + * @implements AssignmentNotificator + */ class DefaultAssignmentNotificator implements AssignmentNotificator { - /** - * @var User - */ - protected $user; - - /** - * @var EntityManager - */ - protected $entityManager; - - /** - * @var UserEnabledChecker - */ - protected $userChecker; + protected User $user; + protected EntityManager $entityManager; + protected UserEnabledChecker $userChecker; public function __construct(User $user, EntityManager $entityManager, UserEnabledChecker $userChecker) { diff --git a/application/Espo/Tools/Notification/HookProcessor.php b/application/Espo/Tools/Notification/HookProcessor.php index 4d322b2655..b76500a2fb 100644 --- a/application/Espo/Tools/Notification/HookProcessor.php +++ b/application/Espo/Tools/Notification/HookProcessor.php @@ -32,18 +32,13 @@ namespace Espo\Tools\Notification; use Espo\Core\Notification\AssignmentNotificatorFactory; use Espo\Core\Notification\AssignmentNotificator; use Espo\Core\Notification\AssignmentNotificator\Params as AssignmentNotificatorParams; - use Espo\Core\Utils\Metadata; use Espo\Core\Utils\Config; - use Espo\Tools\Stream\Service as StreamService; - use Espo\ORM\EntityManager; use Espo\ORM\Entity; - use Espo\Entities\User; use Espo\Entities\Notification; - use Espo\Core\ORM\Entity as CoreEntity; /** @@ -51,30 +46,20 @@ use Espo\Core\ORM\Entity as CoreEntity; */ class HookProcessor { - /** - * @var array - */ - private $notifatorsHash = []; - - /** - * @var array - */ + /** @var array> */ + private $notificatorsHash = []; + /** @var array */ private $hasStreamCache = []; + /** @var array */ + private $userNameHash = []; private Metadata $metadata; private Config $config; private EntityManager $entityManager; private StreamService $streamService; - private AssignmentNotificatorFactory $notificatorFactory; - private User $user; - /** - * @var array - */ - private $userNameHash = []; - public function __construct( Metadata $metadata, Config $config, @@ -201,17 +186,17 @@ class HookProcessor } /** - * @return AssignmentNotificator + * @return AssignmentNotificator */ private function getNotificator(string $entityType): object { - if (empty($this->notifatorsHash[$entityType])) { + if (empty($this->notificatorsHash[$entityType])) { $notificator = $this->notificatorFactory->create($entityType); - $this->notifatorsHash[$entityType] = $notificator; + $this->notificatorsHash[$entityType] = $notificator; } - return $this->notifatorsHash[$entityType]; + return $this->notificatorsHash[$entityType]; } private function getUserNameById(string $id): string @@ -221,7 +206,7 @@ class HookProcessor } if (!array_key_exists($id, $this->userNameHash)) { - /** @var User|null $user */ + /** @var ?User $user */ $user = $this->entityManager->getEntityById(User::ENTITY_TYPE, $id); if ($user) {