Skip to content

Commit 15287c7

Browse files
guiwodapatrickbrouwers
authored andcommitted
[FEATURE] Alternative Pagination traits (#200)
* Alternative Pagination traits to decouple(ish) from Laravel's Request * Mocked most of Doctrine to test the PaginatorAdapter without a database * Rolled back the `resolveCurrentPath` private method creation
1 parent e2a8780 commit 15287c7

File tree

5 files changed

+312
-83
lines changed

5 files changed

+312
-83
lines changed

src/Pagination/Paginatable.php

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,13 @@
22

33
namespace LaravelDoctrine\ORM\Pagination;
44

5-
use Doctrine\ORM\Query;
6-
5+
/**
6+
* @deprecated Backwards compatibility trait. You should switch to use one of the specific Paginator traits:
7+
*
8+
* @see PaginatesFromRequest
9+
* @see PaginatesFromParams
10+
*/
711
trait Paginatable
812
{
9-
/**
10-
* @param int $perPage
11-
* @param string $pageName
12-
*
13-
* @return \Illuminate\Pagination\LengthAwarePaginator
14-
*/
15-
public function paginateAll($perPage = 15, $pageName = 'page')
16-
{
17-
$query = $this->createQueryBuilder('o')->getQuery();
18-
19-
return $this->paginate($query, $perPage, $pageName);
20-
}
21-
22-
/**
23-
* @param Query $query
24-
* @param int $perPage
25-
* @param bool $fetchJoinCollection
26-
* @param string $pageName
27-
*
28-
* @return \Illuminate\Pagination\LengthAwarePaginator
29-
*/
30-
public function paginate(Query $query, $perPage, $pageName = 'page', $fetchJoinCollection = true)
31-
{
32-
return (new PaginatorAdapter())->make(
33-
$query,
34-
$perPage,
35-
$pageName,
36-
$fetchJoinCollection
37-
);
38-
}
39-
40-
/**
41-
* Creates a new QueryBuilder instance that is prepopulated for this entity name.
42-
*
43-
* @param string $alias
44-
* @param string $indexBy The index for the from.
45-
*
46-
* @return \Doctrine\ORM\QueryBuilder
47-
*/
48-
abstract public function createQueryBuilder($alias, $indexBy = null);
13+
use PaginatesFromRequest;
4914
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace LaravelDoctrine\ORM\Pagination;
4+
5+
use Doctrine\ORM\Query;
6+
7+
trait PaginatesFromParams
8+
{
9+
/**
10+
* @param int $perPage
11+
* @param string $pageName
12+
*
13+
* @return \Illuminate\Pagination\LengthAwarePaginator
14+
*/
15+
public function paginateAll($perPage = 15, $pageName = 'page')
16+
{
17+
$query = $this->createQueryBuilder('o')->getQuery();
18+
19+
return $this->paginate($query, $perPage, $pageName);
20+
}
21+
22+
/**
23+
* @param Query $query
24+
* @param int $perPage
25+
* @param int $page
26+
* @param bool $fetchJoinCollection
27+
*
28+
* @return \Illuminate\Pagination\LengthAwarePaginator
29+
*/
30+
public function paginate(Query $query, $perPage, $page = 1, $fetchJoinCollection = true)
31+
{
32+
return PaginatorAdapter::fromParams(
33+
$query,
34+
$perPage,
35+
$page,
36+
$fetchJoinCollection
37+
)->make();
38+
}
39+
40+
/**
41+
* Creates a new QueryBuilder instance that is prepopulated for this entity name.
42+
*
43+
* @param string $alias
44+
* @param string $indexBy The index for the from.
45+
*
46+
* @return \Doctrine\ORM\QueryBuilder
47+
*/
48+
abstract public function createQueryBuilder($alias, $indexBy = null);
49+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace LaravelDoctrine\ORM\Pagination;
4+
5+
use Doctrine\ORM\Query;
6+
7+
trait PaginatesFromRequest
8+
{
9+
/**
10+
* @param int $perPage
11+
* @param string $pageName
12+
*
13+
* @return \Illuminate\Pagination\LengthAwarePaginator
14+
*/
15+
public function paginateAll($perPage = 15, $pageName = 'page')
16+
{
17+
$query = $this->createQueryBuilder('o')->getQuery();
18+
19+
return $this->paginate($query, $perPage, $pageName);
20+
}
21+
22+
/**
23+
* @param Query $query
24+
* @param int $perPage
25+
* @param bool $fetchJoinCollection
26+
* @param string $pageName
27+
*
28+
* @return \Illuminate\Pagination\LengthAwarePaginator
29+
*/
30+
public function paginate(Query $query, $perPage, $pageName = 'page', $fetchJoinCollection = true)
31+
{
32+
return PaginatorAdapter::fromRequest(
33+
$query,
34+
$perPage,
35+
$pageName,
36+
$fetchJoinCollection
37+
)->make();
38+
}
39+
40+
/**
41+
* Creates a new QueryBuilder instance that is prepopulated for this entity name.
42+
*
43+
* @param string $alias
44+
* @param string $indexBy The index for the from.
45+
*
46+
* @return \Doctrine\ORM\QueryBuilder
47+
*/
48+
abstract public function createQueryBuilder($alias, $indexBy = null);
49+
}

src/Pagination/PaginatorAdapter.php

Lines changed: 85 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace LaravelDoctrine\ORM\Pagination;
44

55
use Doctrine\ORM\AbstractQuery;
6+
use Doctrine\ORM\Query;
67
use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator;
78
use Illuminate\Pagination\LengthAwarePaginator;
89
use Illuminate\Pagination\Paginator;
@@ -14,24 +15,87 @@ class PaginatorAdapter
1415
*/
1516
protected $query;
1617

18+
/**
19+
* @var int
20+
*/
21+
private $perPage;
22+
23+
/**
24+
* @var callable
25+
*/
26+
private $pageResolver;
27+
28+
/**
29+
* @var bool
30+
*/
31+
private $fetchJoinCollection;
32+
33+
/**
34+
* @param AbstractQuery $query
35+
* @param int $perPage
36+
* @param callable $pageResolver
37+
* @param bool $fetchJoinCollection
38+
*/
39+
private function __construct(AbstractQuery $query, $perPage, $pageResolver, $fetchJoinCollection)
40+
{
41+
$this->query = $query;
42+
$this->perPage = $perPage;
43+
$this->pageResolver = $pageResolver;
44+
$this->fetchJoinCollection = $fetchJoinCollection;
45+
}
46+
1747
/**
1848
* @param AbstractQuery $query
1949
* @param int $perPage
2050
* @param string $pageName
2151
* @param bool $fetchJoinCollection
2252
*
23-
* @return LengthAwarePaginator
53+
* @return PaginatorAdapter
2454
*/
25-
public function make(AbstractQuery $query, $perPage = 15, $pageName = 'page', $fetchJoinCollection = true)
55+
public static function fromRequest(AbstractQuery $query, $perPage = 15, $pageName = 'page', $fetchJoinCollection = true)
2656
{
27-
$this->query($query)
28-
->skip($this->getSkipAmount($perPage, $pageName))
29-
->take($perPage);
57+
return new static(
58+
$query,
59+
$perPage,
60+
function () use ($pageName) {
61+
return Paginator::resolveCurrentPage($pageName);
62+
},
63+
$fetchJoinCollection
64+
);
65+
}
3066

31-
return $this->convertToLaravelPaginator(
32-
$this->getDoctrinePaginator($fetchJoinCollection),
67+
/**
68+
* @param AbstractQuery $query
69+
* @param int $perPage
70+
* @param int $page
71+
* @param bool $fetchJoinCollection
72+
*
73+
* @return PaginatorAdapter
74+
*/
75+
public static function fromParams(AbstractQuery $query, $perPage = 15, $page = 1, $fetchJoinCollection = true)
76+
{
77+
return new static(
78+
$query,
3379
$perPage,
34-
$pageName
80+
function () use ($page) {
81+
return $page;
82+
},
83+
$fetchJoinCollection
84+
);
85+
}
86+
87+
public function make()
88+
{
89+
$page = $this->getCurrentPage();
90+
91+
$this->query($this->query)
92+
->skip($this->getSkipAmount($this->perPage, $page))
93+
->take($this->perPage);
94+
95+
return $this->convertToLaravelPaginator(
96+
$this->getDoctrinePaginator(),
97+
$this->perPage,
98+
$page
3599
);
36100
}
37101

@@ -48,7 +112,7 @@ protected function query(AbstractQuery $query)
48112
}
49113

50114
/**
51-
* @return AbstractQuery
115+
* @return AbstractQuery|Query
52116
*/
53117
public function getQuery()
54118
{
@@ -80,74 +144,54 @@ protected function take($perPage)
80144
}
81145

82146
/**
83-
* @param int $perPage
84-
* @param string $pageName
147+
* @param int $perPage
148+
* @param int $page
85149
*
86150
* @return int
87151
*/
88-
protected function getSkipAmount($perPage, $pageName = 'page')
152+
protected function getSkipAmount($perPage, $page)
89153
{
90-
return ($this->getCurrentPage($pageName) - 1) * $perPage;
154+
return ($page - 1) * $perPage;
91155
}
92156

93157
/**
94-
* @param bool $fetchJoinCollection
95-
*
96158
* @return DoctrinePaginator
97159
*/
98-
private function getDoctrinePaginator($fetchJoinCollection)
160+
private function getDoctrinePaginator()
99161
{
100162
return new DoctrinePaginator(
101163
$this->getQuery(),
102-
$fetchJoinCollection
164+
$this->fetchJoinCollection
103165
);
104166
}
105167

106168
/**
107169
* @param DoctrinePaginator $doctrinePaginator
108170
* @param int $perPage
109-
* @param string $pageName
171+
* @param int $page
110172
*
111173
* @return LengthAwarePaginator
112174
*/
113-
protected function convertToLaravelPaginator(DoctrinePaginator $doctrinePaginator, $perPage, $pageName = 'page')
175+
protected function convertToLaravelPaginator(DoctrinePaginator $doctrinePaginator, $perPage, $page)
114176
{
115-
$results = $this->getResults($doctrinePaginator);
116-
$currentPage = $this->getCurrentPage($pageName);
177+
$results = iterator_to_array($doctrinePaginator);
117178
$path = Paginator::resolveCurrentPath();
118179

119180
return new LengthAwarePaginator(
120181
$results,
121182
$doctrinePaginator->count(),
122183
$perPage,
123-
$currentPage,
184+
$page,
124185
compact('path')
125186
);
126187
}
127188

128189
/**
129-
* @param DoctrinePaginator $doctrinePaginator
130-
*
131-
* @return array
132-
*/
133-
protected function getResults(DoctrinePaginator $doctrinePaginator)
134-
{
135-
$results = [];
136-
foreach ($doctrinePaginator as $entity) {
137-
$results[] = $entity;
138-
};
139-
140-
return $results;
141-
}
142-
143-
/**
144-
* @param int $pageName
145-
*
146190
* @return int
147191
*/
148-
protected function getCurrentPage($pageName)
192+
protected function getCurrentPage()
149193
{
150-
$page = Paginator::resolveCurrentPage($pageName);
194+
$page = call_user_func($this->pageResolver);
151195

152196
return $page > 0 ? $page : 1;
153197
}

0 commit comments

Comments
 (0)