|
1 <?php |
|
2 |
|
3 /* |
|
4 * This file is part of the Pagerfanta package. |
|
5 * |
|
6 * (c) Pablo Díez <pablodip@gmail.com> |
|
7 * |
|
8 * For the full copyright and license information, please view the LICENSE |
|
9 * file that was distributed with this source code. |
|
10 */ |
|
11 |
|
12 namespace Pagerfanta\Adapter; |
|
13 |
|
14 use Doctrine\ORM\QueryBuilder; |
|
15 use Doctrine\ORM\Query; |
|
16 use Doctrine\ORM\NoResultException; |
|
17 |
|
18 /** |
|
19 * DoctrineORMAdapter. |
|
20 * |
|
21 * @author Pablo Díez <pablodip@gmail.com> |
|
22 * @author Benjamin Eberlei <kontakt@beberlei.de> |
|
23 * |
|
24 * @api |
|
25 */ |
|
26 class DoctrineORMAdapter implements AdapterInterface |
|
27 { |
|
28 /** |
|
29 * @var Query |
|
30 */ |
|
31 private $query; |
|
32 |
|
33 private $fetchJoinCollection; |
|
34 |
|
35 /** |
|
36 * Constructor. |
|
37 * |
|
38 * @param Query|QueryBuilder $query A Doctrine ORM query or query builder. |
|
39 * @param Boolean $fetchJoinCollection Whether the query joins a collection (false by default). |
|
40 * |
|
41 * @api |
|
42 */ |
|
43 public function __construct($query, $fetchJoinCollection = false) |
|
44 { |
|
45 if ($query instanceof QueryBuilder) { |
|
46 $query = $query->getQuery(); |
|
47 } |
|
48 |
|
49 $this->query = $query; |
|
50 $this->fetchJoinCollection = (Boolean) $fetchJoinCollection; |
|
51 } |
|
52 |
|
53 /** |
|
54 * Returns the query |
|
55 * |
|
56 * @return Query |
|
57 * |
|
58 * @api |
|
59 */ |
|
60 public function getQuery() |
|
61 { |
|
62 return $this->query; |
|
63 } |
|
64 |
|
65 /** |
|
66 * Returns whether the query joins a collection. |
|
67 * |
|
68 * @return Boolean Whether the query joins a collection. |
|
69 */ |
|
70 public function getFetchJoinCollection() |
|
71 { |
|
72 return $this->fetchJoinCollection; |
|
73 } |
|
74 |
|
75 /** |
|
76 * {@inheritdoc} |
|
77 */ |
|
78 public function getNbResults() |
|
79 { |
|
80 /* @var $countQuery Query */ |
|
81 $countQuery = $this->cloneQuery($this->query); |
|
82 |
|
83 $countQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\CountWalker')); |
|
84 $countQuery->setFirstResult(null)->setMaxResults(null); |
|
85 |
|
86 try { |
|
87 $data = $countQuery->getScalarResult(); |
|
88 $data = array_map('current', $data); |
|
89 return array_sum($data); |
|
90 } catch(NoResultException $e) { |
|
91 return 0; |
|
92 } |
|
93 } |
|
94 |
|
95 /** |
|
96 * {@inheritdoc} |
|
97 */ |
|
98 public function getSlice($offset, $length) |
|
99 { |
|
100 if ($this->fetchJoinCollection) { |
|
101 $subQuery = $this->cloneQuery($this->query); |
|
102 $subQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\LimitSubqueryWalker')) |
|
103 ->setFirstResult($offset) |
|
104 ->setMaxResults($length); |
|
105 |
|
106 $ids = array_map('current', $subQuery->getScalarResult()); |
|
107 |
|
108 $whereInQuery = $this->cloneQuery($this->query); |
|
109 // don't do this for an empty id array |
|
110 if (count($ids) > 0) { |
|
111 $namespace = 'pg_'; |
|
112 |
|
113 $whereInQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\WhereInWalker')); |
|
114 $whereInQuery->setHint('id.count', count($ids)); |
|
115 $whereInQuery->setHint('pg.ns', $namespace); |
|
116 $whereInQuery->setFirstResult(null)->setMaxResults(null); |
|
117 foreach ($ids as $i => $id) { |
|
118 $i++; |
|
119 $whereInQuery->setParameter("{$namespace}_{$i}", $id); |
|
120 } |
|
121 } |
|
122 |
|
123 return $whereInQuery->getResult($this->query->getHydrationMode()); |
|
124 } |
|
125 |
|
126 return $this->cloneQuery($this->query) |
|
127 ->setMaxResults($length) |
|
128 ->setFirstResult($offset) |
|
129 ->getResult($this->query->getHydrationMode()) |
|
130 ; |
|
131 } |
|
132 |
|
133 /** |
|
134 * Clones a query. |
|
135 * |
|
136 * @param Query $query The query. |
|
137 * |
|
138 * @return Query The cloned query. |
|
139 */ |
|
140 private function cloneQuery(Query $query) |
|
141 { |
|
142 /* @var $cloneQuery Query */ |
|
143 $cloneQuery = clone $query; |
|
144 $cloneQuery->setParameters($query->getParameters()); |
|
145 foreach ($query->getHints() as $name => $value) { |
|
146 $cloneQuery->setHint($name, $value); |
|
147 } |
|
148 |
|
149 return $cloneQuery; |
|
150 } |
|
151 } |