Skip to content

Commit

Permalink
unify logic around cursor paginate (#47094)
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell authored May 15, 2023
1 parent d6ffa44 commit 3dfe181
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 19 deletions.
25 changes: 16 additions & 9 deletions src/Illuminate/Database/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -969,19 +969,26 @@ protected function ensureOrderForCursorPagination($shouldReverse = false)
$this->enforceOrderBy();
}

if ($shouldReverse) {
$this->query->orders = collect($this->query->orders)->map(function ($order) {
$order['direction'] = $order['direction'] === 'asc' ? 'desc' : 'asc';

$reverseDirection = function ($order) {
if (! isset($order['direction'])) {
return $order;
})->toArray();
}
}

$order['direction'] = $order['direction'] === 'asc' ? 'desc' : 'asc';

if ($this->query->unionOrders) {
return collect($this->query->unionOrders);
return $order;
};

if ($shouldReverse) {
$this->query->orders = collect($this->query->orders)->map($reverseDirection)->toArray();
$this->query->unionOrders = collect($this->query->unionOrders)->map($reverseDirection)->toArray();
}

return collect($this->query->orders);
$orders = ! empty($this->query->unionOrders) ? $this->query->unionOrders : $this->query->orders;

return collect($orders)
->filter(fn ($order) => Arr::has($order, 'direction'))
->values();
}

/**
Expand Down
31 changes: 22 additions & 9 deletions src/Illuminate/Database/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2793,17 +2793,30 @@ public function cursorPaginate($perPage = 15, $columns = ['*'], $cursorName = 'c
*/
protected function ensureOrderForCursorPagination($shouldReverse = false)
{
$this->enforceOrderBy();

return collect($this->orders ?? $this->unionOrders ?? [])->filter(function ($order) {
return Arr::has($order, 'direction');
})->when($shouldReverse, function (Collection $orders) {
return $orders->map(function ($order) {
$order['direction'] = $order['direction'] === 'asc' ? 'desc' : 'asc';
if (empty($this->orders) && empty($this->unionOrders)) {
$this->enforceOrderBy();
}

$reverseDirection = function ($order) {
if (! isset($order['direction'])) {
return $order;
});
})->values();
}

$order['direction'] = $order['direction'] === 'asc' ? 'desc' : 'asc';

return $order;
};

if ($shouldReverse) {
$this->orders = collect($this->orders)->map($reverseDirection)->toArray();
$this->unionOrders = collect($this->unionOrders)->map($reverseDirection)->toArray();
}

$orders = ! empty($this->unionOrders) ? $this->unionOrders : $this->orders;

return collect($orders)
->filter(fn ($order) => Arr::has($order, 'direction'))
->values();
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/Database/DatabaseQueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5008,7 +5008,7 @@ public function testCursorPaginateWithUnionWheresReverseOrder()

$builder->shouldReceive('get')->once()->andReturnUsing(function () use ($builder, $results, $ts) {
$this->assertEquals(
'(select "id", "start_time" as "created_at", \'video\' as type from "videos" where ("start_time" < ?)) union (select "id", "created_at", \'news\' as type from "news" where ("start_time" < ?)) order by "created_at" asc limit 17',
'(select "id", "start_time" as "created_at", \'video\' as type from "videos" where ("start_time" < ?)) union (select "id", "created_at", \'news\' as type from "news" where ("start_time" < ?)) order by "created_at" desc limit 17',
$builder->toSql());
$this->assertEquals([$ts], $builder->bindings['where']);
$this->assertEquals([$ts], $builder->bindings['union']);
Expand Down

0 comments on commit 3dfe181

Please sign in to comment.