diff --git a/application/Espo/Core/Record/Service.php b/application/Espo/Core/Record/Service.php index bfffbc2024..d9164395f9 100644 --- a/application/Espo/Core/Record/Service.php +++ b/application/Espo/Core/Record/Service.php @@ -399,8 +399,8 @@ class Service implements Crud, } /** - * @param stdClass $data * @param TEntity $entity + * @param stdClass $data * @return void * @throws BadRequest */ diff --git a/application/Espo/Modules/Crm/Controllers/TargetList.php b/application/Espo/Modules/Crm/Controllers/TargetList.php index 8d01b6d03d..c597dd0810 100644 --- a/application/Espo/Modules/Crm/Controllers/TargetList.php +++ b/application/Espo/Modules/Crm/Controllers/TargetList.php @@ -36,7 +36,7 @@ use Espo\Core\Controllers\Record; class TargetList extends Record { - public function postActionUnlinkAll(Request $request) + public function postActionUnlinkAll(Request $request): bool { $data = $request->getParsedBody(); @@ -48,10 +48,12 @@ class TargetList extends Record throw new BadRequest(); } - return $this->getTargetListService()->unlinkAll($data->id, $data->link); + $this->getTargetListService()->unlinkAll($data->id, $data->link); + + return true; } - public function postActionOptOut(Request $request) + public function postActionOptOut(Request $request): bool { $data = $request->getParsedBody(); @@ -70,10 +72,12 @@ class TargetList extends Record $data->id = strval($data->id); $data->targetId = strval($data->targetId); - return $this->getTargetListService()->optOut($data->id, $data->targetType, $data->targetId); + $this->getTargetListService()->optOut($data->id, $data->targetType, $data->targetId); + + return true; } - public function postActionCancelOptOut(Request $request) + public function postActionCancelOptOut(Request $request): bool { $data = $request->getParsedBody(); @@ -92,7 +96,9 @@ class TargetList extends Record $data->id = strval($data->id); $data->targetId = strval($data->targetId); - return $this->getTargetListService()->cancelOptOut($data->id, $data->targetType, $data->targetId); + $this->getTargetListService()->cancelOptOut($data->id, $data->targetType, $data->targetId); + + return true; } private function getTargetListService(): Service diff --git a/application/Espo/Modules/Crm/Services/Campaign.php b/application/Espo/Modules/Crm/Services/Campaign.php index 527487c1c6..ec78cad239 100644 --- a/application/Espo/Modules/Crm/Services/Campaign.php +++ b/application/Espo/Modules/Crm/Services/Campaign.php @@ -39,7 +39,7 @@ use Espo\Core\Exceptions\Error; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; -use \Espo\Services\Record; +use Espo\Services\Record; use Espo\Core\Di; @@ -52,6 +52,9 @@ class Campaign extends Record implements { use Di\DefaultLanguageSetter; + /** + * @var array + */ protected $entityTypeAddressFieldListMap = [ 'Account' => ['billingAddress', 'shippingAddress'], 'Contact' => ['address'], @@ -59,6 +62,9 @@ class Campaign extends Record implements 'User' => [], ]; + /** + * @var string[] + */ protected $targetLinkList = [ 'accounts', 'contacts', @@ -66,8 +72,13 @@ class Campaign extends Record implements 'users', ]; - public function logLeadCreated($campaignId, Entity $target, $actionDate = null, $isTest = false) - { + public function logLeadCreated( + string $campaignId, + Entity $target, + ?string $actionDate = null, + bool $isTest = false + ): void { + if (empty($actionDate)) { $actionDate = date('Y-m-d H:i:s'); } @@ -91,10 +102,11 @@ class Campaign extends Record implements ?string $queueItemId, Entity $target, ?Entity $emailOrEmailTemplate, - $emailAddress, - $actionDate = null, - $isTest = false - ) { + string $emailAddress, + ?string $actionDate = null, + bool $isTest = false + ): void { + if (empty($actionDate)) { $actionDate = date('Y-m-d H:i:s'); } @@ -123,14 +135,15 @@ class Campaign extends Record implements } public function logBounced( - $campaignId, - $queueItemId, + string $campaignId, + ?string $queueItemId, Entity $target, - $emailAddress, - $isHard = false, - $actionDate = null, - $isTest = false - ) { + string $emailAddress, + bool $isHard = false, + ?string $actionDate = null, + bool $isTest = false + ): void { + if ( $queueItemId && $this->entityManager @@ -171,13 +184,14 @@ class Campaign extends Record implements } public function logOptedIn( - $campaignId, - $queueItemId, + string $campaignId, + ?string $queueItemId, Entity $target, - $emailAddress = null, - $actionDate = null, - $isTest = false - ) { + ?string $emailAddress = null, + ?string $actionDate = null, + bool $isTest = false + ): void { + if ( $queueItemId && $this->entityManager @@ -217,13 +231,14 @@ class Campaign extends Record implements } public function logOptedOut( - $campaignId, - $queueItemId, + string $campaignId, + ?string $queueItemId, Entity $target, - $emailAddress = null, - $actionDate = null, - $isTest = false - ) { + ?string $emailAddress = null, + ?string $actionDate = null, + bool $isTest = false + ): void { + if ( $queueItemId && $this->entityManager @@ -258,8 +273,14 @@ class Campaign extends Record implements $this->entityManager->saveEntity($logRecord); } - public function logOpened($campaignId, $queueItemId, Entity $target, $actionDate = null, $isTest = false) - { + public function logOpened( + string $campaignId, + ?string $queueItemId, + Entity $target, + ?string $actionDate = null, + bool $isTest = false + ): void { + if (empty($actionDate)) { $actionDate = date('Y-m-d H:i:s'); } @@ -285,6 +306,7 @@ class Campaign extends Record implements if ($massEmail && $massEmail->getId()) { $logRecord = $this->entityManager->getEntity('CampaignLogRecord'); + $logRecord->set([ 'campaignId' => $campaignId, 'actionDate' => $actionDate, @@ -303,13 +325,14 @@ class Campaign extends Record implements } public function logClicked( - $campaignId, - $queueItemId, + string $campaignId, + string $queueItemId, Entity $target, Entity $trackingUrl, - $actionDate = null, - $isTest = false - ) { + ?string $actionDate = null, + bool $isTest = false + ): void { + if ($this->config->get('massEmailOpenTracking')) { $this->logOpened($campaignId, $queueItemId, $target); } @@ -351,7 +374,7 @@ class Campaign extends Record implements $this->entityManager->saveEntity($logRecord); } - public function generateMailMergePdf(string $campaignId, string $link, bool $checkAcl = false) + public function generateMailMergePdf(string $campaignId, string $link, bool $checkAcl = false): string { /** @var CampaignEntity $campaign */ $campaign = $this->entityManager->getEntity('Campaign', $campaignId); diff --git a/application/Espo/Modules/Crm/Services/CaseObj.php b/application/Espo/Modules/Crm/Services/CaseObj.php index 3e571c8d06..8f6bd94dff 100644 --- a/application/Espo/Modules/Crm/Services/CaseObj.php +++ b/application/Espo/Modules/Crm/Services/CaseObj.php @@ -50,10 +50,10 @@ class CaseObj extends Record { parent::beforeCreateEntity($entity, $data); - if ($this->getUser()->isPortal()) { + if ($this->user->isPortal()) { if (!$entity->has('accountId')) { - if ($this->getUser()->get('contactId')) { - $contact = $this->getEntityManager()->getEntity('Contact', $this->getUser()->get('contactId')); + if ($this->user->get('contactId')) { + $contact = $this->entityManager->getEntity('Contact', $this->user->get('contactId')); if ($contact && $contact->get('accountId')) { $entity->set('accountId', $contact->get('accountId')); @@ -61,8 +61,8 @@ class CaseObj extends Record } } if (!$entity->has('contactId')) { - if ($this->getUser()->get('contactId')) { - $entity->set('contactId', $this->getUser()->get('contactId')); + if ($this->user->get('contactId')) { + $entity->set('contactId', $this->user->get('contactId')); } } } @@ -73,7 +73,7 @@ class CaseObj extends Record parent::afterCreateEntity($entity, $data); if (!empty($data->emailId)) { - $email = $this->getEntityManager()->getEntity('Email', $data->emailId); + $email = $this->entityManager->getEntity('Email', $data->emailId); if ($email && !$email->get('parentId') && $this->getAcl()->check($email)) { $email->set([ @@ -81,11 +81,14 @@ class CaseObj extends Record 'parentId' => $entity->getId(), ]); - $this->getEntityManager()->saveEntity($email); + $this->entityManager->saveEntity($email); } } } + /** + * @return stdClass[] + */ public function getEmailAddressList(string $id): array { /** @var CaseEntity */ @@ -133,6 +136,9 @@ class CaseObj extends Record return $list; } + /** + * @param stdClass[] $dataList + */ protected function getAccountEmailAddress(CaseEntity $entity, array $dataList): ?stdClass { $account = $this->entityManager->getEntity('Account', $entity->get('accountId')); @@ -160,6 +166,9 @@ class CaseObj extends Record ]; } + /** + * @param stdClass[] $dataList + */ protected function getLeadEmailAddress(CaseEntity $entity, array $dataList): ?stdClass { $lead = $this->entityManager->getEntity('Account', $entity->get('leadId')); @@ -187,6 +196,9 @@ class CaseObj extends Record ]; } + /** + * @return stdClass[] + */ protected function getContactEmailAddressList(CaseEntity $entity): array { $contactIdList = $entity->getLinkMultipleIdList('contacts'); diff --git a/application/Espo/Modules/Crm/Services/Contact.php b/application/Espo/Modules/Crm/Services/Contact.php index fcc180c8bc..cd40262481 100644 --- a/application/Espo/Modules/Crm/Services/Contact.php +++ b/application/Espo/Modules/Crm/Services/Contact.php @@ -43,10 +43,6 @@ class Contact extends Record 'portalUserId' ]; - protected $exportAllowedAttributeList = [ - 'title' - ]; - protected $linkMandatorySelectAttributeList = [ 'targetLists' => ['isOptedOut'], ]; diff --git a/application/Espo/Modules/Crm/Services/KnowledgeBaseArticle.php b/application/Espo/Modules/Crm/Services/KnowledgeBaseArticle.php index 9ce2871d3b..1f0088df38 100644 --- a/application/Espo/Modules/Crm/Services/KnowledgeBaseArticle.php +++ b/application/Espo/Modules/Crm/Services/KnowledgeBaseArticle.php @@ -58,19 +58,6 @@ class KnowledgeBaseArticle extends Record implements protected $readOnlyAttributeList = ['order']; - protected function init() - { - parent::init(); - $this->addDependencyList([ - 'fileStorageManager' - ]); - } - - protected function getFileStorageManager() - { - return $this->fileStorageManager; - } - public function getCopiedAttachments(string $id, ?string $parentType = null, ?string $parentId = null): stdClass { $ids = []; @@ -81,13 +68,13 @@ class KnowledgeBaseArticle extends Record implements } /** @var KnowledgeBaseArticleEntity|null $entity */ - $entity = $this->getEntityManager()->getEntity('KnowledgeBaseArticle', $id); + $entity = $this->entityManager->getEntity('KnowledgeBaseArticle', $id); if (!$entity) { throw new NotFound(); } - if (!$this->getAcl()->checkEntity($entity, 'read')) { + if (!$this->acl->checkEntity($entity, 'read')) { throw new Forbidden(); } @@ -97,10 +84,10 @@ class KnowledgeBaseArticle extends Record implements foreach ($attachmentsIds as $attachmentId) { /** @var Attachment|null $source */ - $source = $this->getEntityManager()->getEntity('Attachment', $attachmentId); + $source = $this->entityManager->getEntity('Attachment', $attachmentId); if ($source) { - $attachment = $this->getEntityManager()->getEntity('Attachment'); + $attachment = $this->entityManager->getEntity('Attachment'); $attachment->set('role', 'Attachment'); $attachment->set('type', $source->get('type')); $attachment->set('size', $source->get('size')); @@ -114,12 +101,12 @@ class KnowledgeBaseArticle extends Record implements $attachment->set('parentId', $parentId); } - if ($this->getFileStorageManager()->exists($source)) { - $this->getEntityManager()->saveEntity($attachment); + if ($this->fileStorageManager->exists($source)) { + $this->entityManager->saveEntity($attachment); - $contents = $this->getFileStorageManager()->getContents($source) ?? ''; + $contents = $this->fileStorageManager->getContents($source); - $this->getFileStorageManager()->putContents($attachment, $contents); + $this->fileStorageManager->putContents($attachment, $contents); $ids[] = $attachment->getId(); @@ -134,15 +121,21 @@ class KnowledgeBaseArticle extends Record implements ]; } - public function moveUp(string $id, ?array $where = null) + /** + * @param ?array $where + * @throws NotFound + * @throws Forbidden + * @throws Error + */ + public function moveUp(string $id, ?array $where = null): void { - $entity = $this->getEntityManager()->getEntity('KnowledgeBaseArticle', $id); + $entity = $this->entityManager->getEntity('KnowledgeBaseArticle', $id); if (!$entity) { throw new NotFound(); } - if (!$this->getAcl()->check($entity, 'edit')) { + if (!$this->acl->check($entity, 'edit')) { throw new Forbidden(); } @@ -186,19 +179,25 @@ class KnowledgeBaseArticle extends Record implements $previousEntity->set('order', $currentIndex); - $this->getEntityManager()->saveEntity($entity); - $this->getEntityManager()->saveEntity($previousEntity); + $this->entityManager->saveEntity($entity); + $this->entityManager->saveEntity($previousEntity); } - public function moveDown(string $id, ?array $where = null) + /** + * @param ?array $where + * @throws NotFound + * @throws Forbidden + * @throws Error + */ + public function moveDown(string $id, ?array $where = null): void { - $entity = $this->getEntityManager()->getEntity('KnowledgeBaseArticle', $id); + $entity = $this->entityManager->getEntity('KnowledgeBaseArticle', $id); if (!$entity) { throw new NotFound(); } - if (!$this->getAcl()->check($entity, 'edit')) { + if (!$this->acl->check($entity, 'edit')) { throw new Forbidden(); } @@ -242,19 +241,25 @@ class KnowledgeBaseArticle extends Record implements $nextEntity->set('order', $currentIndex); - $this->getEntityManager()->saveEntity($entity); - $this->getEntityManager()->saveEntity($nextEntity); + $this->entityManager->saveEntity($entity); + $this->entityManager->saveEntity($nextEntity); } - public function moveToTop(string $id, ?array $where = null) + /** + * @param ?array $where + * @throws NotFound + * @throws Forbidden + * @throws Error + */ + public function moveToTop(string $id, ?array $where = null): void { - $entity = $this->getEntityManager()->getEntity('KnowledgeBaseArticle', $id); + $entity = $this->entityManager->getEntity('KnowledgeBaseArticle', $id); if (!$entity) { throw new NotFound(); } - if (!$this->getAcl()->check($entity, 'edit')) { + if (!$this->acl->check($entity, 'edit')) { throw new Forbidden(); } @@ -296,18 +301,24 @@ class KnowledgeBaseArticle extends Record implements $entity->set('order', $previousEntity->get('order') - 1); - $this->getEntityManager()->saveEntity($entity); + $this->entityManager->saveEntity($entity); } - public function moveToBottom(string $id, ?array $where = null) + /** + * @param ?array $where + * @throws NotFound + * @throws Forbidden + * @throws Error + */ + public function moveToBottom(string $id, ?array $where = null): void { - $entity = $this->getEntityManager()->getEntity('KnowledgeBaseArticle', $id); + $entity = $this->entityManager->getEntity('KnowledgeBaseArticle', $id); if (!$entity) { throw new NotFound(); } - if (!$this->getAcl()->check($entity, 'edit')) { + if (!$this->acl->check($entity, 'edit')) { throw new Forbidden(); } @@ -349,6 +360,6 @@ class KnowledgeBaseArticle extends Record implements $entity->set('order', $nextEntity->get('order') + 1); - $this->getEntityManager()->saveEntity($entity); + $this->entityManager->saveEntity($entity); } } diff --git a/application/Espo/Modules/Crm/Services/Lead.php b/application/Espo/Modules/Crm/Services/Lead.php index 848a816661..1a79e15ca4 100644 --- a/application/Espo/Modules/Crm/Services/Lead.php +++ b/application/Espo/Modules/Crm/Services/Lead.php @@ -94,6 +94,10 @@ class Lead extends Record implements } } + /** + * @return array> + * @throws Forbidden + */ public function getConvertAttributes(string $id): array { /** @var LeadEntity */ diff --git a/application/Espo/Modules/Crm/Services/MassEmail.php b/application/Espo/Modules/Crm/Services/MassEmail.php index c5f76b7303..2bc78e7206 100644 --- a/application/Espo/Modules/Crm/Services/MassEmail.php +++ b/application/Espo/Modules/Crm/Services/MassEmail.php @@ -79,6 +79,13 @@ class MassEmail extends Record $this->getEntityManager()->getQueryExecutor()->execute($delete); } + /** + * @param \stdClass[] $targetDataList + * @throws BadRequest + * @throws Error + * @throws Forbidden + * @throws NotFound + */ public function processTest(string $id, array $targetDataList): void { $targetList = []; @@ -123,6 +130,9 @@ class MassEmail extends Record $this->processTestSending($massEmail); } + /** + * @param iterable $targetList + */ protected function createTestQueue(MassEmailEntity $massEmail, iterable $targetList): void { $queue = $this->injectableFactory->create(Queue::class); @@ -137,6 +147,10 @@ class MassEmail extends Record $processor->process($massEmail, true); } + /** + * @return \stdClass[] + * @throws Forbidden + */ public function getSmtpAccountDataList(): array { if ( diff --git a/application/Espo/Modules/Crm/Services/Opportunity.php b/application/Espo/Modules/Crm/Services/Opportunity.php index 0db48c3d63..badecb5a30 100644 --- a/application/Espo/Modules/Crm/Services/Opportunity.php +++ b/application/Espo/Modules/Crm/Services/Opportunity.php @@ -47,6 +47,9 @@ use DateInterval; use PDO; use stdClass; +/** + * @extends Record<\Espo\Modules\Crm\Entities\Opportunity> + */ class Opportunity extends Record { protected $mandatorySelectAttributeList = [ @@ -418,8 +421,10 @@ class Opportunity extends Record /** * A grouping-by with distinct will give wrong results. Need to use sub-query. + * + * @param array $whereClause */ - protected function handleDistinctReportQueryBuilder(SelectBuilder $queryBuilder, array $whereClause) + protected function handleDistinctReportQueryBuilder(SelectBuilder $queryBuilder, array $whereClause): void { if (!$queryBuilder->build()->isDistinct()) { return; @@ -438,6 +443,11 @@ class Opportunity extends Record ]); } + /** + * + * @param string $dateFilter + * @return array{string,string} + */ protected function getDateRangeByFilter(string $dateFilter): array { switch ($dateFilter) { @@ -516,9 +526,12 @@ class Opportunity extends Record ]; } - return [0, 0]; + return ['0', '0']; } + /** + * @return string[] + */ protected function getLostStageList(): array { $lostStageList = []; @@ -538,6 +551,9 @@ class Opportunity extends Record return $lostStageList; } + /** + * @return string[] + */ protected function getWonStageList(): array { $wonStageList = []; @@ -557,6 +573,9 @@ class Opportunity extends Record return $wonStageList; } + /** + * @return stdClass[] + */ public function getEmailAddressList(string $id): array { /** @var OpportunityEntity */ @@ -591,6 +610,9 @@ class Opportunity extends Record return $list; } + /** + * @param stdClass[] $dataList + */ protected function getAccountEmailAddress(OpportunityEntity $entity, array $dataList): ?stdClass { $account = $this->entityManager->getEntity('Account', $entity->get('accountId')); @@ -618,6 +640,9 @@ class Opportunity extends Record ]; } + /** + * @return stdClass[] + */ protected function getContactEmailAddressList(OpportunityEntity $entity): array { $contactIdList = $entity->getLinkMultipleIdList('contacts'); diff --git a/application/Espo/Modules/Crm/Services/TargetList.php b/application/Espo/Modules/Crm/Services/TargetList.php index f25a664ec4..58156dbf3a 100644 --- a/application/Espo/Modules/Crm/Services/TargetList.php +++ b/application/Espo/Modules/Crm/Services/TargetList.php @@ -60,6 +60,9 @@ class TargetList extends Record implements { use Di\HookManagerSetter; + /** + * @var string[] + */ protected $targetLinkList = []; protected $noEditAccessRequiredLinkList = []; @@ -68,6 +71,9 @@ class TargetList extends Record implements protected $linkMandatorySelectAttributeList = []; + /** + * @var array + */ protected $entityTypeLinkMap = []; public function setMetadata(Metadata $metadata): void @@ -113,12 +119,20 @@ class TargetList extends Record implements } } + /** + * @param string[] $includingActionList + * @param string[] $excludingActionList + * @throws BadRequest + * @throws NotFound + * @throws Forbidden + */ protected function populateFromCampaignLog( TargetListEntity $entity, string $sourceCampaignId, array $includingActionList, array $excludingActionList - ) { + ): void { + if (empty($sourceCampaignId)) { throw new BadRequest(); } @@ -203,7 +217,7 @@ class TargetList extends Record implements } } - public function unlinkAll(string $id, string $link) + public function unlinkAll(string $id, string $link): void { /** @var TargetListEntity|null $entity */ $entity = $this->getRepository()->get($id); @@ -244,8 +258,6 @@ class TargetList extends Record implements $this->entityManager->getQueryExecutor()->execute($updateQuery); $this->hookManager->process('TargetList', 'afterUnlinkAll', $entity, [], ['link' => $link]); - - return true; } protected function getOptedOutSelectQueryForLink(string $targetListId, string $link): Select @@ -296,6 +308,9 @@ class TargetList extends Record implements ->build(); } + /** + * @return RecordCollection + */ protected function findLinkedOptedOut(string $id, SearchParams $searchParams): RecordCollection { $offset = $searchParams->getOffset() ?? 0; @@ -350,10 +365,11 @@ class TargetList extends Record implements $collection[] = $itemEntity; } + /** @var RecordCollection */ return new RecordCollection($collection, $totalCount); } - public function optOut(string $id, string $targetType, string $targetId) + public function optOut(string $id, string $targetType, string $targetId): void { $targetList = $this->entityManager->getEntity('TargetList', $id); @@ -387,11 +403,9 @@ class TargetList extends Record implements ]; $this->hookManager->process('TargetList', 'afterOptOut', $targetList, [], $hookData); - - return true; } - public function cancelOptOut(string $id, string $targetType, string $targetId) + public function cancelOptOut(string $id, string $targetType, string $targetId): void { $targetList = $this->entityManager->getEntity('TargetList', $id); @@ -425,8 +439,6 @@ class TargetList extends Record implements ]; $this->hookManager->process('TargetList', 'afterCancelOptOut', $targetList, [], $hookData); - - return true; } /** diff --git a/application/Espo/Modules/Crm/Tools/MassEmail/Queue.php b/application/Espo/Modules/Crm/Tools/MassEmail/Queue.php index 233ac88634..94a531ff30 100644 --- a/application/Espo/Modules/Crm/Tools/MassEmail/Queue.php +++ b/application/Espo/Modules/Crm/Tools/MassEmail/Queue.php @@ -80,7 +80,7 @@ class Queue } /** - * @param iterable $additionalTargetList + * @param iterable<\Espo\ORM\Entity> $additionalTargetList * @throws Error */ public function create(MassEmail $massEmail, bool $isTest = false, iterable $additionalTargetList = []): void