-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathArrayQuery.php
More file actions
259 lines (230 loc) · 6.6 KB
/
ArrayQuery.php
File metadata and controls
259 lines (230 loc) · 6.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
<?php
/**
* This file is part of braincrafted/arrayquery.
*
* (c) Florian Eckerstorfer <florian@eckerstorfer.co>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Braincrafted\ArrayQuery;
/**
* ArrayQuery
*
* @package braincrafted/arrayquery
* @author Florian Eckerstorfer <florian@eckerstorfer.co>
* @copyright 2013 Florian Eckerstorfer
* @license http://opensource.org/licenses/MIT The MIT License
*/
class ArrayQuery
{
/** @var SelectEvaluation */
private $selectEvaluation;
/** @var WhereEvaluation */
private $whereEvaluation;
/** @var array */
private $select = [];
/** @var array */
private $from = [];
/** @var array */
private $where = [];
/**
* @param WhereEvaluation $whereEvaluation
*
* @codeCoverageIgnore
*/
public function __construct(SelectEvaluation $selectEvaluation, WhereEvaluation $whereEvaluation)
{
$this->selectEvaluation = $selectEvaluation;
$this->whereEvaluation = $whereEvaluation;
}
/**
* The names of the fields that should be selected by the query.
*
* Example 1: **One field**
*
* `$query->select('name');`
*
* Example 2: **One field with filters**
*
* `$query->select('name', 'length')`
*
* Example 3: **Two fields as array**
*
* `$query->select([ 'name', 'age' ]);`
*
* Example 4: **Two fields with filters**
*
* `$query->select([ 'name' => [ 'replace 3,e', 'trim' ], 'bio' => 'trim' ]);`
*
* @param mixed $select Either an array of field names or each field name as parameter
*
* @return ArrayQuery
*/
public function select($select, $filters = array())
{
if (false === is_array($select)) {
$newSelect = [ $select => $filters ];
} else {
$newSelect = [];
foreach ($select as $key => $filters) {
if (true === is_int($key) || '*' === $key) {
$newSelect[$filters] = [];
} else {
$newSelect[$key] = $filters;
}
}
}
$this->select = $newSelect;
return $this;
}
/**
* The data source of the query.
*
* @param array $from Array to query elements from
*
* @return ArrayQuery
*/
public function from(array $from)
{
$this->from = $from;
return $this;
}
/**
* Add a clause that elements have to match to be returned.
*
* Example 1: **Simple where**
*
* `$select->where('name', 'Bilbo Baggings');`
*
* Example 2: **Different operator**
*
* `$select->where('age', 50, '>=');`
*
* Example 3: **Add filters**
*
* `$select->where('name', 5, '=', [ 'trim', 'count' ]);`
*
* @param mixed $key Key of the element to evaluate
* @param mixed $value Value the evaluated element has to match (occording to the operator)
* @param string $operator Operator used for the evluation
* @param array $filters Array of filters to be applied to a value before it is evaluated
*
* @return ArrayQuery
*/
public function where($key, $value, $operator = '=', $filters = array())
{
$this->where[] = [
'key' => $key,
'value' => $value,
'operator' => $operator,
'filters' => $filters
];
return $this;
}
/**
* Returns all items from the result.
*
* @return array The full result
*/
public function findAll($preserveKeys = false)
{
return $this->execute(false, false, $preserveKeys);
}
/**
* Returns one item of the array.
*
* @return array An item of the array
*/
public function findOne()
{
return $this->execute(true);
}
/**
* Returns an array of scalar values.
*
* @return array An array of scalar values.
*/
public function findScalar($preserveKeys = false)
{
return $this->execute(false, true, $preserveKeys);
}
/**
* Returns a single scalar value.
*
* @return mixed A scalar value
*/
public function findOneScalar()
{
return $this->execute(true, true);
}
/**
* Executes the query and returns the result.
*
* @return array Array of elements that match the query
*
* @throws \InvalidArgumentException when `$scalar` is `true` and more than one field is selected.
*/
public function execute($one = false, $scalar = false, $preserveKeys = false)
{
if (true === $scalar && (count($this->select) > 1 || true === isset($this->select['*']))) {
throw new \InvalidArgumentException('$scalar can only be true if only one field is selected.');
}
$result = [];
foreach ($this->from as $key => $item) {
if (true === $this->evaluateWhere($item)) {
$resultItem = $this->evaluateSelect($item, $scalar);
if (true === $one) {
return $resultItem;
}
if ($preserveKeys) {
$result[$key] = $resultItem;
}
else {
$result[] = $resultItem;
}
}
}
return $result;
}
/**
* Evaluates the where clauses on the given item.
*
* @param array $item The item to evaluate
*
* @return boolean `true` if all where clauses evaluate to `true`, `false` otherwise
*/
protected function evaluateWhere(array $item)
{
$result = true;
foreach ($this->where as $clause) {
$result = $result && $this->whereEvaluation->evaluate($item, $clause);
}
return $result;
}
/**
* Evaluates the select.
*
* @param array $item
* @param boolean $scalar
*
* @return mixed
*/
protected function evaluateSelect(array $item, $scalar)
{
$resultItem = [];
foreach ($item as $key => $value) {
if (true === isset($this->select['*']) || true === isset($this->select[$key])) {
if (true === isset($this->select[$key])) {
$value = $this->selectEvaluation->evaluate($value, $this->select[$key]);
}
if (true === $scalar) {
$resultItem = $value;
} else {
$resultItem[$key] = $value;
}
}
}
return $resultItem;
}
}