diff --git a/application/Espo/Core/Select/Applier/Appliers/Order.php b/application/Espo/Core/Select/Applier/Appliers/Order.php index 92651ac16b..b33f3cdb6a 100644 --- a/application/Espo/Core/Select/Applier/Appliers/Order.php +++ b/application/Espo/Core/Select/Applier/Appliers/Order.php @@ -29,6 +29,8 @@ namespace Espo\Core\Select\Applier\Appliers; +use Espo\ORM\Query\Part\OrderList; + use Espo\Core\{ Exceptions\Error, Exceptions\Forbidden, @@ -141,11 +143,13 @@ class Order if ($hasItemConverter) { $converter = $this->itemConverterFactory->create($this->entityType, $orderBy); - $resultOrderBy = $converter->convert( - OrderItem::fromArray([ - 'orderBy' => $orderBy, - 'order' => $order, - ]) + $resultOrderBy = $this->orderListToArray( + $converter->convert( + OrderItem::fromArray([ + 'orderBy' => $orderBy, + 'order' => $order, + ]) + ) ); } else if (in_array($type, ['link', 'file', 'image', 'linkOne'])) { @@ -185,4 +189,18 @@ class Order $queryBuilder->order($resultOrderBy); } + + private function orderListToArray(OrderList $orderList): array + { + $list = []; + + foreach ($orderList as $order) { + $list[] = [ + $order->getExpression()->getValue(), + $order->getDirection(), + ]; + } + + return $list; + } } diff --git a/application/Espo/Core/Select/Order/ItemConverter.php b/application/Espo/Core/Select/Order/ItemConverter.php index 0593a1b04c..b5cc820b04 100644 --- a/application/Espo/Core/Select/Order/ItemConverter.php +++ b/application/Espo/Core/Select/Order/ItemConverter.php @@ -29,7 +29,9 @@ namespace Espo\Core\Select\Order; +use Espo\ORM\Query\Part\OrderList; + interface ItemConverter { - public function convert(Item $item): array; + public function convert(Item $item): OrderList; } diff --git a/application/Espo/Core/Select/Order/ItemConverters/AddressType.php b/application/Espo/Core/Select/Order/ItemConverters/AddressType.php index 6fb45b04c2..2cc95cd252 100644 --- a/application/Espo/Core/Select/Order/ItemConverters/AddressType.php +++ b/application/Espo/Core/Select/Order/ItemConverters/AddressType.php @@ -29,6 +29,9 @@ 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, @@ -36,15 +39,15 @@ use Espo\Core\{ class AddressType implements ItemConverter { - public function convert(Item $item): array + public function convert(Item $item): OrderList { $orderBy = $item->getOrderBy(); - $order = $item->getOrder(); + $order = $item->getOrder() ?? Order::ASC; - return [ - [$orderBy . 'Country', $order], - [$orderBy . 'City', $order], - [$orderBy . 'Street', $order], - ]; + return OrderList::create([ + Order::fromString($orderBy . 'Country')->withDirection($order), + Order::fromString($orderBy . 'City')->withDirection($order), + Order::fromString($orderBy . 'Street')->withDirection($order), + ]); } } diff --git a/application/Espo/Core/Select/Order/ItemConverters/EnumType.php b/application/Espo/Core/Select/Order/ItemConverters/EnumType.php index bbc53f0316..9fab7e4fa3 100644 --- a/application/Espo/Core/Select/Order/ItemConverters/EnumType.php +++ b/application/Espo/Core/Select/Order/ItemConverters/EnumType.php @@ -29,6 +29,10 @@ 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, @@ -50,19 +54,19 @@ class EnumType implements ItemConverter $this->metadata = $metadata; } - public function convert(Item $item): array + public function convert(Item $item): OrderList { $orderBy = $item->getOrderBy(); - $order = $item->getOrder(); + $order = $item->getOrder() ?? SearchParams::ORDER_ASC; $list = $this->metadata->get([ 'entityDefs', $this->entityType, 'fields', $orderBy, 'options' ]); if (!$list || !is_array($list) || !count($list)) { - return [ - [$orderBy, $order] - ]; + return OrderList::create([ + Order::fromString($orderBy)->withDirection($order) + ]); } $isSorted = $this->metadata->get([ @@ -77,14 +81,8 @@ class EnumType implements ItemConverter $list = array_reverse($list); } - foreach ($list as $i => $listItem) { - $list[$i] = str_replace(',', '_COMMA_', $listItem); - } - - return [ - [ - 'LIST:' . $orderBy . ':' . implode(',', $list) - ] - ]; + return OrderList::create([ + Order::createByPositionInList(Expression::column($orderBy), $list), + ]); } } diff --git a/application/Espo/ORM/Query/Part/OrderList.php b/application/Espo/ORM/Query/Part/OrderList.php new file mode 100644 index 0000000000..901031807b --- /dev/null +++ b/application/Espo/ORM/Query/Part/OrderList.php @@ -0,0 +1,100 @@ +list = $list; + } + + /** + * Create an instance. + * + * @param Order[] $list + */ + public static function create(array $list): self + { + return new self($list); + } + + /** + * @return void + */ + public function rewind() + { + $this->position = 0; + } + + /** + * @return Order + */ + public function current() + { + return $this->list[$this->position]; + } + + /** + * + * @return int + */ + public function key() + { + return $this->position; + } + + public function next() + { + ++$this->position; + } + + /** + * @return bool + */ + public function valid() + { + return isset($this->list[$this->position]); + } +} diff --git a/tests/unit/Espo/Core/Select/Applier/Appliers/OrderApplierTest.php b/tests/unit/Espo/Core/Select/Applier/Appliers/OrderApplierTest.php index 2a28296fff..f786503bd8 100644 --- a/tests/unit/Espo/Core/Select/Applier/Appliers/OrderApplierTest.php +++ b/tests/unit/Espo/Core/Select/Applier/Appliers/OrderApplierTest.php @@ -29,6 +29,9 @@ namespace tests\unit\Espo\Core\Select\Applier\Appliers; +use Espo\ORM\Query\Part\OrderList; +use Espo\ORM\Query\Part\Order; + use Espo\Core\{ Exceptions\Error, Select\Applier\Appliers\Order as OrderApplier, @@ -47,7 +50,7 @@ use Espo\{ class OrderApplierTest extends \PHPUnit\Framework\TestCase { - protected function setUp() : void + protected function setUp(): void { $this->user = $this->createMock(User::class); $this->metadataProvider = $this->createMock(MetadataProvider::class); @@ -147,7 +150,11 @@ class OrderApplierTest extends \PHPUnit\Framework\TestCase ->with($this->entityType) ->willReturn($orderBy); - $this->initApplyOrderTest($orderBy, $order, 'varchar', [['hello', SearchParams::ORDER_DESC]]); + $converterResult = OrderList::create([ + Order::fromString('hello')->withDesc(), + ]); + + $this->initApplyOrderTest($orderBy, $order, 'varchar', $converterResult); $this->applier->apply($this->queryBuilder, $this->params); } @@ -184,7 +191,7 @@ class OrderApplierTest extends \PHPUnit\Framework\TestCase } protected function initApplyOrderTest( - string $orderBy, string $order, string $fieldType, ?array $converterResult = null, bool $notExisting = false + string $orderBy, string $order, string $fieldType, ?OrderList $converterResult = null, bool $notExisting = false ) { $this->metadataProvider ->expects($this->any()) @@ -246,7 +253,8 @@ class OrderApplierTest extends \PHPUnit\Framework\TestCase ->willReturn(false); } - $expectedOrderBy = $converterResult ?? [[$orderBy, $order]]; + $expectedOrderBy = ($converterResult ? $this->orderListToArray($converterResult): null) + ?? [[$orderBy, $order]]; $expectedOrderBy[] = ['id', $order]; @@ -255,4 +263,18 @@ class OrderApplierTest extends \PHPUnit\Framework\TestCase ->method('order') ->with($expectedOrderBy); } + + private function orderListToArray(OrderList $orderList): array + { + $list = []; + + foreach ($orderList as $order) { + $list[] = [ + $order->getExpression()->getValue(), + $order->getDirection(), + ]; + } + + return $list; + } }