This commit is contained in:
Yuri Kuznetsov
2023-02-17 15:46:44 +02:00
parent 75749efacb
commit 702b3f4e2b
33 changed files with 268 additions and 522 deletions

View File

@@ -30,45 +30,24 @@
namespace Espo\Core\Select\AccessControl;
use Espo\Core\Select\OrmSelectBuilder;
use Espo\Core\Select\AccessControl\FilterFactory as AccessControlFilterFactory;
use Espo\Core\Select\AccessControl\FilterResolverFactory as AccessControlFilterResolverFactory;
use Espo\Core\Select\SelectManager;
use Espo\Core\{
Select\SelectManager,
Select\AccessControl\FilterFactory as AccessControlFilterFactory,
Select\AccessControl\FilterResolverFactory as AccessControlFilterResolverFactory,
};
use Espo\{
ORM\Query\SelectBuilder as QueryBuilder,
Entities\User,
};
use Espo\Entities\User;
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
use RuntimeException;
class Applier
{
private string $entityType;
private User $user;
private AccessControlFilterFactory $accessControlFilterFactory;
private AccessControlFilterResolverFactory $accessControlFilterResolverFactory;
private SelectManager $selectManager;
public function __construct(
string $entityType,
User $user,
AccessControlFilterFactory $accessControlFilterFactory,
AccessControlFilterResolverFactory $accessControlFilterResolverFactory,
SelectManager $selectManager
) {
$this->entityType = $entityType;
$this->user = $user;
$this->accessControlFilterFactory = $accessControlFilterFactory;
$this->accessControlFilterResolverFactory = $accessControlFilterResolverFactory;
$this->selectManager = $selectManager;
}
private string $entityType,
private User $user,
private AccessControlFilterFactory $accessControlFilterFactory,
private AccessControlFilterResolverFactory $accessControlFilterResolverFactory,
private SelectManager $selectManager
) {}
public function apply(QueryBuilder $queryBuilder): void
{

View File

@@ -33,15 +33,8 @@ use Espo\Core\Acl;
class DefaultFilterResolver implements FilterResolver
{
private $entityType;
private $acl;
public function __construct(string $entityType, Acl $acl)
{
$this->entityType = $entityType;
$this->acl = $acl;
}
public function __construct(private string $entityType, private Acl $acl)
{}
public function resolve(): ?string
{

View File

@@ -33,15 +33,8 @@ use Espo\Core\Portal\Acl;
class DefaultPortalFilterResolver implements FilterResolver
{
private $entityType;
private $acl;
public function __construct(string $entityType, Acl $acl)
{
$this->entityType = $entityType;
$this->acl = $acl;
}
public function __construct(private string $entityType, private Acl $acl)
{}
public function resolve(): ?string
{

View File

@@ -29,38 +29,26 @@
namespace Espo\Core\Select\AccessControl;
use Espo\Core\{
Exceptions\Error,
Select\Helpers\FieldHelper,
InjectableFactory,
Utils\Metadata,
AclManager,
Acl,
Binding\BindingContainer,
Binding\Binder,
Binding\BindingData,
};
use Espo\Core\Acl;
use Espo\Core\AclManager;
use Espo\Core\Binding\Binder;
use Espo\Core\Binding\BindingContainer;
use Espo\Core\Binding\BindingData;
use Espo\Core\InjectableFactory;
use Espo\Core\Select\Helpers\FieldHelper;
use Espo\Core\Utils\Metadata;
use Espo\{
Entities\User,
};
use Espo\Entities\User;
use RuntimeException;
class FilterFactory
{
private $injectableFactory;
private $metadata;
private $aclManager;
public function __construct(InjectableFactory $injectableFactory, Metadata $metadata, AclManager $aclManager)
{
$this->injectableFactory = $injectableFactory;
$this->metadata = $metadata;
$this->aclManager = $aclManager;
}
public function __construct(
private InjectableFactory $injectableFactory,
private Metadata $metadata,
private AclManager $aclManager
) {}
public function create(string $entityType, User $user, string $name): Filter
{
@@ -73,15 +61,12 @@ class FilterFactory
$bindingData = new BindingData();
$binder = new Binder($bindingData);
$binder
->bindInstance(User::class, $user)
->bindInstance(Acl::class, $this->aclManager->createUserAcl($user));
$binder
->for($className)
->bindValue('$entityType', $entityType);
$binder
->for(FieldHelper::class)
->bindValue('$entityType', $entityType);

View File

@@ -29,6 +29,7 @@
namespace Espo\Core\Select\AccessControl;
use Espo\Core\Exceptions\Error;
use Espo\Core\InjectableFactory;
use Espo\Core\Acl;
use Espo\Core\Portal\Acl as PortalAcl;
@@ -39,24 +40,15 @@ use Espo\Core\Binding\Binder;
use Espo\Core\Binding\BindingData;
use Espo\Entities\User;
use RuntimeException;
class FilterResolverFactory
{
private InjectableFactory $injectableFactory;
private Metadata $metadata;
private UserAclManagerProvider $userAclManagerProvider;
public function __construct(
InjectableFactory $injectableFactory,
Metadata $metadata,
UserAclManagerProvider $userAclManagerProvider
) {
$this->injectableFactory = $injectableFactory;
$this->metadata = $metadata;
$this->userAclManagerProvider = $userAclManagerProvider;
}
private InjectableFactory $injectableFactory,
private Metadata $metadata,
private UserAclManagerProvider $userAclManagerProvider
) {}
public function create(string $entityType, User $user): FilterResolver
{
@@ -64,14 +56,18 @@ class FilterResolverFactory
$this->getClassName($entityType) :
$this->getPortalClassName($entityType);
$acl = $this->userAclManagerProvider
->get($user)
->createUserAcl($user);
try {
$acl = $this->userAclManagerProvider
->get($user)
->createUserAcl($user);
}
catch (Error $e) {
throw new RuntimeException($e->getMessage());
}
$bindingData = new BindingData();
$binder = new Binder($bindingData);
$binder
->bindInstance(User::class, $user)
->bindInstance(Acl::class, $acl);
@@ -95,9 +91,8 @@ class FilterResolverFactory
private function getClassName(string $entityType): string
{
/** @var class-string<FilterResolver> */
return $this->metadata->get([
'selectDefs', $entityType, 'accessControlFilterResolverClassName'
]) ?? DefaultFilterResolver::class;
return $this->metadata->get(['selectDefs', $entityType, 'accessControlFilterResolverClassName']) ??
DefaultFilterResolver::class;
}
/**
@@ -106,8 +101,7 @@ class FilterResolverFactory
private function getPortalClassName(string $entityType): string
{
/** @var class-string<FilterResolver> */
return $this->metadata->get([
'selectDefs', $entityType, 'portalAccessControlFilterResolverClassName'
]) ?? DefaultPortalFilterResolver::class;
return $this->metadata->get(['selectDefs', $entityType, 'portalAccessControlFilterResolverClassName']) ??
DefaultPortalFilterResolver::class;
}
}

View File

@@ -39,15 +39,8 @@ use Espo\Entities\User;
class Additional
{
private User $user;
private InjectableFactory $injectableFactory;
public function __construct(User $user, InjectableFactory $injectableFactory)
{
$this->user = $user;
$this->injectableFactory = $injectableFactory;
}
public function __construct(private User $user, private InjectableFactory $injectableFactory)
{}
/**
* @param class-string<AdditionalApplier>[] $classNameList

View File

@@ -38,20 +38,16 @@ use Espo\Core\Select\Order\Applier as OrderApplier;
use Espo\Core\Select\Bool\Applier as BoolFilterListApplier;
use Espo\Core\Select\Applier\Appliers\Additional as AdditionalApplier;
use Espo\Core\Select\Applier\Appliers\Limit as LimitApplier;
use Espo\Core\Exceptions\Error;
use Espo\Core\{
InjectableFactory,
Utils\Metadata,
Select\SelectManagerFactory,
Select\SelectManager,
Binding\BindingContainer,
Binding\Binder,
Binding\BindingData,
};
use Espo\Core\Binding\Binder;
use Espo\Core\Binding\BindingContainer;
use Espo\Core\Binding\BindingData;
use Espo\Core\InjectableFactory;
use Espo\Core\Select\SelectManager;
use Espo\Core\Select\SelectManagerFactory;
use Espo\Core\Utils\Metadata;
use Espo\Entities\User;
use RuntimeException;
class Factory
{
@@ -66,7 +62,7 @@ class Factory
public const ADDITIONAL = 'additional';
/**
* @var array<string,class-string<object>>
* @var array<string, class-string<object>>
*/
private array $defaultClassNameMap = [
self::TEXT_FILTER => TextFilterApplier::class,
@@ -80,21 +76,11 @@ class Factory
self::LIMIT => LimitApplier::class,
];
private InjectableFactory $injectableFactory;
private Metadata $metadata;
private SelectManagerFactory $selectManagerFactory;
public function __construct(
InjectableFactory $injectableFactory,
Metadata $metadata,
SelectManagerFactory $selectManagerFactory
) {
$this->injectableFactory = $injectableFactory;
$this->metadata = $metadata;
$this->selectManagerFactory = $selectManagerFactory;
}
private InjectableFactory $injectableFactory,
private Metadata $metadata,
private SelectManagerFactory $selectManagerFactory
) {}
private function create(string $entityType, User $user, string $type): object
{
@@ -114,7 +100,6 @@ class Factory
$bindingData = new BindingData();
$binder = new Binder($bindingData);
$binder
->bindInstance(User::class, $user)
->bindInstance(SelectManager::class, $selectManager)
@@ -183,7 +168,6 @@ class Factory
/**
* @return class-string<object>
* @throws Error
*/
private function getDefaultClassName(string $type): string
{
@@ -191,6 +175,6 @@ class Factory
return $this->defaultClassNameMap[$type];
}
throw new Error("Applier `$type` does not exist.");
throw new RuntimeException("Applier `$type` does not exist.");
}
}

View File

@@ -43,25 +43,12 @@ use Espo\Entities\User;
class Applier
{
private string $entityType;
private User $user;
private SelectManager $selectManager;
private BoolFilterFactory $boolFilterFactory;
public function __construct(
string $entityType,
User $user,
BoolFilterFactory $boolFilterFactory,
SelectManager $selectManager
) {
$this->entityType = $entityType;
$this->user = $user;
$this->boolFilterFactory = $boolFilterFactory;
$this->selectManager = $selectManager;
}
private string $entityType,
private User $user,
private BoolFilterFactory $boolFilterFactory,
private SelectManager $selectManager
) {}
/**
* @param string[] $boolFilterNameList

View File

@@ -40,15 +40,8 @@ class FieldHelper
{
private ?Entity $seed = null;
private string $entityType;
private EntityManager $entityManager;
public function __construct(string $entityType, EntityManager $entityManager)
{
$this->entityType = $entityType;
$this->entityManager = $entityManager;
}
public function __construct(private string $entityType, private EntityManager $entityManager)
{}
private function getSeed(): Entity
{

View File

@@ -33,8 +33,6 @@ class RandomStringGenerator
{
public function generate(): string
{
return strval(
rand(10000, 99999)
);
return strval(rand(10000, 99999));
}
}

View File

@@ -36,18 +36,11 @@ use Espo\Core\Utils\Config;
class UserTimeZoneProvider
{
private $user;
private $entityManager;
private $config;
public function __construct(User $user, EntityManager $entityManager, Config $config)
{
$this->user = $user;
$this->entityManager = $entityManager;
$this->config = $config;
}
public function __construct(
private User $user,
private EntityManager $entityManager,
private Config $config
) {}
public function get(): string
{

View File

@@ -41,22 +41,12 @@ use Espo\ORM\Query\SelectBuilder as QueryBuilder;
class Applier
{
private string $entityType;
private MetadataProvider $metadataProvider;
private ItemConverterFactory $itemConverterFactory;
private OrdererFactory $ordererFactory;
public function __construct(
string $entityType,
MetadataProvider $metadataProvider,
ItemConverterFactory $itemConverterFactory,
OrdererFactory $ordererFactory
) {
$this->entityType = $entityType;
$this->metadataProvider = $metadataProvider;
$this->itemConverterFactory = $itemConverterFactory;
$this->ordererFactory = $ordererFactory;
}
private string $entityType,
private MetadataProvider $metadataProvider,
private ItemConverterFactory $itemConverterFactory,
private OrdererFactory $ordererFactory
) {}
/**
* @throws Forbidden
@@ -75,8 +65,8 @@ class Applier
if ($params->forbidComplexExpressions() && $orderBy) {
if (
!is_string($orderBy) ||
strpos($orderBy, '.') !== false ||
strpos($orderBy, ':') !== false
str_contains($orderBy, '.') ||
str_contains($orderBy, ':')
) {
throw new Forbidden("Complex expressions are forbidden in 'orderBy'.");
}
@@ -179,8 +169,8 @@ class Applier
$resultOrderBy .= 'Type';
}
else if (
strpos($orderBy, '.') === false &&
strpos($orderBy, ':') === false &&
!str_contains($orderBy, '.') &&
!str_contains($orderBy, ':') &&
!$this->metadataProvider->hasAttribute($this->entityType, $orderBy)
) {
throw new Error("Order by non-existing field '{$orderBy}'.");
@@ -211,7 +201,7 @@ class Applier
}
/**
* @return array<array{string,string}>
* @return array<array{string, string}>
*/
private function orderListToArray(OrderList $orderList): array
{

View File

@@ -31,27 +31,20 @@ namespace Espo\Core\Select\Order;
use Espo\Entities\User;
use Espo\Core\Exceptions\Error;
use Espo\Core\InjectableFactory;
use Espo\Core\Utils\Metadata;
use Espo\Core\Binding\BindingContainerBuilder;
use Espo\Core\Binding\ContextualBinder;
use RuntimeException;
class ItemConverterFactory
{
private InjectableFactory $injectableFactory;
private Metadata $metadata;
private User $user;
public function __construct(InjectableFactory $injectableFactory, Metadata $metadata, User $user)
{
$this->injectableFactory = $injectableFactory;
$this->metadata = $metadata;
$this->user = $user;
}
public function __construct(
private InjectableFactory $injectableFactory,
private Metadata $metadata,
private User $user
) {}
public function has(string $entityType, string $field): bool
{
@@ -63,7 +56,7 @@ class ItemConverterFactory
$className = $this->getClassName($entityType, $field);
if (!$className) {
throw new Error("Order item converter class name is not defined.");
throw new RuntimeException("Order item converter class name is not defined.");
}
$container = BindingContainerBuilder::create()

View File

@@ -32,10 +32,8 @@ namespace Espo\Core\Select\Order\ItemConverters;
use Espo\ORM\Query\Part\OrderList;
use Espo\ORM\Query\Part\Order;
use Espo\Core\{
Select\Order\ItemConverter,
Select\Order\Item,
};
use Espo\Core\Select\Order\Item;
use Espo\Core\Select\Order\ItemConverter;
class AddressType implements ItemConverter
{

View File

@@ -32,31 +32,20 @@ namespace Espo\Core\Select\Order\ItemConverters;
use Espo\ORM\Query\Part\OrderList;
use Espo\ORM\Query\Part\Order;
use Espo\ORM\Query\Part\Expression;
use Espo\Core\{
Select\Order\ItemConverter,
Select\Order\Item,
Select\SearchParams,
Utils\Metadata,
};
use Espo\Core\Select\Order\Item;
use Espo\Core\Select\Order\ItemConverter;
use Espo\Core\Select\SearchParams;
use Espo\Core\Utils\Metadata;
class EnumType implements ItemConverter
{
private $entityType;
private $metadata;
public function __construct(
string $entityType,
Metadata $metadata
) {
$this->entityType = $entityType;
$this->metadata = $metadata;
}
private string $entityType,
private Metadata $metadata
) {}
public function convert(Item $item): OrderList
{
/** @var string $orderBy */
$orderBy = $item->getOrderBy();
$order = $item->getOrder();

View File

@@ -29,25 +29,13 @@
namespace Espo\Core\Select\Order;
use Espo\Core\{
Utils\Metadata,
};
use Espo\{
ORM\EntityManager,
};
use Espo\Core\Utils\Metadata;
use Espo\ORM\EntityManager;
class MetadataProvider
{
private $metadata;
private $entityManager;
public function __construct(Metadata $metadata, EntityManager $entityManager)
{
$this->metadata = $metadata;
$this->entityManager = $entityManager;
}
public function __construct(private Metadata $metadata, private EntityManager $entityManager)
{}
public function getFieldType(string $entityType, string $field): ?string
{

View File

@@ -29,29 +29,21 @@
namespace Espo\Core\Select\Order;
use Espo\Core\Exceptions\Error;
use Espo\Core\InjectableFactory;
use Espo\Core\Utils\Metadata;
use Espo\Entities\User;
use Espo\Core\Binding\BindingContainerBuilder;
use Espo\Core\Binding\ContextualBinder;
use Espo\Entities\User;
use RuntimeException;
class OrdererFactory
{
private InjectableFactory $injectableFactory;
private Metadata $metadata;
private User $user;
public function __construct(InjectableFactory $injectableFactory, Metadata $metadata, User $user)
{
$this->injectableFactory = $injectableFactory;
$this->metadata = $metadata;
$this->user = $user;
}
public function __construct(
private InjectableFactory $injectableFactory,
private Metadata $metadata,
private User $user
) {}
public function has(string $entityType, string $field): bool
{
@@ -63,7 +55,7 @@ class OrdererFactory
$className = $this->getClassName($entityType, $field);
if (!$className) {
throw new Error("Orderer class name is not defined.");
throw new RuntimeException("Orderer class name is not defined.");
}
$container = BindingContainerBuilder::create()

View File

@@ -48,7 +48,7 @@ class Params
private function __construct() {}
/**
* @param array<string,mixed> $params
* @param array<string, mixed> $params
*/
public static function fromArray(array $params): self
{

View File

@@ -31,7 +31,6 @@ namespace Espo\Core\Select\Primary;
use Espo\Core\Exceptions\Error;
use Espo\Core\Select\SelectManager;
use Espo\Core\Select\Primary\FilterFactory;
use Espo\Core\Select\OrmSelectBuilder;
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
@@ -39,26 +38,16 @@ use Espo\Entities\User;
class Applier
{
private string $entityType;
private User $user;
private SelectManager $selectManager;
private FilterFactory $primaryFilterFactory;
public function __construct(
string $entityType,
User $user,
FilterFactory $primaryFilterFactory,
SelectManager $selectManager
) {
$this->entityType = $entityType;
$this->user = $user;
$this->primaryFilterFactory = $primaryFilterFactory;
$this->selectManager = $selectManager;
}
private string $entityType,
private User $user,
private FilterFactory $primaryFilterFactory,
private SelectManager $selectManager
) {}
/**
* @throws Error
*/
public function apply(QueryBuilder $queryBuilder, string $filterName): void
{
if ($this->primaryFilterFactory->has($this->entityType, $filterName)) {

View File

@@ -31,6 +31,9 @@ namespace Espo\Core\Select\Primary;
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
/**
* A primary filter.
*/
interface Filter
{
public function apply(QueryBuilder $queryBuilder): void;

View File

@@ -29,35 +29,26 @@
namespace Espo\Core\Select\Primary;
use Espo\Core\{
Exceptions\Error,
InjectableFactory,
Utils\Metadata,
Binding\BindingContainer,
Binding\Binder,
Binding\BindingData,
};
use Espo\Core\Binding\Binder;
use Espo\Core\Binding\BindingContainer;
use Espo\Core\Binding\BindingData;
use Espo\Core\InjectableFactory;
use Espo\Core\Utils\Metadata;
use Espo\Entities\User;
use RuntimeException;
class FilterFactory
{
private InjectableFactory $injectableFactory;
private Metadata $metadata;
public function __construct(InjectableFactory $injectableFactory, Metadata $metadata)
{
$this->injectableFactory = $injectableFactory;
$this->metadata = $metadata;
}
public function __construct(private InjectableFactory $injectableFactory, private Metadata $metadata)
{}
public function create(string $entityType, User $user, string $name): Filter
{
$className = $this->getClassName($entityType, $name);
if (!$className) {
throw new Error("Primary filter '{$name}' for '{$entityType}' does not exist.");
throw new RuntimeException("Primary filter '{$name}' for '{$entityType}' does not exist.");
}
$bindingData = new BindingData();
@@ -81,12 +72,11 @@ class FilterFactory
/**
* @return ?class-string<Filter>
* @throws Error
*/
protected function getClassName(string $entityType, string $name): ?string
{
if (!$name) {
throw new Error("Empty primary filter name.");
throw new RuntimeException("Empty primary filter name.");
}
$className = $this->metadata->get(

View File

@@ -29,23 +29,14 @@
namespace Espo\Core\Select\Primary\Filters;
use Espo\{
ORM\Query\SelectBuilder as QueryBuilder,
Core\Select\Primary\Filter,
Entities\User,
};
use Espo\Core\Select\Primary\Filter;
use Espo\Entities\User;
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
class Followed implements Filter
{
private $entityType;
private $user;
public function __construct(string $entityType, User $user)
{
$this->entityType = $entityType;
$this->user = $user;
}
public function __construct(private string $entityType, private User $user)
{}
public function apply(QueryBuilder $queryBuilder): void
{
@@ -57,7 +48,7 @@ class Followed implements Filter
[
$alias . '.entityType' => $this->entityType,
$alias . '.entityId=:' => 'id',
$alias . '.userId' => $this->user->id,
$alias . '.userId' => $this->user->getId(),
]
);
}

View File

@@ -29,31 +29,22 @@
namespace Espo\Core\Select\Select;
use Espo\Core\{
Select\SearchParams,
Select\Select\MetadataProvider,
Utils\FieldUtil,
};
use Espo\Core\Select\SearchParams;
use Espo\Core\Utils\FieldUtil;
use Espo\{
ORM\Query\SelectBuilder as QueryBuilder,
ORM\Entity,
Entities\User,
};
use Espo\Entities\User;
use Espo\ORM\Entity;
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
class Applier
{
/**
* @var string[]
*/
/** @var string[] */
private $aclAttributeList = [
'assignedUserId',
'createdById',
];
/**
* @var string[]
*/
/** @var string[] */
private $aclPortalAttributeList = [
'assignedUserId',
'createdById',
@@ -61,25 +52,12 @@ class Applier
'accountId',
];
private string $entityType;
private User $user;
private FieldUtil $fieldUtil;
private MetadataProvider $metadataProvider;
public function __construct(
string $entityType,
User $user,
FieldUtil $fieldUtil,
MetadataProvider $metadataProvider
) {
$this->entityType = $entityType;
$this->user = $user;
$this->fieldUtil = $fieldUtil;
$this->metadataProvider = $metadataProvider;
}
private string $entityType,
private User $user,
private FieldUtil $fieldUtil,
private MetadataProvider $metadataProvider
) {}
public function apply(QueryBuilder $queryBuilder, SearchParams $searchParams): void
{
@@ -94,7 +72,7 @@ class Applier
/**
* @param string[] $attributeList
* @return array<int,array{string,string}|string>
* @return array<int, array{string, string}|string>
*/
private function prepareAttributeList(array $attributeList, SearchParams $searchParams): array
{

View File

@@ -30,20 +30,12 @@
namespace Espo\Core\Select\Select;
use Espo\Core\Utils\Metadata;
use Espo\ORM\EntityManager;
class MetadataProvider
{
private Metadata $metadata;
private EntityManager $entityManager;
public function __construct(Metadata $metadata, EntityManager $entityManager)
{
$this->metadata = $metadata;
$this->entityManager = $entityManager;
}
public function __construct(private Metadata $metadata, private EntityManager $entityManager)
{}
public function getDefaultOrderBy(string $entityType): ?string
{
@@ -53,7 +45,7 @@ class MetadataProvider
}
/**
* @return array<string,string[]>|null
* @return ?array<string, string[]>
*/
public function getSelectAttributesDependencyMap(string $entityType): ?array
{
@@ -63,7 +55,7 @@ class MetadataProvider
}
/**
* @return string[]
* @return ?string[]
*/
public function getAclPortalAttributeList(string $entityType): ?array
{
@@ -73,7 +65,7 @@ class MetadataProvider
}
/**
* @return string[]
* @return ?string[]
*/
public function getAclAttributeList(string $entityType): ?array
{

View File

@@ -29,6 +29,9 @@
namespace Espo\Core\Select;
use Espo\Core\Exceptions\BadRequest;
use Espo\Core\Exceptions\Error;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Select\Applier\Factory as ApplierFactory;
use Espo\Core\Select\Where\Params as WhereParams;
use Espo\Core\Select\Where\Item as WhereItem;
@@ -59,49 +62,27 @@ use LogicException;
class SelectBuilder
{
private ?string $entityType = null;
private ?OrmSelectBuilder $queryBuilder = null;
private ?Query $sourceQuery = null;
private ?SearchParams $searchParams = null;
private bool $applyAccessControlFilter = false;
private bool $applyDefaultOrder = false;
private ?string $textFilter = null;
private ?string $primaryFilter = null;
/**
* @var string[]
*/
/** @var string[] */
private array $boolFilterList = [];
/**
* @var WhereItem[]
*/
/** @var WhereItem[] */
private array $whereItemList = [];
private bool $applyWherePermissionCheck = false;
private bool $applyComplexExpressionsForbidden = false;
/**
* @var class-string<\Espo\Core\Select\Applier\AdditionalApplier>[]
*/
/** @var class-string<Applier\AdditionalApplier>[] */
private array $additionalApplierClassNameList = [];
private User $user;
private ApplierFactory $applierFactory;
public function __construct(User $user, ApplierFactory $applierFactory)
{
$this->user = $user;
$this->applierFactory = $applierFactory;
}
public function __construct(
private User $user,
private ApplierFactory $applierFactory
) {}
/**
* Specify an entity type to select from.
@@ -134,6 +115,10 @@ class SelectBuilder
/**
* Build a result query.
*
* @throws Error
* @throws Forbidden
* @throws BadRequest
*/
public function build(): Query
{
@@ -142,6 +127,10 @@ class SelectBuilder
/**
* Build an ORM query builder. Used to continue building but by means of ORM.
*
* @throws Error
* @throws Forbidden
* @throws BadRequest
*/
public function buildQueryBuilder(): QueryBuilder
{
@@ -335,7 +324,7 @@ class SelectBuilder
/**
* Apply a list of additional applier class names.
*
* @param class-string<\Espo\Core\Select\Applier\AdditionalApplier>[] $additionalApplierClassNameList
* @param class-string<Applier\AdditionalApplier>[] $additionalApplierClassNameList
*/
public function withAdditionalApplierClassNameList(array $additionalApplierClassNameList): self
{
@@ -347,6 +336,9 @@ class SelectBuilder
return $this;
}
/**
* @throws Error
*/
private function applyPrimaryFilter(): void
{
assert($this->queryBuilder !== null);
@@ -359,6 +351,9 @@ class SelectBuilder
);
}
/**
* @throws Error
*/
private function applyBoolFilterList(): void
{
assert($this->queryBuilder !== null);
@@ -393,15 +388,15 @@ class SelectBuilder
);
}
/**
* @throws Forbidden
* @throws Error
*/
private function applyDefaultOrder(): void
{
assert($this->queryBuilder !== null);
$order = null;
if ($this->searchParams) {
$order = $this->searchParams->getOrder();
}
$order = $this->searchParams?->getOrder();
$params = OrderParams::fromArray([
'forceDefault' => true,
@@ -415,6 +410,11 @@ class SelectBuilder
);
}
/**
* @throws BadRequest
* @throws Forbidden
* @throws Error
*/
private function applyWhereItemList(): void
{
foreach ($this->whereItemList as $whereItem) {
@@ -422,6 +422,11 @@ class SelectBuilder
}
}
/**
* @throws BadRequest
* @throws Forbidden
* @throws Error
*/
private function applyWhereItem(WhereItem $whereItem): void
{
assert($this->queryBuilder !== null);
@@ -439,6 +444,10 @@ class SelectBuilder
);
}
/**
* @throws Forbidden
* @throws Error
*/
private function applyFromSearchParams(): void
{
if (!$this->searchParams) {

View File

@@ -29,46 +29,34 @@
namespace Espo\Core\Select\Where;
use Espo\Core\{
Select\Where\Params,
Select\Where\ConverterFactory,
Select\Where\CheckerFactory,
Select\Where\Item as WhereItem,
};
use Espo\Core\Exceptions\BadRequest;
use Espo\Core\Exceptions\Error;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Select\Where\Item as WhereItem;
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
use Espo\{
ORM\Query\SelectBuilder as QueryBuilder,
Entities\User,
};
use Espo\Entities\User;
class Applier
{
private string $entityType;
private User $user;
private ConverterFactory $converterFactory;
private CheckerFactory $checkerFactory;
public function __construct(
string $entityType,
User $user,
ConverterFactory $converterFactory,
CheckerFactory $checkerFactory
) {
$this->entityType = $entityType;
$this->user = $user;
$this->converterFactory = $converterFactory;
$this->checkerFactory = $checkerFactory;
}
private string $entityType,
private User $user,
private ConverterFactory $converterFactory,
private CheckerFactory $checkerFactory
) {}
/**
* @throws BadRequest
* @throws Forbidden
* @throws Error
*/
public function apply(QueryBuilder $queryBuilder, WhereItem $whereItem, Params $params): void
{
$checker = $this->checkerFactory->create($this->entityType, $this->user);
$checker->check($whereItem, $params);
$converter = $this->converterFactory->create($this->entityType, $this->user);
$whereClause = $converter->convert($queryBuilder, $whereItem);
$queryBuilder->where($whereClause);

View File

@@ -32,7 +32,6 @@ namespace Espo\Core\Select\Where;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\BadRequest;
use Espo\Core\Acl;
use Espo\Core\Select\Where\Item\Type;
use Espo\ORM\QueryComposer\BaseQueryComposer as QueryComposer;
use Espo\ORM\QueryComposer\Util as QueryUtil;

View File

@@ -29,27 +29,29 @@
namespace Espo\Core\Select\Where;
use Espo\Core\Exceptions\Error;
use Espo\Entities\User;
use Espo\Core\InjectableFactory;
use Espo\Core\Utils\Acl\UserAclManagerProvider;
use RuntimeException;
class CheckerFactory
{
private InjectableFactory $injectableFactory;
private UserAclManagerProvider $userAclManagerProvider;
public function __construct(InjectableFactory $injectableFactory, UserAclManagerProvider $userAclManagerProvider)
{
$this->injectableFactory = $injectableFactory;
$this->userAclManagerProvider = $userAclManagerProvider;
}
public function __construct(
private InjectableFactory $injectableFactory,
private UserAclManagerProvider $userAclManagerProvider
) {}
public function create(string $entityType, User $user): Checker
{
$acl = $this->userAclManagerProvider
->get($user)
->createUserAcl($user);
try {
$acl = $this->userAclManagerProvider
->get($user)
->createUserAcl($user);
}
catch (Error $e) {
throw new RuntimeException($e->getMessage());
}
return $this->injectableFactory->createWith(Checker::class, [
'entityType' => $entityType,

View File

@@ -29,31 +29,22 @@
namespace Espo\Core\Select\Where;
use Espo\Core\{
Utils\Metadata,
InjectableFactory,
Binding\BindingContainer,
Binding\Binder,
Binding\BindingData,
};
use Espo\Core\Binding\Binder;
use Espo\Core\Binding\BindingContainer;
use Espo\Core\Binding\BindingData;
use Espo\Core\InjectableFactory;
use Espo\Core\Utils\Metadata;
use Espo\Entities\User;
class ConverterFactory
{
private InjectableFactory $injectableFactory;
private Metadata $metadata;
public function __construct(InjectableFactory $injectableFactory, Metadata $metadata)
{
$this->injectableFactory = $injectableFactory;
$this->metadata = $metadata;
}
public function __construct(private InjectableFactory $injectableFactory, private Metadata $metadata)
{}
public function create(string $entityType, User $user): Converter
{
$dateTimeItemTransformer = $this->createDateTimeItemTranformer($entityType, $user);
$dateTimeItemTransformer = $this->createDateTimeItemTransformer($entityType, $user);
$itemConverter = $this->createItemConverter($entityType, $user, $dateTimeItemTransformer);
@@ -62,10 +53,8 @@ class ConverterFactory
$bindingData = new BindingData();
$binder = new Binder($bindingData);
$binder
->bindInstance(User::class, $user);
$binder
->for($className)
->bindValue('$entityType', $entityType)
@@ -76,7 +65,7 @@ class ConverterFactory
return $this->injectableFactory->createWithBinding($className, $bindingContainer);
}
private function createDateTimeItemTranformer(string $entityType, User $user): DateTimeItemTransformer
private function createDateTimeItemTransformer(string $entityType, User $user): DateTimeItemTransformer
{
$className = $this->getDateTimeItemTransformerClassName($entityType);
@@ -111,15 +100,12 @@ class ConverterFactory
$bindingData = new BindingData();
$binder = new Binder($bindingData);
$binder
->bindInstance(User::class, $user);
$binder
->for($className)
->bindValue('$entityType', $entityType)
->bindInstance(DateTimeItemTransformer::class, $dateTimeItemTransformer);
$binder
->for(ItemGeneralConverter::class)
->bindValue('$entityType', $entityType)

View File

@@ -30,11 +30,10 @@
namespace Espo\Core\Select\Where;
use Espo\Core\Exceptions\Error;
use Espo\Entities\User;
use Espo\Core\Utils\DateTime as DateTimeUtil;
use Espo\Core\Utils\Config;
use Espo\Core\Select\Where\Item\Type;
use Espo\Entities\User;
use DateTime;
use DateTimeZone;
@@ -45,16 +44,12 @@ use DateInterval;
*/
class DateTimeItemTransformer
{
protected User $user;
private Config $config;
public function __construct(User $user, Config $config)
{
$this->user = $user;
$this->config = $config;
}
public function __construct(protected User $user, private Config $config)
{}
/**
* @throws Error
*/
public function transform(Item $item): Item
{
$format = DateTimeUtil::SYSTEM_DATE_TIME_FORMAT;
@@ -296,7 +291,6 @@ class DateTimeItemTransformer
case Type::NEXT_MONTH:
$where['type'] = Type::BETWEEN;
$dtFrom = new DateTime('now', new DateTimeZone($timeZone));
$dtFrom = $dt->modify('first day of this month')->setTime(0, 0, 0);
if ($type == Type::LAST_MONTH) {

View File

@@ -29,10 +29,8 @@
namespace Espo\Core\Select\Where;
use Espo\{
ORM\Query\SelectBuilder as QueryBuilder,
ORM\Query\Part\WhereItem as WhereClauseItem,
};
use Espo\ORM\Query\Part\WhereItem as WhereClauseItem;
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
/**
* Converts a where item to a where clause item (for ORM).

View File

@@ -29,28 +29,19 @@
namespace Espo\Core\Select\Where;
use Espo\Core\{
Exceptions\Error,
InjectableFactory,
Utils\Metadata,
Binding\BindingContainer,
Binding\Binder,
Binding\BindingData,
};
use Espo\Core\Binding\Binder;
use Espo\Core\Binding\BindingContainer;
use Espo\Core\Binding\BindingData;
use Espo\Core\InjectableFactory;
use Espo\Core\Utils\Metadata;
use Espo\Entities\User;
use RuntimeException;
class ItemConverterFactory
{
private InjectableFactory $injectableFactory;
private Metadata $metadata;
public function __construct(InjectableFactory $injectableFactory, Metadata $metadata)
{
$this->injectableFactory = $injectableFactory;
$this->metadata = $metadata;
}
public function __construct(private InjectableFactory $injectableFactory, private Metadata $metadata)
{}
public function hasForType(string $type): bool
{
@@ -62,7 +53,7 @@ class ItemConverterFactory
$className = $this->getClassNameForType($type);
if (!$className) {
throw new Error("Where item converter class name is not defined.");
throw new RuntimeException("Where item converter class name is not defined.");
}
$bindingData = new BindingData();
@@ -86,9 +77,7 @@ class ItemConverterFactory
*/
protected function getClassNameForType(string $type): ?string
{
return $this->metadata->get([
'app', 'select', 'whereItemConverterClassNameMap', $type
]);
return $this->metadata->get(['app', 'select', 'whereItemConverterClassNameMap', $type]);
}
public function has(string $entityType, string $attribute, string $type): bool
@@ -101,16 +90,14 @@ class ItemConverterFactory
$className = $this->getClassName($entityType, $attribute, $type);
if (!$className) {
throw new Error("Where item converter class name is not defined.");
throw new RuntimeException("Where item converter class name is not defined.");
}
$bindingData = new BindingData();
$binder = new Binder($bindingData);
$binder
->bindInstance(User::class, $user);
$binder
->for($className)
->bindValue('$entityType', $entityType);
@@ -125,8 +112,7 @@ class ItemConverterFactory
*/
protected function getClassName(string $entityType, string $attribute, string $type): ?string
{
return $this->metadata->get([
'selectDefs', $entityType, 'whereItemConverterClassNameMap', $attribute . '_' . $type
]);
return $this->metadata
->get(['selectDefs', $entityType, 'whereItemConverterClassNameMap', $attribute . '_' . $type]);
}
}

View File

@@ -40,8 +40,7 @@ class Params
private bool $forbidComplexExpressions = false;
private function __construct()
{
}
{}
/**
* @param array<string,mixed> $params