Skip to content

Commit 0eeb9fa

Browse files
committed
Refactor out item retrieval into ItemRetriever
In addition we also now have an IdResolver
1 parent e344086 commit 0eeb9fa

File tree

3 files changed

+714
-491
lines changed

3 files changed

+714
-491
lines changed
Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
<?php
2+
3+
/**
4+
* This file is part of MetaModels/core.
5+
*
6+
* (c) 2012-2017 The MetaModels team.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* This project is provided in good faith and hope to be usable by anyone.
12+
*
13+
* @package MetaModels
14+
* @subpackage Core
15+
* @author Christian Schiffler <[email protected]>
16+
* @copyright 2012-2017 The MetaModels team.
17+
* @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0
18+
* @filesource
19+
*/
20+
21+
namespace MetaModels\DataAccess;
22+
23+
use Contao\Database;
24+
use MetaModels\Filter\IFilter;
25+
use MetaModels\IMetaModel;
26+
27+
/**
28+
* This class resolves an id list.
29+
*/
30+
class IdResolver
31+
{
32+
use DatabaseHelperTrait;
33+
34+
/**
35+
* The database.
36+
*
37+
* @var Database
38+
*/
39+
private $database;
40+
41+
/**
42+
* The metamodel we work on.
43+
*
44+
* @var IMetaModel
45+
*/
46+
private $metaModel;
47+
48+
/**
49+
* The MetaModel table name.
50+
*
51+
* @var string
52+
*/
53+
private $tableName;
54+
55+
/**
56+
* The filter.
57+
*
58+
* @var IFilter
59+
*/
60+
private $filter;
61+
62+
/**
63+
* The sort attribute.
64+
*
65+
* @var string
66+
*/
67+
private $sortBy;
68+
69+
/**
70+
* The sort order.
71+
*
72+
* @var string
73+
*/
74+
private $sortOrder = 'ASC';
75+
76+
/**
77+
* The offset.
78+
*
79+
* @var int
80+
*/
81+
private $offset = 0;
82+
83+
/**
84+
* The limit.
85+
*
86+
* @var int
87+
*/
88+
private $limit = 0;
89+
90+
/**
91+
* Create a new instance.
92+
*
93+
* @param IMetaModel $metaModel The MetaModel.
94+
* @param Database $database The database.
95+
*/
96+
public function __construct(IMetaModel $metaModel, Database $database)
97+
{
98+
$this->database = $database;
99+
$this->metaModel = $metaModel;
100+
$this->tableName = $metaModel->getTableName();
101+
}
102+
103+
/**
104+
* Create a new instance.
105+
*
106+
* @param IMetaModel $metaModel The MetaModel.
107+
* @param Database $database The database.
108+
*
109+
* @return IdResolver
110+
*/
111+
public static function create(IMetaModel $metaModel, Database $database)
112+
{
113+
return new static($metaModel, $database);
114+
}
115+
116+
/**
117+
* Retrieve filter.
118+
*
119+
* @return IFilter
120+
*/
121+
public function getFilter()
122+
{
123+
return $this->filter;
124+
}
125+
126+
/**
127+
* Set filter.
128+
*
129+
* @param IFilter $filter The new value.
130+
*
131+
* @return IdResolver
132+
*/
133+
public function setFilter(IFilter $filter = null)
134+
{
135+
$this->filter = $filter;
136+
137+
return $this;
138+
}
139+
140+
/**
141+
* Retrieve attribute.
142+
*
143+
* @return string
144+
*/
145+
public function getSortBy()
146+
{
147+
return $this->sortBy;
148+
}
149+
150+
/**
151+
* Set attribute.
152+
*
153+
* @param string $sortBy The new value.
154+
*
155+
* @return IdResolver
156+
*/
157+
public function setSortBy($sortBy)
158+
{
159+
$this->sortBy = (string) $sortBy;
160+
161+
return $this;
162+
}
163+
164+
/**
165+
* Retrieve sort order.
166+
*
167+
* @return string
168+
*/
169+
public function getSortOrder()
170+
{
171+
return $this->sortOrder;
172+
}
173+
174+
/**
175+
* Set sort order.
176+
*
177+
* @param string $sortOrder The new value.
178+
*
179+
* @return IdResolver
180+
*/
181+
public function setSortOrder($sortOrder)
182+
{
183+
$this->sortOrder = $sortOrder == 'DESC' ? 'DESC' : 'ASC';
184+
185+
return $this;
186+
}
187+
188+
/**
189+
* Retrieve offset.
190+
*
191+
* @return int
192+
*/
193+
public function getOffset()
194+
{
195+
return $this->offset;
196+
}
197+
198+
/**
199+
* Set offset.
200+
*
201+
* @param int $offset The new value.
202+
*
203+
* @return IdResolver
204+
*/
205+
public function setOffset($offset)
206+
{
207+
$this->offset = (int) $offset;
208+
209+
return $this;
210+
}
211+
212+
/**
213+
* Retrieve limit.
214+
*
215+
* @return int
216+
*/
217+
public function getLimit()
218+
{
219+
return $this->limit;
220+
}
221+
222+
/**
223+
* Set limit.
224+
*
225+
* @param int $limit The new value.
226+
*
227+
* @return IdResolver
228+
*/
229+
public function setLimit($limit)
230+
{
231+
$this->limit = (int) $limit;
232+
233+
return $this;
234+
}
235+
236+
/**
237+
* Retrieve the id list.
238+
*
239+
* @return string[]
240+
*/
241+
public function getIds()
242+
{
243+
$filteredIds = $this->getMatchingIds();
244+
245+
// If desired, sort the entries.
246+
if (!empty($filteredIds) && null !== $this->sortBy) {
247+
$filteredIds = $this->sortIds($filteredIds);
248+
}
249+
250+
// Apply limiting then.
251+
if ($this->offset > 0 || $this->limit > 0) {
252+
$filteredIds = array_slice($filteredIds, $this->offset, $this->limit ?: null);
253+
}
254+
return array_unique(array_filter($filteredIds));
255+
}
256+
257+
/**
258+
* Fetch the amount of matching items.
259+
*
260+
* @return int
261+
*/
262+
public function count()
263+
{
264+
$filteredIds = $this->getMatchingIds();
265+
if (count($filteredIds) == 0) {
266+
return 0;
267+
}
268+
269+
$result = $this
270+
->database
271+
->prepare(sprintf(
272+
'SELECT COUNT(id) AS count FROM %s WHERE id IN(%s)',
273+
$this->tableName,
274+
$this->buildDatabaseParameterList($filteredIds)
275+
))
276+
->execute($filteredIds);
277+
278+
return $result->count;
279+
}
280+
281+
/**
282+
* Narrow down the list of Ids that match the given filter.
283+
*
284+
* @return array all matching Ids.
285+
*/
286+
private function getMatchingIds()
287+
{
288+
if (null !== $this->filter && null !== ($matchingIds = $this->filter->getMatchingIds())) {
289+
return $matchingIds;
290+
}
291+
292+
// Either no filter object or all ids allowed => return all ids.
293+
// if no id filter is passed, we assume all ids are provided.
294+
$rows = $this->database->execute('SELECT id FROM ' . $this->tableName);
295+
296+
return $rows->fetchEach('id');
297+
}
298+
299+
/**
300+
* Sort the ids.
301+
*
302+
* @param string[] $filteredIds The id list.
303+
*
304+
* @return array
305+
*/
306+
private function sortIds($filteredIds)
307+
{
308+
switch (true) {
309+
case ('random' === $this->sortBy):
310+
shuffle($filteredIds);
311+
return $filteredIds;
312+
case (null !== ($attribute = $this->metaModel->getAttribute($this->sortBy))):
313+
return $attribute->sortIds($filteredIds, $this->sortOrder);
314+
case (in_array($this->sortBy, ['id', 'pid', 'tstamp', 'sorting'])):
315+
// Sort by database values.
316+
return $this
317+
->database
318+
->prepare(
319+
sprintf(
320+
'SELECT id FROM %s WHERE id IN(%s) ORDER BY %s %s',
321+
$this->tableName,
322+
$this->buildDatabaseParameterList($filteredIds),
323+
$this->sortBy,
324+
$this->sortOrder
325+
)
326+
)
327+
->execute($filteredIds)
328+
->fetchEach('id');
329+
default:
330+
// Nothing we can do about this.
331+
}
332+
333+
return $filteredIds;
334+
}
335+
}

0 commit comments

Comments
 (0)