Skip to content

Commit bd2cf3b

Browse files
committed
[#514] Isolate paginator count while preserving terminal count semantics
1 parent 432b88d commit bd2cf3b

3 files changed

Lines changed: 25 additions & 10 deletions

File tree

src/Database/Adapters/Sleekdb/Statements/Result.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,12 @@ public function first(): DbalInterface
128128
*/
129129
public function count(): int
130130
{
131-
$counter = clone $this;
132-
$counter->queryBuilder = null;
133-
$counter->builderPrepared = false;
134-
135-
return count($counter->fetchFilteredResultsFromBuilder($counter->getBuilder()));
131+
try {
132+
$results = $this->fetchFilteredResultsFromBuilder($this->getBuilder());
133+
return count($results);
134+
} finally {
135+
$this->resetBuilderState();
136+
}
136137
}
137138

138139
/**

src/Paginator/Adapters/ModelPaginator.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Quantum\Paginator\Contracts\PaginatorInterface;
2020
use Quantum\Paginator\Traits\PaginatorTrait;
2121
use Quantum\App\Exceptions\BaseException;
22+
use Quantum\Model\Exceptions\ModelException;
2223
use Quantum\Di\Exceptions\DiException;
2324
use Quantum\Model\ModelCollection;
2425
use Quantum\Model\DbModel;
@@ -38,15 +39,15 @@ class ModelPaginator implements PaginatorInterface
3839
private DbModel $model;
3940

4041
/**
41-
* @throws DiException|ReflectionException
42+
* @throws DiException|ReflectionException|ModelException|BaseException
4243
*/
4344
public function __construct(DbModel $model, int $perPage, int $page = 1)
4445
{
4546
$this->initialize($perPage, $page);
4647

4748
$this->model = $model;
4849
$this->modelClass = $model->getModelName();
49-
$this->total = $model->count();
50+
$this->total = $this->getCountFromClonedModel($model);
5051
}
5152

5253
/**
@@ -99,4 +100,17 @@ public function lastItem(): ?Model
99100

100101
return $data->last();
101102
}
103+
104+
/**
105+
* Counts results on an isolated model/ORM clone so total calculation cannot mutate
106+
* the live model query state later used by paginator data().
107+
* @throws ModelException|BaseException
108+
*/
109+
private function getCountFromClonedModel(DbModel $model): int
110+
{
111+
$countModel = clone $model;
112+
$countModel->setOrmInstance(clone $model->getOrmInstance());
113+
114+
return $countModel->count();
115+
}
102116
}

tests/Unit/Database/Adapters/Sleekdb/Statements/ResultSleekTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function testSleekAsArray(): void
8787
$this->assertIsArray($user->asArray());
8888
}
8989

90-
public function testSleekCountDoesNotResetCriteriaState(): void
90+
public function testSleekCountResetsCriteriaState(): void
9191
{
9292
$eventsModel = new SleekDbal('events');
9393

@@ -99,8 +99,8 @@ public function testSleekCountDoesNotResetCriteriaState(): void
9999
->orderBy('title', 'asc')
100100
->get();
101101

102-
$this->assertCount(3, $events);
103-
$this->assertEquals('Design', $events[0]->prop('title'));
102+
$this->assertCount(7, $events);
103+
$this->assertEquals('Art', $events[0]->prop('title'));
104104
}
105105

106106
public function testSleekPaginateRetainsCriteriaAfterCount(): void

0 commit comments

Comments
 (0)