select orderer, passing user to order converter
This commit is contained in:
@@ -39,33 +39,31 @@ use Espo\Core\{
|
||||
Select\Order\Item as OrderItem,
|
||||
Select\Order\ItemConverterFactory,
|
||||
Select\Order\MetadataProvider,
|
||||
Select\Order\OrdererFactory,
|
||||
};
|
||||
|
||||
use Espo\{
|
||||
ORM\Query\SelectBuilder as QueryBuilder,
|
||||
Entities\User,
|
||||
};
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
|
||||
class Order
|
||||
{
|
||||
protected string $entityType;
|
||||
private string $entityType;
|
||||
|
||||
protected User $user;
|
||||
private MetadataProvider $metadataProvider;
|
||||
|
||||
protected MetadataProvider $metadataProvider;
|
||||
private ItemConverterFactory $itemConverterFactory;
|
||||
|
||||
protected ItemConverterFactory $itemConverterFactory;
|
||||
private OrdererFactory $ordererFactory;
|
||||
|
||||
public function __construct(
|
||||
string $entityType,
|
||||
User $user,
|
||||
MetadataProvider $metadataProvider,
|
||||
ItemConverterFactory $itemConverterFactory
|
||||
ItemConverterFactory $itemConverterFactory,
|
||||
OrdererFactory $ordererFactory
|
||||
) {
|
||||
$this->entityType = $entityType;
|
||||
$this->user = $user;
|
||||
$this->metadataProvider = $metadataProvider;
|
||||
$this->itemConverterFactory = $itemConverterFactory;
|
||||
$this->ordererFactory = $ordererFactory;
|
||||
}
|
||||
|
||||
public function apply(QueryBuilder $queryBuilder, OrderParams $params): void
|
||||
@@ -88,7 +86,9 @@ class Order
|
||||
}
|
||||
}
|
||||
|
||||
$orderBy = $orderBy ?? $this->metadataProvider->getDefaultOrderBy($this->entityType);
|
||||
if ($orderBy === null) {
|
||||
$orderBy = $this->metadataProvider->getDefaultOrderBy($this->entityType);
|
||||
}
|
||||
|
||||
if (!$orderBy) {
|
||||
return;
|
||||
@@ -97,7 +97,7 @@ class Order
|
||||
$this->applyOrder($queryBuilder, $orderBy, $params->getOrder());
|
||||
}
|
||||
|
||||
protected function applyDefaultOrder(QueryBuilder $queryBuilder, ?string $order): void
|
||||
private function applyDefaultOrder(QueryBuilder $queryBuilder, ?string $order): void
|
||||
{
|
||||
$orderBy = $this->metadataProvider->getDefaultOrderBy($this->entityType);
|
||||
|
||||
@@ -124,13 +124,28 @@ class Order
|
||||
$this->applyOrder($queryBuilder, $orderBy, $order);
|
||||
}
|
||||
|
||||
protected function applyOrder(QueryBuilder $queryBuilder, string $orderBy, ?string $order): void
|
||||
private function applyOrder(QueryBuilder $queryBuilder, string $orderBy, ?string $order): void
|
||||
{
|
||||
if (!$orderBy) {
|
||||
throw new Error("Could not apply order.");
|
||||
throw new Error("Could not apply empty order.");
|
||||
}
|
||||
|
||||
$order = $order ?? SearchParams::ORDER_ASC;
|
||||
if ($order === null) {
|
||||
$order = SearchParams::ORDER_ASC;
|
||||
}
|
||||
|
||||
$hasOrderer = $this->ordererFactory->has($this->entityType, $orderBy);
|
||||
|
||||
if ($hasOrderer) {
|
||||
$orderer = $this->ordererFactory->create($this->entityType, $orderBy);
|
||||
|
||||
$orderer->apply(
|
||||
$queryBuilder,
|
||||
OrderItem::create($orderBy, $order)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$resultOrderBy = $orderBy;
|
||||
|
||||
|
||||
@@ -29,11 +29,14 @@
|
||||
|
||||
namespace Espo\Core\Select\Order;
|
||||
|
||||
use Espo\Core\{
|
||||
Exceptions\Error,
|
||||
InjectableFactory,
|
||||
Utils\Metadata,
|
||||
};
|
||||
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;
|
||||
|
||||
class ItemConverterFactory
|
||||
{
|
||||
@@ -41,10 +44,13 @@ class ItemConverterFactory
|
||||
|
||||
private Metadata $metadata;
|
||||
|
||||
public function __construct(InjectableFactory $injectableFactory, 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 has(string $entityType, string $field): bool
|
||||
@@ -60,9 +66,14 @@ class ItemConverterFactory
|
||||
throw new Error("Order item converter class name is not defined.");
|
||||
}
|
||||
|
||||
return $this->injectableFactory->createWith($className, [
|
||||
'entityType' => $entityType,
|
||||
]);
|
||||
$container = BindingContainerBuilder::create()
|
||||
->bindInstance(User::class, $this->user)
|
||||
->inContext($className, function (ContextualBinder $binder) use ($entityType) {
|
||||
$binder->bindValue('$entityType', $entityType);
|
||||
})
|
||||
->build();
|
||||
|
||||
return $this->injectableFactory->createWithBinding($className, $container);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,12 +82,12 @@ class ItemConverterFactory
|
||||
private function getClassName(string $entityType, string $field): ?string
|
||||
{
|
||||
/** @var ?class-string<ItemConverter> */
|
||||
$className = $this->metadata->get([
|
||||
$className1 = $this->metadata->get([
|
||||
'selectDefs', $entityType, 'orderItemConverterClassNameMap', $field
|
||||
]);
|
||||
|
||||
if ($className) {
|
||||
return $className;
|
||||
if ($className1) {
|
||||
return $className1;
|
||||
}
|
||||
|
||||
$type = $this->metadata->get([
|
||||
@@ -88,19 +99,19 @@ class ItemConverterFactory
|
||||
}
|
||||
|
||||
/** @var ?class-string<ItemConverter> */
|
||||
$className = $this->metadata->get([
|
||||
$className2 = $this->metadata->get([
|
||||
'app', 'select', 'orderItemConverterClassNameMap', $type
|
||||
]);
|
||||
|
||||
if ($className) {
|
||||
return $className;
|
||||
if ($className2) {
|
||||
return $className2;
|
||||
}
|
||||
|
||||
$className = 'Espo\\Core\\Select\\Order\\ItemConverters\\' . ucfirst($type) . 'Type';
|
||||
$className3 = 'Espo\\Core\\Select\\Order\\ItemConverters\\' . ucfirst($type) . 'Type';
|
||||
|
||||
if (class_exists($className)) {
|
||||
if (class_exists($className3)) {
|
||||
/** @var class-string<ItemConverter> */
|
||||
return $className;
|
||||
return $className3;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2022 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* 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 General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Select\Order;
|
||||
|
||||
use Espo\ORM\Query\SelectBuilder;
|
||||
|
||||
interface Orderer
|
||||
{
|
||||
public function apply(SelectBuilder $queryBuilder, Item $item): void;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2022 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* 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 General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
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;
|
||||
|
||||
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 has(string $entityType, string $field): bool
|
||||
{
|
||||
return (bool) $this->getClassName($entityType, $field);
|
||||
}
|
||||
|
||||
public function create(string $entityType, string $field): Orderer
|
||||
{
|
||||
$className = $this->getClassName($entityType, $field);
|
||||
|
||||
if (!$className) {
|
||||
throw new Error("Orderer class name is not defined.");
|
||||
}
|
||||
|
||||
$container = BindingContainerBuilder::create()
|
||||
->bindInstance(User::class, $this->user)
|
||||
->inContext($className, function (ContextualBinder $binder) use ($entityType) {
|
||||
$binder->bindValue('$entityType', $entityType);
|
||||
})
|
||||
->build();
|
||||
|
||||
return $this->injectableFactory->createWithBinding($className, $container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ?class-string<Orderer>
|
||||
*/
|
||||
private function getClassName(string $entityType, string $field): ?string
|
||||
{
|
||||
/** @var ?class-string<Orderer> */
|
||||
return $this->metadata->get([
|
||||
'selectDefs', $entityType, 'ordererClassNameMap', $field
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -41,20 +41,23 @@ use Espo\Core\{
|
||||
Select\Order\ItemConverterFactory,
|
||||
Select\Order\ItemConverter,
|
||||
Select\Order\MetadataProvider,
|
||||
Select\Order\OrdererFactory,
|
||||
Select\Order\Orderer,
|
||||
};
|
||||
|
||||
use Espo\{
|
||||
ORM\Query\SelectBuilder as QueryBuilder,
|
||||
Entities\User,
|
||||
};
|
||||
|
||||
class OrderApplierTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
private ?OrdererFactory $ordererFactory = null;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->user = $this->createMock(User::class);
|
||||
$this->metadataProvider = $this->createMock(MetadataProvider::class);
|
||||
$this->itemConverterFactory = $this->createMock(ItemConverterFactory::class);
|
||||
$this->ordererFactory = $this->createMock(OrdererFactory::class);
|
||||
$this->queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
$this->params = $this->createMock(OrderParams::class);
|
||||
|
||||
@@ -62,9 +65,9 @@ class OrderApplierTest extends \PHPUnit\Framework\TestCase
|
||||
|
||||
$this->applier = new OrderApplier(
|
||||
$this->entityType,
|
||||
$this->user,
|
||||
$this->metadataProvider,
|
||||
$this->itemConverterFactory
|
||||
$this->itemConverterFactory,
|
||||
$this->ordererFactory
|
||||
);
|
||||
}
|
||||
|
||||
@@ -190,8 +193,54 @@ class OrderApplierTest extends \PHPUnit\Framework\TestCase
|
||||
$this->applier->apply($this->queryBuilder, $this->params);
|
||||
}
|
||||
|
||||
public function testApplyWithOrderer()
|
||||
{
|
||||
$order = SearchParams::ORDER_DESC;
|
||||
$orderBy = 'testField';
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('forceDefault')
|
||||
->willReturn(false);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrder')
|
||||
->willReturn($order);
|
||||
|
||||
$this->params
|
||||
->expects($this->any())
|
||||
->method('getOrderBy')
|
||||
->willReturn($orderBy);
|
||||
|
||||
$this->ordererFactory
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with($this->entityType, $orderBy)
|
||||
->willReturn(true);
|
||||
|
||||
$orderer = $this->createMock(Orderer::class);
|
||||
|
||||
$this->ordererFactory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->entityType, $orderBy)
|
||||
->willReturn($orderer);
|
||||
|
||||
$orderer
|
||||
->expects($this->once())
|
||||
->method('apply')
|
||||
->with($this->queryBuilder, Item::create($orderBy, $order));
|
||||
|
||||
$this->applier->apply($this->queryBuilder, $this->params);
|
||||
}
|
||||
|
||||
protected function initApplyOrderTest(
|
||||
string $orderBy, string $order, string $fieldType, ?OrderList $converterResult = null, bool $notExisting = false
|
||||
string $orderBy,
|
||||
string $order,
|
||||
string $fieldType,
|
||||
?OrderList $converterResult = null,
|
||||
bool $notExisting = false
|
||||
) {
|
||||
$this->metadataProvider
|
||||
->expects($this->any())
|
||||
@@ -235,8 +284,8 @@ class OrderApplierTest extends \PHPUnit\Framework\TestCase
|
||||
->method('convert')
|
||||
->with($item)
|
||||
->willReturn($converterResult);
|
||||
} else {
|
||||
|
||||
}
|
||||
else {
|
||||
if ($notExisting) {
|
||||
$this->expectException(Error::class);
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
namespace tests\unit\Espo\Core\Select\Order;
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\Core\{
|
||||
Select\Order\ItemConverterFactory,
|
||||
Select\Order\ItemConverter,
|
||||
@@ -37,16 +39,21 @@ use Espo\Core\{
|
||||
InjectableFactory,
|
||||
};
|
||||
|
||||
use Espo\Core\Binding\BindingContainerBuilder;
|
||||
use Espo\Core\Binding\ContextualBinder;
|
||||
|
||||
class ItemConverterFactoryTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->injectableFactory = $this->createMock(InjectableFactory::class);
|
||||
$this->metadata = $this->createMock(Metadata::class);
|
||||
$this->user = $this->createMock(User::class);
|
||||
|
||||
$this->factory = new ItemConverterFactory(
|
||||
$this->injectableFactory,
|
||||
$this->metadata
|
||||
$this->metadata,
|
||||
$this->user
|
||||
);
|
||||
}
|
||||
|
||||
@@ -105,14 +112,19 @@ class ItemConverterFactoryTest extends \PHPUnit\Framework\TestCase
|
||||
|
||||
$object = $this->createMock($className);
|
||||
|
||||
$container = BindingContainerBuilder::create()
|
||||
->bindInstance(User::class, $this->user)
|
||||
->inContext($className, function (ContextualBinder $binder) use ($entityType) {
|
||||
$binder->bindValue('$entityType', $entityType);
|
||||
})
|
||||
->build();
|
||||
|
||||
$this->injectableFactory
|
||||
->expects($this->once())
|
||||
->method('createWith')
|
||||
->method('createWithBinding')
|
||||
->with(
|
||||
$className,
|
||||
[
|
||||
'entityType' => $entityType,
|
||||
]
|
||||
$container
|
||||
)
|
||||
->willReturn($object);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user