diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a0a120f2..777a22304 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. ## [4.6.0] - upcoming * Add `DocumentTrait` to use any 3rd party model with MongoDB @GromNaN in [#2580](https://github.com/mongodb/laravel-mongodb/pull/2580) +* Add support for Closure for Embed pagination @GromNaN in [#3027](https://github.com/mongodb/laravel-mongodb/pull/3027) ## [4.5.0] - 2024-06-20 diff --git a/src/Relations/EmbedsMany.php b/src/Relations/EmbedsMany.php index be7039506..72c77b598 100644 --- a/src/Relations/EmbedsMany.php +++ b/src/Relations/EmbedsMany.php @@ -4,6 +4,7 @@ namespace MongoDB\Laravel\Relations; +use Closure; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; use Illuminate\Pagination\LengthAwarePaginator; @@ -18,6 +19,7 @@ use function is_array; use function method_exists; use function throw_if; +use function value; class EmbedsMany extends EmbedsOneOrMany { @@ -288,21 +290,22 @@ protected function associateExisting($model) } /** - * @param int|null $perPage - * @param array $columns - * @param string $pageName - * @param int|null $page + * @param int|Closure $perPage + * @param array|string $columns + * @param string $pageName + * @param int|null $page + * @param Closure|int|null $total * * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator */ - public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null) + public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null, $total = null) { $page = $page ?: Paginator::resolveCurrentPage($pageName); - $perPage = $perPage ?: $this->related->getPerPage(); - $results = $this->getEmbedded(); $results = $this->toCollection($results); - $total = $results->count(); + $total = value($total) ?? $results->count(); + $perPage = $perPage ?: $this->related->getPerPage(); + $perPage = $perPage instanceof Closure ? $perPage($total) : $perPage; $start = ($page - 1) * $perPage; $sliced = $results->slice( diff --git a/tests/EmbeddedRelationsTest.php b/tests/EmbeddedRelationsTest.php index 2dd558679..00a84360c 100644 --- a/tests/EmbeddedRelationsTest.php +++ b/tests/EmbeddedRelationsTest.php @@ -925,6 +925,12 @@ public function testPaginateEmbedsMany() $results = $user->addresses()->paginate(2); $this->assertEquals(2, $results->count()); $this->assertEquals(3, $results->total()); + + // With Closures + $results = $user->addresses()->paginate(fn () => 3, page: 1, total: fn () => 5); + $this->assertEquals(3, $results->count()); + $this->assertEquals(5, $results->total()); + $this->assertEquals(3, $results->perPage()); } public function testGetQueueableRelationsEmbedsMany()