Skip to content

Commit 00fe653

Browse files
committed
Add custom filter functions
1 parent d18a983 commit 00fe653

File tree

1 file changed

+78
-49
lines changed

1 file changed

+78
-49
lines changed

src/BaseRepository.php

Lines changed: 78 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@ class BaseRepository extends EntityRepository
1414
protected $joins = array();
1515
protected $disableJoins = false;
1616
protected $setupFunction = null;
17+
protected $filterFunctions = array();
18+
19+
public function addFilterFunction(callable $func)
20+
{
21+
$this->filterFunctions[] = $func;
22+
23+
return $this;
24+
}
25+
26+
public function getFilterFunctions()
27+
{
28+
return $this->filterFunctions;
29+
}
1730

1831
public function disableJoins(bool $disableJoins)
1932
{
@@ -51,6 +64,9 @@ public function findFiltered(array $filters = array(), $order = array(), $limit
5164
// Get the query
5265
$query = $queryBuilder->getQuery();
5366

67+
// Clear filters
68+
$this->filterFunctions = [];
69+
5470
// Execute and return
5571
return $query->getResult();
5672
}
@@ -63,6 +79,9 @@ public function findOneFiltered(array $filters = array(), $order = array(), $off
6379
// Get the query
6480
$query = $queryBuilder->getQuery();
6581

82+
// Clear filters
83+
$this->filterFunctions = [];
84+
6685
// Execute and return
6786
return $query->getOneOrNullResult();
6887
}
@@ -76,7 +95,7 @@ public function buildQuery(array $filters = array(), $order = array(), $limit =
7695
));
7796

7897
// Got a setup function?
79-
if(is_callable($this->setupFunction))
98+
if (is_callable($this->setupFunction))
8099
{
81100
// Run it
82101
$queryBuilder = call_user_func($this->setupFunction, $this->alias, $queryBuilder);
@@ -91,15 +110,15 @@ public function buildQuery(array $filters = array(), $order = array(), $limit =
91110
), $opt);
92111

