diff --git a/src/ExpressionWithShorthands.php b/src/ExpressionWithShorthands.php index 37f3c85083ab59f0b957aaa628427fedee271fc4..d56b407079284b2b42ab6b6c782746985b594a87 100644 --- a/src/ExpressionWithShorthands.php +++ b/src/ExpressionWithShorthands.php @@ -10,6 +10,8 @@ use Grifart\Tables\Conditions\IsNull; use Grifart\Tables\OrderBy\Direction; use Grifart\Tables\OrderBy\Nulls; use Grifart\Tables\OrderBy\OrderBy; +use Grifart\Tables\OrderBy\OrderByDirection; +use Grifart\Tables\OrderBy\OrderByValues; /** * @template ValueType @@ -35,11 +37,19 @@ abstract class ExpressionWithShorthands implements Expression public function ascending(Nulls|null $nulls = null): OrderBy { - return new OrderBy($this, nulls: $nulls); + return new OrderByDirection($this, nulls: $nulls); } public function descending(Nulls|null $nulls = null): OrderBy { - return new OrderBy($this, direction: Direction::Descending, nulls: $nulls); + return new OrderByDirection($this, direction: Direction::Descending, nulls: $nulls); + } + + /** + * @param list<ValueType> $values + */ + public function byValues(array $values): OrderBy + { + return new OrderByValues($this, $values); } } diff --git a/src/OrderBy/OrderBy.php b/src/OrderBy/OrderBy.php index a5fe538784da391acbfc1a7f92b37959069902b3..932fdc4b0e7c63862f87792a18823cd1bb55f648 100644 --- a/src/OrderBy/OrderBy.php +++ b/src/OrderBy/OrderBy.php @@ -5,31 +5,11 @@ declare(strict_types=1); namespace Grifart\Tables\OrderBy; use Dibi\Expression as DibiExpression; -use Grifart\Tables\Expression; -final class OrderBy +interface OrderBy { - private readonly Nulls $nulls; - /** - * @param Expression<mixed> $expression + * @return DibiExpression the ORDER BY part of a Dibi query */ - public function __construct( - private readonly Expression $expression, - private readonly Direction $direction = Direction::Ascending, - Nulls|null $nulls = null, - ) - { - $this->nulls = $nulls ?? Nulls::default($this->direction); - } - - public function toSql(): DibiExpression - { - return new DibiExpression( - '? %ex %ex', - $this->expression->toSql(), - $this->direction->toSql(), - $this->nulls->toSql(), - ); - } + public function toSql(): DibiExpression; } diff --git a/src/OrderBy/OrderByDirection.php b/src/OrderBy/OrderByDirection.php new file mode 100644 index 0000000000000000000000000000000000000000..30c271642ffc172e6ed5d5004c6012a77ca7ce65 --- /dev/null +++ b/src/OrderBy/OrderByDirection.php @@ -0,0 +1,35 @@ +<?php + +declare(strict_types=1); + +namespace Grifart\Tables\OrderBy; + +use Dibi\Expression as DibiExpression; +use Grifart\Tables\Expression; + +final class OrderByDirection implements OrderBy +{ + private readonly Nulls $nulls; + + /** + * @param Expression<mixed> $expression + */ + public function __construct( + private readonly Expression $expression, + private readonly Direction $direction = Direction::Ascending, + Nulls|null $nulls = null, + ) + { + $this->nulls = $nulls ?? Nulls::default($this->direction); + } + + public function toSql(): DibiExpression + { + return new DibiExpression( + '? %ex %ex', + $this->expression->toSql(), + $this->direction->toSql(), + $this->nulls->toSql(), + ); + } +} diff --git a/src/OrderBy/OrderByValues.php b/src/OrderBy/OrderByValues.php new file mode 100644 index 0000000000000000000000000000000000000000..a318c3497464bd506f567f3e784b76f9ba23d3cb --- /dev/null +++ b/src/OrderBy/OrderByValues.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +namespace Grifart\Tables\OrderBy; + +use Dibi\Expression as DibiExpression; +use Grifart\Tables\Expression; +use Grifart\Tables\Types\ArrayType; + +/** + * @template ValueType + */ +final class OrderByValues implements OrderBy +{ + /** + * @param Expression<ValueType> $expression + * @param ValueType[] $values + */ + public function __construct( + private readonly Expression $expression, + private readonly array $values, + ) {} + + public function toSql(): DibiExpression + { + return new DibiExpression( + 'array_position(?, ?)', + (ArrayType::of($this->expression->getType()))->toDatabase($this->values), + $this->expression->toSql(), + ); + } +} diff --git a/src/TableManager.php b/src/TableManager.php index 1299ae380802871cf4d7cd155585ee3019ab0c82..75bd5ea5d3d0be8e3e25ff639ab0d9061214eadf 100644 --- a/src/TableManager.php +++ b/src/TableManager.php @@ -8,6 +8,7 @@ use Dibi\Connection; use Grifart\Tables\Conditions\Composite; use Grifart\Tables\Conditions\Condition; use Grifart\Tables\OrderBy\OrderBy; +use Grifart\Tables\OrderBy\OrderByDirection; use Nette\Utils\Paginator; use function Functional\map; @@ -85,7 +86,7 @@ final class TableManager 'ORDER BY %by', \count($orderBy) > 0 ? map($orderBy, function (OrderBy|Expression $orderBy) { if ($orderBy instanceof Expression) { - $orderBy = new OrderBy($orderBy); + $orderBy = new OrderByDirection($orderBy); } return $orderBy->toSql()->getValues(); diff --git a/tests/TableTest.php b/tests/TableTest.php index 0262c0d779ba6666ac63d8818272f7775e22bf54..edfccfa0d1f0f648d7b7887dc230a2cac4a047ec 100644 --- a/tests/TableTest.php +++ b/tests/TableTest.php @@ -72,6 +72,16 @@ $orderByNullsLast = $table->findBy([], orderBy: [$table->details()->ascending(Nu Assert::count(3, $orderByNullsLast); Assert::same(null, $orderByNullsLast[2]->getDetails()); +$orderByValues = $table->findBy([], orderBy: [$table->id()->byValues([ + new Uuid('2bec3f23-a210-455c-b907-bb69a99d07b2'), + new Uuid('9493decd-4b9c-45d6-9960-0c94dc9be353'), + new Uuid('fb05a832-5729-4b1f-b064-fbc08cacbe43'), +])]); +Assert::count(3, $orderByValues); +Assert::same('2bec3f23-a210-455c-b907-bb69a99d07b2', $orderByValues[0]->getId()->get()); +Assert::same('9493decd-4b9c-45d6-9960-0c94dc9be353', $orderByValues[1]->getId()->get()); +Assert::same('fb05a832-5729-4b1f-b064-fbc08cacbe43', $orderByValues[2]->getId()->get()); + $paginator = new Paginator(); $paginator->setItemsPerPage(1); $paginator->setPage(2);