From af7d88dd6be3a9372a2bb8bacbfa7bd3cbf7a61d Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Sun, 15 Sep 2024 14:23:12 +0300 Subject: [PATCH] RelationQueryHelper --- .../Select/AccessControl/Filters/OnlyOwn.php | 26 ++---- .../Select/Helpers/RelationQueryHelper.php | 80 +++++++++++++++++++ .../Modules/Crm/Tools/Calendar/Service.php | 13 ++- 3 files changed, 91 insertions(+), 28 deletions(-) create mode 100644 application/Espo/Core/Select/Helpers/RelationQueryHelper.php diff --git a/application/Espo/Core/Select/AccessControl/Filters/OnlyOwn.php b/application/Espo/Core/Select/AccessControl/Filters/OnlyOwn.php index 6d6bb64e24..c9fe4d33c5 100644 --- a/application/Espo/Core/Select/AccessControl/Filters/OnlyOwn.php +++ b/application/Espo/Core/Select/AccessControl/Filters/OnlyOwn.php @@ -30,9 +30,9 @@ namespace Espo\Core\Select\AccessControl\Filters; use Espo\Core\Select\AccessControl\Filter; +use Espo\Core\Select\Helpers\RelationQueryHelper; use Espo\Core\Select\Helpers\FieldHelper; use Espo\Entities\User; -use Espo\ORM\Defs; use Espo\ORM\Query\SelectBuilder as QueryBuilder; class OnlyOwn implements Filter @@ -41,31 +41,15 @@ class OnlyOwn implements Filter private User $user, private FieldHelper $fieldHelper, private string $entityType, - private Defs $defs + private RelationQueryHelper $relationQueryHelper, ) {} public function apply(QueryBuilder $queryBuilder): void { if ($this->fieldHelper->hasAssignedUsersField()) { - $relationDefs = $this->defs - ->getEntity($this->entityType) - ->getRelation('assignedUsers'); - - $middleEntityType = ucfirst($relationDefs->getRelationshipName()); - $key1 = $relationDefs->getMidKey(); - $key2 = $relationDefs->getForeignMidKey(); - - $subQuery = QueryBuilder::create() - ->select('id') - ->from($this->entityType) - ->leftJoin($middleEntityType, 'assignedUsersMiddle', [ - "assignedUsersMiddle.$key1:" => 'id', - 'assignedUsersMiddle.deleted' => false, - ]) - ->where(["assignedUsersMiddle.$key2" => $this->user->getId()]) - ->build(); - - $queryBuilder->where(['id=s' => $subQuery]); + $queryBuilder->where( + $this->relationQueryHelper->prepareAssignedUsersWhere($this->entityType, $this->user->getId()) + ); return; } diff --git a/application/Espo/Core/Select/Helpers/RelationQueryHelper.php b/application/Espo/Core/Select/Helpers/RelationQueryHelper.php new file mode 100644 index 0000000000..bfb464249a --- /dev/null +++ b/application/Espo/Core/Select/Helpers/RelationQueryHelper.php @@ -0,0 +1,80 @@ +. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +namespace Espo\Core\Select\Helpers; + +use Espo\ORM\Defs; +use Espo\ORM\Query\Part\Condition; +use Espo\ORM\Query\Part\Expression; +use Espo\ORM\Query\Part\WhereItem; +use Espo\ORM\Query\SelectBuilder as QueryBuilder; + +/** + * @since 8.5.0 + */ +class RelationQueryHelper +{ + public function __construct( + private Defs $defs, + ) {} + + /** + * @param string|string[] $id + */ + public function prepareMiddleWhere(string $entityType, string $link, string|array $id): WhereItem + { + $relationDefs = $this->defs + ->getEntity($entityType) + ->getRelation($link); + + $middleEntityType = ucfirst($relationDefs->getRelationshipName()); + $key1 = $relationDefs->getMidKey(); + $key2 = $relationDefs->getForeignMidKey(); + + $subQuery = QueryBuilder::create() + ->select('id') + ->from($entityType) + ->leftJoin($middleEntityType, 'm', [ + "m.$key1:" => 'id', + 'm.deleted' => false, + ]) + ->where(["m.$key2" => $id]) + ->build(); + + return Condition::in( + Expression::column('id'), + $subQuery + ); + } + + public function prepareAssignedUsersWhere(string $entityType, string $userId): WhereItem + { + return $this->prepareMiddleWhere($entityType, 'assignedUsers', $userId); + } +} diff --git a/application/Espo/Modules/Crm/Tools/Calendar/Service.php b/application/Espo/Modules/Crm/Tools/Calendar/Service.php index a9a13167aa..dcac84dab6 100644 --- a/application/Espo/Modules/Crm/Tools/Calendar/Service.php +++ b/application/Espo/Modules/Crm/Tools/Calendar/Service.php @@ -37,6 +37,7 @@ use Espo\Core\Exceptions\Error; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\NotFound; use Espo\Core\Field\DateTime as DateTimeField; +use Espo\Core\Select\Helpers\RelationQueryHelper; use Espo\Core\Select\SelectBuilderFactory; use Espo\Core\Utils\Config; use Espo\Core\Utils\Metadata; @@ -76,7 +77,8 @@ class Service private Metadata $metadata, private SelectBuilderFactory $selectBuilderFactory, private User $user, - private ServiceFactory $serviceFactory + private ServiceFactory $serviceFactory, + private RelationQueryHelper $relationQueryHelper, ) {} /** @@ -524,12 +526,9 @@ class Service $this->metadata->get(['entityDefs', 'Task', 'fields', 'assignedUsers', 'type']) === 'linkMultiple' && !$this->metadata->get(['entityDefs', 'Task', 'fields', 'assignedUsers', 'disabled']) ) { - $queryBuilder - ->distinct() - ->leftJoin('assignedUsers', 'assignedUsers') - ->where([ - 'assignedUsers.id' => $userId, - ]); + $queryBuilder->where( + $this->relationQueryHelper->prepareAssignedUsersWhere(Task::ENTITY_TYPE, $userId) + ); } else { $queryBuilder->where([ 'assignedUserId' => $userId,