93112
// Any joins?
94-
if(count($this->joins) && !$opt['disable_joins'] && !$this->disableJoins)
113+
if (count($this->joins) && !$opt['disable_joins'] && !$this->disableJoins)
95114
{
96115
// Loop joins
97-
foreach($this->joins AS $someJoin)
116+
foreach ($this->joins as $someJoin)
98117
{
99118
list($joinType, $joinColumn, $joinTable) = $someJoin;
100119

101120
// Not got a dot, prefix table alias
102-
if(stripos($joinColumn, ".") === false)
121+
if (stripos($joinColumn, ".") === false)
103122
$joinColumn = $this->alias . "." . $joinColumn;
104123

105124
// Join
@@ -108,32 +127,42 @@ public function buildQuery(array $filters = array(), $order = array(), $limit =
108127
}
109128

110129
// Order
111-
if(count($order))
130+
if (count($order))
112131
{
113132
// Loop columns to order
114-
foreach($order AS $key => $val)
133+
foreach ($order as $key => $val)
115134
{
116135
// Not got a dot, prefix table alias
117-
if(is_string($key) && stripos($key, ".") === false && in_array($key, $this->getClassMetadata($this->getClassName())->getColumnNames()))
136+
if (is_string($key) && stripos($key, ".") === false && in_array($key, $this->getClassMetadata($this->getClassName())->getColumnNames()))
118137
$key = $this->alias . "." . $key;
119138

120139
$queryBuilder->addOrderBy($key, $val);
121140
}
122141
}
123142

124143
// Limit
125-
if($limit)
144+
if ($limit)
126145
$queryBuilder->setMaxResults($limit);
127146

128147
// Offset
129-
if($offset)
148+
if ($offset)
130149
$queryBuilder->setFirstResult($offset);
131150

151+
// Loop the filter functions
152+
foreach ($this->getFilterFunctions() as $someFunc)
153+
{
154+
$queryBuilder = $someFunc($queryBuilder);
155+
}
156+
157+
158+
159+
$queryBuilder->addGroupBy($this->alias . ".id");
160+
132161
// Got any filters?
133-
if(count($filters))
162+
if (count($filters))
134163
{
135164
// Add the where
136-
$queryBuilder->where($this->addCriteria($queryBuilder, $queryBuilder->expr()->andX(), $filters));
165+
$queryBuilder->andWhere($this->addCriteria($queryBuilder, $queryBuilder->expr()->andX(), $filters));
137166
}
138167

139168
return $queryBuilder;
@@ -142,19 +171,19 @@ public function buildQuery(array $filters = array(), $order = array(), $limit =
142171
public function addCriteria(QueryBuilder $queryBuilder, Composite $expr, array $criteria)
143172
{
144173
// Got criteria
145-
if(count($criteria))
174+
if (count($criteria))
146175
{
147-
foreach($criteria AS $k => $v)
176+
foreach ($criteria as $k => $v)
148177
{
149178
// Numeric (i.e. it's being passed in as an operator e.g. ["id", "eq", 999])
150-
if(is_numeric($k))
179+
if (is_numeric($k))
151180
{
152181
// Not an array
153-
if(!is_array($v))
182+
if (!is_array($v))
154183
throw new \Exception("Non-indexed criteria must be in array form e.g. ['id', 'eq', 1234]");
155184

156185
// Extract
157-
if(count($v) == 3)
186+
if (count($v) == 3)
158187
list($field, $operator, $value) = $v;
159188
else
160189
{
@@ -165,7 +194,7 @@ public function addCriteria(QueryBuilder $queryBuilder, Composite $expr, array $
165194
}
166195

167196
// Is this a special case i.e. or/and
168-
if(in_array($field, array("or", "and")))
197+
if (in_array($field, array("or", "and")))
169198
{
170199
// Move things around
171200
$value = $operator;
@@ -179,11 +208,11 @@ public function addCriteria(QueryBuilder $queryBuilder, Composite $expr, array $
179208
else
180209
{
181210
// Is the value an array?
182-
if(is_array($v))
211+
if (is_array($v))
183212
throw new \Exception("Indexed criteria does not support array values");
184213

185214
// Is the value null?
186-
if(is_null($v))
215+
if (is_null($v))
187216
{
188217
// Use "is_null" operator
189218
$field = $k;
@@ -200,42 +229,42 @@ public function addCriteria(QueryBuilder $queryBuilder, Composite $expr, array $
200229
}
201230

202231
// Not got a dot, prefix table alias
203-
if(stripos($field, ".") === false)
232+
if (stripos($field, ".") === false)
204233
$field = $this->alias . "." . $field;
205234

206235
// Raw
207-
if($operator === 'raw')
236+
if ($operator === 'raw')
208237
$expr->add($value);
209238
// Or
210-
elseif($operator === 'or')
239+
elseif ($operator === 'or')
211240
$expr->add($this->addCriteria($queryBuilder, $queryBuilder->expr()->orX(), $value));
212241
// And
213-
elseif($operator === 'and')
242+
elseif ($operator === 'and')
214243
$expr->add($this->addCriteria($queryBuilder, $queryBuilder->expr()->andX(), $value));
215244
// Basic operators
216-
elseif(in_array($operator, array("eq", "neq", "gt", "gte", "lt", "lte", "like")))
245+
elseif (in_array($operator, array("eq", "neq", "gt", "gte", "lt", "lte", "like")))
217246
{
218247
// Arrays not supported for this operator
219-
if(is_array($value))
248+
if (is_array($value))
220249
throw new \Exception("Array lookups are not supported for the '" . $operator . "' operator");
221250

222251
// DateTime
223-
if(is_object($value) && $value instanceof \DateTime)
252+
if (is_object($value) && $value instanceof \DateTime)
224253
{
225254
$expr->add($queryBuilder->expr()->{$operator}($field, $this->createNamedParameter($queryBuilder, $this->prepareValue($value))));
226255
}
227256
// Is it a UUID?
228-
elseif($value instanceof Uuid)
257+
elseif ($value instanceof Uuid)
229258
{
230259
$expr->add($queryBuilder->expr()->{$operator}($field, $this->createNamedParameter($queryBuilder, $this->prepareValue($value->toBinary()), ParameterType::BINARY)));
231260
}
232261
// Other object (likely an association)
233-
elseif(is_object($value))
262+
elseif (is_object($value))
234263
{
235264
$expr->add($queryBuilder->expr()->{$operator}($field, $this->createNamedParameter($queryBuilder, $this->prepareValue($value))));
236265
}
237266
// Is it null?
238-
elseif(is_null($value))
267+
elseif (is_null($value))
239268
{
240269
$expr->add($queryBuilder->expr()->isNull($field));
241270
}
@@ -246,39 +275,39 @@ public function addCriteria(QueryBuilder $queryBuilder, Composite $expr, array $
246275
}
247276
}
248277
// Null operator
249-
elseif(in_array($operator, array("is_null", "not_null")))
278+
elseif (in_array($operator, array("is_null", "not_null")))
250279
{
251280
// Is null
252-
if($operator == "is_null")
281+
if ($operator == "is_null")
253282
{
254283
// True or false value?
255-
if($value)
284+
if ($value)
256285
$expr->add($queryBuilder->expr()->isNull($field));
257286
else
258287
$expr->add($queryBuilder->expr()->isNotNull($field));
259288
}
260289
// Not null
261-
elseif($operator == "not_null")
290+
elseif ($operator == "not_null")
262291
{
263292
// True or false value?
264-
if($value)
293+
if ($value)
265294
$expr->add($queryBuilder->expr()->isNotNull($field));
266295
else
267296
$expr->add($queryBuilder->expr()->isNull($field));
268297
}
269298
}
270299
// In/NotIn operators
271-
elseif(in_array($operator, array("in", "not_in")))
300+
elseif (in_array($operator, array("in", "not_in")))
272301
{
273302
// Make sure it's an array
274-
if(!is_array($value))
303+
if (!is_array($value))
275304
throw new \Exception("Invalid value for operator: " . $operator);
276305

277306
// In
278-
if($operator == "in")
307+
if ($operator == "in")
279308
$expr->add($queryBuilder->expr()->in($field, $this->createNamedParameter($queryBuilder, $this->prepareValue($value))));
280309
// Not in
281-
elseif($operator == "not_in")
310+
elseif ($operator == "not_in")
282311
{
283312
// Need to use multiple != operations because "NOT IN" is not null-safe
284313
// We therefore loop the values and build the SQL string
@@ -287,10 +316,10 @@ public function addCriteria(QueryBuilder $queryBuilder, Composite $expr, array $
287316
$builtArraySQL = array();
288317

289318
// Loop the values
290-
foreach($this->prepareValue($value) AS $someValue)
319+
foreach ($this->prepareValue($value) as $someValue)
291320
{
292321
// Is it null?
293-
if(is_null($someValue))
322+
if (is_null($someValue))
294323
{
295324
// Make sure we don't return if null
296325
$builtArraySQL[] = '(' . $field . ' IS NOT NULL)';
@@ -304,10 +333,10 @@ public function addCriteria(QueryBuilder $queryBuilder, Composite $expr, array $
304333
}
305334

306335
// Got anything?
307-
if(count($builtArraySQL))
336+
if (count($builtArraySQL))
308337
{
309338
// Implode into full array
310-
if(phpversion() >= 8)
339+
if (phpversion() >= 8)
311340
$fullSQL = "(" . implode(' AND ', $builtArraySQL) . ")";
312341
else
313342
$fullSQL = "(" . implode($builtArraySQL, ' AND ') . ")";
@@ -345,20 +374,20 @@ public function createNamedParameter(QueryBuilder $queryBuilder, $value)
345374
public function prepareValue($value)
346375
{
347376
// DateTime
348-
if(is_object($value) && $value instanceof \DateTime)
377+
if (is_object($value) && $value instanceof \DateTime)
349378
{
350379
return $value->format('Y-m-d H:i:s');
351380
}
352381
// Object
353-
elseif(is_object($value))
382+
elseif (is_object($value))
354383
{
355384
return $value;
356385
}
357386
// Array
358-
elseif(is_array($value))
387+
elseif (is_array($value))
359388
{
360389
// Loop
361-
foreach($value AS $k => $v)
390+
foreach ($value as $k => $v)
362391
{
363392
// Prepare it
364393
$value[$k] = $this->prepareValue($v);
@@ -374,7 +403,7 @@ public function prepareValue($value)
374403
public function buildSearchCriteria(string $keywords, array $searchableColumns = array())
375404
{
376405
// Got no searchable columns
377-
if(!count($searchableColumns))
406+
if (!count($searchableColumns))
378407
throw new \Exception("No searchable columns specified");
379408

380409
// Explode individual keywords
@@ -384,13 +413,13 @@ public function buildSearchCriteria(string $keywords, array $searchableColumns =
384413
$keywordCriteria = array();
385414

386415
// Loop keywords
387-
foreach($keywords AS $someKeyword)
416+
foreach ($keywords as $someKeyword)
388417
{
389418
// Grab this group
390419
$keywordGroup = array();
391420

392421
// Loop search columns
393-
foreach($searchableColumns AS $searchColumn)
422+
foreach ($searchableColumns as $searchColumn)
394423
{
395424
// Grab it
396425
$keywordGroup[] = array($searchColumn, "like", "%" . $someKeyword . "%");

0 commit comments

Comments
 (0)