This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Macroparts\Vortex; |
||
4 | |||
5 | use Doctrine\ORM\Query; |
||
6 | |||
7 | abstract class Vortex |
||
8 | { |
||
9 | use \UnserAllerLib_Api_V4_AdapterProvider; |
||
10 | |||
11 | const DIRECTIVE_FIELDS = 'fields'; |
||
12 | const META_ON_OBJECT_LEVEL_ENABLED = 1; |
||
13 | const META_ON_OBJECT_LEVEL_DISABLED = 0; |
||
14 | |||
15 | /** |
||
16 | * @var \Doctrine\ORM\EntityManager |
||
17 | */ |
||
18 | private $entityManager; |
||
19 | |||
20 | /** |
||
21 | * Defines data that can be included with an api call. You'd try to return only the most frequently used data |
||
22 | * in default payload. Other available raw and aggregated data you'd make includable. Every availableInclude |
||
23 | * has it's own include method and has to be mentioned in this configuration. |
||
24 | * |
||
25 | * Go to the Project Repository for an example configuration |
||
26 | * |
||
27 | * @var array |
||
28 | */ |
||
29 | protected static $includeWhitelist = []; |
||
30 | protected static $filterWhitelist = []; |
||
31 | protected static $orderWhitelist = []; |
||
32 | |||
33 | private $abstractFilterWhitelist = [ |
||
34 | 'id' => '', |
||
35 | 'any' => '', |
||
36 | 'all' => '' |
||
37 | ]; |
||
38 | |||
39 | /** |
||
40 | * Used in the include configuration to tell if a property is a recursive inclusion or not |
||
41 | */ |
||
42 | const INCLUDE_DIRECT = 0; |
||
43 | const INCLUDE_RECURSIVE = 1; |
||
44 | |||
45 | /** |
||
46 | * Collects operations that have to be run on the doctrine result after query execution |
||
47 | * |
||
48 | * @var array |
||
49 | */ |
||
50 | private $resultArrayFixSchedule = []; |
||
51 | |||
52 | /** |
||
53 | * Repositories can define a set of properties that are included by default |
||
54 | * |
||
55 | * @var array |
||
56 | */ |
||
57 | protected static $defaultIncludes = []; |
||
58 | |||
59 | /** |
||
60 | * Repositories can define a default order which is taken by default |
||
61 | * |
||
62 | * @var array |
||
63 | */ |
||
64 | protected static $defaultOrder = []; |
||
65 | |||
66 | /** |
||
67 | * If an ID is specified in the URL, it will be saved here for usage in child adapters. |
||
68 | * |
||
69 | * @var int|null |
||
70 | */ |
||
71 | protected $id = null; |
||
72 | |||
73 | /** |
||
74 | * All parameters unsorted |
||
75 | * |
||
76 | * @var array |
||
77 | */ |
||
78 | protected $unsortedParams = []; |
||
79 | |||
80 | protected $supportedLanguages; |
||
81 | |||
82 | |||
83 | private $finalIncludeWhitelist; |
||
84 | private $finalFilterWhitelist; |
||
85 | private $finalOrderWhitelist; |
||
86 | |||
87 | public function __construct($entityManager, $supportedLanguages = []) |
||
88 | { |
||
89 | $this->entityManager = $entityManager; |
||
90 | $this->supportedLanguages = $supportedLanguages; |
||
91 | |||
92 | //Cache customized whitelists merged with core whitelists |
||
93 | $this->finalFilterWhitelist = array_merge($this->getStaticPropertyOfClassMergedWithParents( |
||
94 | static::class, |
||
95 | 'filterWhitelist' |
||
96 | ), $this->abstractFilterWhitelist); |
||
97 | $this->finalOrderWhitelist = $this->getStaticPropertyOfClassMergedWithParents(static::class, 'orderWhitelist'); |
||
98 | $this->finalIncludeWhitelist = $this->getStaticPropertyOfClassMergedWithParents( |
||
99 | static::class, |
||
100 | 'includeWhitelist' |
||
101 | ); |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * @return \Doctrine\ORM\EntityManager |
||
106 | */ |
||
107 | public function getEntityManager() |
||
108 | { |
||
109 | return $this->entityManager; |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * @param \Doctrine\ORM\EntityManager $entityManager |
||
114 | * @return $this |
||
115 | */ |
||
116 | public function setEntityManager($entityManager) |
||
0 ignored issues
–
show
|
|||
117 | { |
||
118 | $this->entityManager = $entityManager; |
||
119 | return $this; |
||
120 | } |
||
121 | |||
122 | private function isNotIncludableProperty($property) |
||
123 | { |
||
124 | return !isset($this->finalIncludeWhitelist[$property]); |
||
125 | } |
||
126 | |||
127 | private function isNotFilterableProperty($property) |
||
128 | { |
||
129 | return !isset($this->finalFilterWhitelist[$property]) && !isset($this->abstractFilterWhitelist[$property]); |
||
130 | } |
||
131 | |||
132 | private function isNotOrderableProperty($property) |
||
133 | { |
||
134 | return !isset($this->finalOrderWhitelist[$property]); |
||
135 | } |
||
136 | |||
137 | public function getTranslatableIncludeNames() |
||
138 | { |
||
139 | return array_keys(array_filter($this->finalIncludeWhitelist, function ($inc) { |
||
140 | return isset($inc['translatable']) && $inc['translatable']; |
||
141 | })); |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * @return array |
||
146 | */ |
||
147 | private function getPlatformOptions() |
||
148 | { |
||
149 | return \Zend_Registry::get('platformOptions'); |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * @return bool |
||
154 | */ |
||
155 | protected function arePlatformUsersPublic() |
||
156 | { |
||
157 | return (bool)$this->getPlatformOptions()['user']['public']; |
||
158 | } |
||
159 | |||
160 | /** |
||
161 | * @return bool |
||
162 | */ |
||
163 | protected function arePlatformUsersPrivate() |
||
164 | { |
||
165 | return !$this->arePlatformUsersPublic(); |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * @param \Doctrine\ORM\QueryBuilder $query |
||
170 | * @param string $alias |
||
171 | * @param \UnserAller_Model_User $currentUser |
||
172 | * @param array $additionalParams |
||
173 | * @param $language |
||
174 | * @param $filtername |
||
175 | * @return \Doctrine\ORM\Query\Expr\Orx |
||
176 | * @throws \UnserAllerLib_Api_V4_Exception_MissingFilterDirective |
||
177 | * @throws \UnserAllerLib_Api_V4_Exception_SafeForPrinting |
||
178 | */ |
||
179 | private function filterAny($query, $alias, $currentUser, $additionalParams, $language, $filtername) |
||
180 | { |
||
181 | return $this->abstractFilterMultipleFields( |
||
182 | $query, |
||
183 | 'orX', |
||
184 | $currentUser, |
||
185 | $additionalParams, |
||
186 | $language, |
||
187 | $filtername |
||
188 | ); |
||
189 | } |
||
190 | |||
191 | /** |
||
192 | * @param \Doctrine\ORM\QueryBuilder $query |
||
193 | * @param string $alias |
||
194 | * @param \UnserAller_Model_User $currentUser |
||
195 | * @param array $additionalParams |
||
196 | * @param $language |
||
197 | * @param $filtername |
||
198 | * @return \Doctrine\ORM\Query\Expr\Orx |
||
199 | * @throws \UnserAllerLib_Api_V4_Exception_MissingFilterDirective |
||
200 | * @throws \UnserAllerLib_Api_V4_Exception_SafeForPrinting |
||
201 | */ |
||
202 | private function filterAll($query, $alias, $currentUser, $additionalParams, $language, $filtername) |
||
203 | { |
||
204 | return $this->abstractFilterMultipleFields( |
||
205 | $query, |
||
206 | 'andX', |
||
207 | $currentUser, |
||
208 | $additionalParams, |
||
209 | $language, |
||
210 | $filtername |
||
211 | ); |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * @param \Doctrine\ORM\QueryBuilder $query |
||
216 | * @param string $expressionType |
||
217 | * @param \UnserAller_Model_User $currentUser |
||
218 | * @param array $additionalParams |
||
219 | * @param $language |
||
220 | * @param $filtername |
||
221 | * @return \Doctrine\ORM\Query\Expr\Orx |
||
222 | * @throws \UnserAllerLib_Api_V4_Exception_MissingFilterDirective |
||
223 | * @throws \UnserAllerLib_Api_V4_Exception_SafeForPrinting |
||
224 | */ |
||
225 | private function abstractFilterMultipleFields( |
||
226 | $query, |
||
227 | $expressionType, |
||
228 | $currentUser, |
||
229 | $additionalParams, |
||
230 | $language, |
||
231 | $filtername |
||
232 | ) { |
||
233 | if (!isset($additionalParams[self::DIRECTIVE_FIELDS])) { |
||
234 | throw new \UnserAllerLib_Api_V4_Exception_MissingFilterDirective( |
||
235 | $filtername, |
||
236 | self::DIRECTIVE_FIELDS, |
||
237 | ['fieldname1', 'fieldname2'], |
||
238 | ':someFilterDirective(params):maySomeMoreDirectives...' |
||
239 | ); |
||
240 | } |
||
241 | |||
242 | $fields = $additionalParams[self::DIRECTIVE_FIELDS]; |
||
243 | if (count(array_intersect_key($this->finalFilterWhitelist, array_flip($fields))) !== count($fields)) { |
||
244 | throw new \UnserAllerLib_Api_V4_Exception_SafeForPrinting( |
||
245 | 'Wrong use of "' . $filtername . '" filter. '. |
||
246 | 'One of your specified fields is not filterable. '. |
||
247 | 'Try using fields that are filterable.' |
||
248 | ); |
||
249 | } |
||
250 | |||
251 | unset($additionalParams[self::DIRECTIVE_FIELDS]); |
||
252 | |||
253 | $expression = call_user_func([$query->expr(), $expressionType]); |
||
254 | foreach ($fields as $field) { |
||
255 | $filterMethod = $this->decodeMethodFromRequestedFilter($field); |
||
256 | $expression->add($this->$filterMethod( |
||
257 | $query, $filterMethod, $currentUser, $additionalParams, $language, $field, |
||
258 | $this->finalFilterWhitelist[$field] |
||
259 | )); |
||
260 | } |
||
261 | |||
262 | return $expression; |
||
263 | } |
||
264 | |||
265 | /** |
||
266 | * Executes include methods driven by a include string. See API docs to know how this string looks like |
||
267 | * |
||
268 | * @param \Doctrine\ORM\QueryBuilder $query |
||
269 | * @param \UnserAller_Model_User $currentUser |
||
270 | * @param $language |
||
271 | * @param string $includeString |
||
272 | * @param array $meta |
||
273 | * @return \Doctrine\ORM\QueryBuilder |
||
274 | */ |
||
275 | protected function addIncludeStatements($query, $currentUser, $language, $includeString, &$meta = []) |
||
276 | { |
||
277 | $requestedIncludes = $this->parseIncludeString($includeString, $this->finalIncludeWhitelist); |
||
278 | |||
279 | $requestedIncludes = $requestedIncludes + static::$defaultIncludes; |
||
280 | foreach ($requestedIncludes as $requestedInclude => $additionalParams) { |
||
281 | if ($this->isNotIncludableProperty($requestedInclude)) { |
||
282 | continue; |
||
283 | } |
||
284 | |||
285 | $includeMethod = $this->decodeMethodFromRequestedInclude($requestedInclude); |
||
286 | $postProcessDirections = $this->$includeMethod($query, $includeMethod, $currentUser, $additionalParams, |
||
287 | $language); |
||
288 | |||
289 | if ($postProcessDirections) { |
||
290 | $this->schedulePostProcessingDirections($postProcessDirections); |
||
291 | } |
||
292 | |||
293 | $this->updateMetaOnInclude($meta, $requestedInclude); |
||
294 | } |
||
295 | return $query; |
||
296 | } |
||
297 | |||
298 | /** |
||
299 | * Collecting whitelist not just for current class but merged with all whitelists from parent classes. |
||
300 | * So when we overwrite whitelists locally they are still including all the elements from core adapters. |
||
301 | * |
||
302 | * @param null|string $class |
||
303 | * @param $propertyname |
||
304 | * @return array |
||
305 | */ |
||
306 | private function getStaticPropertyOfClassMergedWithParents($class, $propertyname) |
||
307 | { |
||
308 | $class = $class ? $class : static::class; |
||
309 | $parent = get_parent_class($class); |
||
310 | return $parent ? $this->getStaticPropertyOfClassOrArray( |
||
311 | $class, |
||
312 | $propertyname |
||
313 | ) + $this->getStaticPropertyOfClassMergedWithParents( |
||
314 | $parent, |
||
315 | $propertyname |
||
316 | ) : $this->getStaticPropertyOfClassOrArray($class, $propertyname); |
||
317 | } |
||
318 | |||
319 | private function getStaticPropertyOfClassOrArray($class, $propertyname) |
||
320 | { |
||
321 | return isset($class::$$propertyname) ? $class::$$propertyname : []; |
||
322 | } |
||
323 | |||
324 | private function updateMetaOnInclude(&$meta, $includeName) |
||
325 | { |
||
326 | $include = $this->finalIncludeWhitelist[$includeName]; |
||
327 | if (isset($include['model'])) { |
||
328 | $meta['modelnameIndex']["{$include['model']}"][] = $includeName; |
||
329 | } |
||
330 | } |
||
331 | |||
332 | /** |
||
333 | * Calls methods that add where conditions to a query driven by a string (see api docs for string format) |
||
334 | * |
||
335 | * @param \Doctrine\ORM\QueryBuilder $query |
||
336 | * @param \UnserAller_Model_User $currentUser |
||
337 | * @param string $filterString |
||
338 | * @param $language |
||
339 | * @param string $joinFiltersWith |
||
340 | * @return \Doctrine\ORM\QueryBuilder |
||
341 | * @throws \UnserAllerLib_Api_V4_Exception_InvalidFilter |
||
342 | * @uses filterAny |
||
343 | * @uses filterAll |
||
344 | */ |
||
345 | protected function addFilterStatements($query, $currentUser, $filterString, $language, $joinFiltersWith = 'AND') |
||
346 | { |
||
347 | $requestedFilters = array_filter($this->parseRichParamString($filterString)); |
||
348 | if (!$requestedFilters) { |
||
0 ignored issues
–
show
The expression
$requestedFilters of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
349 | return $query; |
||
350 | } |
||
351 | |||
352 | $expression = mb_strtoupper($joinFiltersWith) === 'OR' ? $query->expr()->orX() : $query->expr()->andX(); |
||
353 | foreach ($requestedFilters as $requestedFilter => $additionalParams) { |
||
354 | if ($this->isNotFilterableProperty($requestedFilter)) { |
||
355 | throw new \UnserAllerLib_Api_V4_Exception_InvalidFilter( |
||
356 | sprintf( |
||
357 | 'The request filter "%s" does not exist on the current adapter "%s".', |
||
358 | $requestedFilter, |
||
359 | get_class($this) |
||
360 | ) |
||
361 | ); |
||
362 | } |
||
363 | |||
364 | $filterMethod = $this->decodeMethodFromRequestedFilter($requestedFilter); |
||
365 | $expression->add($this->$filterMethod( |
||
366 | $query, $filterMethod, $currentUser, $additionalParams, $language, $requestedFilter, |
||
367 | $this->finalFilterWhitelist[$requestedFilter] |
||
368 | )); |
||
369 | } |
||
370 | |||
371 | return $query->andWhere($expression); |
||
372 | } |
||
373 | |||
374 | abstract protected function getFallbackLanguage($resultItem, $requestedLanguage); |
||
375 | |||
376 | /** |
||
377 | * Transforms additionalParams for included collections into params which are used |
||
378 | * during post processing to call a findXForApi method |
||
379 | * |
||
380 | * @param array $additionalParams |
||
381 | * @return array |
||
382 | */ |
||
383 | protected function parseAdditionalIncludeParams($additionalParams) |
||
384 | { |
||
385 | $filter = \UnserAllerLib_Tool_Array::spliceElemOrNull($additionalParams, 'filter'); |
||
386 | $filter = is_array($filter) ? implode(',', $filter) : ''; |
||
387 | |||
388 | $include = \UnserAllerLib_Tool_Array::spliceElemOrNull($additionalParams, 'include'); |
||
389 | $include = is_array($include) ? implode(',', $include) : ''; |
||
390 | |||
391 | $order = \UnserAllerLib_Tool_Array::spliceElemOrNull($additionalParams, 'order'); |
||
392 | $order = is_array($order) ? implode(',', $order) : ''; |
||
393 | |||
394 | $limit = \UnserAllerLib_Tool_Array::spliceElemOrNull($additionalParams, 'limit'); |
||
395 | $limit = is_array($limit) ? (int)array_shift($limit) : 0; |
||
396 | |||
397 | $page = \UnserAllerLib_Tool_Array::spliceElemOrNull($additionalParams, 'page'); |
||
398 | $page = is_array($page) ? (int)array_shift($page) : 1; |
||
399 | |||
400 | $filterMode = \UnserAllerLib_Tool_Array::spliceElemOrNull($additionalParams, 'filterMode'); |
||
401 | $filterMode = is_array($filterMode) ? array_shift($filterMode) : 'AND'; |
||
402 | |||
403 | return [$filter, $include, $order, $limit, $page, $filterMode]; |
||
404 | } |
||
405 | |||
406 | /** |
||
407 | * Calls methods that add orderBy statements to a query driven by a string (see api docs for the string format) |
||
408 | * |
||
409 | * @param \Doctrine\ORM\QueryBuilder $query |
||
410 | * @param \UnserAller_Model_User $currentUser |
||
411 | * @param string $orderString |
||
412 | * @return \Doctrine\ORM\QueryBuilder |
||
413 | * @throws \UnserAllerLib_Api_V4_Exception_InvalidOrder |
||
414 | */ |
||
415 | private function addOrderStatements($query, $currentUser, $orderString) |
||
416 | { |
||
417 | $requestedOrders = array_filter($this->parseRichParamString($orderString)); |
||
418 | |||
419 | if (!$requestedOrders) { |
||
0 ignored issues
–
show
The expression
$requestedOrders of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
420 | $requestedOrders = static::$defaultOrder; |
||
421 | } |
||
422 | |||
423 | foreach ($requestedOrders as $field => $order) { |
||
424 | if ($this->isNotOrderableProperty($field)) { |
||
425 | throw new \UnserAllerLib_Api_V4_Exception_InvalidOrder($field); |
||
426 | } |
||
427 | |||
428 | $orderMethod = $this->decodeMethodFromRequestedOrder($field); |
||
429 | $postProcessTasks = $this->$orderMethod($query, $orderMethod, $currentUser, |
||
430 | isset($order['desc']) ? 'DESC' : 'ASC', $order); |
||
431 | if ($postProcessTasks) { |
||
432 | $this->schedulePostProcessingDirections($postProcessTasks); |
||
433 | } |
||
434 | } |
||
435 | |||
436 | return $query; |
||
437 | } |
||
438 | |||
439 | /** |
||
440 | * Knows how to append post processing directions to the post process schedule |
||
441 | * |
||
442 | * @param array $tasks |
||
443 | */ |
||
444 | private function schedulePostProcessingDirections($tasks) |
||
445 | { |
||
446 | if (!$tasks) { |
||
0 ignored issues
–
show
The expression
$tasks of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
447 | return; |
||
448 | } |
||
449 | |||
450 | if (!is_array($tasks[0])) { |
||
451 | $tasks = [$tasks]; |
||
452 | } |
||
453 | |||
454 | foreach ($tasks as $task) { |
||
455 | $this->resultArrayFixSchedule[array_shift($task)] = $task; |
||
456 | } |
||
457 | } |
||
458 | |||
459 | /** |
||
460 | * Returns the name of the appropriate include method for $requestedInclude. The rule is simple: |
||
461 | * uppercase first letter and every letter that comes after a dot, remove dots and prepend 'include'. Examples: |
||
462 | * |
||
463 | * returns includeProject when $requestedInclude = project |
||
464 | * returns includePhaseProjectNumberOfLikes when $requestedInclude = phase.project.numerOfLikes |
||
465 | * |
||
466 | * @param string $requestedInclude |
||
467 | * @return string |
||
468 | */ |
||
469 | private function decodeMethodFromRequestedInclude($requestedInclude) |
||
470 | { |
||
471 | return 'include' . implode('', array_map('ucfirst', explode('.', str_replace('[]', '_cp', $requestedInclude)))); |
||
472 | } |
||
473 | |||
474 | /** |
||
475 | * Returns the name of the appropriate include method for $requestedInclude. The rule is simple: |
||
476 | * uppercase first letter and every letter that comes after a dot, remove dots, prepend 'include'. Examples: |
||
477 | * |
||
478 | * returns includeProject when $requestedInclude = project |
||
479 | * returns includePhaseProjectNumberOfLikes when $requestedInclude = phase.project.numerOfLikes |
||
480 | * |
||
481 | * @param string $requestedInclude |
||
482 | * @return string |
||
483 | */ |
||
484 | private function decodeMethodFromRequestedFilter($requestedInclude) |
||
485 | { |
||
486 | return 'filter' . implode('', array_map('ucfirst', explode('.', $requestedInclude))); |
||
487 | } |
||
488 | |||
489 | /** |
||
490 | * Returns the name of the appropriate include method for $requestedInclude. The rule is simple: |
||
491 | * uppercase first letter and every letter that comes after a dot, remove dots, prepend 'include'. Examples: |
||
492 | * |
||
493 | * returns includeProject when $requestedInclude = project |
||
494 | * returns includePhaseProjectNumberOfLikes when $requestedInclude = phase.project.numerOfLikes |
||
495 | * |
||
496 | * @param string $field |
||
497 | * @return string |
||
498 | */ |
||
499 | private function decodeMethodFromRequestedOrder($field) |
||
500 | { |
||
501 | return 'orderBy' . implode('', array_map('ucfirst', explode('.', $field))); |
||
502 | } |
||
503 | |||
504 | /** |
||
505 | * Calculates total pages for an $incompleteStatement. Incomplete statements are doctrine query builder instances |
||
506 | * with all required conditions but no select statement and no additional includes. |
||
507 | * |
||
508 | * @param int $numberOfRows |
||
509 | * @param int $limit |
||
510 | * @return float|int |
||
511 | */ |
||
512 | private function calculateTotalPages($numberOfRows, $limit) |
||
513 | { |
||
514 | if ($limit) { |
||
515 | return (int) ceil($numberOfRows / $limit); |
||
516 | } |
||
517 | |||
518 | return 1; |
||
519 | } |
||
520 | |||
521 | /** |
||
522 | * @param \Doctrine\ORM\QueryBuilder $incompleteStatement |
||
523 | * @return int |
||
524 | */ |
||
525 | private function selectTotalNumberOfRows($incompleteStatement) |
||
526 | { |
||
527 | $rootAlias = $this->getRootAlias($incompleteStatement); |
||
528 | $primaryIndexCol = $rootAlias . '.' . $this->getPrimaryIndexCol(); |
||
529 | |||
530 | if ($incompleteStatement->getDQLPart('having')) { |
||
531 | $rootEntities = $incompleteStatement->getRootEntities(); |
||
532 | return (int)$incompleteStatement->getEntityManager()->createQueryBuilder() |
||
533 | ->select('COUNT(x)') |
||
534 | ->from(array_shift($rootEntities), 'x') |
||
535 | ->where( |
||
536 | $incompleteStatement->expr()->in( |
||
537 | 'x.'.$this->getPrimaryIndexCol(), |
||
538 | $incompleteStatement->select($primaryIndexCol)->getDQL() |
||
539 | ) |
||
540 | )->setParameters($incompleteStatement->getParameters())->getQuery()->getSingleScalarResult(); |
||
541 | } |
||
542 | |||
543 | return (int)$incompleteStatement |
||
544 | ->select("COUNT(DISTINCT $primaryIndexCol)") |
||
545 | ->getQuery() |
||
546 | ->getSingleScalarResult(); |
||
547 | } |
||
548 | |||
549 | /** |
||
550 | * Doctrine will throw errors if a table has a multi column primary index |
||
551 | * http://stackoverflow.com/questions/18968963/select-countdistinct-error-on-multiple-columns |
||
552 | * @return string |
||
553 | */ |
||
554 | protected function getPrimaryIndexCol() |
||
555 | { |
||
556 | return 'id'; |
||
557 | } |
||
558 | |||
559 | /** |
||
560 | * Todo: Include collections by additional params and not by includes and adjust docs |
||
561 | * Takes the include string and decodes it to an array with include names as keys and an array with additionalParams |
||
562 | * as the value. Includes that are nested inside included collections are grouped and added as additional params |
||
563 | * to the included collection. |
||
564 | * |
||
565 | * @param $string |
||
566 | * @param $availableIncludes |
||
567 | * @return array |
||
568 | */ |
||
569 | private function parseIncludeString($string, $availableIncludes) |
||
570 | { |
||
571 | if ($string === '') { |
||
572 | return []; |
||
573 | } |
||
574 | |||
575 | if (is_string($string)) { |
||
576 | $string = explode(',', $string); |
||
577 | } |
||
578 | |||
579 | if (!is_array($string)) { |
||
580 | return []; |
||
581 | } |
||
582 | |||
583 | $requestedIncludes = []; |
||
584 | $implicitIncludes = []; |
||
585 | foreach ($string as $include) { |
||
586 | list($includeName, $allModifiersStr) = array_pad(explode(':', $include, 2), 2, null); |
||
587 | |||
588 | $pathToFirstRecursiveInclusion = $this->pathForNestedInclude($includeName, $availableIncludes); |
||
589 | if ($pathToFirstRecursiveInclusion) { |
||
590 | $requestedIncludes[$pathToFirstRecursiveInclusion]['include'][] = substr( |
||
591 | $include, |
||
592 | strlen($pathToFirstRecursiveInclusion) + 1 |
||
593 | ); |
||
594 | continue; |
||
595 | } |
||
596 | |||
597 | $implicitIncludes = array_merge($implicitIncludes, $this->getImplicitIncludes($includeName)); |
||
598 | |||
599 | if ($allModifiersStr === null) { |
||
600 | if (!isset($requestedIncludes[$includeName])) { |
||
601 | $requestedIncludes[$includeName] = []; |
||
602 | } |
||
603 | continue; |
||
604 | } |
||
605 | |||
606 | if (preg_match('~filter\(~u', $allModifiersStr)) { |
||
607 | $modifierArr = $this->parseModifierArraySlowButAccurate($allModifiersStr); |
||
608 | } else { |
||
609 | $modifierArr = $this->parseModifierStringQuickButInaccurate($allModifiersStr); |
||
610 | } |
||
611 | |||
612 | if (isset($requestedIncludes[$includeName])) { |
||
613 | $requestedIncludes[$includeName] = $requestedIncludes[$includeName] + $modifierArr; |
||
614 | } else { |
||
615 | $requestedIncludes[$includeName] = $modifierArr; |
||
616 | } |
||
617 | } |
||
618 | |||
619 | return $this->mergeWithImplicitIncludes($requestedIncludes, $implicitIncludes); |
||
620 | } |
||
621 | |||
622 | /** |
||
623 | * creates an array out of string in this format: |
||
624 | * |
||
625 | * modifierName1(modifierParam1|modifierParam2):modifierName2(modifierParam3) |
||
626 | * |
||
627 | * Result: |
||
628 | * [ |
||
629 | * 'modifierName1' => ['modifierParam1','modifierParam2'], |
||
630 | * 'modifierName2' => ['modifierParam3'] |
||
631 | * ] |
||
632 | * |
||
633 | * But doesn't work when modifier params contain other modifiers with params themselves |
||
634 | * |
||
635 | * @param string $allModifiersStr |
||
636 | * @return array |
||
637 | */ |
||
638 | private function parseModifierStringQuickButInaccurate($allModifiersStr) |
||
639 | { |
||
640 | // Matches multiple instances of 'something(foo|bar|baz)' in the string |
||
641 | // I guess it ignores : so you could use anything, but probably don't do that |
||
642 | preg_match_all('/([\w]+)(\(([^\)]+)\))?/', $allModifiersStr, $allModifiersArr); |
||
643 | // [0] is full matched strings... |
||
644 | $modifierCount = count($allModifiersArr[0]); |
||
645 | $modifierArr = []; |
||
646 | View Code Duplication | for ($modifierIt = 0; $modifierIt < $modifierCount; $modifierIt++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
647 | // [1] is the modifier |
||
648 | $modifierName = $allModifiersArr[1][$modifierIt]; |
||
649 | // and [3] is delimited params |
||
650 | $modifierParamStr = $allModifiersArr[3][$modifierIt]; |
||
651 | // Make modifier array key with an array of params as the value |
||
652 | $modifierArr[$modifierName] = explode('|', $modifierParamStr); |
||
653 | } |
||
654 | |||
655 | return $modifierArr; |
||
656 | } |
||
657 | |||
658 | /** |
||
659 | * creates an array out of string in this format: |
||
660 | * |
||
661 | * modifierName1(modifierParam1|modifierParam2):modifierName2(modifierParam3)) |
||
662 | * |
||
663 | * Can also handle modifier params that contain other modifier with params |
||
664 | * |
||
665 | * @param string $s |
||
666 | * @return array |
||
667 | */ |
||
668 | View Code Duplication | private function parseModifierArraySlowButAccurate($s) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
669 | { |
||
670 | $modifierArr = []; |
||
671 | $modifierName = ''; |
||
672 | $modifierParamStr = ''; |
||
673 | |||
674 | $depth = 0; |
||
675 | for ($i = 0; $i < strlen($s); $i++) { |
||
676 | switch ($s[$i]) { |
||
677 | case '(': |
||
678 | if ($depth) { |
||
679 | $modifierParamStr .= $s[$i]; |
||
680 | } |
||
681 | $depth++; |
||
682 | break; |
||
683 | |||
684 | case ')': |
||
685 | $depth--; |
||
686 | if ($depth) { |
||
687 | $modifierParamStr .= $s[$i]; |
||
688 | } |
||
689 | break; |
||
690 | case ':': |
||
691 | if ($depth) { |
||
692 | $modifierParamStr .= $s[$i]; |
||
693 | } else { |
||
694 | $modifierArr[$modifierName] = $this->parseModifierParamStringSlowButAccurate($modifierParamStr); |
||
695 | $modifierName = ''; |
||
696 | $modifierParamStr = ''; |
||
697 | } |
||
698 | break; |
||
699 | default: |
||
700 | if ($depth) { |
||
701 | $modifierParamStr .= $s[$i]; |
||
702 | } else { |
||
703 | $modifierName .= $s[$i]; |
||
704 | } |
||
705 | } |
||
706 | } |
||
707 | |||
708 | if ($modifierName) { |
||
709 | $modifierArr[$modifierName] = $this->parseModifierParamStringSlowButAccurate($modifierParamStr); |
||
710 | } |
||
711 | |||
712 | return $modifierArr; |
||
713 | } |
||
714 | |||
715 | /** |
||
716 | * Can make an array out of parameter string that looks like this: |
||
717 | * |
||
718 | * param1|param2|param3 |
||
719 | * |
||
720 | * Can also handle params that contain other modifiers with params like this: |
||
721 | * param1|modifier(innerParam1|innerParam2)|param3 |
||
722 | * |
||
723 | * @param string $s |
||
724 | * @return array |
||
725 | */ |
||
726 | private function parseModifierParamStringSlowButAccurate($s) |
||
727 | { |
||
728 | $paramArr = []; |
||
729 | $tmpStr = ''; |
||
730 | |||
731 | $depth = 0; |
||
732 | for ($i = 0; $i < strlen($s); $i++) { |
||
733 | switch ($s[$i]) { |
||
734 | case '(': |
||
735 | $tmpStr .= $s[$i]; |
||
736 | $depth++; |
||
737 | break; |
||
738 | |||
739 | case ')': |
||
740 | $tmpStr .= $s[$i]; |
||
741 | $depth--; |
||
742 | break; |
||
743 | |||
744 | case '|': |
||
745 | if ($depth) { |
||
746 | $tmpStr .= $s[$i]; |
||
747 | } else { |
||
748 | $paramArr[] = $tmpStr; |
||
749 | $tmpStr = ''; |
||
750 | } |
||
751 | break; |
||
752 | |||
753 | default: |
||
754 | $tmpStr .= $s[$i]; |
||
755 | } |
||
756 | } |
||
757 | |||
758 | if (strlen($tmpStr)) { |
||
759 | $paramArr[] = $tmpStr; |
||
760 | } |
||
761 | |||
762 | return $paramArr; |
||
763 | } |
||
764 | |||
765 | /** |
||
766 | * Checks if includeName is an include nested inside a recursive inclusion. |
||
767 | * If yes, return the path to that item - false otherwise. |
||
768 | * |
||
769 | * Example: |
||
770 | * For projects there can be an include for phases. Phases are included recursively in its own adapter. So you'd |
||
771 | * want when you include phases.steps that the steps inclusion is executed in the phase adapter and not in the |
||
772 | * project adapter. That's why we need to separate includes that need to be passed further here. |
||
773 | * |
||
774 | * "recursiveinclude" results to false |
||
775 | * "normalprop1" results to false |
||
776 | * "recursiveinclude.normalprop1.normalprop2" results to "recursiveinclude" |
||
777 | * "normalprop1.recursiveinclude.normalprop2" results to "normalprop1.recursiveinclude" |
||
778 | * |
||
779 | * @param $includeName |
||
780 | * @param $availableIncludes |
||
781 | * @return bool|string |
||
782 | */ |
||
783 | private function pathForNestedInclude($includeName, $availableIncludes) |
||
784 | { |
||
785 | $pathArray = explode('.', $includeName); |
||
786 | if (!isset($pathArray[1])) { |
||
787 | return false; |
||
788 | } |
||
789 | |||
790 | $pathArrayLength = count($pathArray); |
||
791 | for ($i = 1; $i < $pathArrayLength; $i++) { |
||
792 | $implicitPath = implode('.', array_slice($pathArray, 0, $i)); |
||
793 | if ($this->extractStrategyForInclude($availableIncludes[$implicitPath]) === self::INCLUDE_RECURSIVE) { |
||
794 | return $implicitPath; |
||
795 | } |
||
796 | } |
||
797 | |||
798 | return false; |
||
799 | } |
||
800 | |||
801 | /** |
||
802 | * Include configuration can either have just the strategy or a configuration array with the strategy inside. |
||
803 | * |
||
804 | * @param mixed $include |
||
805 | * @return integer |
||
806 | */ |
||
807 | private function extractStrategyForInclude($include) |
||
808 | { |
||
809 | return is_array($include) ? $include['strategy'] : $include; |
||
810 | } |
||
811 | |||
812 | /** |
||
813 | * Validates the include string and returns an array with requiredIncludes |
||
814 | * |
||
815 | * @param string $string |
||
816 | * @return array |
||
817 | */ |
||
818 | private function parseRichParamString($string) |
||
819 | { |
||
820 | if ($string === '') { |
||
821 | return []; |
||
822 | } |
||
823 | |||
824 | if (is_string($string)) { |
||
825 | $string = explode(',', $string); |
||
826 | } |
||
827 | |||
828 | if (!is_array($string)) { |
||
829 | return []; |
||
830 | } |
||
831 | |||
832 | $requestedIncludes = []; |
||
833 | $implicitIncludes = []; |
||
834 | foreach ($string as $include) { |
||
835 | list($includeName, $allModifiersStr) = array_pad(explode(':', $include, 2), 2, null); |
||
836 | $implicitIncludes = array_merge($implicitIncludes, $this->getImplicitIncludes($includeName)); |
||
837 | |||
838 | if ($allModifiersStr === null) { |
||
839 | $requestedIncludes[$includeName] = []; |
||
840 | continue; |
||
841 | } |
||
842 | |||
843 | // Matches multiple instances of 'something(foo|bar|baz)' in the string |
||
844 | // I guess it ignores : so you could use anything, but probably don't do that |
||
845 | preg_match_all('/([\w]+)(\(([^\)]+)\))?/', $allModifiersStr, $allModifiersArr); |
||
846 | // [0] is full matched strings... |
||
847 | $modifierCount = count($allModifiersArr[0]); |
||
848 | $modifierArr = []; |
||
849 | View Code Duplication | for ($modifierIt = 0; $modifierIt < $modifierCount; $modifierIt++) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
850 | // [1] is the modifier |
||
851 | $modifierName = $allModifiersArr[1][$modifierIt]; |
||
852 | // and [3] is delimited params |
||
853 | $modifierParamStr = $allModifiersArr[3][$modifierIt]; |
||
854 | // Make modifier array key with an array of params as the value |
||
855 | $modifierArr[$modifierName] = explode('|', $modifierParamStr); |
||
856 | } |
||
857 | $requestedIncludes[$includeName] = $modifierArr; |
||
858 | } |
||
859 | |||
860 | return $this->mergeWithImplicitIncludes($requestedIncludes, $implicitIncludes); |
||
861 | } |
||
862 | |||
863 | private function mergeWithImplicitIncludes($includes, $implicitIncludes) |
||
864 | { |
||
865 | foreach ($implicitIncludes as $implicitInclude) { |
||
866 | if (isset($includes[$implicitInclude])) { |
||
867 | continue; |
||
868 | } |
||
869 | |||
870 | $includes[$implicitInclude] = []; |
||
871 | } |
||
872 | |||
873 | return $includes; |
||
874 | } |
||
875 | |||
876 | /** |
||
877 | * @param \Doctrine\ORM\QueryBuilder $query |
||
878 | * @param string $alias |
||
879 | * @param \UnserAller_Model_User $currentUser |
||
880 | * @param array $additionalParams |
||
881 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
882 | */ |
||
883 | protected function filterId($query, $alias, $currentUser, $additionalParams) |
||
884 | { |
||
885 | $rootAliasArr = $query->getRootAliases(); |
||
886 | $rootAlias = array_shift($rootAliasArr); |
||
887 | return $this->createConditionsForEntityColumn("$rootAlias.id", $query, $alias, $currentUser, $additionalParams); |
||
888 | } |
||
889 | |||
890 | private function getImplicitIncludes($includeName) |
||
891 | { |
||
892 | $parts = explode('.', $includeName); |
||
893 | $numberOfParts = count($parts); |
||
894 | |||
895 | if ($numberOfParts < 2) { |
||
896 | return []; |
||
897 | } |
||
898 | |||
899 | $implicitIncludes = []; |
||
900 | for ($i = 1; $i < $numberOfParts; $i++) { |
||
901 | $implicitIncludes[] = implode('.', array_slice($parts, 0, $i)); |
||
902 | } |
||
903 | |||
904 | return $implicitIncludes; |
||
905 | } |
||
906 | |||
907 | /** |
||
908 | * @param \UnserAller_Model_User $currentUser |
||
909 | * @return \Doctrine\ORM\QueryBuilder |
||
910 | */ |
||
911 | abstract protected function initIncompleteStatement($currentUser); |
||
912 | |||
913 | private function createIncompleteStatement( |
||
914 | $currentUser, |
||
915 | $filterString, |
||
916 | $language, |
||
917 | $joinFiltersWith = 'AND', |
||
918 | &$meta = [] |
||
919 | ) { |
||
920 | return $this->addFilterStatements( |
||
921 | $this->initIncompleteStatement($currentUser), |
||
922 | $currentUser, |
||
923 | $filterString, |
||
924 | $language, |
||
925 | $joinFiltersWith |
||
926 | ); |
||
927 | } |
||
928 | |||
929 | /** |
||
930 | * @param \UnserAller_Model_User $currentUser |
||
931 | * @param string $filterString |
||
932 | * @param $language |
||
933 | * @param string $joinFiltersWith |
||
934 | * @return int |
||
935 | */ |
||
936 | public function findTotalNumberOfRows($currentUser, $filterString = '', $language = '', $joinFiltersWith = 'AND') |
||
937 | { |
||
938 | return $this->selectTotalNumberOfRows( |
||
939 | $this->createIncompleteStatement($currentUser, $filterString, $language, $joinFiltersWith) |
||
940 | ); |
||
941 | } |
||
942 | |||
943 | /** |
||
944 | * @param \UnserAller_Model_User $currentUser |
||
945 | * @param string $language |
||
946 | * @param string $filterString |
||
947 | * @param string $includeString |
||
948 | * @param string $orderString |
||
949 | * @param int $limit |
||
950 | * @param int $page |
||
951 | * @param string $joinFiltersWith |
||
952 | * @param int $metaOnObjectLevelOption |
||
953 | * @return array |
||
954 | */ |
||
955 | public function findMultipleForApi( |
||
956 | $currentUser, |
||
957 | $language = '', |
||
958 | $filterString = '', |
||
959 | $includeString = '', |
||
960 | $orderString = '', |
||
961 | $limit = 0, |
||
962 | $page = 1, |
||
963 | $joinFiltersWith = 'AND', |
||
964 | $metaOnObjectLevelOption = self::META_ON_OBJECT_LEVEL_ENABLED |
||
965 | ) { |
||
966 | if ($page <= 0) { |
||
967 | $page = 1; |
||
968 | } |
||
969 | |||
970 | $meta = $this->initMetaArray('', $language); |
||
971 | |||
972 | $incompleteStatement = $this->createIncompleteStatement( |
||
973 | $currentUser, |
||
974 | $filterString, |
||
975 | $language, |
||
976 | $joinFiltersWith, |
||
977 | $meta |
||
978 | ); |
||
979 | |||
980 | $completeStatement = $this->completeStatement( |
||
981 | $currentUser, |
||
982 | $language, |
||
983 | $incompleteStatement, |
||
984 | $includeString, |
||
985 | $orderString, |
||
986 | $meta |
||
987 | ); |
||
988 | if ($limit > 0) { |
||
989 | $completeStatement |
||
990 | ->setFirstResult(($page - 1) * $limit) |
||
991 | ->setMaxResults($limit); |
||
992 | } |
||
993 | |||
994 | $meta['numberOfItemsFound'] = $this->selectTotalNumberOfRows($incompleteStatement); |
||
995 | $meta['numberOfPages'] = $this->calculateTotalPages($meta['numberOfItemsFound'], $limit); |
||
996 | $meta['appliedFilters'] = (string) $filterString; |
||
997 | $meta['appliedIncludes'] = (string) $includeString; |
||
998 | $meta['appliedOrders'] = (string) $orderString; |
||
999 | $meta['currentPage'] = $page; |
||
1000 | $meta['pagesize'] = $limit; |
||
1001 | |||
1002 | return [ |
||
1003 | 'totalPages' => $meta['numberOfPages'], |
||
1004 | 'filter' => $filterString, |
||
1005 | 'include' => $includeString, |
||
1006 | 'page' => $page, |
||
1007 | 'pageSize' => $limit, |
||
1008 | 'data' => $this->applyScheduledFixes( |
||
1009 | $this->getRawResult($completeStatement), |
||
1010 | $currentUser, |
||
1011 | $language, |
||
1012 | $meta, |
||
1013 | $metaOnObjectLevelOption |
||
1014 | ), |
||
1015 | 'meta' => $meta |
||
1016 | ]; |
||
1017 | } |
||
1018 | |||
1019 | private function initMetaArray($modelPathOffset = '', $language = '') |
||
1020 | { |
||
1021 | return [ |
||
1022 | 'modelnameIndex' => [ |
||
1023 | $this->getModelForMeta() => [$modelPathOffset] |
||
1024 | ], |
||
1025 | 'language' => $language |
||
1026 | ]; |
||
1027 | } |
||
1028 | |||
1029 | /** |
||
1030 | * @param string $language |
||
1031 | * @param string $filterString |
||
1032 | * @param string $includeString |
||
1033 | * @param string $orderString |
||
1034 | * @param int $limit |
||
1035 | * @param int $page |
||
1036 | * @param string $filterMode |
||
1037 | * @return array |
||
1038 | */ |
||
1039 | public function findMultiple( |
||
1040 | $language = '', |
||
1041 | $filterString = '', |
||
1042 | $includeString = '', |
||
1043 | $orderString = '', |
||
1044 | $limit = 0, |
||
1045 | $page = 1, |
||
1046 | $filterMode = 'AND' |
||
1047 | ) { |
||
1048 | return json_decode(json_encode($this->findMultipleForApi( |
||
1049 | $this->getCurrentlyAuthenticatedUser(), |
||
1050 | $language, |
||
1051 | $filterString, |
||
1052 | $includeString, |
||
1053 | $orderString, |
||
1054 | $limit, |
||
1055 | $page, |
||
1056 | $filterMode, |
||
1057 | self::META_ON_OBJECT_LEVEL_DISABLED |
||
1058 | )), true); |
||
1059 | } |
||
1060 | |||
1061 | /** |
||
1062 | * @param \UnserAller_Model_User $currentUser |
||
1063 | * @param string $language |
||
1064 | * @param string $filterString |
||
1065 | * @param string $includeString |
||
1066 | * @param string $orderString |
||
1067 | * @param int $limit |
||
1068 | * @param string $filterMode |
||
1069 | * @return \Generator |
||
1070 | */ |
||
1071 | public function batchFindMultiple( |
||
1072 | $currentUser, |
||
1073 | $language = '', |
||
1074 | $filterString = '', |
||
1075 | $includeString = '', |
||
1076 | $orderString = '', |
||
1077 | $limit = 500, |
||
1078 | $filterMode = 'AND' |
||
1079 | ) { |
||
1080 | $page = 1; |
||
1081 | |||
1082 | $result = $this->findMultipleForApi( |
||
1083 | $currentUser, |
||
1084 | $language, |
||
1085 | $filterString, |
||
1086 | $includeString, |
||
1087 | $orderString, |
||
1088 | $limit, |
||
1089 | $page, |
||
1090 | $filterMode |
||
1091 | ); |
||
1092 | |||
1093 | yield $result; |
||
1094 | |||
1095 | $totalPages = $result['totalPages']; |
||
1096 | unset($result); |
||
1097 | $page++; |
||
1098 | while ($page <= $totalPages) { |
||
1099 | $result = $this->findMultipleForApi( |
||
1100 | $currentUser, |
||
1101 | $language, |
||
1102 | $filterString, |
||
1103 | $includeString, |
||
1104 | $orderString, |
||
1105 | $limit, |
||
1106 | $page, |
||
1107 | $filterMode |
||
1108 | ); |
||
1109 | yield $result; |
||
1110 | $page++; |
||
1111 | unset($result); |
||
1112 | } |
||
1113 | } |
||
1114 | |||
1115 | |||
1116 | /** |
||
1117 | * @param \UnserAller_Model_User $currentUser |
||
1118 | * @param string $language |
||
1119 | * @param string $filterString |
||
1120 | * @param string $includeString |
||
1121 | * @param string $orderString |
||
1122 | * @param int $limit |
||
1123 | * @param int $page |
||
1124 | * @param string $filterMode |
||
1125 | * @return array |
||
1126 | */ |
||
1127 | public function getNativeSqlIngredientsForFindMultiple( |
||
1128 | $currentUser, |
||
1129 | $language = '', |
||
1130 | $filterString = '', |
||
1131 | $includeString = '', |
||
1132 | $orderString = '', |
||
1133 | $limit = 0, |
||
1134 | $page = 1, |
||
1135 | $filterMode = 'AND' |
||
1136 | ) { |
||
1137 | return $this->getNativeSqlIngredients( |
||
1138 | $this->getQueryBuilderFromFindMultiple( |
||
1139 | $currentUser, $language, $filterString, $includeString, $orderString, $limit, $page, $filterMode |
||
1140 | )->getQuery() |
||
1141 | ); |
||
1142 | } |
||
1143 | |||
1144 | /** |
||
1145 | * Returns a query builder from the findMultipleForApi method. |
||
1146 | * |
||
1147 | * @param $currentUser |
||
1148 | * @param string $language |
||
1149 | * @param string $filterString |
||
1150 | * @param string $includeString |
||
1151 | * @param string $orderString |
||
1152 | * @param int $limit |
||
1153 | * @param int $page |
||
1154 | * @param string $filterMode |
||
1155 | * @return QueryBuilder |
||
1156 | */ |
||
1157 | public function getQueryBuilderFromFindMultiple( |
||
1158 | $currentUser, |
||
1159 | $language = '', |
||
1160 | $filterString = '', |
||
1161 | $includeString = '', |
||
1162 | $orderString = '', |
||
1163 | $limit = 0, |
||
1164 | $page = 1, |
||
1165 | $filterMode = 'AND' |
||
1166 | ) { |
||
1167 | if ($page <= 0) { |
||
1168 | $page = 1; |
||
1169 | } |
||
1170 | |||
1171 | $incompleteStatement = $this->createIncompleteStatement($currentUser, $filterString, $language, $filterMode); |
||
1172 | $completeStatement = $this->completeStatement( |
||
1173 | $currentUser, |
||
1174 | $language, |
||
1175 | $incompleteStatement, |
||
1176 | $includeString, |
||
1177 | $orderString |
||
1178 | ); |
||
1179 | if ($limit > 0) { |
||
1180 | $completeStatement |
||
1181 | ->setFirstResult(($page - 1) * $limit) |
||
1182 | ->setMaxResults($limit); |
||
1183 | } |
||
1184 | |||
1185 | return $completeStatement; |
||
1186 | } |
||
1187 | |||
1188 | /** |
||
1189 | * @param Query $query |
||
1190 | * @return array |
||
1191 | */ |
||
1192 | private function getNativeSqlIngredients($query) |
||
1193 | { |
||
1194 | $sql = $query->getSQL(); |
||
1195 | $c = new \ReflectionClass('Doctrine\ORM\Query'); |
||
1196 | $parser = $c->getProperty('_parserResult'); |
||
1197 | $parser->setAccessible(true); |
||
1198 | /** @var \ReflectionProperty $parser */ |
||
1199 | $parser = $parser->getValue($query); |
||
1200 | /** @var \Doctrine\ORM\Query\ParserResult $parser */ |
||
1201 | $resultSet = $parser->getResultSetMapping(); |
||
1202 | |||
1203 | // Change the aliases back to what was originally specified in the QueryBuilder. |
||
1204 | $sql = preg_replace_callback('/AS\s([a-zA-Z0-9_]+)/', function ($matches) use ($resultSet) { |
||
1205 | $ret = 'AS '; |
||
1206 | if ($resultSet->isScalarResult($matches[1])) { |
||
1207 | $ret .= $resultSet->getScalarAlias($matches[1]); |
||
1208 | } else { |
||
1209 | $ret .= $matches[1]; |
||
1210 | } |
||
1211 | return $ret; |
||
1212 | }, $sql); |
||
1213 | $m = $c->getMethod('processParameterMappings'); |
||
1214 | $m->setAccessible(true); |
||
1215 | list($params, $types) = $m->invoke($query, $parser->getParameterMappings()); |
||
1216 | return [$sql, $params, $types]; |
||
1217 | } |
||
1218 | |||
1219 | /** |
||
1220 | * @param \UnserAller_Model_User $currentUser |
||
1221 | * @param string $language |
||
1222 | * @param string $filterString |
||
1223 | * @param string $includeString |
||
1224 | * @param string $orderString |
||
1225 | * @param int $metaOnObjectLevelOption |
||
1226 | * @return array|null |
||
1227 | */ |
||
1228 | public function findOneForApi( |
||
1229 | $currentUser, |
||
1230 | $language = '', |
||
1231 | $filterString = '', |
||
1232 | $includeString = '', |
||
1233 | $orderString = '', |
||
1234 | $metaOnObjectLevelOption = self::META_ON_OBJECT_LEVEL_ENABLED |
||
1235 | ) { |
||
1236 | return $this->createSingleResult( |
||
1237 | $currentUser, |
||
1238 | $language, |
||
1239 | $filterString, |
||
1240 | $includeString, |
||
1241 | $orderString, |
||
1242 | $metaOnObjectLevelOption |
||
1243 | ); |
||
1244 | } |
||
1245 | |||
1246 | /** |
||
1247 | * @param string $language |
||
1248 | * @param string $filterString |
||
1249 | * @param string $includeString |
||
1250 | * @param string $orderString |
||
1251 | * @return array|null |
||
1252 | */ |
||
1253 | public function findOne($language = '', $filterString = '', $includeString = '', $orderString = '') |
||
1254 | { |
||
1255 | return json_decode(json_encode($this->findOneForApi( |
||
1256 | $this->getCurrentlyAuthenticatedUser(), |
||
1257 | $language, |
||
1258 | $filterString, |
||
1259 | $includeString, |
||
1260 | $orderString, |
||
1261 | self::META_ON_OBJECT_LEVEL_DISABLED |
||
1262 | )), true); |
||
1263 | } |
||
1264 | |||
1265 | /** |
||
1266 | * @param \UnserAller_Model_User $currentUser |
||
1267 | * @param int $id |
||
1268 | * @param string $language |
||
1269 | * @param string $include |
||
1270 | * @param int $metaOnObjectLevelOption |
||
1271 | * @return array|null |
||
1272 | */ |
||
1273 | public function findForApi( |
||
1274 | $currentUser, |
||
1275 | $id, |
||
1276 | $language = '', |
||
1277 | $include = '', |
||
1278 | $metaOnObjectLevelOption = self::META_ON_OBJECT_LEVEL_ENABLED |
||
1279 | ) { |
||
1280 | $this->id = (int)$id; |
||
1281 | return $this->findOneForApi( |
||
1282 | $currentUser, |
||
1283 | $language, |
||
1284 | "id:is($id)", |
||
1285 | $include, |
||
1286 | '', |
||
1287 | $metaOnObjectLevelOption |
||
1288 | ); |
||
1289 | } |
||
1290 | |||
1291 | /** |
||
1292 | * @param int $id |
||
1293 | * @param string $language |
||
1294 | * @param string $include |
||
1295 | * @return array|null |
||
1296 | */ |
||
1297 | public function find($id, $language = '', $include = '') |
||
1298 | { |
||
1299 | return json_decode(json_encode($this->findForApi( |
||
1300 | $this->getCurrentlyAuthenticatedUser(), |
||
1301 | $id, |
||
1302 | $language, |
||
1303 | $include, |
||
1304 | self::META_ON_OBJECT_LEVEL_DISABLED |
||
1305 | )), true); |
||
1306 | } |
||
1307 | |||
1308 | /** |
||
1309 | * @return null|\UnserAller_Model_User|object |
||
1310 | */ |
||
1311 | private function getCurrentlyAuthenticatedUser() |
||
1312 | { |
||
1313 | return $this->getEntityManager()->find( |
||
1314 | \UnserAller_Model_User::class, |
||
1315 | (int)\Zend_Auth::getInstance()->getIdentity() |
||
1316 | ); |
||
1317 | } |
||
1318 | |||
1319 | /** |
||
1320 | * @param \UnserAller_Model_User $currentUser |
||
1321 | * @param string $language |
||
1322 | * @param string $filterString |
||
1323 | * @param string $includeString |
||
1324 | * @param string $orderString |
||
1325 | * @param int $metaOnObjectLevelOption |
||
1326 | * @return array|null |
||
1327 | */ |
||
1328 | protected function createSingleResult( |
||
1329 | $currentUser, |
||
1330 | $language, |
||
1331 | $filterString, |
||
1332 | $includeString, |
||
1333 | $orderString, |
||
1334 | $metaOnObjectLevelOption = self::META_ON_OBJECT_LEVEL_ENABLED |
||
1335 | ) { |
||
1336 | $meta = $this->initMetaArray('', $language); |
||
1337 | |||
1338 | $result = $this->getRawResult( |
||
1339 | $this->completeStatement( |
||
1340 | $currentUser, |
||
1341 | $language, |
||
1342 | $this->createIncompleteStatement($currentUser, $filterString, $language, 'AND', $meta), |
||
1343 | $includeString, |
||
1344 | $orderString, |
||
1345 | $meta |
||
1346 | )->setFirstResult(0)->setMaxResults(1) |
||
1347 | ); |
||
1348 | |||
1349 | if (!isset($result[0])) { |
||
1350 | return null; |
||
1351 | } |
||
1352 | |||
1353 | $result = $this->applyScheduledFixes($result, $currentUser, $language, $meta, $metaOnObjectLevelOption)[0]; |
||
1354 | if ($metaOnObjectLevelOption === self::META_ON_OBJECT_LEVEL_ENABLED) { |
||
1355 | $result['meta'] = $result['meta'] + $meta; |
||
1356 | } |
||
1357 | return $result; |
||
1358 | } |
||
1359 | |||
1360 | protected function getDefaultPostProcessDirections() |
||
1361 | { |
||
1362 | return []; |
||
1363 | } |
||
1364 | |||
1365 | /** |
||
1366 | * Adds the default select statement, all includes and order statements to the incomplete statement |
||
1367 | * and returns the qurey builder instance |
||
1368 | * |
||
1369 | * @param \UnserAller_Model_User $currentUser |
||
1370 | * @param $language |
||
1371 | * @param \Doctrine\ORM\QueryBuilder $incompleteStatement |
||
1372 | * @param string $includeString |
||
1373 | * @param string $orderString |
||
1374 | * @param array $meta |
||
1375 | * @return \Doctrine\ORM\QueryBuilder |
||
1376 | */ |
||
1377 | private function completeStatement( |
||
1378 | $currentUser, |
||
1379 | $language, |
||
1380 | $incompleteStatement, |
||
1381 | $includeString, |
||
1382 | $orderString, |
||
1383 | &$meta = [] |
||
1384 | ) { |
||
1385 | $statement = clone $incompleteStatement; |
||
1386 | |||
1387 | $this->schedulePostProcessingDirections($this->getDefaultPostProcessDirections()); |
||
1388 | |||
1389 | return $this->addOrderStatements( |
||
1390 | $this->addIncludeStatements( |
||
1391 | $statement->select($this->getDefaultSelectStatement($statement)), |
||
1392 | $currentUser, |
||
1393 | $language, |
||
1394 | $includeString, |
||
1395 | $meta |
||
1396 | ), |
||
1397 | $currentUser, |
||
1398 | $orderString |
||
1399 | ); |
||
1400 | } |
||
1401 | |||
1402 | /** |
||
1403 | * Returns the default select statement. In this case it just returns the first root entity which means the |
||
1404 | * entire root entity will be selected |
||
1405 | * |
||
1406 | * @param \Doctrine\ORM\QueryBuilder $query |
||
1407 | * @return string |
||
1408 | */ |
||
1409 | protected function getDefaultSelectStatement($query) |
||
1410 | { |
||
1411 | return 'DISTINCT ' . $this->getRootAlias($query); |
||
1412 | } |
||
1413 | |||
1414 | /** |
||
1415 | * Returns first root alias from query builder |
||
1416 | * |
||
1417 | * @param \Doctrine\ORM\QueryBuilder $query |
||
1418 | * @return string |
||
1419 | */ |
||
1420 | protected function getRootAlias($query) |
||
1421 | { |
||
1422 | $rootAliasArr = $query->getRootAliases(); |
||
1423 | return array_shift($rootAliasArr); |
||
1424 | } |
||
1425 | |||
1426 | /** |
||
1427 | * Returns true if result item has an additional layer in the hierarchy because of custom subselects |
||
1428 | * |
||
1429 | * @param array $item |
||
1430 | * @return bool |
||
1431 | */ |
||
1432 | private function mustFlattenResultItem($item) |
||
1433 | { |
||
1434 | return isset($item[0]); |
||
1435 | } |
||
1436 | |||
1437 | /** |
||
1438 | * Returns doctrine array results with all fixes applied |
||
1439 | * |
||
1440 | * @param \Doctrine\ORM\QueryBuilder $statement |
||
1441 | * @return array |
||
1442 | */ |
||
1443 | private function getRawResult($statement) |
||
1444 | { |
||
1445 | //Output raw sql here if you like to debug hard |
||
1446 | //echo $statement->getQuery()->getSQL(); die; |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
74% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
1447 | return $statement->getQuery()->getResult(Query::HYDRATE_ARRAY); |
||
1448 | } |
||
1449 | |||
1450 | /** |
||
1451 | * Doctrine will create an additional result layer when values are selected that do not belong |
||
1452 | * to the doctrine object model. This function removes this additional layer and merges custom values with |
||
1453 | * the doctrine object model for a single result item - not the whole result array. |
||
1454 | * |
||
1455 | * @param array $item |
||
1456 | * @return array |
||
1457 | */ |
||
1458 | private function flattenResultItem($item) |
||
1459 | { |
||
1460 | if (!$this->mustFlattenResultItem($item)) { |
||
1461 | return $item; |
||
1462 | } |
||
1463 | |||
1464 | return array_merge(array_shift($item), $item); |
||
1465 | } |
||
1466 | |||
1467 | /** |
||
1468 | * Parses $string for orderBy statements and returns an array where order statements are values. |
||
1469 | * |
||
1470 | * When string is "latestFirst, longestFirst" result would be: ['latestFirst', 'longestFirst'] |
||
1471 | * |
||
1472 | * @param string $string |
||
1473 | * @return array |
||
1474 | */ |
||
1475 | protected function parseOrderString($string) |
||
1476 | { |
||
1477 | return array_filter(array_map('trim', explode(',', $string))); |
||
1478 | } |
||
1479 | |||
1480 | /** |
||
1481 | * @uses getFallbackLanguage |
||
1482 | * @uses getRequestedLanguage |
||
1483 | * @param $language |
||
1484 | * @return callable |
||
1485 | */ |
||
1486 | private function getItemLanguageGetter($language) |
||
1487 | { |
||
1488 | return $language === '' ? 'getFallbackLanguage' : 'getRequestedLanguage'; |
||
1489 | } |
||
1490 | |||
1491 | /** |
||
1492 | * @param mixed[] $resultItem |
||
1493 | * @param string $requestedLanguage |
||
1494 | * @return string |
||
1495 | */ |
||
1496 | private function getRequestedLanguage($resultItem, $requestedLanguage) |
||
1497 | { |
||
1498 | return $requestedLanguage; |
||
1499 | } |
||
1500 | |||
1501 | /** |
||
1502 | * Executes all operations that were scheduled for post processing |
||
1503 | * |
||
1504 | * @param array $result |
||
1505 | * @param \UnserAller_Model_User $currentUser |
||
1506 | * @param $language |
||
1507 | * @param array $meta |
||
1508 | * @param int $metaOnObjectLevelOption |
||
1509 | * @return array |
||
1510 | */ |
||
1511 | private function applyScheduledFixes( |
||
1512 | $result, |
||
1513 | $currentUser, |
||
1514 | $language, |
||
1515 | &$meta = [], |
||
1516 | $metaOnObjectLevelOption = self::META_ON_OBJECT_LEVEL_ENABLED |
||
1517 | ) { |
||
1518 | $scheduledFixes = $this->flushResultArrayFixSchedule(); |
||
1519 | |||
1520 | if (!$result) { |
||
0 ignored issues
–
show
The expression
$result of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
1521 | return $result; |
||
1522 | } |
||
1523 | |||
1524 | $numberOfResults = count($result); |
||
1525 | |||
1526 | $this->applyFixesToItem( |
||
1527 | $result[0], |
||
1528 | $scheduledFixes, |
||
1529 | $currentUser, |
||
1530 | $meta, |
||
1531 | 'retrieveNestedCollectionAndMergeMeta', |
||
1532 | $language, |
||
1533 | $this->getItemLanguageGetter($language), |
||
1534 | $metaOnObjectLevelOption |
||
1535 | ); |
||
1536 | for ($i = 1; $i < $numberOfResults; $i++) { |
||
1537 | $this->applyFixesToItem( |
||
1538 | $result[$i], |
||
1539 | $scheduledFixes, |
||
1540 | $currentUser, |
||
1541 | $meta, |
||
1542 | 'retrieveNestedCollection', |
||
1543 | $language, |
||
1544 | $this->getItemLanguageGetter($language), |
||
1545 | $metaOnObjectLevelOption |
||
1546 | ); |
||
1547 | } |
||
1548 | |||
1549 | return $result; |
||
1550 | } |
||
1551 | |||
1552 | private function retrieveNestedCollectionResult($value, $nestingOptions, $language = '') |
||
1553 | { |
||
1554 | list($model, $filterFunction, $currentUser, $additionalParams) = $nestingOptions; |
||
1555 | list( |
||
1556 | $filterString, |
||
1557 | $includeString, |
||
1558 | $orderString, |
||
1559 | $limit, |
||
1560 | $page, |
||
1561 | $filterMode |
||
1562 | ) = $this->parseAdditionalIncludeParams($additionalParams); |
||
1563 | |||
1564 | if ($filterString) { |
||
1565 | $filterString = $filterString . ','; |
||
1566 | } |
||
1567 | |||
1568 | if (is_array($value)) { |
||
1569 | $filterFunctionString = vsprintf($filterFunction, array_merge($value)); |
||
1570 | } else { |
||
1571 | $filterFunctionString = sprintf($filterFunction, $value); |
||
1572 | } |
||
1573 | |||
1574 | return $this->getAdapter($model)->findMultipleForApi( |
||
1575 | $currentUser, |
||
1576 | $language, |
||
1577 | $filterString . $filterFunctionString, |
||
1578 | $includeString, |
||
1579 | $orderString, |
||
1580 | $limit, |
||
1581 | $page, |
||
1582 | $filterMode |
||
1583 | ); |
||
1584 | } |
||
1585 | |||
1586 | private function retrieveNestedCollection($value, $nestingOptions, $language, $finalPath, $meta) |
||
1587 | { |
||
1588 | return $this->retrieveNestedCollectionResult($value, $nestingOptions, $language)['data']; |
||
1589 | } |
||
1590 | |||
1591 | private function retrieveNestedCollectionAndMergeMeta($value, $nestingOptions, $language, $finalPath, &$meta) |
||
1592 | { |
||
1593 | $result = $this->retrieveNestedCollectionResult($value, $nestingOptions, $language); |
||
1594 | $this->mergeNestedMeta($meta, $result['meta'], $finalPath); |
||
1595 | return $result['data']; |
||
1596 | } |
||
1597 | |||
1598 | private function retrieveNestedSingleResult($value, $nestingOptions, $language = '') |
||
1599 | { |
||
1600 | list($model, $filterFunction, $currentUser, $additionalParams) = $nestingOptions; |
||
1601 | list($filterString, $includeString, $orderString, , ,) = $this->parseAdditionalIncludeParams($additionalParams); |
||
1602 | |||
1603 | if ($filterString) { |
||
1604 | $filterString = $filterString . ','; |
||
1605 | } |
||
1606 | |||
1607 | return $this->getAdapter($model)->findOneForApi( |
||
1608 | $currentUser, |
||
1609 | $language, |
||
1610 | $filterString . sprintf($filterFunction, $value), |
||
1611 | $includeString, |
||
1612 | $orderString |
||
1613 | ); |
||
1614 | } |
||
1615 | |||
1616 | private function retrieveNestedSingleAndMergeMeta($value, $nestingOptions, $language, $finalPath, &$meta) |
||
1617 | { |
||
1618 | $result = $this->retrieveNestedSingleResult($value, $nestingOptions, $language); |
||
1619 | $this->mergeNestedMeta($meta, $result['meta'], $finalPath); |
||
1620 | return $result; |
||
1621 | } |
||
1622 | |||
1623 | private function mergeNestedMeta(&$meta, $nestedMeta, $includeName) |
||
1624 | { |
||
1625 | foreach ($nestedMeta['modelnameIndex'] as $model => $paths) { |
||
1626 | foreach ($paths as $path) { |
||
1627 | $fullPath = $includeName . '.' . $path; |
||
1628 | if ($path && (!isset($meta['modelnameIndex'][$model]) || !in_array($fullPath, $meta['modelnameIndex'][$model]))) { |
||
1629 | $meta['modelnameIndex'][$model][] = $fullPath; |
||
1630 | } |
||
1631 | } |
||
1632 | } |
||
1633 | } |
||
1634 | |||
1635 | /** |
||
1636 | * @param $item |
||
1637 | * @param $scheduledFixes |
||
1638 | * @param $currentUser |
||
1639 | * @param $meta |
||
1640 | * @param $collectionNestingMethod |
||
1641 | * @param $language |
||
1642 | * @param $itemLanguageGetter |
||
1643 | * @param int $metaOnObjectLevelOption |
||
1644 | * @uses retrieveNestedCollection |
||
1645 | * @uses retrieveNestedCollectionAndMergeMeta |
||
1646 | */ |
||
1647 | private function applyFixesToItem( |
||
1648 | &$item, |
||
1649 | $scheduledFixes, |
||
1650 | $currentUser, |
||
1651 | &$meta, |
||
1652 | $collectionNestingMethod, |
||
1653 | $language, |
||
1654 | $itemLanguageGetter, |
||
1655 | $metaOnObjectLevelOption = self::META_ON_OBJECT_LEVEL_ENABLED |
||
1656 | ) { |
||
1657 | $item = $this->flattenResultItem($item); |
||
1658 | |||
1659 | //If deleteion is not scheduled and done at the end, multiple tasks on same field can fail |
||
1660 | $scheduledDeletions = []; |
||
1661 | |||
1662 | foreach ($scheduledFixes as $path => $fix) { |
||
1663 | if (isset($fix['delete'])) { |
||
1664 | $scheduledDeletions[$path] = $fix; |
||
1665 | continue; |
||
1666 | } |
||
1667 | |||
1668 | if (isset($fix['cast'])) { |
||
1669 | \UnserAllerLib_Tool_Array::castNestedValue($item, $path, $fix['cast']); |
||
1670 | } |
||
1671 | |||
1672 | $value = \UnserAllerLib_Tool_Array::readNestedValue($item, $path); |
||
1673 | |||
1674 | if (isset($fix['additionalFilterValues'])) { |
||
1675 | $value = [$value]; |
||
1676 | |||
1677 | foreach ($fix['additionalFilterValues'] as $additionalFilterValue) { |
||
1678 | $value[] = \UnserAllerLib_Tool_Array::readNestedValue($item, $additionalFilterValue); |
||
1679 | } |
||
1680 | } |
||
1681 | |||
1682 | View Code Duplication | if (isset($fix['nestCollection'])) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1683 | $value = $this->$collectionNestingMethod( |
||
1684 | $value, |
||
1685 | $fix['nestCollection'], |
||
1686 | $this->$itemLanguageGetter($item, $language), |
||
1687 | $fix['move'] ? $fix['move'] : $path, |
||
1688 | $meta |
||
1689 | ); |
||
1690 | } |
||
1691 | |||
1692 | View Code Duplication | if (isset($fix['nestSingle'])) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1693 | $value = $this->retrieveNestedSingleAndMergeMeta( |
||
1694 | $value, |
||
1695 | $fix['nestSingle'], |
||
1696 | $this->$itemLanguageGetter($item, $language), |
||
1697 | $fix['move'] ? $fix['move'] : $path, |
||
1698 | $meta |
||
1699 | ); |
||
1700 | } |
||
1701 | |||
1702 | if (isset($fix['filter'])) { |
||
1703 | $value = $this->filterValue($fix['filter'], $value, $currentUser); |
||
1704 | } |
||
1705 | |||
1706 | if (isset($fix['cFilter'])) { |
||
1707 | $value = $this->filterValue($fix['cFilter'], $value, $currentUser); |
||
1708 | } |
||
1709 | |||
1710 | if (isset($fix['mFilter'])) { |
||
1711 | $value = $this->filterValue($fix['mFilter'], $item, $currentUser); |
||
1712 | } |
||
1713 | |||
1714 | if (isset($fix['move'])) { |
||
1715 | \UnserAllerLib_Tool_Array::integrateNestedValue($item, $fix['move'], $value); |
||
1716 | if ($path != $fix['move']) { |
||
1717 | $scheduledDeletions[$path] = ['delete' => 1]; |
||
1718 | } |
||
1719 | } |
||
1720 | |||
1721 | if (isset($fix['addMeta'])) { |
||
1722 | $item[$fix['addMeta']['alias']]['meta'] = $this->createMetadataForResultItem($item[$fix['addMeta']['alias']], $language, $itemLanguageGetter, $fix['addMeta']['model']); |
||
1723 | } |
||
1724 | } |
||
1725 | |||
1726 | foreach ($scheduledDeletions as $path => $fix) { |
||
1727 | \UnserAllerLib_Tool_Array::unsetNestedValue($item, $path); |
||
1728 | } |
||
1729 | |||
1730 | if ($metaOnObjectLevelOption === self::META_ON_OBJECT_LEVEL_ENABLED) { |
||
1731 | $item['meta'] = $this->createMetadataForResultItem($item, $language, $itemLanguageGetter); |
||
1732 | } |
||
1733 | } |
||
1734 | |||
1735 | /** |
||
1736 | * @param mixed[] $resultItem |
||
1737 | * @param string $requestedLanguage |
||
1738 | * @param callable $itemLanguageGetter |
||
1739 | * @return array |
||
1740 | */ |
||
1741 | private function createMetadataForResultItem($resultItem, $requestedLanguage, $itemLanguageGetter, $model = null) |
||
1742 | { |
||
1743 | return [ |
||
1744 | 'language' => $this->$itemLanguageGetter($resultItem, $requestedLanguage), |
||
1745 | 'model' => $model ? $model : $this->getModelForMeta(), |
||
1746 | ]; |
||
1747 | } |
||
1748 | |||
1749 | /** |
||
1750 | * Applies filter methods for $filterName to $value |
||
1751 | * @uses filterJsonAfterwards |
||
1752 | * @uses filterJsonIfNullSetEmptyObjectAfterwards |
||
1753 | * @uses filterJsonOrNullAfterwards |
||
1754 | * @uses filterDatetimeAfterwards |
||
1755 | * @uses filterDatetimeOrNullAfterwards |
||
1756 | * @uses filterIntOrNullAfterwards |
||
1757 | * @uses filterNl2BrAfterwards |
||
1758 | * @param string $filterName |
||
1759 | * @param mixed $value |
||
1760 | * @param $currentUser |
||
1761 | * @return mixed |
||
1762 | */ |
||
1763 | private function filterValue($filterName, $value, $currentUser) |
||
1764 | { |
||
1765 | if (!is_callable([$this, $filterName])) { |
||
1766 | throw new \InvalidArgumentException('Post Processing Filter method not found: ' . $filterName); |
||
1767 | } |
||
1768 | |||
1769 | return call_user_func_array([$this, $filterName], [$value, $currentUser]); |
||
1770 | } |
||
1771 | |||
1772 | /** |
||
1773 | * @param $field |
||
1774 | * @param \Doctrine\ORM\QueryBuilder $query |
||
1775 | * @param string $alias |
||
1776 | * @param \UnserAller_Model_User $currentUser |
||
1777 | * @param array $methods |
||
1778 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
1779 | * @uses stringContainExpression |
||
1780 | * @uses stringContainsExpression |
||
1781 | * @uses stringIsExpression |
||
1782 | * @uses stringNotExpression |
||
1783 | * @uses stringFalseExpression |
||
1784 | * @uses stringTrueExpression |
||
1785 | */ |
||
1786 | protected function createConditionsForStringColumn($field, $query, $alias, $currentUser, $methods) |
||
1787 | { |
||
1788 | if (\UnserAllerLib_Tool_Array::hasMoreKeysThan( |
||
1789 | $methods, |
||
1790 | ['contain', 'contains', 'is', 'not', 'false', 'true'] |
||
1791 | ) |
||
1792 | ) { |
||
1793 | throw new \InvalidArgumentException('Invalid expression methods used'); |
||
1794 | } |
||
1795 | |||
1796 | return $this->createExpression('string', $field, $query, $alias, $currentUser, $methods); |
||
1797 | } |
||
1798 | |||
1799 | /** |
||
1800 | * @param \Doctrine\ORM\QueryBuilder $query |
||
1801 | * @param $fallbackField |
||
1802 | * @param $translationName |
||
1803 | * @param $language |
||
1804 | * @param string $alias |
||
1805 | * @param \UnserAller_Model_User $currentUser |
||
1806 | * @param $additionalParams |
||
1807 | * @return \Doctrine\ORM\Query\Expr\Composite |
||
1808 | * @throws \UnserAllerLib_Api_V4_Exception_InvalidFilter |
||
1809 | */ |
||
1810 | protected function createConditionsForMultilanguageStringColumn( |
||
1811 | $query, |
||
1812 | $fallbackField, |
||
1813 | $translationName, |
||
1814 | $language, |
||
1815 | $alias, |
||
1816 | $currentUser, |
||
1817 | $additionalParams |
||
1818 | ) { |
||
1819 | if (isset($additionalParams['overAllTranslations'])) { |
||
1820 | if (!$this->supportedLanguages) { |
||
0 ignored issues
–
show
The expression
$this->supportedLanguages of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
1821 | throw new \UnserAllerLib_Api_V4_Exception_InvalidFilter('Supported languages are not set'); |
||
1822 | } |
||
1823 | |||
1824 | unset($additionalParams['overAllTranslations']); |
||
1825 | |||
1826 | $expr = $query->expr()->orX(); |
||
1827 | foreach ($this->supportedLanguages as $supportedLanguage) { |
||
1828 | $expr->add($this->createConditionsForStringColumn( |
||
1829 | "COALESCE(" . $this->joinTranslationOnce( |
||
1830 | $query, |
||
1831 | $translationName, |
||
1832 | $supportedLanguage |
||
1833 | ) . ".translation, $fallbackField)", |
||
1834 | $query, |
||
1835 | $alias, |
||
1836 | $currentUser, |
||
1837 | $additionalParams |
||
1838 | )); |
||
1839 | } |
||
1840 | |||
1841 | return $expr; |
||
1842 | } |
||
1843 | |||
1844 | return $this->createConditionsForStringColumn( |
||
1845 | "COALESCE(" . $this->joinTranslationOnce( |
||
1846 | $query, |
||
1847 | $translationName, |
||
1848 | $language |
||
1849 | ) . ".translation, $fallbackField)", |
||
1850 | $query, |
||
1851 | $alias, |
||
1852 | $currentUser, |
||
1853 | $additionalParams |
||
1854 | ); |
||
1855 | } |
||
1856 | |||
1857 | |||
1858 | /** |
||
1859 | * @param $field |
||
1860 | * @param \Doctrine\ORM\QueryBuilder $query |
||
1861 | * @param string $alias |
||
1862 | * @param \UnserAller_Model_User $currentUser |
||
1863 | * @param array $methods |
||
1864 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
1865 | * @uses dateGtExpression |
||
1866 | * @uses dateGteExpression |
||
1867 | * @uses dateLtExpression |
||
1868 | * @uses dateLteExpression |
||
1869 | * @uses dateFalseExpression |
||
1870 | * @uses dateTrueExpression |
||
1871 | * @uses dateIsExpression |
||
1872 | * @uses dateNotExpression |
||
1873 | */ |
||
1874 | View Code Duplication | protected function createConditionsForDatetimeColumn($field, $query, $alias, $currentUser, $methods) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1875 | { |
||
1876 | if (\UnserAllerLib_Tool_Array::hasMoreKeysThan( |
||
1877 | $methods, |
||
1878 | ['is', 'not', 'gt', 'gte', 'lt', 'lte', 'false', 'true'] |
||
1879 | ) |
||
1880 | ) { |
||
1881 | throw new \InvalidArgumentException('Invalid expression methods used'); |
||
1882 | } |
||
1883 | |||
1884 | return $this->createExpression('date', $field, $query, $alias, $currentUser, $methods); |
||
1885 | } |
||
1886 | |||
1887 | /** |
||
1888 | * @param $field |
||
1889 | * @param \Doctrine\ORM\QueryBuilder $query |
||
1890 | * @param string $alias |
||
1891 | * @param \UnserAller_Model_User $currentUser |
||
1892 | * @param array $methods |
||
1893 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
1894 | * @uses entityFalseExpression |
||
1895 | * @uses entityTrueExpression |
||
1896 | * @uses entityIsExpression |
||
1897 | * @uses entityIsOrNullExpression |
||
1898 | * @uses entityNotExpression |
||
1899 | * @uses entityMeExpression |
||
1900 | * @uses entityNotmeExpression |
||
1901 | * @uses entityLtExpression |
||
1902 | * @uses entityLteExpression |
||
1903 | * @uses entityGtExpression |
||
1904 | * @uses entityGteExpression |
||
1905 | */ |
||
1906 | View Code Duplication | protected function createConditionsForEntityColumn($field, $query, $alias, $currentUser, $methods) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1907 | { |
||
1908 | if (\UnserAllerLib_Tool_Array::hasMoreKeysThan( |
||
1909 | $methods, |
||
1910 | ['false', 'true', 'is', 'not', 'me', 'notme', 'isOrNull', 'lt', 'lte', 'gt', 'gte'] |
||
1911 | )) { |
||
1912 | throw new \InvalidArgumentException('Invalid expression methods used'); |
||
1913 | } |
||
1914 | |||
1915 | return $this->createExpression('entity', $field, $query, $alias, $currentUser, $methods); |
||
1916 | } |
||
1917 | |||
1918 | /** |
||
1919 | * @param $subquery |
||
1920 | * @param $query |
||
1921 | * @param $alias |
||
1922 | * @param $currentUser |
||
1923 | * @param $methods |
||
1924 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
1925 | * @uses subqueryIsExpression |
||
1926 | * @uses subqueryFalseExpression |
||
1927 | * @uses subqueryTrueExpression |
||
1928 | * @uses subqueryNotExpression |
||
1929 | * @uses subqueryMeExpression |
||
1930 | * @uses subqueryNotmeExpression |
||
1931 | * @uses subqueryEqExpression |
||
1932 | */ |
||
1933 | protected function createConditionsForEntitySubquery($subquery, $query, $alias, $currentUser, $methods) |
||
1934 | { |
||
1935 | if (\UnserAllerLib_Tool_Array::hasMoreKeysThan($methods, ['false', 'true', 'is', 'not', 'me', 'notme', 'eq'])) { |
||
1936 | throw new \InvalidArgumentException('Invalid expression methods used'); |
||
1937 | } |
||
1938 | |||
1939 | return $this->createExpression('subquery', $subquery, $query, $alias, $currentUser, $methods); |
||
1940 | } |
||
1941 | |||
1942 | /** |
||
1943 | * @param \Doctrine\ORM\QueryBuilder $query |
||
1944 | * @param string $field |
||
1945 | * @param array $params |
||
1946 | * @param string $alias |
||
1947 | * @return mixed |
||
1948 | */ |
||
1949 | private function entityIsExpression($query, $field, $params, $alias) |
||
1950 | { |
||
1951 | return $query->expr()->in($field, $params); |
||
1952 | } |
||
1953 | |||
1954 | /** |
||
1955 | * @param \Doctrine\ORM\QueryBuilder $query |
||
1956 | * @param string $field |
||
1957 | * @param array $params |
||
1958 | * @param string $alias |
||
1959 | * @return mixed |
||
1960 | */ |
||
1961 | private function entityIsOrNullExpression($query, $field, $params, $alias) |
||
1962 | { |
||
1963 | return $query->expr()->orX( |
||
1964 | $query->expr()->in($field, $params), |
||
1965 | $query->expr()->isNull($field) |
||
1966 | ); |
||
1967 | } |
||
1968 | |||
1969 | /** |
||
1970 | * @param \Doctrine\ORM\QueryBuilder $query |
||
1971 | * @param string $field |
||
1972 | * @param array $params |
||
1973 | * @param string $alias |
||
1974 | * @param \UnserAller_Model_User $currentUser |
||
1975 | * @return mixed |
||
1976 | * @throws \UnserAllerLib_Api_V4_Exception_UserRequiredButNotAuthenticated |
||
1977 | */ |
||
1978 | private function entityMeExpression($query, $field, $params, $alias, $currentUser) |
||
1979 | { |
||
1980 | if (!$currentUser) { |
||
1981 | throw new \UnserAllerLib_Api_V4_Exception_UserRequiredButNotAuthenticated(); |
||
1982 | } |
||
1983 | return $query->expr()->eq($field, $currentUser->getId()); |
||
1984 | } |
||
1985 | |||
1986 | |||
1987 | /** |
||
1988 | * @param \Doctrine\ORM\QueryBuilder $query |
||
1989 | * @param string $field |
||
1990 | * @param array $params |
||
1991 | * @param string $alias |
||
1992 | * @param \UnserAller_Model_User $currentUser |
||
1993 | * @return \Doctrine\ORM\Query\Expr\Comparison |
||
1994 | * @throws \UnserAllerLib_Api_V4_Exception_UserRequiredButNotAuthenticated |
||
1995 | */ |
||
1996 | private function entityNotmeExpression($query, $field, $params, $alias, $currentUser) |
||
1997 | { |
||
1998 | if (!$currentUser) { |
||
1999 | throw new \UnserAllerLib_Api_V4_Exception_UserRequiredButNotAuthenticated(); |
||
2000 | } |
||
2001 | return $query->expr()->neq($field, $currentUser->getId()); |
||
2002 | } |
||
2003 | |||
2004 | /** |
||
2005 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2006 | * @param string $field |
||
2007 | * @param array $params |
||
2008 | * @param string $alias |
||
2009 | * @return \Doctrine\ORM\Query\Expr\Func |
||
2010 | */ |
||
2011 | private function entityNotExpression($query, $field, $params, $alias) |
||
2012 | { |
||
2013 | return $query->expr()->notIn($field, $params); |
||
2014 | } |
||
2015 | |||
2016 | /** |
||
2017 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2018 | * @param string $field |
||
2019 | * @param array $params |
||
2020 | * @param string $alias |
||
2021 | * @return \Doctrine\ORM\Query\Expr\Comparison |
||
2022 | */ |
||
2023 | private function entityFalseExpression($query, $field, $params, $alias) |
||
2024 | { |
||
2025 | return $query->expr()->eq("COALESCE(IDENTITY($field),0)", 0); |
||
2026 | } |
||
2027 | |||
2028 | /** |
||
2029 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2030 | * @param string $field |
||
2031 | * @param array $params |
||
2032 | * @param string $alias |
||
2033 | * @return \Doctrine\ORM\Query\Expr\Comparison |
||
2034 | */ |
||
2035 | private function entityTrueExpression($query, $field, $params, $alias) |
||
2036 | { |
||
2037 | return $query->expr()->neq("COALESCE(IDENTITY($field),0)", 0); |
||
2038 | } |
||
2039 | |||
2040 | /** |
||
2041 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2042 | * @param string $field |
||
2043 | * @param array $params |
||
2044 | * @param string $alias |
||
2045 | * @return mixed |
||
2046 | */ |
||
2047 | private function entityLtExpression($query, $field, $params, $alias) |
||
2048 | { |
||
2049 | $lt = $query->expr()->orX(); |
||
2050 | $index = 0; |
||
2051 | foreach ($params as $datetime) { |
||
2052 | $lt->add($query->expr()->lt("IDENTITY($field)", ":lt_{$alias}_{$index}")); |
||
2053 | $query->setParameter("lt_{$alias}_{$index}", $datetime); |
||
2054 | $index++; |
||
2055 | } |
||
2056 | |||
2057 | return $lt; |
||
2058 | } |
||
2059 | |||
2060 | /** |
||
2061 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2062 | * @param string $field |
||
2063 | * @param array $params |
||
2064 | * @param string $alias |
||
2065 | * @return mixed |
||
2066 | */ |
||
2067 | private function entityLteExpression($query, $field, $params, $alias) |
||
2068 | { |
||
2069 | $lte = $query->expr()->orX(); |
||
2070 | $index = 0; |
||
2071 | foreach ($params as $datetime) { |
||
2072 | $lte->add($query->expr()->lte("IDENTITY($field)", ":lte_{$alias}_{$index}")); |
||
2073 | $query->setParameter("lte_{$alias}_{$index}", $datetime); |
||
2074 | $index++; |
||
2075 | } |
||
2076 | |||
2077 | return $lte; |
||
2078 | } |
||
2079 | |||
2080 | /** |
||
2081 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2082 | * @param string $field |
||
2083 | * @param array $params |
||
2084 | * @param string $alias |
||
2085 | * @return mixed |
||
2086 | */ |
||
2087 | private function entityGtExpression($query, $field, $params, $alias) |
||
2088 | { |
||
2089 | $gt = $query->expr()->orX(); |
||
2090 | $index = 0; |
||
2091 | foreach ($params as $datetime) { |
||
2092 | $gt->add($query->expr()->gt("IDENTITY($field)", ":gt_{$alias}_{$index}")); |
||
2093 | $query->setParameter("gt_{$alias}_{$index}", $datetime); |
||
2094 | $index++; |
||
2095 | } |
||
2096 | |||
2097 | return $gt; |
||
2098 | } |
||
2099 | |||
2100 | /** |
||
2101 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2102 | * @param string $field |
||
2103 | * @param array $params |
||
2104 | * @param string $alias |
||
2105 | * @return mixed |
||
2106 | */ |
||
2107 | private function entityGteExpression($query, $field, $params, $alias) |
||
2108 | { |
||
2109 | $gte = $query->expr()->orX(); |
||
2110 | $index = 0; |
||
2111 | foreach ($params as $datetime) { |
||
2112 | $gte->add($query->expr()->gte("IDENTITY($field)", ":gte_{$alias}_{$index}")); |
||
2113 | $query->setParameter("gte_{$alias}_{$index}", $datetime); |
||
2114 | $index++; |
||
2115 | } |
||
2116 | |||
2117 | return $gte; |
||
2118 | } |
||
2119 | |||
2120 | /** |
||
2121 | * Translates params into where conditions. The subquery must really return an integer for it to work! |
||
2122 | * Returning null will cause wrong bahvior!!! In DQL it seems to be impossible to do an IS NULL comparison |
||
2123 | * on a subquery. And it seems to be impossible to not return null values either |
||
2124 | * Todo: Needs research, for time being only true comparison is working as expected |
||
2125 | * |
||
2126 | * |
||
2127 | * @param $subquery |
||
2128 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2129 | * @param string $alias |
||
2130 | * @param \UnserAller_Model_User $currentUser |
||
2131 | * @param array $methods |
||
2132 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
2133 | * @uses subqueryFalseExpression |
||
2134 | * @uses subqueryTrueExpression |
||
2135 | * @uses subqueryGtExpression |
||
2136 | * @uses subqueryGteExpression |
||
2137 | * @uses subqueryLtExpression |
||
2138 | * @uses subqueryLteExpression |
||
2139 | * @uses subqueryEqExpression |
||
2140 | * @uses subqueryAnyExpression |
||
2141 | * @uses subqueryNullExpression |
||
2142 | */ |
||
2143 | View Code Duplication | protected function createConditionsForIntegerSubquery($subquery, $query, $alias, $currentUser, $methods) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2144 | { |
||
2145 | if (\UnserAllerLib_Tool_Array::hasMoreKeysThan( |
||
2146 | $methods, |
||
2147 | ['false', 'true', 'gt', 'gte', 'lt', 'lte', 'eq', 'any', 'null'] |
||
2148 | ) |
||
2149 | ) { |
||
2150 | throw new \InvalidArgumentException('Invalid expression methods used'); |
||
2151 | } |
||
2152 | |||
2153 | return $this->createExpression('subquery', $subquery, $query, $alias, $currentUser, $methods); |
||
2154 | } |
||
2155 | |||
2156 | /** |
||
2157 | * @param $subquery |
||
2158 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2159 | * @param string $alias |
||
2160 | * @param \UnserAller_Model_User $currentUser |
||
2161 | * @param array $methods |
||
2162 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
2163 | */ |
||
2164 | View Code Duplication | protected function createConditionsForIntegerCollectionSubquery($subquery, $query, $alias, $currentUser, $methods) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2165 | { |
||
2166 | if (\UnserAllerLib_Tool_Array::hasMoreKeysThan($methods, ['anyis'])) { |
||
2167 | throw new \InvalidArgumentException('Invalid expression methods used'); |
||
2168 | } |
||
2169 | |||
2170 | return $this->createExpression('subquery', $subquery, $query, $alias, $currentUser, $methods); |
||
2171 | } |
||
2172 | |||
2173 | /** |
||
2174 | * Translates params into where conditions. The subquery must really return an integer for it to work! |
||
2175 | * Returning null will cause wrong bahvior!!! In DQL it seems to be impossible to do an IS NULL comparison |
||
2176 | * on a subquery. And it seems to be impossible to not return null values either |
||
2177 | * Todo: Needs research, for time being only true comparison is working as expected |
||
2178 | * |
||
2179 | * |
||
2180 | * @param $subquery |
||
2181 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2182 | * @param string $alias |
||
2183 | * @param \UnserAller_Model_User $currentUser |
||
2184 | * @param array $methods |
||
2185 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
2186 | * @uses subqueryAnyisExpression |
||
2187 | */ |
||
2188 | View Code Duplication | protected function createConditionsForStringCollectionSubquery($subquery, $query, $alias, $currentUser, $methods) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2189 | { |
||
2190 | if (\UnserAllerLib_Tool_Array::hasMoreKeysThan($methods, ['anyis'])) { |
||
2191 | throw new \InvalidArgumentException('Invalid expression methods used'); |
||
2192 | } |
||
2193 | |||
2194 | return $this->createExpression('subquery', $subquery, $query, $alias, $currentUser, $methods); |
||
2195 | } |
||
2196 | |||
2197 | /** |
||
2198 | * Translates params into where conditions. The subquery must really return an integer for it to work! |
||
2199 | * Returning null will cause wrong bahvior!!! In DQL it seems to be impossible to do an IS NULL comparison |
||
2200 | * on a subquery. And it seems to be impossible to not return null values either |
||
2201 | * Todo: Needs research, for time being only true comparison is working as expected |
||
2202 | * |
||
2203 | * |
||
2204 | * @param $subquery |
||
2205 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2206 | * @param string $alias |
||
2207 | * @param \UnserAller_Model_User $currentUser |
||
2208 | * @param array $methods |
||
2209 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
2210 | * @uses subqueryTrueExpression |
||
2211 | * @uses subqueryFalseExpression |
||
2212 | */ |
||
2213 | View Code Duplication | protected function createConditionsForDatetimeSubquery($subquery, $query, $alias, $currentUser, $methods) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2214 | { |
||
2215 | if (\UnserAllerLib_Tool_Array::hasMoreKeysThan($methods, ['false', 'true', 'gte', 'lte', 'gt', 'lt'])) { |
||
2216 | throw new \InvalidArgumentException('Invalid expression methods used'); |
||
2217 | } |
||
2218 | |||
2219 | return $this->createExpression('subquery', $subquery, $query, $alias, $currentUser, $methods); |
||
2220 | } |
||
2221 | |||
2222 | /** |
||
2223 | * Translates params into where conditions. Null values are handled as you would expect it. |
||
2224 | * |
||
2225 | * @param $col |
||
2226 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2227 | * @param string $alias |
||
2228 | * @param \UnserAller_Model_User $currentUser |
||
2229 | * @param array $methods |
||
2230 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
2231 | * @uses integerIsExpression |
||
2232 | * @uses integerNotExpression |
||
2233 | * @uses integerGtExpression |
||
2234 | * @uses integerGteExpression |
||
2235 | * @uses integerLtExpression |
||
2236 | * @uses integerLteExpression |
||
2237 | * @uses integerFalseExpression |
||
2238 | * @uses integerTrueExpression |
||
2239 | */ |
||
2240 | View Code Duplication | protected function createConditionsForIntegerColumn($col, $query, $alias, $currentUser, $methods) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2241 | { |
||
2242 | if (\UnserAllerLib_Tool_Array::hasMoreKeysThan( |
||
2243 | $methods, |
||
2244 | ['is', 'not', 'gt', 'gte', 'lt', 'lte', 'false', 'true'] |
||
2245 | ) |
||
2246 | ) { |
||
2247 | throw new \InvalidArgumentException('Invalid expression methods used'); |
||
2248 | } |
||
2249 | |||
2250 | return $this->createExpression('integer', $col, $query, $alias, $currentUser, $methods); |
||
2251 | } |
||
2252 | |||
2253 | /** |
||
2254 | * Todo: Whitelisting allowed subqueries for the any filter makes having this extra function unnecessary |
||
2255 | * |
||
2256 | * This one allows some filter directives that result to function calls on protected methods. Don't ever redirect |
||
2257 | * user content here. |
||
2258 | * |
||
2259 | * Translates params into where conditions. Null values are handled as you would expect it. |
||
2260 | * |
||
2261 | * @param $col |
||
2262 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2263 | * @param string $alias |
||
2264 | * @param \UnserAller_Model_User $currentUser |
||
2265 | * @param array $methods |
||
2266 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
2267 | * @uses integerIsExpression |
||
2268 | * @uses integerNotExpression |
||
2269 | * @uses integerGtExpression |
||
2270 | * @uses integerGteExpression |
||
2271 | * @uses integerLtExpression |
||
2272 | * @uses integerLteExpression |
||
2273 | * @uses integerFalseExpression |
||
2274 | * @uses integerTrueExpression |
||
2275 | * @uses integerAnyExpression |
||
2276 | */ |
||
2277 | View Code Duplication | protected function createConditionsForIntegerColumnInternal($col, $query, $alias, $currentUser, $methods) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2278 | { |
||
2279 | if (\UnserAllerLib_Tool_Array::hasMoreKeysThan( |
||
2280 | $methods, |
||
2281 | ['is', 'not', 'gt', 'gte', 'lt', 'lte', 'false', 'true', 'any'] |
||
2282 | ) |
||
2283 | ) { |
||
2284 | throw new \InvalidArgumentException('Invalid expression methods used'); |
||
2285 | } |
||
2286 | |||
2287 | return $this->createExpression('integer', $col, $query, $alias, $currentUser, $methods); |
||
2288 | } |
||
2289 | |||
2290 | /** |
||
2291 | * Knows how to create a callable from a subquery definition |
||
2292 | * |
||
2293 | * @param string $name of subquery |
||
2294 | * @param mixed[] $params for subquerymethod |
||
2295 | * @return callable |
||
2296 | */ |
||
2297 | protected function locateCallableSubquery($name, $params) |
||
2298 | { |
||
2299 | return [$this, $name]; |
||
2300 | } |
||
2301 | |||
2302 | /** |
||
2303 | * @param array $subqueryDefinition |
||
2304 | * @return string DQL |
||
2305 | */ |
||
2306 | private function consumeSubquery($subqueryDefinition) |
||
2307 | { |
||
2308 | list($name, $params) = $subqueryDefinition; |
||
2309 | return call_user_func_array( |
||
2310 | $this->locateCallableSubquery($name, $params), |
||
2311 | $params |
||
2312 | ); |
||
2313 | } |
||
2314 | |||
2315 | /** |
||
2316 | * @param $prefix |
||
2317 | * @param string $field |
||
2318 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2319 | * @param string $alias |
||
2320 | * @param \UnserAller_Model_User $currentUser |
||
2321 | * @param array $methods |
||
2322 | * @return \Doctrine\ORM\Query\Expr\Andx |
||
2323 | */ |
||
2324 | private function createExpression($prefix, $field, $query, $alias, $currentUser, $methods) |
||
2325 | { |
||
2326 | $expression = $query->expr()->andX(); |
||
2327 | foreach ($methods as $method => $params) { |
||
2328 | $expression->add(call_user_func_array( |
||
2329 | [$this, $prefix . ucfirst($method) . 'Expression'], |
||
2330 | [$query, $field, $params, $alias, $currentUser] |
||
2331 | )); |
||
2332 | } |
||
2333 | |||
2334 | return $expression; |
||
2335 | } |
||
2336 | |||
2337 | /** |
||
2338 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2339 | * @param array $field |
||
2340 | * @param array $params |
||
2341 | * @param string $alias |
||
2342 | * @return mixed |
||
2343 | */ |
||
2344 | private function subqueryFalseExpression($query, $field, $params, $alias) |
||
2345 | { |
||
2346 | return $query->expr()->orX( |
||
2347 | $query->expr()->not($query->expr()->exists($this->consumeSubquery($field))), |
||
2348 | $query->expr()->eq('(' . $this->consumeSubquery($field) . ')', 0) |
||
2349 | ); |
||
2350 | } |
||
2351 | |||
2352 | /** |
||
2353 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2354 | * @param array $field |
||
2355 | * @param array $params |
||
2356 | * @param string $alias |
||
2357 | * @return mixed |
||
2358 | */ |
||
2359 | private function subqueryNullExpression($query, $field, $params, $alias) |
||
2360 | { |
||
2361 | return $query->expr()->not($query->expr()->exists($this->consumeSubquery($field))); |
||
2362 | } |
||
2363 | |||
2364 | /** |
||
2365 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2366 | * @param array $subquery |
||
2367 | * @param array $params |
||
2368 | * @param string $alias |
||
2369 | * @return mixed |
||
2370 | */ |
||
2371 | View Code Duplication | private function subqueryTrueExpression($query, $subquery, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2372 | { |
||
2373 | return $query->expr()->andX( |
||
2374 | $query->expr()->exists($this->consumeSubquery($subquery)), |
||
2375 | $query->expr()->neq('(' . $this->consumeSubquery($subquery) . ')', 0) |
||
2376 | ); |
||
2377 | } |
||
2378 | |||
2379 | /** |
||
2380 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2381 | * @param array $subquery |
||
2382 | * @param array $params |
||
2383 | * @param string $alias |
||
2384 | * @return mixed |
||
2385 | */ |
||
2386 | private function subqueryAnyisExpression($query, $subquery, $params, $alias) |
||
2387 | { |
||
2388 | $expression = $query->expr()->orX(); |
||
2389 | foreach ($params as $param) { |
||
2390 | $alias = uniqid(); |
||
2391 | $query->setParameter("param$alias", $param); |
||
2392 | $expression->add( |
||
2393 | $query->expr()->eq(":param$alias", $query->expr()->any($this->consumeSubquery($subquery))) |
||
2394 | ); |
||
2395 | } |
||
2396 | return $expression; |
||
2397 | } |
||
2398 | |||
2399 | /** |
||
2400 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2401 | * @param array $subquery |
||
2402 | * @param array $params |
||
2403 | * @param string $alias |
||
2404 | * @return mixed |
||
2405 | */ |
||
2406 | View Code Duplication | private function subqueryGtExpression($query, $subquery, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2407 | { |
||
2408 | $expression = $query->expr()->orX(); |
||
2409 | foreach ($params as $param) { |
||
2410 | $alias = uniqid(); |
||
2411 | $query->setParameter("param$alias", $param); |
||
2412 | $expression->add( |
||
2413 | $query->expr()->gt('(' . $this->consumeSubquery($subquery) . ')', ":param$alias") |
||
2414 | ); |
||
2415 | } |
||
2416 | |||
2417 | return $query->expr()->andX( |
||
2418 | $query->expr()->exists($this->consumeSubquery($subquery)), |
||
2419 | $expression |
||
2420 | ); |
||
2421 | } |
||
2422 | |||
2423 | /** |
||
2424 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2425 | * @param array $subquery |
||
2426 | * @param array $params |
||
2427 | * @return Query\Expr\Andx |
||
2428 | */ |
||
2429 | View Code Duplication | private function subqueryGteExpression($query, $subquery, $params) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2430 | { |
||
2431 | $expression = $query->expr()->orX(); |
||
2432 | foreach ($params as $param) { |
||
2433 | $alias = uniqid(); |
||
2434 | $query->setParameter("param$alias", $param); |
||
2435 | $expression->add( |
||
2436 | $query->expr()->gte('(' . $this->consumeSubquery($subquery) . ')', ":param$alias") |
||
2437 | ); |
||
2438 | } |
||
2439 | |||
2440 | return $query->expr()->andX( |
||
2441 | $query->expr()->exists($this->consumeSubquery($subquery)), |
||
2442 | $expression |
||
2443 | ); |
||
2444 | } |
||
2445 | |||
2446 | /** |
||
2447 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2448 | * @param array $subquery |
||
2449 | * @param array $params |
||
2450 | * @param string $alias |
||
2451 | * @return mixed |
||
2452 | */ |
||
2453 | View Code Duplication | private function subqueryLteExpression($query, $subquery, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2454 | { |
||
2455 | $expression = $query->expr()->orX(); |
||
2456 | foreach ($params as $param) { |
||
2457 | $alias = uniqid(); |
||
2458 | $query->setParameter("param$alias", $param); |
||
2459 | $expression->add( |
||
2460 | $query->expr()->lte('(' . $this->consumeSubquery($subquery) . ')', ":param$alias") |
||
2461 | ); |
||
2462 | } |
||
2463 | |||
2464 | return $query->expr()->andX( |
||
2465 | $query->expr()->exists($this->consumeSubquery($subquery)), |
||
2466 | $expression |
||
2467 | ); |
||
2468 | } |
||
2469 | |||
2470 | /** |
||
2471 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2472 | * @param array $subquery |
||
2473 | * @param array $params |
||
2474 | * @param string $alias |
||
2475 | * @return mixed |
||
2476 | */ |
||
2477 | View Code Duplication | private function subqueryLtExpression($query, $subquery, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2478 | { |
||
2479 | $expression = $query->expr()->orX(); |
||
2480 | foreach ($params as $param) { |
||
2481 | $alias = uniqid(); |
||
2482 | $query->setParameter("param$alias", $param); |
||
2483 | $expression->add( |
||
2484 | $query->expr()->lt('(' . $this->consumeSubquery($subquery) . ')', ":param$alias") |
||
2485 | ); |
||
2486 | } |
||
2487 | |||
2488 | return $query->expr()->andX( |
||
2489 | $query->expr()->exists($this->consumeSubquery($subquery)), |
||
2490 | $expression |
||
2491 | ); |
||
2492 | } |
||
2493 | |||
2494 | /** |
||
2495 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2496 | * @param array $subquery |
||
2497 | * @param array $params |
||
2498 | * @param string $alias |
||
2499 | * @return mixed |
||
2500 | */ |
||
2501 | View Code Duplication | private function subqueryEqExpression($query, $subquery, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2502 | { |
||
2503 | return $query->expr()->andX( |
||
2504 | $query->expr()->exists($this->consumeSubquery($subquery)), |
||
2505 | $query->expr()->eq('(' . $this->consumeSubquery($subquery) . ')', $params[0]) |
||
2506 | ); |
||
2507 | } |
||
2508 | |||
2509 | /** |
||
2510 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2511 | * @param array $subquery |
||
2512 | * @param array $params |
||
2513 | * @param string $alias |
||
2514 | * @return mixed |
||
2515 | */ |
||
2516 | private function subqueryIsExpression($query, $subquery, $params, $alias) |
||
2517 | { |
||
2518 | return $query->expr()->in('(' . $this->consumeSubquery($subquery) . ')', $params); |
||
2519 | } |
||
2520 | |||
2521 | /** |
||
2522 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2523 | * @param string $field |
||
2524 | * @param array $params |
||
2525 | * @param string $alias |
||
2526 | * @return mixed |
||
2527 | */ |
||
2528 | private function dateIsExpression($query, $field, $params, $alias) |
||
2529 | { |
||
2530 | return $query->expr()->in($field, $params); |
||
2531 | } |
||
2532 | |||
2533 | /** |
||
2534 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2535 | * @param string $field |
||
2536 | * @param array $params |
||
2537 | * @param string $alias |
||
2538 | * @return mixed |
||
2539 | */ |
||
2540 | private function integerIsExpression($query, $field, $params, $alias) |
||
2541 | { |
||
2542 | return $query->expr()->in($field, $params); |
||
2543 | } |
||
2544 | |||
2545 | /** |
||
2546 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2547 | * @param string $field |
||
2548 | * @param array $params |
||
2549 | * @param string $alias |
||
2550 | * @return mixed |
||
2551 | */ |
||
2552 | private function stringIsExpression($query, $field, $params, $alias) |
||
2553 | { |
||
2554 | return $query->expr()->in($field, $params); |
||
2555 | } |
||
2556 | |||
2557 | /** |
||
2558 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2559 | * @param string $field |
||
2560 | * @param array $params |
||
2561 | * @param string $alias |
||
2562 | * @return \Doctrine\ORM\Query\Expr\Comparison |
||
2563 | * @throws \UnserAllerLib_Api_V4_Exception_UserRequiredButNotAuthenticated |
||
2564 | */ |
||
2565 | private function integerAnyExpression($query, $field, $params, $alias) |
||
2566 | { |
||
2567 | return $query->expr()->eq($field, $query->expr()->any($this->consumeSubquery($params))); |
||
2568 | } |
||
2569 | |||
2570 | /** |
||
2571 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2572 | * @param string $field |
||
2573 | * @param array $params |
||
2574 | * @param string $alias |
||
2575 | * @return \Doctrine\ORM\Query\Expr\Func |
||
2576 | */ |
||
2577 | private function integerNotExpression($query, $field, $params, $alias) |
||
2578 | { |
||
2579 | return $query->expr()->notIn($field, $params); |
||
2580 | } |
||
2581 | |||
2582 | /** |
||
2583 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2584 | * @param string $field |
||
2585 | * @param array $params |
||
2586 | * @param string $alias |
||
2587 | * @return \Doctrine\ORM\Query\Expr\Func |
||
2588 | */ |
||
2589 | private function dateNotExpression($query, $field, $params, $alias) |
||
2590 | { |
||
2591 | return $query->expr()->notIn($field, $params); |
||
2592 | } |
||
2593 | |||
2594 | /** |
||
2595 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2596 | * @param string $field |
||
2597 | * @param array $params |
||
2598 | * @param string $alias |
||
2599 | * @return mixed |
||
2600 | */ |
||
2601 | private function stringNotExpression($query, $field, $params, $alias) |
||
2602 | { |
||
2603 | return $query->expr()->notIn($field, $params); |
||
2604 | } |
||
2605 | |||
2606 | /** |
||
2607 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2608 | * @param string $field |
||
2609 | * @param array $params |
||
2610 | * @param string $alias |
||
2611 | * @return \Doctrine\ORM\Query\Expr\Comparison |
||
2612 | */ |
||
2613 | private function integerFalseExpression($query, $field, $params, $alias) |
||
2614 | { |
||
2615 | return $query->expr()->eq('COALESCE(' . $field . ',0)', 0); |
||
2616 | } |
||
2617 | |||
2618 | /** |
||
2619 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2620 | * @param string $field |
||
2621 | * @param array $params |
||
2622 | * @param string $alias |
||
2623 | * @return \Doctrine\ORM\Query\Expr\Comparison |
||
2624 | */ |
||
2625 | private function dateFalseExpression($query, $field, $params, $alias) |
||
2626 | { |
||
2627 | return $query->expr()->eq('COALESCE(' . $field . ',0)', 0); |
||
2628 | } |
||
2629 | |||
2630 | /** |
||
2631 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2632 | * @param string $field |
||
2633 | * @param array $params |
||
2634 | * @param string $alias |
||
2635 | * @return \Doctrine\ORM\Query\Expr\Base |
||
2636 | */ |
||
2637 | private function stringFalseExpression($query, $field, $params, $alias) |
||
2638 | { |
||
2639 | return $query->expr()->orX( |
||
2640 | $query->expr()->isNull($field), |
||
2641 | $query->expr()->eq($field, "''") |
||
2642 | ); |
||
2643 | } |
||
2644 | |||
2645 | /** |
||
2646 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2647 | * @param string $field |
||
2648 | * @param array $params |
||
2649 | * @param string $alias |
||
2650 | * @return \Doctrine\ORM\Query\Expr\Comparison |
||
2651 | */ |
||
2652 | private function integerTrueExpression($query, $field, $params, $alias) |
||
2653 | { |
||
2654 | return $query->expr()->neq('COALESCE(' . $field . ',0)', 0); |
||
2655 | } |
||
2656 | |||
2657 | /** |
||
2658 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2659 | * @param string $field |
||
2660 | * @param array $params |
||
2661 | * @param string $alias |
||
2662 | * @return \Doctrine\ORM\Query\Expr\Comparison |
||
2663 | */ |
||
2664 | private function dateTrueExpression($query, $field, $params, $alias) |
||
2665 | { |
||
2666 | return $query->expr()->neq('COALESCE(' . $field . ',0)', 0); |
||
2667 | } |
||
2668 | |||
2669 | /** |
||
2670 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2671 | * @param string $field |
||
2672 | * @param array $params |
||
2673 | * @param string $alias |
||
2674 | * @return \Doctrine\ORM\Query\Expr\Base |
||
2675 | */ |
||
2676 | private function stringTrueExpression($query, $field, $params, $alias) |
||
2677 | { |
||
2678 | return $query->expr()->andX( |
||
2679 | $query->expr()->isNotNull($field), |
||
2680 | $query->expr()->neq($field, "''") |
||
2681 | ); |
||
2682 | } |
||
2683 | |||
2684 | /** |
||
2685 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2686 | * @param string $field |
||
2687 | * @param array $params |
||
2688 | * @param string $alias |
||
2689 | * @return mixed |
||
2690 | */ |
||
2691 | View Code Duplication | private function stringContainsExpression($query, $field, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2692 | { |
||
2693 | $contains = $query->expr()->orX(); |
||
2694 | |||
2695 | $index = 0; |
||
2696 | foreach ($params as $string) { |
||
2697 | $contains->add($query->expr()->like($field, ":contains_{$alias}_{$index}")); |
||
2698 | $query->setParameter("contains_{$alias}_{$index}", '%' . $string . '%'); |
||
2699 | $index++; |
||
2700 | } |
||
2701 | |||
2702 | return $contains; |
||
2703 | } |
||
2704 | |||
2705 | /** |
||
2706 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2707 | * @param string $field |
||
2708 | * @param array $params |
||
2709 | * @param string $alias |
||
2710 | * @return mixed |
||
2711 | */ |
||
2712 | private function stringContainExpression($query, $field, $params, $alias) |
||
2713 | { |
||
2714 | return $this->stringContainsExpression($query, $field, $params, $alias); |
||
2715 | } |
||
2716 | |||
2717 | /** |
||
2718 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2719 | * @param string $field |
||
2720 | * @param array $params |
||
2721 | * @param string $alias |
||
2722 | * @return mixed |
||
2723 | */ |
||
2724 | View Code Duplication | private function dateLtExpression($query, $field, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2725 | { |
||
2726 | $lt = $query->expr()->orX(); |
||
2727 | $index = 0; |
||
2728 | foreach ($params as $datetime) { |
||
2729 | $lt->add($query->expr()->lt($field, ":lt_{$alias}_{$index}")); |
||
2730 | $query->setParameter("lt_{$alias}_{$index}", $datetime); |
||
2731 | $index++; |
||
2732 | } |
||
2733 | |||
2734 | return $lt; |
||
2735 | } |
||
2736 | |||
2737 | /** |
||
2738 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2739 | * @param string $field |
||
2740 | * @param array $params |
||
2741 | * @param string $alias |
||
2742 | * @return mixed |
||
2743 | */ |
||
2744 | View Code Duplication | private function integerLtExpression($query, $field, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2745 | { |
||
2746 | $lt = $query->expr()->orX(); |
||
2747 | $index = 0; |
||
2748 | foreach ($params as $datetime) { |
||
2749 | $lt->add($query->expr()->lt($field, ":lt_{$alias}_{$index}")); |
||
2750 | $query->setParameter("lt_{$alias}_{$index}", $datetime); |
||
2751 | $index++; |
||
2752 | } |
||
2753 | |||
2754 | return $lt; |
||
2755 | } |
||
2756 | |||
2757 | /** |
||
2758 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2759 | * @param string $field |
||
2760 | * @param array $params |
||
2761 | * @param string $alias |
||
2762 | * @return mixed |
||
2763 | */ |
||
2764 | View Code Duplication | private function integerLteExpression($query, $field, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2765 | { |
||
2766 | $lte = $query->expr()->orX(); |
||
2767 | $index = 0; |
||
2768 | foreach ($params as $datetime) { |
||
2769 | $lte->add($query->expr()->lte($field, ":lte_{$alias}_{$index}")); |
||
2770 | $query->setParameter("lte_{$alias}_{$index}", $datetime); |
||
2771 | $index++; |
||
2772 | } |
||
2773 | |||
2774 | return $lte; |
||
2775 | } |
||
2776 | |||
2777 | /** |
||
2778 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2779 | * @param string $field |
||
2780 | * @param array $params |
||
2781 | * @param string $alias |
||
2782 | * @return mixed |
||
2783 | */ |
||
2784 | View Code Duplication | private function dateLteExpression($query, $field, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2785 | { |
||
2786 | $lte = $query->expr()->orX(); |
||
2787 | $index = 0; |
||
2788 | foreach ($params as $datetime) { |
||
2789 | $lte->add($query->expr()->lte($field, ":lte_{$alias}_{$index}")); |
||
2790 | $query->setParameter("lte_{$alias}_{$index}", $datetime); |
||
2791 | $index++; |
||
2792 | } |
||
2793 | |||
2794 | return $lte; |
||
2795 | } |
||
2796 | |||
2797 | /** |
||
2798 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2799 | * @param string $field |
||
2800 | * @param array $params |
||
2801 | * @param string $alias |
||
2802 | * @return mixed |
||
2803 | */ |
||
2804 | View Code Duplication | private function dateGtExpression($query, $field, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2805 | { |
||
2806 | $gt = $query->expr()->orX(); |
||
2807 | $index = 0; |
||
2808 | foreach ($params as $datetime) { |
||
2809 | $gt->add($query->expr()->gt($field, ":gt_{$alias}_{$index}")); |
||
2810 | $query->setParameter("gt_{$alias}_{$index}", $datetime); |
||
2811 | $index++; |
||
2812 | } |
||
2813 | |||
2814 | return $gt; |
||
2815 | } |
||
2816 | |||
2817 | /** |
||
2818 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2819 | * @param string $field |
||
2820 | * @param array $params |
||
2821 | * @param string $alias |
||
2822 | * @return mixed |
||
2823 | */ |
||
2824 | View Code Duplication | private function integerGtExpression($query, $field, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2825 | { |
||
2826 | $gt = $query->expr()->orX(); |
||
2827 | $index = 0; |
||
2828 | foreach ($params as $datetime) { |
||
2829 | $gt->add($query->expr()->gt($field, ":gt_{$alias}_{$index}")); |
||
2830 | $query->setParameter("gt_{$alias}_{$index}", $datetime); |
||
2831 | $index++; |
||
2832 | } |
||
2833 | |||
2834 | return $gt; |
||
2835 | } |
||
2836 | |||
2837 | /** |
||
2838 | * @return string |
||
2839 | */ |
||
2840 | protected function getModelForMeta() |
||
2841 | { |
||
2842 | return uniqid('UnknownClass'); |
||
2843 | } |
||
2844 | |||
2845 | /** |
||
2846 | * @return string |
||
2847 | */ |
||
2848 | public function getClassnameForRepresentedModel() |
||
2849 | { |
||
2850 | return $this->getModelForMeta(); |
||
2851 | } |
||
2852 | |||
2853 | /** |
||
2854 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2855 | * @param string $field |
||
2856 | * @param array $params |
||
2857 | * @param string $alias |
||
2858 | * @return mixed |
||
2859 | */ |
||
2860 | View Code Duplication | private function integerGteExpression($query, $field, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2861 | { |
||
2862 | $gte = $query->expr()->orX(); |
||
2863 | $index = 0; |
||
2864 | foreach ($params as $datetime) { |
||
2865 | $gte->add($query->expr()->gte($field, ":gte_{$alias}_{$index}")); |
||
2866 | $query->setParameter("gte_{$alias}_{$index}", $datetime); |
||
2867 | $index++; |
||
2868 | } |
||
2869 | |||
2870 | return $gte; |
||
2871 | } |
||
2872 | |||
2873 | /** |
||
2874 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2875 | * @param string $field |
||
2876 | * @param array $params |
||
2877 | * @param string $alias |
||
2878 | * @return mixed |
||
2879 | */ |
||
2880 | View Code Duplication | private function dateGteExpression($query, $field, $params, $alias) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
2881 | { |
||
2882 | $gte = $query->expr()->orX(); |
||
2883 | $index = 0; |
||
2884 | foreach ($params as $datetime) { |
||
2885 | $gte->add($query->expr()->gte($field, ":gte_{$alias}_{$index}")); |
||
2886 | $query->setParameter("gte_{$alias}_{$index}", $datetime); |
||
2887 | $index++; |
||
2888 | } |
||
2889 | |||
2890 | return $gte; |
||
2891 | } |
||
2892 | |||
2893 | /** |
||
2894 | * Does some crazy things |
||
2895 | * |
||
2896 | * @param string $value |
||
2897 | * @return array |
||
2898 | */ |
||
2899 | private function filterJsonAfterwards($value) |
||
2900 | { |
||
2901 | return json_decode($value, true); |
||
2902 | } |
||
2903 | |||
2904 | /** |
||
2905 | * Does some crazy things |
||
2906 | * |
||
2907 | * @param string $value |
||
2908 | * @return mixed |
||
2909 | */ |
||
2910 | private function filterJsonIfNullSetEmptyObjectAfterwards($value) |
||
2911 | { |
||
2912 | return $value === null ? new \stdClass() : json_decode($value, true); |
||
2913 | } |
||
2914 | |||
2915 | /** |
||
2916 | * Does some crazy things |
||
2917 | * |
||
2918 | * @param string $value |
||
2919 | * @return string |
||
2920 | */ |
||
2921 | private function filterNl2BrAfterwards($value) |
||
2922 | { |
||
2923 | return nl2br($value, false); |
||
2924 | } |
||
2925 | |||
2926 | /** |
||
2927 | * Does some crazy things |
||
2928 | * |
||
2929 | * @param string $value |
||
2930 | * @return array |
||
2931 | */ |
||
2932 | private function filterJsonOrNullAfterwards($value) |
||
2933 | { |
||
2934 | return $value === null ? null : json_decode($value, true); |
||
2935 | } |
||
2936 | |||
2937 | /** |
||
2938 | * Too complex to explain |
||
2939 | * |
||
2940 | * @param string $value |
||
2941 | * @return \DateTime |
||
2942 | */ |
||
2943 | private function filterDatetimeAfterwards($value) |
||
2944 | { |
||
2945 | return new \DateTime($value); |
||
2946 | } |
||
2947 | |||
2948 | /** |
||
2949 | * Too complex to explain |
||
2950 | * |
||
2951 | * @param string $value |
||
2952 | * @return \DateTime |
||
2953 | */ |
||
2954 | private function filterDatetimeOrNullAfterwards($value) |
||
2955 | { |
||
2956 | return $value === null ? null : new \DateTime($value); |
||
2957 | } |
||
2958 | |||
2959 | /** |
||
2960 | * Too complex to explain |
||
2961 | * |
||
2962 | * @param string|null $value |
||
2963 | * @return int|null |
||
2964 | */ |
||
2965 | private function filterIntOrNullAfterwards($value) |
||
2966 | { |
||
2967 | return $value === null ? null : (int)$value; |
||
2968 | } |
||
2969 | |||
2970 | /** |
||
2971 | * Returns the current resultArrayFixSchedule. Afterwards the schedule will be empty again. |
||
2972 | * |
||
2973 | * @return array |
||
2974 | */ |
||
2975 | private function flushResultArrayFixSchedule() |
||
2976 | { |
||
2977 | $scheduledFixes = $this->resultArrayFixSchedule; |
||
2978 | $this->resultArrayFixSchedule = []; |
||
2979 | return $scheduledFixes; |
||
2980 | } |
||
2981 | |||
2982 | /** |
||
2983 | * Returns true if $alias was used in $query already - false otherwise |
||
2984 | * |
||
2985 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2986 | * @param string $alias |
||
2987 | * @return bool |
||
2988 | */ |
||
2989 | protected function wasAliasUsed($query, $alias) |
||
2990 | { |
||
2991 | return in_array($alias, $query->getAllAliases()); |
||
2992 | } |
||
2993 | |||
2994 | /** |
||
2995 | * Returns true if $alias was used in $query already - false otherwise |
||
2996 | * |
||
2997 | * @param \Doctrine\ORM\QueryBuilder $query |
||
2998 | * @param string $alias |
||
2999 | * @return bool |
||
3000 | */ |
||
3001 | protected function wasntAliasUsed($query, $alias) |
||
3002 | { |
||
3003 | return !$this->wasAliasUsed($query, $alias); |
||
3004 | } |
||
3005 | |||
3006 | /** |
||
3007 | * @return array |
||
3008 | */ |
||
3009 | public function getUnsortedParams() |
||
3010 | { |
||
3011 | return $this->unsortedParams; |
||
3012 | } |
||
3013 | |||
3014 | /** |
||
3015 | * @param array $unsortedParams |
||
3016 | * @return $this |
||
3017 | */ |
||
3018 | public function setUnsortedParams($unsortedParams) |
||
3019 | { |
||
3020 | $this->unsortedParams = $unsortedParams; |
||
3021 | |||
3022 | return $this; |
||
3023 | } |
||
3024 | |||
3025 | /** |
||
3026 | * @param \Doctrine\ORM\QueryBuilder $query |
||
3027 | * @param string $translationName |
||
3028 | * @param string $language |
||
3029 | * @return string alias of joined translation table |
||
3030 | */ |
||
3031 | protected function joinTranslationOnce($query, $translationName, $language) |
||
3032 | { |
||
3033 | $alias = 'translation' . $translationName . $language; |
||
3034 | |||
3035 | if ($this->wasAliasUsed($query, $alias)) { |
||
3036 | return $alias; |
||
3037 | } |
||
3038 | |||
3039 | $rootAlias = $this->getRootAlias($query); |
||
3040 | |||
3041 | $query->setParameter("name$alias", $translationName); |
||
3042 | $query->setParameter("target$alias", $language); |
||
3043 | |||
3044 | $query->leftJoin( |
||
3045 | 'UnserAller_Model_Translation', |
||
3046 | $alias, |
||
3047 | 'WITH', |
||
3048 | "$alias.name = CONCAT(:name$alias,$rootAlias.id) AND $alias.target = :target$alias" |
||
3049 | ); |
||
3050 | |||
3051 | return $alias; |
||
3052 | } |
||
3053 | |||
3054 | /** |
||
3055 | * @param \Doctrine\ORM\QueryBuilder $query |
||
3056 | * @param string $alias |
||
3057 | * @param string $col |
||
3058 | * @param string $name |
||
3059 | * @param string $translationName |
||
3060 | * @param string $language |
||
3061 | * @return array |
||
3062 | */ |
||
3063 | protected function abstractIncludeMultilanguageStringColumn( |
||
3064 | $query, |
||
3065 | $alias, |
||
3066 | $col, |
||
3067 | $name, |
||
3068 | $translationName, |
||
3069 | $language |
||
3070 | ) { |
||
3071 | if (!$language) { |
||
3072 | $query->addSelect("($col) $alias"); |
||
3073 | } else { |
||
3074 | $query->addSelect("(COALESCE(" . $this->joinTranslationOnce( |
||
3075 | $query, |
||
3076 | $translationName, |
||
3077 | $language |
||
3078 | ) . ".translation,$col)) $alias"); |
||
3079 | } |
||
3080 | |||
3081 | return [ |
||
3082 | $alias, |
||
3083 | 'move' => $name |
||
3084 | ]; |
||
3085 | } |
||
3086 | |||
3087 | protected function getAdditionalUserParamOrFail(&$additionalParams) |
||
3088 | { |
||
3089 | if (!isset($additionalParams['user'][0])) { |
||
3090 | throw new \InvalidArgumentException('User identifier required but not given'); |
||
3091 | } |
||
3092 | |||
3093 | $param = $additionalParams['user']; |
||
3094 | unset($additionalParams['user']); |
||
3095 | return \UnserAllerLib_Validate_Helper::integerOrFail($param[0], 1); |
||
3096 | } |
||
3097 | } |
||
3098 |
The
EntityManager
might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManager
is closed. Any other code which depends on the same instance of theEntityManager
during this request will fail.On the other hand, if you instead inject the
ManagerRegistry
, thegetManager()
method guarantees that you will always get a usable manager instance.