From d34bc6d7d2e224af548ce1085816b5e5c533aadd Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 10 Nov 2021 15:10:53 +0200 Subject: [PATCH 01/12] type fixes --- application/Espo/Services/Attachment.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/application/Espo/Services/Attachment.php b/application/Espo/Services/Attachment.php index aa67e9e106..ed19937441 100644 --- a/application/Espo/Services/Attachment.php +++ b/application/Espo/Services/Attachment.php @@ -254,7 +254,7 @@ class Attachment extends Record } } - public function getCopiedAttachment($data) + public function getCopiedAttachment(stdClass $data): AttachmentEntity { if (empty($data->id)) { throw new BadRequest(); @@ -303,7 +303,7 @@ class Attachment extends Record return $copied; } - public function getAttachmentFromImageUrl($data) + public function getAttachmentFromImageUrl(stdClass $data): AttachmentEntity { $attachment = $this->getAttachmentRepository()->getNew(); @@ -331,14 +331,14 @@ class Attachment extends Record $this->checkAttachmentField($relatedEntityType, $field); - $data = $this->getImageDataByUrl($url); + $imageData = $this->getImageDataByUrl($url); - if (!$data) { + if (!$imageData) { throw new Error('Attachment::getAttachmentFromImageUrl: Bad image data.'); } - $type = $data['type']; - $contents = $data['contents']; + $type = $imageData->type; + $contents = $imageData->contents; $size = mb_strlen($contents, '8bit'); @@ -378,7 +378,7 @@ class Attachment extends Record return $attachment; } - protected function getImageDataByUrl($url) + protected function getImageDataByUrl(string $url): ?stdClass { $type = null; @@ -451,14 +451,14 @@ class Attachment extends Record curl_close($ch); if (!$type) { - return; + return null; } if (!in_array($type, $this->imageTypeList)) { - return; + return null; } - return [ + return (object) [ 'type' => $type, 'contents' => $body, ]; From 9e641e65ed76f18c86dc45336705fdbbf950a559 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 10 Nov 2021 15:34:24 +0200 Subject: [PATCH 02/12] type fixes --- .../Espo/EntryPoints/ChangePassword.php | 5 +++- application/Espo/EntryPoints/Download.php | 3 +++ application/Espo/EntryPoints/Image.php | 16 ++++++++++- application/Espo/Services/Integration.php | 18 ++++++++++--- application/Espo/Services/Layout.php | 27 ++++++++++++++++--- 5 files changed, 61 insertions(+), 8 deletions(-) diff --git a/application/Espo/EntryPoints/ChangePassword.php b/application/Espo/EntryPoints/ChangePassword.php index b3f085b5f1..44beee24f3 100644 --- a/application/Espo/EntryPoints/ChangePassword.php +++ b/application/Espo/EntryPoints/ChangePassword.php @@ -46,10 +46,13 @@ class ChangePassword implements EntryPoint { use NoAuth; + /** @var Config */ protected $config; + /** @var ClientManager */ protected $clientManager; + /** @var EntityManager */ protected $entityManager; public function __construct(Config $config, ClientManager $clientManager, EntityManager $entityManager) @@ -68,7 +71,7 @@ class ChangePassword implements EntryPoint } $passwordChangeRequest = $this->entityManager - ->getRepository('PasswordChangeRequest') + ->getRDBRepository('PasswordChangeRequest') ->where([ 'requestId' => $requestId, ]) diff --git a/application/Espo/EntryPoints/Download.php b/application/Espo/EntryPoints/Download.php index 6228c5c0c5..8360099216 100644 --- a/application/Espo/EntryPoints/Download.php +++ b/application/Espo/EntryPoints/Download.php @@ -54,10 +54,13 @@ class Download implements EntryPoint 'application/msexcel', ]; + /** @var FileStorageManager */ protected $fileStorageManager; + /** @var Acl */ protected $acl; + /** @var EntityManager */ protected $entityManager; public function __construct(FileStorageManager $fileStorageManager, Acl $acl, EntityManager $entityManager) diff --git a/application/Espo/EntryPoints/Image.php b/application/Espo/EntryPoints/Image.php index 3b40fa081c..feb80993a6 100644 --- a/application/Espo/EntryPoints/Image.php +++ b/application/Espo/EntryPoints/Image.php @@ -29,6 +29,8 @@ namespace Espo\EntryPoints; +use Espo\Repositories\Attachment as AttachmentRepository; + use Espo\Core\{ Exceptions\NotFound, Exceptions\NotFoundSilent, @@ -54,16 +56,22 @@ class Image implements EntryPoint protected $allowedFieldList = null; + /** @var FileStorageManager */ protected $fileStorageManager; + /** @var Acl */ protected $acl; + /** @var EntityManager */ protected $entityManager; + /** @var FileManager */ protected $fileManager; + /** @var Config */ protected $config; + /** @var Metadata */ private $metadata; public function __construct( @@ -172,7 +180,7 @@ class Image implements EntryPoint return $this->fileManager->getContents($cacheFilePath); } - $filePath = $this->entityManager->getRepository('Attachment')->getFilePath($attachment); + $filePath = $this->getAttachmentRepository()->getFilePath($attachment); if (!$this->fileManager->isFile($filePath)) { throw new NotFound(); @@ -358,4 +366,10 @@ class Image implements EntryPoint { return $this->metadata->get(['app', 'image', 'sizes']) ?? []; } + + protected function getAttachmentRepository(): AttachmentRepository + { + /** @var AttachmentRepository */ + return $this->entityManager->getRepository(Attachment::ENTITY_TYPE); + } } diff --git a/application/Espo/Services/Integration.php b/application/Espo/Services/Integration.php index 0a6f063d1c..64227b2029 100644 --- a/application/Espo/Services/Integration.php +++ b/application/Espo/Services/Integration.php @@ -39,16 +39,28 @@ use Espo\{ Entities\User, }; -use StdClass; +use stdClass; class Integration { + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var User + */ protected $user; + /** + * @var Config + */ protected $config; + /** + * @var ConfigWriter + */ protected $configWriter; public function __construct( @@ -83,7 +95,7 @@ class Integration return $entity; } - public function update(string $id, StdClass $data): Entity + public function update(string $id, stdClass $data): Entity { $this->processAccessCheck(); @@ -99,7 +111,7 @@ class Integration $integrationsConfigData = $this->config->get('integrations') ?? (object) []; - if (!($integrationsConfigData instanceof StdClass)) { + if (!($integrationsConfigData instanceof stdClass)) { $integrationsConfigData = (object) []; } diff --git a/application/Espo/Services/Layout.php b/application/Espo/Services/Layout.php index d49304a559..a0f2f94361 100644 --- a/application/Espo/Services/Layout.php +++ b/application/Espo/Services/Layout.php @@ -48,18 +48,39 @@ use Espo\{ class Layout { + /** + * @var Acl + */ protected $acl; + /** + * @var LayoutUtil + */ protected $layout; + /** + * @var LayoutManager + */ protected $layoutManager; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var Metadata + */ protected $metadata; + /** + * @var DataManager + */ protected $dataManager; + /** + * @var User + */ protected $user; public function __construct( @@ -132,7 +153,7 @@ class Layout if ($portalId) { $portal = $em - ->getRepository('Portal') + ->getRDBRepository('Portal') ->select(['layoutSetId']) ->where(['id' => $portalId]) ->findOne(); @@ -146,7 +167,7 @@ class Layout if ($teamId) { $team = $em - ->getRepository('Team') + ->getRDBRepository('Team') ->select(['layoutSetId']) ->where(['id' => $teamId]) ->findOne(); @@ -245,7 +266,7 @@ class Layout } $layout = $em - ->getRepository('LayoutRecord') + ->getRDBRepository('LayoutRecord') ->where([ 'layoutSetId' => $setId, 'name' => $fullName, From f496f386eea2eb809ec256f8b0b51fd794a79457 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 10 Nov 2021 15:44:05 +0200 Subject: [PATCH 03/12] type fixes --- application/Espo/ORM/CollectionFactory.php | 3 ++ application/Espo/ORM/Mapper/BaseMapper.php | 35 ++++++++++++++----- .../ORM/QueryComposer/BaseQueryComposer.php | 14 +++++++- .../Espo/ORM/Repository/RDBRepository.php | 11 ++++-- 4 files changed, 52 insertions(+), 11 deletions(-) diff --git a/application/Espo/ORM/CollectionFactory.php b/application/Espo/ORM/CollectionFactory.php index 950b47f5df..4657b9946b 100644 --- a/application/Espo/ORM/CollectionFactory.php +++ b/application/Espo/ORM/CollectionFactory.php @@ -38,6 +38,9 @@ use Espo\ORM\{ */ class CollectionFactory { + /** + * @var EntityManager + */ protected $entityManager; public function __construct(EntityManager $entityManager) diff --git a/application/Espo/ORM/Mapper/BaseMapper.php b/application/Espo/ORM/Mapper/BaseMapper.php index b58de0489b..a8b26f77d6 100644 --- a/application/Espo/ORM/Mapper/BaseMapper.php +++ b/application/Espo/ORM/Mapper/BaseMapper.php @@ -61,20 +61,39 @@ class BaseMapper implements RDBMapper protected $aliasesCache = []; + /** + * @var PDO + */ protected $pdo; - protected $entityFactroy; - - protected $collectionFactory; - - protected $queryComposer; - + /** + * @var EntityFactory + */ protected $entityFactory; + /** + * @var CollectionFactory + */ + protected $collectionFactory; + + /** + * @var QueryComposer + */ + protected $queryComposer; + + /** + * @var Metadata + */ protected $metadata; + /** + * @var SqlExecutor + */ protected $sqlExecutor; + /** + * @var Helper + */ protected $helper; public function __construct( @@ -1237,7 +1256,7 @@ class BaseMapper implements RDBMapper { $id = $this->pdo->lastInsertId(); - if ($id === '' || $id === null) { + if ($id === '' || $id === null) { /** @phpstan-ignore-line */ return; } @@ -1560,7 +1579,7 @@ class BaseMapper implements RDBMapper $foreignEntity = $this->entityFactory->create($foreignEntityType); - $map = $foreignEntity->getRelationParam($foreign, 'columnAttributeMap') ?? []; + $map = $this->getRelationParam($foreignEntity, $foreign, 'columnAttributeMap') ?? []; $select = []; diff --git a/application/Espo/ORM/QueryComposer/BaseQueryComposer.php b/application/Espo/ORM/QueryComposer/BaseQueryComposer.php index 841bf017e7..644209d320 100644 --- a/application/Espo/ORM/QueryComposer/BaseQueryComposer.php +++ b/application/Espo/ORM/QueryComposer/BaseQueryComposer.php @@ -144,12 +144,24 @@ abstract class BaseQueryComposer implements QueryComposer protected $identifierQuoteCharacter = '`'; + /** + * @var EntityFactory + */ protected $entityFactory; + /** + * @var PDO + */ protected $pdo; + /** + * @var Metadata + */ protected $metadata; + /** + * @var FunctionConverterFactory|null + */ protected $functionConverterFactory; protected $helper; @@ -1070,7 +1082,7 @@ abstract class BaseQueryComposer implements QueryComposer return $function . '(' . $part . ')'; } - private function getFunctionPartFromFactory(string $function, array $argumentPartList): ?string + private function getFunctionPartFromFactory(string $function, array $argumentPartList): string { $obj = $this->functionConverterFactory->create($function); diff --git a/application/Espo/ORM/Repository/RDBRepository.php b/application/Espo/ORM/Repository/RDBRepository.php index 9d4b24190e..fa3ab590ff 100644 --- a/application/Espo/ORM/Repository/RDBRepository.php +++ b/application/Espo/ORM/Repository/RDBRepository.php @@ -61,12 +61,19 @@ class RDBRepository implements Repository */ protected $entityManager; + /** + * @var EntityFactory + */ protected $entityFactory; - protected $mapper; - + /** + * @var HookMediator|null + */ protected $hookMediator; + /** + * @var RDBTransactionManager + */ protected $transactionManager; public function __construct( From 3a68ebcbf418cdced13aa0a82f43e5cc4b6db042 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 10 Nov 2021 16:04:31 +0200 Subject: [PATCH 04/12] type fixes --- .../AppParams/TemplateEntityTypeList.php | 15 ++++++- .../Espo/Classes/Jobs/CheckNewVersion.php | 6 +++ .../Email/Where/ItemConverters/FromEquals.php | 8 +++- .../Email/Where/ItemConverters/InFolder.php | 13 +++++- .../Crm/EntryPoints/CampaignTrackOpened.php | 6 +++ .../Modules/Crm/EntryPoints/CampaignUrl.php | 27 +++++++++++- .../Crm/EntryPoints/EventConfirmation.php | 23 ++++++++-- .../Crm/EntryPoints/SubscribeAgain.php | 44 +++++++++++++++---- .../Modules/Crm/EntryPoints/Unsubscribe.php | 38 +++++++++++++--- application/Espo/Repositories/Preferences.php | 4 ++ 10 files changed, 160 insertions(+), 24 deletions(-) diff --git a/application/Espo/Classes/AppParams/TemplateEntityTypeList.php b/application/Espo/Classes/AppParams/TemplateEntityTypeList.php index 666466b8a6..4e0d0fae95 100644 --- a/application/Espo/Classes/AppParams/TemplateEntityTypeList.php +++ b/application/Espo/Classes/AppParams/TemplateEntityTypeList.php @@ -40,8 +40,19 @@ use Espo\Core\{ */ class TemplateEntityTypeList { + /** + * @var Acl + */ protected $acl; + + /** + * @var SelectBuilderFactory + */ protected $selectBuilderFactory; + + /** + * @var EntityManager + */ protected $entityManager; public function __construct(Acl $acl, SelectBuilderFactory $selectBuilderFactory, EntityManager $entityManager) @@ -51,7 +62,7 @@ class TemplateEntityTypeList $this->entityManager = $entityManager; } - public function get() : array + public function get(): array { if (!$this->acl->checkScope('Template')) { return []; @@ -69,7 +80,7 @@ class TemplateEntityTypeList ->build(); $templateCollection = $this->entityManager - ->getRepository('Template') + ->getRDBRepository('Template') ->clone($query) ->find(); diff --git a/application/Espo/Classes/Jobs/CheckNewVersion.php b/application/Espo/Classes/Jobs/CheckNewVersion.php index dedc98049e..6bb970e6e0 100644 --- a/application/Espo/Classes/Jobs/CheckNewVersion.php +++ b/application/Espo/Classes/Jobs/CheckNewVersion.php @@ -40,8 +40,14 @@ use DateTimeZone; class CheckNewVersion implements JobDataLess { + /** + * @var Config + */ protected $config; + /** + * @var EntityManager + */ protected $entityManager; public function __construct(Config $config, EntityManager $entityManager) diff --git a/application/Espo/Classes/Select/Email/Where/ItemConverters/FromEquals.php b/application/Espo/Classes/Select/Email/Where/ItemConverters/FromEquals.php index 9448339efc..ee0470a49c 100644 --- a/application/Espo/Classes/Select/Email/Where/ItemConverters/FromEquals.php +++ b/application/Espo/Classes/Select/Email/Where/ItemConverters/FromEquals.php @@ -44,12 +44,16 @@ use Espo\{ class FromEquals implements ItemConverter { + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var EmailAddressHelper + */ protected $emailAddressHelper; - protected $randomStringGenerator; - public function __construct( EntityManager $entityManager, EmailAddressHelper $emailAddressHelper diff --git a/application/Espo/Classes/Select/Email/Where/ItemConverters/InFolder.php b/application/Espo/Classes/Select/Email/Where/ItemConverters/InFolder.php index 57f2bd4e9a..28f136a938 100644 --- a/application/Espo/Classes/Select/Email/Where/ItemConverters/InFolder.php +++ b/application/Espo/Classes/Select/Email/Where/ItemConverters/InFolder.php @@ -45,10 +45,19 @@ use Espo\{ class InFolder implements ItemConverter { + /** + * @var User + */ protected $user; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var JoinHelper + */ protected $joinHelper; public function __construct(User $user, EntityManager $entityManager, JoinHelper $joinHelper) @@ -186,7 +195,7 @@ class InFolder implements ItemConverter protected function getEmailAddressIdList(): array { $emailAddressList = $this->entityManager - ->getRepository('User') + ->getRDBRepository('User') ->getRelation($this->user, 'emailAddresses') ->select(['id']) ->find(); @@ -194,7 +203,7 @@ class InFolder implements ItemConverter $emailAddressIdList = []; foreach ($emailAddressList as $emailAddress) { - $emailAddressIdList[] = $emailAddress->id; + $emailAddressIdList[] = $emailAddress->getId(); } return $emailAddressIdList; diff --git a/application/Espo/Modules/Crm/EntryPoints/CampaignTrackOpened.php b/application/Espo/Modules/Crm/EntryPoints/CampaignTrackOpened.php index bc89c2b004..6460902eb7 100644 --- a/application/Espo/Modules/Crm/EntryPoints/CampaignTrackOpened.php +++ b/application/Espo/Modules/Crm/EntryPoints/CampaignTrackOpened.php @@ -45,8 +45,14 @@ class CampaignTrackOpened implements EntryPoint { use NoAuth; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var Service + */ protected $service; public function __construct(EntityManager $entityManager, Service $service) diff --git a/application/Espo/Modules/Crm/EntryPoints/CampaignUrl.php b/application/Espo/Modules/Crm/EntryPoints/CampaignUrl.php index 2cea5c0f52..a442e78c6c 100644 --- a/application/Espo/Modules/Crm/EntryPoints/CampaignUrl.php +++ b/application/Espo/Modules/Crm/EntryPoints/CampaignUrl.php @@ -30,6 +30,7 @@ namespace Espo\Modules\Crm\EntryPoints; use Espo\Modules\Crm\Services\Campaign as Service; +use Espo\Repositories\EmailAddress as EmailAddressRepository; use Espo\{ Modules\Crm\Entities\EmailQueueItem, @@ -54,16 +55,34 @@ class CampaignUrl implements EntryPoint { use NoAuth; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var Service + */ protected $service; + /** + * @var Hasher + */ protected $hasher; + /** + * @var HookManager + */ protected $hookManager; + /** + * @var ClientManager + */ protected $clientManager; + /** + * @var Metadata + */ protected $metadata; public function __construct( @@ -180,7 +199,7 @@ class CampaignUrl implements EntryPoint throw new NotFoundSilent(); } - $eaRepository = $this->entityManager->getRepository('EmailAddress'); + $eaRepository = $this->getEmailAddressRepository(); $ea = $eaRepository->getByAddress($emailAddress); @@ -229,4 +248,10 @@ class CampaignUrl implements EntryPoint $this->clientManager->display($runScript); } + + private function getEmailAddressRepository(): EmailAddressRepository + { + /** @var EmailAddressRepository */ + return $this->entityManager->getRepository('EmailAddress'); + } } diff --git a/application/Espo/Modules/Crm/EntryPoints/EventConfirmation.php b/application/Espo/Modules/Crm/EntryPoints/EventConfirmation.php index e75894f3d0..0216fcbeb3 100644 --- a/application/Espo/Modules/Crm/EntryPoints/EventConfirmation.php +++ b/application/Espo/Modules/Crm/EntryPoints/EventConfirmation.php @@ -46,10 +46,19 @@ class EventConfirmation implements EntryPoint { use NoAuth; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var ClientManager + */ protected $clientManager; + /** + * @var HookManager + */ protected $hookManager; public function __construct(EntityManager $entityManager, ClientManager $clientManager, HookManager $hookManager) { @@ -71,7 +80,10 @@ class EventConfirmation implements EntryPoint throw new BadRequest(); } - $uniqueId = $this->entityManager->getRepository('UniqueId')->where(['name' => $uid])->findOne(); + $uniqueId = $this->entityManager + ->getRDBRepository('UniqueId') + ->where(['name' => $uid]) + ->findOne(); if (!$uniqueId) { throw new NotFound(); @@ -111,18 +123,21 @@ class EventConfirmation implements EntryPoint $data = (object) [ 'status' => $status ]; - $this->entityManager->getRepository($eventType)->updateRelation($event, $link, $invitee->id, $data); + + $this->entityManager + ->getRDBRepository($eventType) + ->updateRelation($event, $link, $invitee->getId(), $data); $actionData = [ 'eventName' => $event->get('name'), 'eventType' => $event->getEntityType(), - 'eventId' => $event->id, + 'eventId' => $event->getId(), 'dateStart' => $event->get('dateStart'), 'action' => $action, 'status' => $status, 'link' => $link, 'inviteeType' => $invitee->getEntityType(), - 'inviteeId' => $invitee->id + 'inviteeId' => $invitee->getId(), ]; $this->hookManager->process($event->getEntityType(), $hookMethodName, $event, [], $actionData); diff --git a/application/Espo/Modules/Crm/EntryPoints/SubscribeAgain.php b/application/Espo/Modules/Crm/EntryPoints/SubscribeAgain.php index 6121ad8b1e..d837609a33 100644 --- a/application/Espo/Modules/Crm/EntryPoints/SubscribeAgain.php +++ b/application/Espo/Modules/Crm/EntryPoints/SubscribeAgain.php @@ -29,6 +29,8 @@ namespace Espo\Modules\Crm\EntryPoints; +use Espo\Repositories\EmailAddress as EmailAddressRepository; + use Espo\Core\{ Exceptions\NotFound, Exceptions\BadRequest, @@ -48,16 +50,34 @@ class SubscribeAgain implements EntryPoint { use NoAuth; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var ClientManager + */ protected $clientManager; + /** + * @var HookManager + */ protected $hookManager; + /** + * @var Config + */ protected $config; + /** + * @var Metadata + */ protected $metadata; + /** + * @var Hasher + */ protected $hasher; public function __construct( @@ -131,7 +151,7 @@ class SubscribeAgain implements EntryPoint $emailAddress = $target->get('emailAddress'); if ($emailAddress) { - $ea = $this->entityManager->getRepository('EmailAddress')->getByAddress($emailAddress); + $ea = $this->getEmailAddressRepository()->getByAddress($emailAddress); if ($ea) { $ea->set('optOut', false); @@ -155,14 +175,14 @@ class SubscribeAgain implements EntryPoint if ($link) { $targetListList = $this->entityManager - ->getRepository('MassEmail') + ->getRDBRepository('MassEmail') ->getRelation($massEmail, 'targetLists') ->find(); foreach ($targetListList as $targetList) { $optedInResult = $this->entityManager - ->getRepository('TargetList') - ->updateRelation($targetList, $link, $target->id, ['optedOut' => false]); + ->getRDBRepository('TargetList') + ->updateRelation($targetList, $link, $target->getId(), ['optedOut' => false]); if ($optedInResult) { $hookData = [ @@ -171,7 +191,8 @@ class SubscribeAgain implements EntryPoint 'targetType' => $targetType, ]; - $this->hookManager->process('TargetList', 'afterCancelOptOut', $targetList, [], $hookData); + $this->hookManager + ->process('TargetList', 'afterCancelOptOut', $targetList, [], $hookData); } } @@ -185,7 +206,7 @@ class SubscribeAgain implements EntryPoint if ($campaign && $target) { $logRecord = $this->entityManager - ->getRepository('CampaignLogRecord')->where([ + ->getRDBRepository('CampaignLogRecord')->where([ 'queueItemId' => $queueItemId, 'action' => 'Opted Out', ]) @@ -225,11 +246,12 @@ class SubscribeAgain implements EntryPoint throw new NotFound(); } - $repository = $this->entityManager->getRepository('EmailAddress'); + $repository = $this->getEmailAddressRepository(); $ea = $repository->getByAddress($emailAddress); + if ($ea) { - $entityList = $repository->getEntityListByAddressId($ea->id); + $entityList = $repository->getEntityListByAddressId($ea->getId()); if ($ea->get('optOut')) { $ea->set('optOut', false); @@ -250,4 +272,10 @@ class SubscribeAgain implements EntryPoint throw new NotFound(); } } + + private function getEmailAddressRepository(): EmailAddressRepository + { + /** @var EmailAddressRepository */ + return $this->entityManager->getRepository('EmailAddress'); + } } diff --git a/application/Espo/Modules/Crm/EntryPoints/Unsubscribe.php b/application/Espo/Modules/Crm/EntryPoints/Unsubscribe.php index 05853673ec..70f8d0359a 100644 --- a/application/Espo/Modules/Crm/EntryPoints/Unsubscribe.php +++ b/application/Espo/Modules/Crm/EntryPoints/Unsubscribe.php @@ -30,6 +30,7 @@ namespace Espo\Modules\Crm\EntryPoints; use Espo\Modules\Crm\Services\Campaign as Service; +use Espo\Repositories\EmailAddress as EmailAddressRepository; use Espo\Core\{ Exceptions\NotFound, @@ -50,18 +51,39 @@ class Unsubscribe implements EntryPoint { use NoAuth; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var ClientManager + */ protected $clientManager; + /** + * @var HookManager + */ protected $hookManager; + /** + * @var Config + */ protected $config; + /** + * @var Metadata + */ protected $metadata; + /** + * @var Hasher + */ protected $hasher; + /** + * @var Service + */ protected $service; public function __construct( @@ -137,7 +159,7 @@ class Unsubscribe implements EntryPoint $emailAddress = $target->get('emailAddress'); if ($emailAddress) { - $ea = $this->entityManager->getRepository('EmailAddress')->getByAddress($emailAddress); + $ea = $this->getEmailAddressRepository()->getByAddress($emailAddress); if ($ea) { $ea->set('optOut', true); @@ -161,14 +183,14 @@ class Unsubscribe implements EntryPoint if ($link) { $targetListList = $this->entityManager - ->getRepository('MassEmail') + ->getRDBRepository('MassEmail') ->getRelation($massEmail, 'targetLists') ->find(); foreach ($targetListList as $targetList) { $optedOutResult = $this->entityManager - ->getRepository('TargetList') - ->updateRelation($targetList, $link, $target->id, ['optedOut' => true]); + ->getRDBRepository('TargetList') + ->updateRelation($targetList, $link, $target->getId(), ['optedOut' => true]); if ($optedOutResult) { $hookData = [ @@ -228,7 +250,7 @@ class Unsubscribe implements EntryPoint throw new NotFound(); } - $repository = $this->entityManager->getRepository('EmailAddress'); + $repository = $this->getEmailAddressRepository(); $ea = $repository->getByAddress($emailAddress); @@ -253,4 +275,10 @@ class Unsubscribe implements EntryPoint throw new NotFound(); } } + + private function getEmailAddressRepository(): EmailAddressRepository + { + /** @var EmailAddressRepository */ + return $this->entityManager->getRepository('EmailAddress'); + } } diff --git a/application/Espo/Repositories/Preferences.php b/application/Espo/Repositories/Preferences.php index 33338842c6..c67df39263 100644 --- a/application/Espo/Repositories/Preferences.php +++ b/application/Espo/Repositories/Preferences.php @@ -55,6 +55,9 @@ class Preferences implements Repository, use Di\ConfigSetter; use Di\EntityManagerSetter; + /** + * @var EntityFactory + */ protected $entityFactory; public function __construct( @@ -76,6 +79,7 @@ class Preferences implements Repository, public function getNew(): Entity { + /** @var PreferencesEntity */ return $this->entityFactory->create('Preferences'); } From d2a1e8f771174396ef772533a2ceab9a482ac286 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 10 Nov 2021 16:40:33 +0200 Subject: [PATCH 05/12] fixes --- application/Espo/Core/AclManager.php | 37 +++++++++++--- .../Core/Action/Actions/ConvertCurrency.php | 17 ++++--- application/Espo/Core/Portal/AclManager.php | 26 +++++++--- .../Database/Schema/BaseRebuildActions.php | 28 +++++++++-- .../Distribution/CaseObj/LeastBusy.php | 6 +++ .../Distribution/CaseObj/RoundRobin.php | 3 ++ .../Business/Distribution/Lead/LeastBusy.php | 47 ++++++++++++----- .../Business/Distribution/Lead/RoundRobin.php | 50 ++++++++++++------- .../Crm/Business/Reminder/EmailReminder.php | 25 +++++++++- .../Modules/Crm/Hooks/Account/Contacts.php | 3 ++ .../ControlKnowledgeBaseArticleStatus.php | 5 +- .../Modules/Crm/Repositories/TargetList.php | 5 +- .../Modules/Crm/Tools/MassEmail/Queue.php | 37 ++++++++------ 13 files changed, 211 insertions(+), 78 deletions(-) diff --git a/application/Espo/Core/AclManager.php b/application/Espo/Core/AclManager.php index 2f5103a404..8cadba407c 100644 --- a/application/Espo/Core/AclManager.php +++ b/application/Espo/Core/AclManager.php @@ -33,8 +33,9 @@ use Espo\ORM\Entity; use Espo\Entities\User; +use Espo\ORM\EntityManager; + use Espo\Core\{ - ORM\EntityManager, Acl, Acl\GlobalRestricton, Acl\OwnerUserFieldProvider, @@ -97,18 +98,39 @@ class AclManager Table::ACTION_STREAM => AccessStreamChecker::class, ]; + /** + * @var AccessCheckerFactory|\Espo\Core\Portal\Acl\AccessChecker\AccessCheckerFactory + */ protected $accessCheckerFactory; + /** + * @var OwnershipCheckerFactory|\Espo\Core\Portal\Acl\OwnershipChecker\OwnershipCheckerFactory + */ protected $ownershipCheckerFactory; - protected $tableFactory; + /** + * @var TableFactory + */ + private $tableFactory; - protected $mapFactory; + /** + * @var MapFactory + */ + private $mapFactory; + /** + * @var GlobalRestricton + */ protected $globalRestricton; + /** + * @var OwnerUserFieldProvider + */ protected $ownerUserFieldProvider; + /** + * @var EntityManager + */ protected $entityManager; public function __construct( @@ -582,11 +604,10 @@ class AclManager if ($permission === Table::LEVEL_TEAM) { $teamIdList = $user->getLinkMultipleIdList('teams'); - if ( - !$this->entityManager - ->getRepository('User') - ->checkBelongsToAnyOfTeams($userId, $teamIdList) - ) { + /** @var \Espo\Repositories\User $userRepository */ + $userRepository = $this->entityManager->getRepository('User'); + + if (!$userRepository->checkBelongsToAnyOfTeams($userId, $teamIdList)) { return false; } } diff --git a/application/Espo/Core/Action/Actions/ConvertCurrency.php b/application/Espo/Core/Action/Actions/ConvertCurrency.php index 37316d634e..f6cd629a5f 100644 --- a/application/Espo/Core/Action/Actions/ConvertCurrency.php +++ b/application/Espo/Core/Action/Actions/ConvertCurrency.php @@ -52,17 +52,17 @@ use Espo\{ class ConvertCurrency implements Action { - protected $acl; + private $acl; - protected $entityManager; + private $entityManager; - protected $fieldUtil; + private $fieldUtil; - protected $metadata; + private $metadata; - protected $configDataProvider; + private $configDataProvider; - protected $currencyConverter; + private $currencyConverter; public function __construct( Acl $acl, @@ -125,7 +125,10 @@ class ConvertCurrency implements Action } protected function convertEntity( - Entity $entity, array $fieldList, string $targetCurrency, CurrencyRates $rates + Entity $entity, + array $fieldList, + string $targetCurrency, + CurrencyRates $rates ) { foreach ($fieldList as $field) { $amount = $entity->get($field); diff --git a/application/Espo/Core/Portal/AclManager.php b/application/Espo/Core/Portal/AclManager.php index 88ab5cb6ff..4ebfbb7ba6 100644 --- a/application/Espo/Core/Portal/AclManager.php +++ b/application/Espo/Core/Portal/AclManager.php @@ -66,11 +66,21 @@ class AclManager extends InternalAclManager private $portal = null; + /** + * @var TableFactory + */ + private $portalTableFactory; + + /** + * @var MapFactory + */ + private $portalMapFactory; + public function __construct( AccessCheckerFactory $accessCheckerFactory, OwnershipCheckerFactory $ownershipCheckerFactory, - TableFactory $tableFactory, - MapFactory $mapFactory, + TableFactory $portalTableFactory, + MapFactory $portalMapFactory, GlobalRestricton $globalRestricton, OwnerUserFieldProvider $ownerUserFieldProvider, EntityManager $entityManager, @@ -78,8 +88,8 @@ class AclManager extends InternalAclManager ) { $this->accessCheckerFactory = $accessCheckerFactory; $this->ownershipCheckerFactory = $ownershipCheckerFactory; - $this->tableFactory = $tableFactory; - $this->mapFactory = $mapFactory; + $this->portalTableFactory = $portalTableFactory; + $this->portalMapFactory = $portalMapFactory; $this->globalRestricton = $globalRestricton; $this->ownerUserFieldProvider = $ownerUserFieldProvider; $this->entityManager = $entityManager; @@ -109,7 +119,7 @@ class AclManager extends InternalAclManager } if (!array_key_exists($key, $this->tableHashMap)) { - $this->tableHashMap[$key] = $this->tableFactory->create($user, $this->getPortal()); + $this->tableHashMap[$key] = $this->portalTableFactory->create($user, $this->getPortal()); } return $this->tableHashMap[$key]; @@ -124,8 +134,10 @@ class AclManager extends InternalAclManager } if (!array_key_exists($key, $this->mapHashMap)) { - $this->mapHashMap[$key] = $this->mapFactory - ->create($user, $this->getTable($user), $this->getPortal()); + /** @var Table */ + $table = $this->getTable($user); + + $this->mapHashMap[$key] = $this->portalMapFactory->create($user, $table, $this->getPortal()); } return $this->mapHashMap[$key]; diff --git a/application/Espo/Core/Utils/Database/Schema/BaseRebuildActions.php b/application/Espo/Core/Utils/Database/Schema/BaseRebuildActions.php index 72df2e8396..1a6368d325 100644 --- a/application/Espo/Core/Utils/Database/Schema/BaseRebuildActions.php +++ b/application/Espo/Core/Utils/Database/Schema/BaseRebuildActions.php @@ -38,16 +38,34 @@ use Espo\Core\{ abstract class BaseRebuildActions { + /** + * @var Metadata + */ protected $metadata; + /** + * @var Config + */ protected $config; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var Log + */ protected $log; + /** + * @var \Doctrine\DBAL\Schema\Schema|null + */ protected $currentSchema = null; + /** + * @var \Doctrine\DBAL\Schema\Schema|null + */ protected $metadataSchema = null; public function __construct( @@ -62,17 +80,17 @@ abstract class BaseRebuildActions $this->log = $log; } - protected function getEntityManager() + protected function getEntityManager(): EntityManager { return $this->entityManager; } - protected function getConfig() + protected function getConfig(): Config { return $this->config; } - protected function getMetadata() + protected function getMetadata(): Metadata { return $this->metadata; } @@ -87,12 +105,12 @@ abstract class BaseRebuildActions $this->metadataSchema = $metadataSchema; } - protected function getCurrentSchema() + protected function getCurrentSchema(): ?\Doctrine\DBAL\Schema\Schema { return $this->currentSchema; } - protected function getMetadataSchema() + protected function getMetadataSchema(): ?\Doctrine\DBAL\Schema\Schema { return $this->metadataSchema; } diff --git a/application/Espo/Modules/Crm/Business/Distribution/CaseObj/LeastBusy.php b/application/Espo/Modules/Crm/Business/Distribution/CaseObj/LeastBusy.php index d1b7707887..2d9f72abfc 100644 --- a/application/Espo/Modules/Crm/Business/Distribution/CaseObj/LeastBusy.php +++ b/application/Espo/Modules/Crm/Business/Distribution/CaseObj/LeastBusy.php @@ -37,8 +37,14 @@ use Espo\Entities\Team; class LeastBusy { + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var Metadata + */ protected $metadata; public function __construct(EntityManager $entityManager, Metadata $metadata) diff --git a/application/Espo/Modules/Crm/Business/Distribution/CaseObj/RoundRobin.php b/application/Espo/Modules/Crm/Business/Distribution/CaseObj/RoundRobin.php index add6e7bfc3..66d7077403 100644 --- a/application/Espo/Modules/Crm/Business/Distribution/CaseObj/RoundRobin.php +++ b/application/Espo/Modules/Crm/Business/Distribution/CaseObj/RoundRobin.php @@ -36,6 +36,9 @@ use Espo\ORM\EntityManager; class RoundRobin { + /** + * @var EntityManager + */ protected $entityManager; public function __construct(EntityManager $entityManager) diff --git a/application/Espo/Modules/Crm/Business/Distribution/Lead/LeastBusy.php b/application/Espo/Modules/Crm/Business/Distribution/Lead/LeastBusy.php index 2a43809e5b..4a09d88308 100644 --- a/application/Espo/Modules/Crm/Business/Distribution/Lead/LeastBusy.php +++ b/application/Espo/Modules/Crm/Business/Distribution/Lead/LeastBusy.php @@ -29,11 +29,19 @@ namespace Espo\Modules\Crm\Business\Distribution\Lead; +use Espo\ORM\EntityManager; + +use Espo\Entities\User; +use Espo\Entities\Team; + class LeastBusy { + /** + * @var EntityManager + */ protected $entityManager; - public function __construct($entityManager) + public function __construct(EntityManager $entityManager) { $this->entityManager = $entityManager; } @@ -43,39 +51,52 @@ class LeastBusy return $this->entityManager; } + /** + * @param Team $team + * @param ?string $targetUserPosition + * @return User|null + */ public function getUser($team, $targetUserPosition = null) { - $params = array(); + $params = []; + if (!empty($targetUserPosition)) { - $params['additionalColumnsConditions'] = array( + $params['additionalColumnsConditions'] = [ 'role' => $targetUserPosition - ); + ]; } $userList = $team->get('users', $params); if (count($userList) == 0) { - return false; + return null; } - $countHash = array(); + $countHash = []; foreach ($userList as $user) { - $where = array( + $where = [ 'assignedUserId' => $user->id, 'status<>' => ['Converted', 'Recycled', 'Dead'] - ); - $count = $this->getEntityManager()->getRepository('Lead')->where($where)->count(); - $countHash[$user->id] = $count; + ]; + + $count = $this->entityManager + ->getRDBRepository('Lead') + ->where($where) + ->count(); + + $countHash[$user->getId()] = $count; } $foundUserId = false; $min = false; + foreach ($countHash as $userId => $count) { if ($min === false) { $min = $count; $foundUserId = $userId; - } else { + } + else { if ($count < $min) { $min = $count; $foundUserId = $userId; @@ -84,8 +105,10 @@ class LeastBusy } if ($foundUserId !== false) { - return $this->getEntityManager()->getEntity('User', $foundUserId); + return $this->entityManager->getEntity('User', $foundUserId); } + + return null; } } diff --git a/application/Espo/Modules/Crm/Business/Distribution/Lead/RoundRobin.php b/application/Espo/Modules/Crm/Business/Distribution/Lead/RoundRobin.php index 5e40683e3d..b521e735f1 100644 --- a/application/Espo/Modules/Crm/Business/Distribution/Lead/RoundRobin.php +++ b/application/Espo/Modules/Crm/Business/Distribution/Lead/RoundRobin.php @@ -29,49 +29,64 @@ namespace Espo\Modules\Crm\Business\Distribution\Lead; +use Espo\ORM\EntityManager; + +use Espo\Entities\User; +use Espo\Entities\Team; + class RoundRobin { + /** + * @var EntityManager + */ protected $entityManager; - public function __construct($entityManager) + public function __construct(EntityManager $entityManager) { $this->entityManager = $entityManager; } - protected function getEntityManager() - { - return $this->entityManager; - } - + /** + * @param Team $team + * @param ?string $targetUserPosition + * @return User|null + */ public function getUser($team, $targetUserPosition = null) { - $params = array(); + $params = []; + if (!empty($targetUserPosition)) { - $params['additionalColumnsConditions'] = array( + $params['additionalColumnsConditions'] = [ 'role' => $targetUserPosition - ); + ]; } $userList = $team->get('users', $params); if (count($userList) == 0) { - return false; + return null; } - $userIdList = array(); + $userIdList = []; foreach ($userList as $user) { - $userIdList[] = $user->id; + $userIdList[] = $user->getId(); } - $lead = $this->getEntityManager()->getRepository('Lead')->where(array( - 'assignedUserId' => $userIdList - ))->order('createdAt', 'DESC')->findOne(); + $lead = $this->entityManager + ->getRDBRepository('Lead') + ->where([ + 'assignedUserId' => $userIdList + ]) + ->order('createdAt', 'DESC') + ->findOne(); if (empty($lead)) { $num = 0; - } else { + } + else { $num = array_search($lead->get('assignedUserId'), $userIdList); + if ($num === false || $num == count($userIdList) - 1) { $num = 0; } else { @@ -79,7 +94,6 @@ class RoundRobin } } - return $this->getEntityManager()->getEntity('User', $userIdList[$num]); + return $this->entityManager->getEntity('User', $userIdList[$num]); } } - diff --git a/application/Espo/Modules/Crm/Business/Reminder/EmailReminder.php b/application/Espo/Modules/Crm/Business/Reminder/EmailReminder.php index 73b5c28e73..2f91f0e7a1 100644 --- a/application/Espo/Modules/Crm/Business/Reminder/EmailReminder.php +++ b/application/Espo/Modules/Crm/Business/Reminder/EmailReminder.php @@ -30,6 +30,7 @@ namespace Espo\Modules\Crm\Business\Reminder; use Espo\ORM\Entity; +use Espo\Core\ORM\Entity as CoreEntity; use Espo\Core\Utils\Util; @@ -44,18 +45,34 @@ use Espo\Core\{ class EmailReminder { + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var EmailSender + */ protected $emailSender; + /** + * @var Config + */ protected $config; - protected $dateTime; - + /** + * @var TemplateFileManager + */ protected $templateFileManager; + /** + * @var Language + */ protected $language; + /** + * @var HtmlizerFactory + */ protected $htmlizerFactory; public function __construct( @@ -89,6 +106,10 @@ class EmailReminder return; } + if (!$entity instanceof CoreEntity) { + return; + } + if ($entity->hasLinkMultipleField('users')) { $entity->loadLinkMultipleField('users', ['status' => 'acceptanceStatus']); $status = $entity->getLinkMultipleColumn('users', 'status', $user->getId()); diff --git a/application/Espo/Modules/Crm/Hooks/Account/Contacts.php b/application/Espo/Modules/Crm/Hooks/Account/Contacts.php index 1e7bf0d972..5fdeaec216 100644 --- a/application/Espo/Modules/Crm/Hooks/Account/Contacts.php +++ b/application/Espo/Modules/Crm/Hooks/Account/Contacts.php @@ -36,6 +36,9 @@ use Espo\ORM\{ class Contacts { + /** + * @var EntityManager + */ protected $entityManager; public function __construct(EntityManager $entityManager) diff --git a/application/Espo/Modules/Crm/Jobs/ControlKnowledgeBaseArticleStatus.php b/application/Espo/Modules/Crm/Jobs/ControlKnowledgeBaseArticleStatus.php index 6b075313dd..bbcb6a024d 100644 --- a/application/Espo/Modules/Crm/Jobs/ControlKnowledgeBaseArticleStatus.php +++ b/application/Espo/Modules/Crm/Jobs/ControlKnowledgeBaseArticleStatus.php @@ -29,6 +29,9 @@ use Espo\Core\{ class ControlKnowledgeBaseArticleStatus implements JobDataLess { + /** + * @var EntityManager + */ protected $entityManager; public function __construct(EntityManager $entityManager) @@ -39,7 +42,7 @@ class ControlKnowledgeBaseArticleStatus implements JobDataLess public function run(): void { $list = $this->entityManager - ->getRepository('KnowledgeBaseArticle') + ->getRDBRepository('KnowledgeBaseArticle') ->where([ 'expirationDate<=' => date('Y-m-d'), 'status' => 'Published', diff --git a/application/Espo/Modules/Crm/Repositories/TargetList.php b/application/Espo/Modules/Crm/Repositories/TargetList.php index 8ecd8a7cfb..372990ba13 100644 --- a/application/Espo/Modules/Crm/Repositories/TargetList.php +++ b/application/Espo/Modules/Crm/Repositories/TargetList.php @@ -33,18 +33,19 @@ use Espo\ORM\Entity; class TargetList extends \Espo\Core\Repositories\Database { - protected $entityTypeLinkMap = array( + protected $entityTypeLinkMap = [ 'Lead' => 'leads', 'Account' => 'accounts', 'Contact' => 'contacts', 'User' => 'users', - ); + ]; public function relateTarget(Entity $entity, Entity $target, $data = null) { if (empty($this->entityTypeLinkMap[$target->getEntityType()])) { return; } + $relation = $this->entityTypeLinkMap[$target->getEntityType()]; $this->relate($entity, $relation, $target, $data); diff --git a/application/Espo/Modules/Crm/Tools/MassEmail/Queue.php b/application/Espo/Modules/Crm/Tools/MassEmail/Queue.php index bc6c25aa4f..acc9d3992a 100644 --- a/application/Espo/Modules/Crm/Tools/MassEmail/Queue.php +++ b/application/Espo/Modules/Crm/Tools/MassEmail/Queue.php @@ -32,15 +32,14 @@ namespace Espo\Modules\Crm\Tools\MassEmail; use Espo\Repositories\EmailAddress as EmailAddressRepository; use Espo\Entities\EmailAddress; +use Espo\Modules\Crm\Entities\TargetList; +use Espo\Modules\Crm\Entities\MassEmail; + use Espo\Core\{ Exceptions\Error, ORM\EntityManager, }; -use Espo\{ - ORM\Entity, -}; - class Queue { protected $targetsLinkList = [ @@ -50,6 +49,9 @@ class Queue 'users', ]; + /** + * @var EntityManager + */ protected $entityManager; public function __construct(EntityManager $entityManager) @@ -57,7 +59,7 @@ class Queue $this->entityManager = $entityManager; } - protected function cleanupQueueItems(Entity $massEmail): void + protected function cleanupQueueItems(MassEmail $massEmail): void { $delete = $this->entityManager ->getQueryBuilder() @@ -72,7 +74,7 @@ class Queue $this->entityManager->getQueryExecutor()->execute($delete); } - public function create(Entity $massEmail, bool $isTest = false, iterable $additionalTargetList = []): void + public function create(MassEmail $massEmail, bool $isTest = false, iterable $additionalTargetList = []): void { if (!$isTest && $massEmail->get('status') !== 'Pending') { throw new Error("Mass Email '" . $massEmail->getId() . "' should be 'Pending'."); @@ -90,19 +92,20 @@ class Queue if (!$isTest) { $excludingTargetListList = $this->entityManager - ->getRDBRepository('MassEmail') - ->getRelation($massEmail, 'excludingTargetLists') - ->find(); + ->getRDBRepository('MassEmail') + ->getRelation($massEmail, 'excludingTargetLists') + ->find(); foreach ($excludingTargetListList as $excludingTargetList) { foreach ($this->targetsLinkList as $link) { - $excludingList = $em->getRepository('TargetList')->findRelated( - $excludingTargetList, - $link, - [ - 'select' => ['id', 'emailAddress'], - ] - ); + $excludingList = $em->getRDBRepository('TargetList') + ->findRelated( + $excludingTargetList, + $link, + [ + 'select' => ['id', 'emailAddress'], + ] + ); foreach ($excludingList as $excludingTarget) { $hashId = $excludingTarget->getEntityType() . '-'. $excludingTarget->getId(); @@ -118,6 +121,7 @@ class Queue } } + /** @var iterable */ $targetListCollection = $em ->getRDBRepository('MassEmail') ->getRelation($massEmail, 'targetLists') @@ -217,6 +221,7 @@ class Queue private function getEmailAddressRepository(): EmailAddressRepository { + /** @var EmailAddressRepository */ return $this->entityManager->getRepository(EmailAddress::ENTITY_TYPE); } } From 33e29e20a25d111c7eeddbff74bd84da1513bd74 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 10 Nov 2021 16:53:15 +0200 Subject: [PATCH 06/12] type fixes --- .../Espo/Core/Controllers/RecordBase.php | 7 +++- .../Core/ExternalAccount/ClientManager.php | 9 ++++++ .../Actions/MassConvertCurrency.php | 25 +++++++++++++-- .../Core/MassAction/Actions/MassDelete.php | 9 ++++++ .../Actions/MassRecalculateFormula.php | 17 +++++++--- .../Core/MassAction/Actions/MassUpdate.php | 12 +++++++ .../DefaultAssignmentNotificator.php | 9 ++++++ .../Espo/Core/ORM/RepositoryFactory.php | 9 ++++++ application/Espo/Core/Password/Recovery.php | 32 +++++++++++++++---- .../Select/Where/ItemGeneralConverter.php | 27 ++++++++++++++++ .../Espo/Tools/Export/Processors/Xlsx.php | 21 ++++++++++++ .../Espo/Tools/LeadCapture/LeadCapture.php | 3 ++ 12 files changed, 165 insertions(+), 15 deletions(-) diff --git a/application/Espo/Core/Controllers/RecordBase.php b/application/Espo/Core/Controllers/RecordBase.php index 58743dcfab..1ee484b3b2 100644 --- a/application/Espo/Core/Controllers/RecordBase.php +++ b/application/Espo/Core/Controllers/RecordBase.php @@ -96,6 +96,9 @@ class RecordBase extends Base implements Di\EntityManagerAware, Di\InjectableFac */ protected $recordServiceContainer; + /** + * @var Config + */ protected $config; /** @@ -103,11 +106,13 @@ class RecordBase extends Base implements Di\EntityManagerAware, Di\InjectableFac */ protected $user; + /** + * @var Acl + */ protected $acl; /** * @deprecated - * * @var EntityManager */ protected $entityManager; diff --git a/application/Espo/Core/ExternalAccount/ClientManager.php b/application/Espo/Core/ExternalAccount/ClientManager.php index 1b22d0e066..1c8ad151f3 100644 --- a/application/Espo/Core/ExternalAccount/ClientManager.php +++ b/application/Espo/Core/ExternalAccount/ClientManager.php @@ -52,10 +52,19 @@ class ClientManager */ protected $entityManager; + /** + * @var Metadata + */ protected $metadata; + /** + * @var Config + */ protected $config; + /** + * @var InjectableFactory|null + */ protected $injectableFactory = null; protected $clientMap = []; diff --git a/application/Espo/Core/MassAction/Actions/MassConvertCurrency.php b/application/Espo/Core/MassAction/Actions/MassConvertCurrency.php index 91341ce7cc..beabc57cfc 100644 --- a/application/Espo/Core/MassAction/Actions/MassConvertCurrency.php +++ b/application/Espo/Core/MassAction/Actions/MassConvertCurrency.php @@ -53,18 +53,39 @@ use Espo\{ class MassConvertCurrency implements MassAction { + /** + * @var QueryBuilder + */ protected $queryBuilder; + /** + * @var Acl + */ protected $acl; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var FieldUtil + */ protected $fieldUtil; + /** + * @var Metadata + */ protected $metadata; + /** + * @var CurrencyConfigDataProvider + */ protected $configDataProvider; + /** + * @var CurrencyConverter + */ protected $currencyConverter; public function __construct( @@ -128,7 +149,7 @@ class MassConvertCurrency implements MassAction $query = $this->queryBuilder->build($params); $collection = $this->entityManager - ->getRepository($entityType) + ->getRDBRepository($entityType) ->clone($query) ->sth() ->find(); @@ -144,7 +165,7 @@ class MassConvertCurrency implements MassAction $this->convertEntity($entity, $fieldList, $targetCurrency, $rates); - $ids[] = $entity->id; + $ids[] = $entity->getId(); $count++; } diff --git a/application/Espo/Core/MassAction/Actions/MassDelete.php b/application/Espo/Core/MassAction/Actions/MassDelete.php index 30bfab825a..2311384a0b 100644 --- a/application/Espo/Core/MassAction/Actions/MassDelete.php +++ b/application/Espo/Core/MassAction/Actions/MassDelete.php @@ -43,10 +43,19 @@ use Espo\Core\{ class MassDelete implements MassAction { + /** + * @var QueryBuilder + */ protected $queryBuilder; + /** + * @var Acl + */ protected $acl; + /** + * @var RecordServiceContainer + */ protected $recordServiceContainer; /** diff --git a/application/Espo/Core/MassAction/Actions/MassRecalculateFormula.php b/application/Espo/Core/MassAction/Actions/MassRecalculateFormula.php index 97cb8dd430..d40df51c96 100644 --- a/application/Espo/Core/MassAction/Actions/MassRecalculateFormula.php +++ b/application/Espo/Core/MassAction/Actions/MassRecalculateFormula.php @@ -39,16 +39,23 @@ use Espo\Core\{ Exceptions\Forbidden, }; -use Espo\{ - Entities\User, -}; +use Espo\Entities\User; class MassRecalculateFormula implements MassAction { + /** + * @var QueryBuilder + */ protected $queryBuilder; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var User + */ protected $user; public function __construct( @@ -72,7 +79,7 @@ class MassRecalculateFormula implements MassAction $query = $this->queryBuilder->build($params); $collection = $this->entityManager - ->getRepository($entityType) + ->getRDBRepository($entityType) ->clone($query) ->sth() ->find(); @@ -84,7 +91,7 @@ class MassRecalculateFormula implements MassAction foreach ($collection as $entity) { $this->entityManager->saveEntity($entity); - $ids[] = $entity->id; + $ids[] = $entity->getId(); $count++; } diff --git a/application/Espo/Core/MassAction/Actions/MassUpdate.php b/application/Espo/Core/MassAction/Actions/MassUpdate.php index 660170c32f..9cb8569239 100644 --- a/application/Espo/Core/MassAction/Actions/MassUpdate.php +++ b/application/Espo/Core/MassAction/Actions/MassUpdate.php @@ -50,10 +50,19 @@ use stdClass; class MassUpdate implements MassAction { + /** + * @var QueryBuilder + */ protected $queryBuilder; + /** + * @var Acl + */ protected $acl; + /** + * @var RecordServiceContainer + */ protected $recordServiceContainer; /** @@ -61,6 +70,9 @@ class MassUpdate implements MassAction */ protected $entityManager; + /** + * @var FieldUtil + */ protected $fieldUtil; public function __construct( diff --git a/application/Espo/Core/Notification/DefaultAssignmentNotificator.php b/application/Espo/Core/Notification/DefaultAssignmentNotificator.php index 7cebb84d50..6e8cb324e5 100644 --- a/application/Espo/Core/Notification/DefaultAssignmentNotificator.php +++ b/application/Espo/Core/Notification/DefaultAssignmentNotificator.php @@ -41,10 +41,19 @@ use Espo\Core\Notification\AssignmentNotificator\Params; class DefaultAssignmentNotificator implements AssignmentNotificator { + /** + * @var User + */ protected $user; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var UserEnabledChecker + */ protected $userChecker; public function __construct(User $user, EntityManager $entityManager, UserEnabledChecker $userChecker) diff --git a/application/Espo/Core/ORM/RepositoryFactory.php b/application/Espo/Core/ORM/RepositoryFactory.php index 1e59a09299..c99e7c403e 100644 --- a/application/Espo/Core/ORM/RepositoryFactory.php +++ b/application/Espo/Core/ORM/RepositoryFactory.php @@ -48,10 +48,19 @@ class RepositoryFactory implements RepositoryFactoryInterface { protected $defaultClassName = DatabaseRepository::class; + /** + * @var EntityFactoryInteface + */ protected $entityFactory; + /** + * @var InjectableFactory + */ protected $injectableFactory; + /** + * @var ClassFinder + */ protected $classFinder; public function __construct( diff --git a/application/Espo/Core/Password/Recovery.php b/application/Espo/Core/Password/Recovery.php index 753b3c9677..d22e957233 100644 --- a/application/Espo/Core/Password/Recovery.php +++ b/application/Espo/Core/Password/Recovery.php @@ -58,16 +58,34 @@ class Recovery const REQUEST_LIFETIME = '3 hours'; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var Config + */ protected $config; + /** + * @var EmailSender + */ protected $emailSender; + /** + * @var HtmlizerFactory + */ protected $htmlizerFactory; + /** + * @var TemplateFileManager + */ protected $templateFileManager; + /** + * @var Log + */ private $log; public function __construct( @@ -96,7 +114,7 @@ class Recovery } $request = $em - ->getRepository('PasswordChangeRequest') + ->getRDBRepository('PasswordChangeRequest') ->where([ 'requestId' => $id, ]) @@ -119,7 +137,7 @@ class Recovery $em = $this->entityManager; $request = $em - ->getRepository('PasswordChangeRequest') + ->getRDBRepository('PasswordChangeRequest') ->where([ 'requestId' => $id, ]) @@ -142,7 +160,7 @@ class Recovery } $user = $em - ->getRepository('User') + ->getRDBRepository('User') ->where([ 'userName' => $userName, 'emailAddress' => $emailAddress, @@ -196,9 +214,9 @@ class Recovery } $passwordChangeRequest = $em - ->getRepository('PasswordChangeRequest') + ->getRDBRepository('PasswordChangeRequest') ->where([ - 'userId' => $user->id, + 'userId' => $user->getId(), ]) ->findOne(); @@ -293,12 +311,12 @@ class Recovery $siteUrl = $config->getSiteUrl(); if ($user->isPortal()) { - $portal = $em->getRepository('Portal') + $portal = $em->getRDBRepository('Portal') ->distinct() ->join('users') ->where([ 'isActive' => true, - 'users.id' => $user->id, + 'users.id' => $user->getId(), ]) ->findOne(); diff --git a/application/Espo/Core/Select/Where/ItemGeneralConverter.php b/application/Espo/Core/Select/Where/ItemGeneralConverter.php index c1b29af5cc..7b215ade7a 100644 --- a/application/Espo/Core/Select/Where/ItemGeneralConverter.php +++ b/application/Espo/Core/Select/Where/ItemGeneralConverter.php @@ -53,22 +53,49 @@ class ItemGeneralConverter implements ItemConverter { protected $entityType; + /** + * @var User + */ protected $user; + /** + * @var DateTimeItemTransformer + */ protected $dateTimeItemTransformer; + /** + * @var Scanner + */ protected $scanner; + /** + * @var ItemConverterFactory + */ protected $itemConverterFactory; + /** + * @var RandomStringGenerator + */ protected $randomStringGenerator; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var ORMDefs + */ protected $ormDefs; + /** + * @var Config + */ protected $config; + /** + * @var Metadata + */ protected $metadata; public function __construct( diff --git a/application/Espo/Tools/Export/Processors/Xlsx.php b/application/Espo/Tools/Export/Processors/Xlsx.php index 9eb5e4274e..c0c1618752 100644 --- a/application/Espo/Tools/Export/Processors/Xlsx.php +++ b/application/Espo/Tools/Export/Processors/Xlsx.php @@ -70,18 +70,39 @@ use RuntimeException; */ class Xlsx implements Processor { + /** + * @var Config + */ protected $config; + /** + * @var Metadata + */ protected $metadata; + /** + * @var Language + */ protected $language; + /** + * @var DateTimeUtil + */ protected $dateTime; + /** + * @var EntityManager + */ protected $entityManager; + /** + * @var FileStorageManager + */ protected $fileStorageManager; + /** + * @var AddressFormatterFactory + */ protected $addressFormatterFactory; public function __construct( diff --git a/application/Espo/Tools/LeadCapture/LeadCapture.php b/application/Espo/Tools/LeadCapture/LeadCapture.php index d7a1d69558..90c5ff9eaa 100644 --- a/application/Espo/Tools/LeadCapture/LeadCapture.php +++ b/application/Espo/Tools/LeadCapture/LeadCapture.php @@ -87,10 +87,13 @@ class LeadCapture /** @var Log */ protected $log; + /** @var CampaignService */ private $campaignService; + /** @var EmailTemplateService */ private $emailTemplateService; + /** @var InboundEmailService */ private $inboundEmailService; public function __construct( From 3e0a8f0af18078a8bc56b4186cbdece914291387 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 11 Nov 2021 11:40:11 +0200 Subject: [PATCH 07/12] fix --- .../Espo/Core/Select/Where/Converter.php | 22 ++++++++----------- .../Select/Where/DateTimeItemTransformer.php | 3 +++ .../Espo/Core/Select/Where/ConverterTest.php | 1 - 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/application/Espo/Core/Select/Where/Converter.php b/application/Espo/Core/Select/Where/Converter.php index bbc72239f7..1a7a3591e6 100644 --- a/application/Espo/Core/Select/Where/Converter.php +++ b/application/Espo/Core/Select/Where/Converter.php @@ -45,28 +45,24 @@ use Espo\{ */ class Converter { - protected $entityType; + private $entityType; - protected $user; + private $itemConverter; - protected $itemConverter; + private $scanner; - protected $scanner; + private $randomStringGenerator; - protected $randomStringGenerator; - - protected $ormDefs; + private $ormDefs; public function __construct( string $entityType, - User $user, ItemConverter $itemConverter, Scanner $scanner, RandomStringGenerator $randomStringGenerator, ORMDefs $ormDefs ) { $this->entityType = $entityType; - $this->user = $user; $this->itemConverter = $itemConverter; $this->scanner = $scanner; $this->randomStringGenerator = $randomStringGenerator; @@ -94,7 +90,7 @@ class Converter return WhereClause::fromRaw($whereClause); } - protected function itemToList(Item $item): array + private function itemToList(Item $item): array { if ($item->getType() !== 'and') { return [ @@ -111,7 +107,7 @@ class Converter return $list; } - protected function processItem(QueryBuilder $queryBuilder, Item $item): ?array + private function processItem(QueryBuilder $queryBuilder, Item $item): ?array { $type = $item->getType(); $attribute = $item->getAttribute(); @@ -136,7 +132,7 @@ class Converter return $this->itemConverter->convert($queryBuilder, $item)->getRaw(); } - protected function applyInCategory(QueryBuilder $queryBuilder, string $attribute, $value): array + private function applyInCategory(QueryBuilder $queryBuilder, string $attribute, $value): array { $link = $attribute; @@ -197,7 +193,7 @@ class Converter throw new Error("Not supported link '{$link}' in where item."); } - protected function applyIsUserFromTeams(QueryBuilder $queryBuilder, string $attribute, $value): array + private function applyIsUserFromTeams(QueryBuilder $queryBuilder, string $attribute, $value): array { $link = $attribute; diff --git a/application/Espo/Core/Select/Where/DateTimeItemTransformer.php b/application/Espo/Core/Select/Where/DateTimeItemTransformer.php index 3c7b27233b..f3a65fb782 100644 --- a/application/Espo/Core/Select/Where/DateTimeItemTransformer.php +++ b/application/Espo/Core/Select/Where/DateTimeItemTransformer.php @@ -43,6 +43,9 @@ use DateInterval; */ class DateTimeItemTransformer { + /** + * @var User + */ protected $user; private $config; diff --git a/tests/unit/Espo/Core/Select/Where/ConverterTest.php b/tests/unit/Espo/Core/Select/Where/ConverterTest.php index 5262cb2948..0ee9623213 100644 --- a/tests/unit/Espo/Core/Select/Where/ConverterTest.php +++ b/tests/unit/Espo/Core/Select/Where/ConverterTest.php @@ -114,7 +114,6 @@ class ConverterTest extends \PHPUnit\Framework\TestCase $this->converter = new Converter( $this->entityType, - $this->user, $this->itemConverter, $this->scanner, $this->randomStringGenerator, From 42d4de77ae23f864533faa9c6eac92d0c865f4ca Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 11 Nov 2021 12:17:05 +0200 Subject: [PATCH 08/12] cs fix --- .../views/mass-email/fields/smtp-account.js | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/client/modules/crm/src/views/mass-email/fields/smtp-account.js b/client/modules/crm/src/views/mass-email/fields/smtp-account.js index 5f27769916..0abc8b8839 100644 --- a/client/modules/crm/src/views/mass-email/fields/smtp-account.js +++ b/client/modules/crm/src/views/mass-email/fields/smtp-account.js @@ -56,20 +56,26 @@ define('crm:views/mass-email/fields/smtp-account', 'views/fields/enum', function if (!this.loadedOptionList) { if (this.model.get('inboundEmailId')) { var item = 'inboundEmail:' + this.model.get('inboundEmailId'); + this.params.options.push(item); + this.translatedOptions[item] = - (this.model.get('inboundEmailName') || this.model.get('inboundEmailId')) + ' (' + this.translate('group', 'labels', 'MassEmail') + ')'; + (this.model.get('inboundEmailName') || this.model.get('inboundEmailId')) + + ' (' + this.translate('group', 'labels', 'MassEmail') + ')'; } } else { - this.loadedOptionList.forEach(function (item) { + this.loadedOptionList.forEach((item) => { this.params.options.push(item); + this.translatedOptions[item] = - (this.loadedOptionTranslations[item] || item) + ' (' + this.translate('group', 'labels', 'MassEmail') + ')'; - }, this); + (this.loadedOptionTranslations[item] || item) + + ' (' + this.translate('group', 'labels', 'MassEmail') + ')'; + }); } this.translatedOptions['system'] = - this.getConfig().get('outboundEmailFromAddress') + ' (' + this.translate('system', 'labels', 'MassEmail') + ')'; + this.getConfig().get('outboundEmailFromAddress') + + ' (' + this.translate('system', 'labels', 'MassEmail') + ')'; }, getValueForDisplay: function () { @@ -91,35 +97,49 @@ define('crm:views/mass-email/fields/smtp-account', 'views/fields/enum', function setup: function () { Dep.prototype.setup.call(this); - if (this.getAcl().checkScope('MassEmail', 'create') || this.getAcl().checkScope('MassEmail', 'edit')) { - this.ajaxGetRequest(this.dataUrl).then(function (dataList) { - if (!dataList.length) return; + if ( + this.getAcl().checkScope('MassEmail', 'create') || + this.getAcl().checkScope('MassEmail', 'edit') + ) { + + this.ajaxGetRequest(this.dataUrl).then(dataList => { + if (!dataList.length) { + return; + } + this.loadedOptionList = []; + this.loadedOptionTranslations = {}; this.loadedOptionAddresses = {}; this.loadedOptionFromNames = {}; - dataList.forEach(function (item) { + + dataList.forEach(item => { this.loadedOptionList.push(item.key); + this.loadedOptionTranslations[item.key] = item.emailAddress; this.loadedOptionAddresses[item.key] = item.emailAddress; this.loadedOptionFromNames[item.key] = item.fromName || ''; - }, this); + }); + this.setupOptions(); this.reRender(); - }.bind(this)); + }); } }, fetch: function () { var data = {}; var value = this.$element.val(); + data[this.name] = value; if (!value || value === 'system') { data.inboundEmailId = null; data.inboundEmailName = null; - } else { + } + else { var arr = value.split(':'); + if (arr.length > 1) { data.inboundEmailId = arr[1]; data.inboundEmailName = this.translatedOptions[data.inboundEmailId] || data.inboundEmailId; From 4bedaef9a87e4e30d8f435dec98e16480b2431c6 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 11 Nov 2021 12:17:21 +0200 Subject: [PATCH 09/12] fixes --- .../Applier/Appliers/AccessControlFilter.php | 34 +++++++++++++++++-- .../Applier/Appliers/BoolFilterList.php | 18 ++++++++-- .../Core/Select/Applier/Appliers/Order.php | 19 +++++++---- .../Select/Applier/Appliers/PrimaryFilter.php | 16 ++++++++- .../Core/Select/Applier/Appliers/Select.php | 9 +++++ .../Select/Applier/Appliers/TextFilter.php | 12 +++++++ .../Core/Select/Applier/Appliers/Where.php | 9 +++++ .../Text/FullTextSearchDataComposer.php | 6 ++++ 8 files changed, 111 insertions(+), 12 deletions(-) diff --git a/application/Espo/Core/Select/Applier/Appliers/AccessControlFilter.php b/application/Espo/Core/Select/Applier/Appliers/AccessControlFilter.php index ef3f38d302..61152a8fc2 100644 --- a/application/Espo/Core/Select/Applier/Appliers/AccessControlFilter.php +++ b/application/Espo/Core/Select/Applier/Appliers/AccessControlFilter.php @@ -29,9 +29,13 @@ namespace Espo\Core\Select\Applier\Appliers; +use Espo\Core\Acl; +use Espo\Core\AclManager; + +use Espo\Core\Select\OrmSelectBuilder; + use Espo\Core\{ Exceptions\Error, - AclManager, Select\SelectManager, Select\AccessControl\FilterFactory as AccessControlFilterFactory, Select\AccessControl\FilterResolverFactory as AccessControlFilterResolverFactory, @@ -44,18 +48,36 @@ use Espo\{ class AccessControlFilter { + /** + * @var Acl + */ protected $acl; protected $entityType; + /** + * @var User + */ protected $user; + /** + * @var AccessControlFilterFactory + */ protected $accessControlFilterFactory; + /** + * @var AccessControlFilterResolverFactory + */ protected $accessControlFilterResolverFactory; + /** + * @var AclManager + */ protected $aclManager; + /** + * @var SelectManager + */ protected $selectManager; public function __construct( @@ -79,7 +101,10 @@ class AccessControlFilter public function apply(QueryBuilder $queryBuilder): void { // For backward compatibility. - if ($this->selectManager->hasInheritedAccessMethod()) { + if ( + $this->selectManager->hasInheritedAccessMethod() && + $queryBuilder instanceof OrmSelectBuilder + ) { $this->selectManager->applyAccessToQueryBuilder($queryBuilder); return; @@ -97,7 +122,10 @@ class AccessControlFilter } // For backward compatibility. - if ($this->selectManager->hasInheritedAccessFilterMethod($filterName)) { + if ( + $this->selectManager->hasInheritedAccessFilterMethod($filterName) && + $queryBuilder instanceof OrmSelectBuilder + ) { $this->selectManager->applyAccessFilterToQueryBuilder($queryBuilder, $filterName); return; diff --git a/application/Espo/Core/Select/Applier/Appliers/BoolFilterList.php b/application/Espo/Core/Select/Applier/Appliers/BoolFilterList.php index 17612d4c03..128197ae8e 100644 --- a/application/Espo/Core/Select/Applier/Appliers/BoolFilterList.php +++ b/application/Espo/Core/Select/Applier/Appliers/BoolFilterList.php @@ -29,6 +29,8 @@ namespace Espo\Core\Select\Applier\Appliers; +use Espo\Core\Select\OrmSelectBuilder; + use Espo\Core\{ Exceptions\Error, Select\SelectManager, @@ -46,10 +48,19 @@ class BoolFilterList { protected $entityType; + /** + * @var User + */ protected $user; + /** + * @var SelectManager + */ protected $selectManager; + /** + * @var BoolFilterFactory + */ protected $boolFilterFactory; public function __construct( @@ -86,13 +97,16 @@ class BoolFilterList if ($this->boolFilterFactory->has($this->entityType, $filterName)) { $filter = $this->boolFilterFactory->create($this->entityType, $this->user, $filterName); - $whereItem = $filter->apply($queryBuilder, $orGroupBuilder); + $filter->apply($queryBuilder, $orGroupBuilder); return; } // For backward compatibility. - if ($this->selectManager->hasBoolFilter($filterName)) { + if ( + $this->selectManager->hasBoolFilter($filterName) && + $queryBuilder instanceof OrmSelectBuilder + ) { $rawWhereClause = $this->selectManager->applyBoolFilterToQueryBuilder($queryBuilder, $filterName); $whereItem = WhereClause::fromRaw($rawWhereClause); diff --git a/application/Espo/Core/Select/Applier/Appliers/Order.php b/application/Espo/Core/Select/Applier/Appliers/Order.php index 94cd11323e..2608c75e48 100644 --- a/application/Espo/Core/Select/Applier/Appliers/Order.php +++ b/application/Espo/Core/Select/Applier/Appliers/Order.php @@ -50,10 +50,19 @@ class Order { protected $entityType; + /** + * @var User + */ protected $user; + /** + * @var MetadataProvider + */ protected $metadataProvider; + /** + * @var ItemConverterFactory + */ protected $itemConverterFactory; public function __construct( @@ -80,10 +89,8 @@ class Order if ($params->forbidComplexExpressions() && $orderBy) { if ( - !is_string($orderBy) - || - strpos($orderBy, '.') !== false - || + !is_string($orderBy) || + strpos($orderBy, '.') !== false || strpos($orderBy, ':') !== false ) { throw new Forbidden("Complex expressions are forbidden in 'orderBy'."); @@ -112,10 +119,10 @@ class Order if (!$order) { $order = $this->metadataProvider->getDefaultOrder($this->entityType); - if ($order === true || strtolower($order) === 'desc') { + if (strtolower($order) === 'desc') { $order = SearchParams::ORDER_DESC; } - else if ($order === false || strtolower($order) === 'asc') { + else if (strtolower($order) === 'asc') { $order = SearchParams::ORDER_ASC; } else if ($order !== null) { diff --git a/application/Espo/Core/Select/Applier/Appliers/PrimaryFilter.php b/application/Espo/Core/Select/Applier/Appliers/PrimaryFilter.php index a4303a4577..c659827ec5 100644 --- a/application/Espo/Core/Select/Applier/Appliers/PrimaryFilter.php +++ b/application/Espo/Core/Select/Applier/Appliers/PrimaryFilter.php @@ -29,6 +29,8 @@ namespace Espo\Core\Select\Applier\Appliers; +use Espo\Core\Select\OrmSelectBuilder; + use Espo\Core\{ Exceptions\Error, Select\SelectManager, @@ -44,10 +46,19 @@ class PrimaryFilter { protected $entityType; + /** + * @var User + */ protected $user; + /** + * @var SelectManager + */ protected $selectManager; + /** + * @var FilterFactory + */ protected $primaryFilterFactory; public function __construct( @@ -73,7 +84,10 @@ class PrimaryFilter } // For backward compatibility. - if ($this->selectManager->hasPrimaryFilter($filterName)) { + if ( + $this->selectManager->hasPrimaryFilter($filterName) && + $queryBuilder instanceof OrmSelectBuilder + ) { $this->selectManager->applyPrimaryFilterToQueryBuilder($queryBuilder, $filterName); return; diff --git a/application/Espo/Core/Select/Applier/Appliers/Select.php b/application/Espo/Core/Select/Applier/Appliers/Select.php index 73a1ecef6e..18b7dd1987 100644 --- a/application/Espo/Core/Select/Applier/Appliers/Select.php +++ b/application/Espo/Core/Select/Applier/Appliers/Select.php @@ -57,10 +57,19 @@ class Select protected $entityType; + /** + * @var User + */ protected $user; + /** + * @var FieldUtil + */ protected $fieldUtil; + /** + * @var MetadataProvider + */ protected $metadataProvider; public function __construct( diff --git a/application/Espo/Core/Select/Applier/Appliers/TextFilter.php b/application/Espo/Core/Select/Applier/Appliers/TextFilter.php index 3c7e63e2e8..7c09028581 100644 --- a/application/Espo/Core/Select/Applier/Appliers/TextFilter.php +++ b/application/Espo/Core/Select/Applier/Appliers/TextFilter.php @@ -61,12 +61,24 @@ class TextFilter private $entityType; + /** + * @var User + */ private $user; + /** + * @var MetadataProvider + */ private $metadataProvider; + /** + * @var FullTextSearchDataComposerFactory + */ private $fullTextSearchDataComposerFactory; + /** + * @var FilterFactory + */ private $filterFactory; public function __construct( diff --git a/application/Espo/Core/Select/Applier/Appliers/Where.php b/application/Espo/Core/Select/Applier/Appliers/Where.php index e53ff75f50..577238edf0 100644 --- a/application/Espo/Core/Select/Applier/Appliers/Where.php +++ b/application/Espo/Core/Select/Applier/Appliers/Where.php @@ -45,10 +45,19 @@ class Where { protected $entityType; + /** + * @var User + */ protected $user; + /** + * @var ConverterFactory + */ protected $converterFactory; + /** + * @var CheckerFactory + */ protected $checkerFactory; public function __construct( diff --git a/application/Espo/Core/Select/Text/FullTextSearchDataComposer.php b/application/Espo/Core/Select/Text/FullTextSearchDataComposer.php index 859221938c..1860740f9f 100644 --- a/application/Espo/Core/Select/Text/FullTextSearchDataComposer.php +++ b/application/Espo/Core/Select/Text/FullTextSearchDataComposer.php @@ -39,8 +39,14 @@ class FullTextSearchDataComposer protected $entityType; + /** + * @var Config + */ protected $config; + /** + * @var MetadataProvider + */ protected $metadataProvider; public function __construct( From 5178c2fbd0fc6ac874df2b7848279b0c752d327b Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 11 Nov 2021 12:47:43 +0200 Subject: [PATCH 10/12] orm pdo refactoring --- .../Espo/Core/ORM/EntityManagerFactory.php | 4 ++ .../Espo/ORM/PDO/DefaultPDOProvider.php | 38 ++-------- application/Espo/ORM/PDO/Options.php | 71 +++++++++++++++++++ 3 files changed, 80 insertions(+), 33 deletions(-) create mode 100644 application/Espo/ORM/PDO/Options.php diff --git a/application/Espo/Core/ORM/EntityManagerFactory.php b/application/Espo/Core/ORM/EntityManagerFactory.php index 4f96cf8e31..047bb497ca 100644 --- a/application/Espo/Core/ORM/EntityManagerFactory.php +++ b/application/Espo/Core/ORM/EntityManagerFactory.php @@ -145,6 +145,10 @@ class EntityManagerFactory ->withSslCipher($config->get('database.sslCipher')) ->withSslVerifyDisabled($config->get('database.sslVerifyDisabled') ?? false); + if (!$databaseParams->getName()) { + throw new RuntimeException('No database name specified.'); + } + if (!$databaseParams->getPlatform()) { $driver = $config->get('database.driver'); diff --git a/application/Espo/ORM/PDO/DefaultPDOProvider.php b/application/Espo/ORM/PDO/DefaultPDOProvider.php index c94b2ae54a..ef144cebf3 100644 --- a/application/Espo/ORM/PDO/DefaultPDOProvider.php +++ b/application/Espo/ORM/PDO/DefaultPDOProvider.php @@ -73,49 +73,21 @@ class DefaultPDOProvider implements PDOProvider throw new RuntimeException("No 'host' parameter."); } - if (!$dbname) { - throw new RuntimeException("No 'dbname' parameter."); - } - - $dsn = - $platform . ':' . - 'host=' . $host; + $dsn = $platform . ':' . 'host=' . $host; if ($port) { $dsn .= ';' . 'port=' . (string) $port; } - $dsn .= ';' . 'dbname=' . $dbname; + if ($dbname) { + $dsn .= ';' . 'dbname=' . $dbname; + } if ($charset) { $dsn .= ';' . 'charset=' . $charset; } - $options = []; - - if ($this->databaseParams->getSslCa()) { - $options[PDO::MYSQL_ATTR_SSL_CA] = $this->databaseParams->getSslCa(); - } - - if ($this->databaseParams->getSslCert()) { - $options[PDO::MYSQL_ATTR_SSL_CERT] = $this->databaseParams->getSslCert(); - } - - if ($this->databaseParams->getSslKey()) { - $options[PDO::MYSQL_ATTR_SSL_KEY] = $this->databaseParams->getSslKey(); - } - - if ($this->databaseParams->getSslCaPath()) { - $options[PDO::MYSQL_ATTR_SSL_CAPATH] = $this->databaseParams->getSslCaPath(); - } - - if ($this->databaseParams->getSslCipher()) { - $options[PDO::MYSQL_ATTR_SSL_CIPHER] = $this->databaseParams->getSslCipher(); - } - - if ($this->databaseParams->isSslVerifyDisabled()) { - $options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false; - } + $options = Options::getOptionsFromDatabaseParams($this->databaseParams); $this->pdo = new PDO($dsn, $username, $password, $options); diff --git a/application/Espo/ORM/PDO/Options.php b/application/Espo/ORM/PDO/Options.php new file mode 100644 index 0000000000..cf8fe56180 --- /dev/null +++ b/application/Espo/ORM/PDO/Options.php @@ -0,0 +1,71 @@ + + */ + public static function getOptionsFromDatabaseParams(DatabaseParams $databaseParams): array + { + $options = []; + + if ($databaseParams->getSslCa()) { + $options[PDO::MYSQL_ATTR_SSL_CA] = $databaseParams->getSslCa(); + } + + if ($databaseParams->getSslCert()) { + $options[PDO::MYSQL_ATTR_SSL_CERT] = $databaseParams->getSslCert(); + } + + if ($databaseParams->getSslKey()) { + $options[PDO::MYSQL_ATTR_SSL_KEY] = $databaseParams->getSslKey(); + } + + if ($databaseParams->getSslCaPath()) { + $options[PDO::MYSQL_ATTR_SSL_CAPATH] = $databaseParams->getSslCaPath(); + } + + if ($databaseParams->getSslCipher()) { + $options[PDO::MYSQL_ATTR_SSL_CIPHER] = $databaseParams->getSslCipher(); + } + + if ($databaseParams->isSslVerifyDisabled()) { + $options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false; + } + + return $options; + } +} From ae056f4a22f26fc9a1667018be37e63e14324376 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 11 Nov 2021 12:49:20 +0200 Subject: [PATCH 11/12] type --- application/Espo/ORM/PDO/DefaultPDOProvider.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application/Espo/ORM/PDO/DefaultPDOProvider.php b/application/Espo/ORM/PDO/DefaultPDOProvider.php index ef144cebf3..cda6937a04 100644 --- a/application/Espo/ORM/PDO/DefaultPDOProvider.php +++ b/application/Espo/ORM/PDO/DefaultPDOProvider.php @@ -38,6 +38,9 @@ class DefaultPDOProvider implements PDOProvider { private $databaseParams; + /** + * @var ?PDO + */ private $pdo = null; public function __construct(DatabaseParams $databaseParams) From db2216adb7b45ceb5b1d540089c6bb012894b27c Mon Sep 17 00:00:00 2001 From: Taras Machyshyn Date: Thu, 11 Nov 2021 15:31:11 +0200 Subject: [PATCH 12/12] Fixed PDO parameters for Dbal connection --- .../Espo/Core/Utils/Database/Helper.php | 172 +++++++++++------- .../Espo/Core/Utils/SystemRequirements.php | 5 +- .../Espo/Core/Utils/Database/HelperTest.php | 10 +- 3 files changed, 116 insertions(+), 71 deletions(-) diff --git a/application/Espo/Core/Utils/Database/Helper.php b/application/Espo/Core/Utils/Database/Helper.php index bb5f5e869d..1acec3adf5 100644 --- a/application/Espo/Core/Utils/Database/Helper.php +++ b/application/Espo/Core/Utils/Database/Helper.php @@ -39,8 +39,15 @@ use Doctrine\DBAL\{ Platforms\AbstractPlatform as DbalPlatform, }; +use Espo\ORM\{ + DatabaseParams, + PDO\DefaultPDOProvider, + PDO\Options as PdoOptions, +}; + use PDO; use ReflectionClass; +use RuntimeException; class Helper { @@ -50,6 +57,11 @@ class Helper private $pdoConnection; + private $driverPlatformMap = [ + 'pdo_mysql' => 'Mysql', + 'mysqli' => 'Mysql', + ]; + protected $dbalDrivers = [ 'mysqli' => 'Doctrine\\DBAL\\Driver\\Mysqli\\Driver', 'pdo_mysql' => 'Espo\\Core\\Utils\\Database\\DBAL\\Driver\\PDO\\MySQL\\Driver', @@ -95,46 +107,57 @@ class Helper $this->pdoConnection = $pdoConnection; } - public function createDbalConnection(array $params = null) + public function createDbalConnection(array $params = []) { - if (!isset($params)) { - $config = $this->config; - - if ($config) { - $params = $config->get('database'); - } + if (empty($params) && isset($this->config)) { + $params = $this->config->get('database'); } - if (empty($params['dbname']) || empty($params['user'])) { - return null; + if (empty($params)) { + throw new RuntimeException('Params cannot be empty for Dbal connection.'); } - $driverName = isset($params['driver']) ? $params['driver'] : 'pdo_mysql'; + $databaseParams = $this->createDatabaseParams($params); - unset($params['driver']); - - if (!isset($this->dbalDrivers[$driverName])) { - throw new Error('Unknown database driver.'); - } - - $driverClass = $this->dbalDrivers[$driverName]; - - if (!class_exists($driverClass)) { - throw new Error('Unknown database class.'); - } - - $driver = new $driverClass(); + $driver = $this->createDbalDriver($params); $version = $this->getFullDatabaseVersion(); $platform = $driver->createDatabasePlatformForVersion($version); - $params['platform'] = $this->createDbalPlatform($platform); - - return new DbalConnection($params, $driver); + return new DbalConnection( + [ + 'platform' => $this->createDbalPlatform($platform), + 'host' => $databaseParams->getHost(), + 'port' => $databaseParams->getPort(), + 'dbname' => $databaseParams->getName(), + 'charset' => $databaseParams->getCharset(), + 'user' => $databaseParams->getUsername(), + 'password' => $databaseParams->getPassword(), + 'driverOptions' => PdoOptions::getOptionsFromDatabaseParams($databaseParams), + ], + $driver + ); } - protected function createDbalPlatform(DbalPlatform $platform) + private function createDbalDriver(array $params) + { + $driverName = $params['driver'] ?? 'pdo_mysql'; + + if (!isset($this->dbalDrivers[$driverName])) { + throw new RuntimeException('Unknown database driver.'); + } + + $driverClass = $this->dbalDrivers[$driverName]; + + if (!class_exists($driverClass)) { + throw new RuntimeException('Unknown database class.'); + } + + return new $driverClass(); + } + + private function createDbalPlatform(DbalPlatform $platform) { $reflect = new ReflectionClass($platform); @@ -155,51 +178,65 @@ class Helper * @param array $params * @return PDO|null */ - public function createPdoConnection(array $params = null) + public function createPdoConnection(array $params = []) { - if (!isset($params)) { - $config = $this->config; + $defaultParams = [ + 'driver' => 'pdo_mysql', + ]; - if ($config) { - $params = $config->get('database'); + if (isset($this->config) && $this->config instanceof Config) { + $defaultParams = array_merge( + $defaultParams, + $this->config->get('database') + ); + } + + $params = array_merge( + $defaultParams, + $params + ); + + $pdoProvider = new DefaultPDOProvider( + $this->createDatabaseParams($params) + ); + + return $pdoProvider->get(); + } + + private function createDatabaseParams(array $params): DatabaseParams + { + $databaseParams = DatabaseParams::create() + ->withHost($params['host'] ?? null) + ->withPort(isset($params['host']) ? (int) $params['host'] : null) + ->withName($params['dbname'] ?? null) + ->withUsername($params['user'] ?? null) + ->withPassword($params['password'] ?? null) + ->withCharset($params['charset'] ?? 'utf8') + ->withPlatform($params['platform'] ?? null) + ->withSslCa($params['sslCA'] ?? null) + ->withSslCert($params['sslCert'] ?? null) + ->withSslKey($params['sslKey'] ?? null) + ->withSslCaPath($params['sslCAPath'] ?? null) + ->withSslCipher($params['sslCipher'] ?? null) + ->withSslVerifyDisabled($params['sslVerifyDisabled'] ?? false); + + if (!$databaseParams->getPlatform()) { + $driver = $params['driver'] ?? null; + + if (!$driver) { + throw new RuntimeException('No database driver specified.'); } + + $platform = $this->driverPlatformMap[$driver] ?? null; + + if (!$platform) { + throw new RuntimeException("Database driver '{$driver}' is not supported."); + } + + $databaseParams = $databaseParams->withPlatform($platform); } - if (empty($params)) { - return null; - } - - $platform = !empty($params['platform']) ? strtolower($params['platform']) : 'mysql'; - $port = empty($params['port']) ? '' : ';port=' . $params['port']; - $dbname = empty($params['dbname']) ? '' : ';dbname=' . $params['dbname']; - - $options = []; - - if (isset($params['sslCA'])) { - $options[PDO::MYSQL_ATTR_SSL_CA] = $params['sslCA']; - } - - if (isset($params['sslCert'])) { - $options[PDO::MYSQL_ATTR_SSL_CERT] = $params['sslCert']; - } - - if (isset($params['sslKey'])) { - $options[PDO::MYSQL_ATTR_SSL_KEY] = $params['sslKey']; - } - - if (isset($params['sslCAPath'])) { - $options[PDO::MYSQL_ATTR_SSL_CAPATH] = $params['sslCAPath']; - } - - if (isset($params['sslCipher'])) { - $options[PDO::MYSQL_ATTR_SSL_CIPHER] = $params['sslCipher']; - } - - $dsn = $platform . ':host='.$params['host'].$port.$dbname; - - $dbh = new PDO($dsn, $params['user'], $params['password'], $options); - - return $dbh; + return $databaseParams; } /** @@ -304,6 +341,7 @@ class Helper protected function getTableEngine($tableName = null, $default = null) { $connection = $this->getPdoConnection(); + if (!$connection) { return $default; } diff --git a/application/Espo/Core/Utils/SystemRequirements.php b/application/Espo/Core/Utils/SystemRequirements.php index 6104a43abd..ee3fab325f 100644 --- a/application/Espo/Core/Utils/SystemRequirements.php +++ b/application/Espo/Core/Utils/SystemRequirements.php @@ -117,7 +117,8 @@ class SystemRequirements $databaseTypeName = 'Mysql'; $databaseHelper = $this->databaseHelper; - $databaseParams = isset($additionalData['database']) ? $additionalData['database'] : null; + $databaseParams = $additionalData['database'] ?? []; + $pdoConnection = $databaseHelper->createPdoConnection($databaseParams); if ($pdoConnection) { @@ -254,7 +255,7 @@ class SystemRequirements $databaseHelper = $this->databaseHelper; - $databaseParams = isset($additionalData['database']) ? $additionalData['database'] : null; + $databaseParams = $additionalData['database'] ?? []; $pdo = $databaseHelper->createPdoConnection($databaseParams); diff --git a/tests/integration/Espo/Core/Utils/Database/HelperTest.php b/tests/integration/Espo/Core/Utils/Database/HelperTest.php index db9b6fe9e8..780c8f4071 100644 --- a/tests/integration/Espo/Core/Utils/Database/HelperTest.php +++ b/tests/integration/Espo/Core/Utils/Database/HelperTest.php @@ -39,6 +39,8 @@ use Espo\Core\Exceptions\Error; use PDO; +use RuntimeException; + class HelperTest extends \tests\integration\Core\BaseTestCase { protected $reflection; @@ -80,7 +82,9 @@ class HelperTest extends \tests\integration\Core\BaseTestCase { $this->initTest(true); - $this->assertNull($this->helper->getDbalConnection()); + $this->expectException(RuntimeException::class); + + $this->helper->getDbalConnection(); } public function testGetDbalConnectionWithConfig() @@ -94,7 +98,9 @@ class HelperTest extends \tests\integration\Core\BaseTestCase { $this->initTest(true); - $this->assertNull($this->helper->getPdoConnection()); + $this->expectException(RuntimeException::class); + + $this->helper->getPdoConnection(); } public function testGetPdoConnectionWithConfig()