Completed
Push — master ( 9803c0...824c84 )
by Fabien
03:56
created
Classes/Domain/Repository/ContentRepository.php 1 patch
Indentation   +820 added lines, -820 removed lines patch added patch discarded remove patch
@@ -34,825 +34,825 @@
 block discarded – undo
34 34
 class ContentRepository implements RepositoryInterface
35 35
 {
36 36
 
37
-    /**
38
-     * Tell whether it is a raw result (array) or object being returned.
39
-     *
40
-     * @var bool
41
-     */
42
-    protected $rawResult = false;
43
-
44
-    /**
45
-     * The data type to be returned, e.g fe_users, fe_groups, tt_content, etc...
46
-     *
47
-     * @var string
48
-     */
49
-    protected $dataType;
50
-
51
-    /**
52
-     * The source field is useful in the context of MM relations to know who is the caller
53
-     * e.g findByItems which eventually corresponds to a field name.
54
-     *
55
-     * @var string
56
-     */
57
-    protected $sourceFieldName = '';
58
-
59
-    /**
60
-     * @var array
61
-     */
62
-    protected $errorMessages = array();
63
-
64
-    /**
65
-     * @var QuerySettingsInterface
66
-     */
67
-    protected $defaultQuerySettings;
68
-
69
-    /**
70
-     * Constructor
71
-     *
72
-     * @param string $dataType
73
-     */
74
-    public function __construct($dataType)
75
-    {
76
-        $this->dataType = $dataType;
77
-    }
78
-
79
-    /**
80
-     * Returns all objects of this repository.
81
-     *
82
-     * @return Content[]
83
-     */
84
-    public function findAll()
85
-    {
86
-        $query = $this->createQuery();
87
-        return $query->execute();
88
-    }
89
-
90
-    /**
91
-     * Returns all "distinct" values for a given property.
92
-     *
93
-     * @param string $propertyName
94
-     * @param Matcher $matcher
95
-     * @return Content[]
96
-     */
97
-    public function findDistinctValues($propertyName, Matcher $matcher = null)
98
-    {
99
-        $query = $this->createQuery();
100
-        $query->setDistinct($propertyName);
101
-
102
-        // Remove empty values from selection.
103
-        $constraint = $query->logicalNot($query->equals($propertyName, ''));
104
-
105
-        // Add some additional constraints from the Matcher object.
106
-        $matcherConstraint = null;
107
-        if (!is_null($matcher)) {
108
-            $matcherConstraint = $this->computeConstraints($query, $matcher);
109
-        }
110
-
111
-        // Assemble the final constraints or not.
112
-        if ($matcherConstraint) {
113
-            $query->logicalAnd($matcherConstraint, $constraint);
114
-            $query->matching($query->logicalAnd($matcherConstraint, $constraint));
115
-        } else {
116
-            $query->matching($constraint);
117
-        }
118
-
119
-        return $query->execute();
120
-    }
121
-
122
-    /**
123
-     * Returns all "distinct" values for a given property.
124
-     *
125
-     * @param string $propertyName
126
-     * @param Matcher $matcher
127
-     * @return int
128
-     */
129
-    public function countDistinctValues($propertyName, Matcher $matcher = null)
130
-    {
131
-        $query = $this->createQuery();
132
-        $query->setDistinct($propertyName);
133
-
134
-        // Remove empty values from selection.
135
-        $constraint = $query->logicalNot($query->equals($propertyName, ''));
136
-
137
-        // Add some additional constraints from the Matcher object.
138
-        $matcherConstraint = null;
139
-        if (!is_null($matcher)) {
140
-            $matcherConstraint = $this->computeConstraints($query, $matcher);
141
-        }
142
-
143
-        // Assemble the final constraints or not.
144
-        if ($matcherConstraint) {
145
-            $query->logicalAnd($matcherConstraint, $constraint);
146
-            $query->matching($query->logicalAnd($matcherConstraint, $constraint));
147
-        } else {
148
-            $query->matching($constraint);
149
-        }
150
-
151
-        return $query->count();
152
-    }
153
-
154
-    /**
155
-     * Finds an object matching the given identifier.
156
-     *
157
-     * @param int $uid The identifier of the object to find
158
-     * @return Content|null
159
-     * @api
160
-     */
161
-    public function findByUid($uid)
162
-    {
163
-        return $this->findByIdentifier($uid);
164
-    }
165
-
166
-    /**
167
-     * Finds all Contents given specified matches.
168
-     *
169
-     * @param string $propertyName
170
-     * @param array $values
171
-     * @return Content[]
172
-     */
173
-    public function findIn($propertyName, array $values)
174
-    {
175
-        $query = $this->createQuery();
176
-        $query->matching($query->in($propertyName, $values));
177
-        return $query->execute();
178
-    }
179
-
180
-    /**
181
-     * Finds all Contents given specified matches.
182
-     *
183
-     * @param Matcher $matcher
184
-     * @param Order $order The order
185
-     * @param int $limit
186
-     * @param int $offset
187
-     * @return Content[]
188
-     */
189
-    public function findBy(Matcher $matcher, Order $order = null, $limit = null, $offset = null)
190
-    {
191
-
192
-        $query = $this->createQuery();
193
-
194
-        $limit = (int)$limit; // make sure to cast
195
-        if ($limit > 0) {
196
-            $query->setLimit($limit);
197
-        }
198
-
199
-        if ($order) {
200
-            $query->setOrderings($order->getOrderings());
201
-
202
-            // Loops around the orderings adding if necessary a dummy condition
203
-            // to make sure the relations can be resolved when transforming the query to plain SQL.
204
-            foreach ($order->getOrderings() as $ordering => $direction) {
205
-                if ($this->hasForeignRelationIn($ordering)) {
206
-                    $relationalField = $this->getForeignRelationFrom($ordering);
207
-                    $matcher->like($relationalField . '.uid', '');
208
-                }
209
-            }
210
-        }
211
-
212
-        if ($offset) {
213
-            $query->setOffset($offset);
214
-        }
215
-
216
-        $constraints = $this->computeConstraints($query, $matcher);
217
-
218
-        if ($constraints) {
219
-            $query->matching($constraints);
220
-        }
221
-
222
-        return $query->execute();
223
-    }
224
-
225
-    /**
226
-     * Find one Content object given specified matches.
227
-     *
228
-     * @param Matcher $matcher
229
-     * @return Content
230
-     */
231
-    public function findOneBy(Matcher $matcher)
232
-    {
233
-
234
-        $query = $this->createQuery();
235
-
236
-        $constraints = $this->computeConstraints($query, $matcher);
237
-
238
-        if ($constraints) {
239
-            $query->matching($constraints);
240
-        }
241
-
242
-        $query->setLimit(1); // only take one!
243
-
244
-        $resultSet = $query->execute();
245
-        if ($resultSet) {
246
-            $resultSet = current($resultSet);
247
-        }
248
-        return $resultSet;
249
-    }
250
-
251
-    /**
252
-     * Count all Contents given specified matches.
253
-     *
254
-     * @param Matcher $matcher
255
-     * @return int
256
-     */
257
-    public function countBy(Matcher $matcher)
258
-    {
259
-
260
-        $query = $this->createQuery();
261
-
262
-        $constraints = $this->computeConstraints($query, $matcher);
263
-
264
-        if ($constraints) {
265
-            $query->matching($constraints);
266
-        }
267
-
268
-        return $query->count();
269
-    }
270
-
271
-    /**
272
-     * Update a content with new information.
273
-     *
274
-     * @param Content $content
275
-     * @param $language
276
-     * @return bool
277
-     */
278
-    public function localize($content, $language)
279
-    {
280
-
281
-        // Security check
282
-        $this->getContentValidator()->validate($content);
283
-        $this->getLanguageValidator()->validate($language);
284
-
285
-        $dataType = $content->getDataType();
286
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::LOCALIZE)->forType($dataType)->getDataHandler();
287
-
288
-        $handlerResult = $handler->processLocalize($content, $language);
289
-        $this->errorMessages = $handler->getErrorMessages();
290
-        return $handlerResult;
291
-    }
292
-
293
-    /**
294
-     * Update a content with new information.
295
-     *
296
-     * @param Content $content
297
-     * @return bool
298
-     */
299
-    public function update($content)
300
-    {
301
-
302
-        // Security check.
303
-        $this->getContentValidator()->validate($content);
304
-
305
-        $dataType = $content->getDataType();
306
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::UPDATE)->forType($dataType)->getDataHandler();
307
-
308
-        $handlerResult = $handler->processUpdate($content);
309
-        $this->errorMessages = $handler->getErrorMessages();
310
-        return $handlerResult;
311
-    }
312
-
313
-    /**
314
-     * Removes an object from this repository.
315
-     *
316
-     * @param Content $content
317
-     * @return boolean
318
-     */
319
-    public function remove($content)
320
-    {
321
-        $dataType = $content->getDataType();
322
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::REMOVE)->forType($dataType)->getDataHandler();
323
-
324
-        $handlerResult = $handler->processRemove($content);
325
-        $this->errorMessages = $handler->getErrorMessages();
326
-        return $handlerResult;
327
-    }
328
-
329
-    /**
330
-     * Move a content within this repository.
331
-     * The $target corresponds to the pid to move the records to.
332
-     * It can also be a negative value in case of sorting. The negative value would be the uid of its predecessor.
333
-     *
334
-     * @param Content $content
335
-     * @param string $target
336
-     * @return bool
337
-     */
338
-    public function move($content, $target)
339
-    {
340
-
341
-        // Security check.
342
-        $this->getContentValidator()->validate($content);
343
-
344
-        $dataType = $content->getDataType();
345
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::MOVE)->forType($dataType)->getDataHandler();
346
-
347
-        $handlerResult = $handler->processMove($content, $target);
348
-        $this->errorMessages = $handler->getErrorMessages();
349
-        return $handlerResult;
350
-    }
351
-
352
-    /**
353
-     * Copy a content within this repository.
354
-     *
355
-     * @param Content $content
356
-     * @return bool
357
-     */
358
-    public function copy($content, $target)
359
-    {
360
-
361
-        // Security check.
362
-        $this->getContentValidator()->validate($content);
363
-
364
-        $dataType = $content->getDataType();
365
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::COPY)->forType($dataType)->getDataHandler();
366
-
367
-        $handlerResult = $handler->processCopy($content, $target);
368
-        $this->errorMessages = $handler->getErrorMessages();
369
-        return $handlerResult;
370
-    }
371
-
372
-    /**
373
-     * Adds an object to this repository.
374
-     *
375
-     * @param object $object The object to add
376
-     * @throws \BadMethodCallException
377
-     * @return void
378
-     * @api
379
-     */
380
-    public function add($object)
381
-    {
382
-        throw new \BadMethodCallException('Repository does not support the add() method.', 1375805599);
383
-    }
384
-
385
-    /**
386
-     * Returns the total number objects of this repository.
387
-     *
388
-     * @return integer The object count
389
-     * @api
390
-     */
391
-    public function countAll()
392
-    {
393
-        $query = $this->createQuery();
394
-        return $query->count();
395
-    }
396
-
397
-    /**
398
-     * Removes all objects of this repository as if remove() was called for
399
-     * all of them.
400
-     *
401
-     * @return void
402
-     * @api
403
-     */
404
-    public function removeAll()
405
-    {
406
-        // TODO: Implement removeAll() method.
407
-    }
408
-
409
-    /**
410
-     * Finds an object matching the given identifier.
411
-     *
412
-     * @param mixed $identifier The identifier of the object to find
413
-     * @return Content|null
414
-     * @api
415
-     */
416
-    public function findByIdentifier($identifier)
417
-    {
418
-        $query = $this->createQuery();
419
-
420
-        $result = $query->matching($query->equals('uid', $identifier))
421
-            ->execute();
422
-
423
-        if (is_array($result)) {
424
-            $result = current($result);
425
-        }
426
-
427
-        return $result;
428
-    }
429
-
430
-    /**
431
-     * Dispatches magic methods (findBy[Property]())
432
-     *
433
-     * @param string $methodName The name of the magic method
434
-     * @param string $arguments The arguments of the magic method
435
-     * @throws UnsupportedMethodException
436
-     * @return mixed
437
-     * @api
438
-     */
439
-    public function __call($methodName, $arguments)
440
-    {
441
-        if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
442
-            $propertyName = strtolower(substr(substr($methodName, 6), 0, 1)) . substr(substr($methodName, 6), 1);
443
-            $result = $this->processMagicCall($propertyName, $arguments[0]);
444
-        } elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
445
-            $propertyName = strtolower(substr(substr($methodName, 9), 0, 1)) . substr(substr($methodName, 9), 1);
446
-            $result = $this->processMagicCall($propertyName, $arguments[0], 'one');
447
-        } elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
448
-            $propertyName = strtolower(substr(substr($methodName, 7), 0, 1)) . substr(substr($methodName, 7), 1);
449
-            $result = $this->processMagicCall($propertyName, $arguments[0], 'count');
450
-        } else {
451
-            throw new UnsupportedMethodException('The method "' . $methodName . '" is not supported by the repository.', 1360838010);
452
-        }
453
-        return $result;
454
-    }
455
-
456
-    /**
457
-     * Returns a query for objects of this repository
458
-     *
459
-     * @return Query
460
-     * @api
461
-     */
462
-    public function createQuery()
463
-    {
464
-        /** @var Query $query */
465
-        $query = $this->getObjectManager()->get('Fab\Vidi\Persistence\Query', $this->dataType);
466
-        $query->setSourceFieldName($this->sourceFieldName);
467
-
468
-        if ($this->defaultQuerySettings) {
469
-            $query->setQuerySettings($this->defaultQuerySettings);
470
-        } else {
471
-
472
-            // Initialize and pass the query settings at this level.
473
-            /** @var \Fab\Vidi\Persistence\QuerySettings $querySettings */
474
-            $querySettings = $this->getObjectManager()->get('Fab\Vidi\Persistence\QuerySettings');
475
-
476
-            // Default choice for the BE.
477
-            if ($this->isBackendMode()) {
478
-                $querySettings->setIgnoreEnableFields(true);
479
-            }
480
-
481
-            $query->setQuerySettings($querySettings);
482
-        }
483
-
484
-        return $query;
485
-    }
486
-
487
-    /**
488
-     * Sets the property names to order the result by per default.
489
-     * Expected like this:
490
-     * array(
491
-     * 'foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
492
-     * 'bar' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
493
-     * )
494
-     *
495
-     * @param array $defaultOrderings The property names to order by
496
-     * @throws \BadMethodCallException
497
-     * @return void
498
-     * @api
499
-     */
500
-    public function setDefaultOrderings(array $defaultOrderings)
501
-    {
502
-        throw new \BadMethodCallException('Repository does not support the setDefaultOrderings() method.', 1375805598);
503
-    }
504
-
505
-    /**
506
-     * Sets the default query settings to be used in this repository
507
-     *
508
-     * @param QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
509
-     * @throws \BadMethodCallException
510
-     * @return void
511
-     * @api
512
-     */
513
-    public function setDefaultQuerySettings(QuerySettingsInterface $defaultQuerySettings)
514
-    {
515
-        $this->defaultQuerySettings = $defaultQuerySettings;
516
-    }
517
-
518
-    /**
519
-     * @return array
520
-     */
521
-    public function getErrorMessages()
522
-    {
523
-        return $this->errorMessages;
524
-    }
525
-
526
-    /**
527
-     * @param string $sourceFieldName
528
-     * @return $this
529
-     */
530
-    public function setSourceFieldName($sourceFieldName)
531
-    {
532
-        $this->sourceFieldName = $sourceFieldName;
533
-        return $this;
534
-    }
535
-
536
-    /**
537
-     * @return string
538
-     */
539
-    public function getDataType()
540
-    {
541
-        return $this->dataType;
542
-    }
543
-
544
-    /**
545
-     * Tell whether the order has a foreign table in its expression, e.g. "metadata.title".
546
-     *
547
-     * @param string $ordering
548
-     * @return bool
549
-     */
550
-    protected function hasForeignRelationIn($ordering)
551
-    {
552
-        return strpos($ordering, '.') !== false;
553
-    }
554
-
555
-    /**
556
-     * Extract the foreign relation of the ordering "metadata.title" -> "metadata"
557
-     *
558
-     * @param string $ordering
559
-     * @return string
560
-     */
561
-    protected function getForeignRelationFrom($ordering)
562
-    {
563
-        $parts = explode('.', $ordering);
564
-        return $parts[0];
565
-    }
566
-
567
-    /**
568
-     * Get the constraints
569
-     *
570
-     * @param Query $query
571
-     * @param Matcher $matcher
572
-     * @return ConstraintInterface|null
573
-     */
574
-    protected function computeConstraints(Query $query, Matcher $matcher)
575
-    {
576
-
577
-        $constraints = null;
578
-
579
-        $collectedConstraints = array();
580
-
581
-        // Search term
582
-        $constraint = $this->computeSearchTermConstraint($query, $matcher);
583
-        if ($constraint) {
584
-            $collectedConstraints[] = $constraint;
585
-        }
586
-
587
-        foreach ($matcher->getSupportedOperators() as $operator) {
588
-            $constraint = $this->computeConstraint($query, $matcher, $operator);
589
-            if ($constraint) {
590
-                $collectedConstraints[] = $constraint;
591
-            }
592
-        }
593
-
594
-        if (count($collectedConstraints) > 1) {
595
-            $logical = $matcher->getDefaultLogicalSeparator();
596
-            $constraints = $query->$logical($collectedConstraints);
597
-        } elseif (!empty($collectedConstraints)) {
598
-
599
-            // true means there is one constraint only and should become the result
600
-            $constraints = current($collectedConstraints);
601
-        }
602
-
603
-        // Trigger signal for post processing the computed constraints object.
604
-        $constraints = $this->emitPostProcessConstraintsSignal($query, $constraints);
605
-
606
-        return $constraints;
607
-    }
608
-
609
-    /**
610
-     * Computes the search constraint and returns it.
611
-     *
612
-     * @param Query $query
613
-     * @param Matcher $matcher
614
-     * @return ConstraintInterface|null
615
-     */
616
-    protected function computeSearchTermConstraint(Query $query, Matcher $matcher)
617
-    {
618
-
619
-        $result = null;
620
-
621
-        // Search term case
622
-        if ($matcher->getSearchTerm()) {
623
-
624
-            $fields = GeneralUtility::trimExplode(',', Tca::table($this->dataType)->getSearchFields(), true);
625
-
626
-            $constraints = array();
627
-            $likeClause = sprintf('%%%s%%', $matcher->getSearchTerm());
628
-            foreach ($fields as $fieldNameAndPath) {
629
-                if ($this->isSuitableForLike($fieldNameAndPath, $matcher->getSearchTerm())) {
630
-
631
-                    $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
632
-                    $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
633
-
634
-                    if (Tca::table($dataType)->hasField($fieldName) && Tca::table($dataType)->field($fieldName)->hasRelation()) {
635
-                        $foreignTable = Tca::table($dataType)->field($fieldName)->getForeignTable();
636
-                        $fieldNameAndPath = $fieldNameAndPath . '.' . Tca::table($foreignTable)->getLabelField();
637
-                    }
638
-                    $constraints[] = $query->like($fieldNameAndPath, $likeClause);
639
-                }
640
-            }
641
-            $logical = $matcher->getLogicalSeparatorForSearchTerm();
642
-            $result = $query->$logical($constraints);
643
-        }
644
-
645
-        return $result;
646
-    }
647
-
648
-    /**
649
-     * It does not make sense to have a "like" in presence of numerical field, e.g "uid".
650
-     * Tell whether the given value makes sense for a "like" clause.
651
-     *
652
-     * @param string $fieldNameAndPath
653
-     * @param string $value
654
-     * @return bool
655
-     */
656
-    protected function isSuitableForLike($fieldNameAndPath, $value)
657
-    {
658
-        $isSuitable = true;
659
-
660
-        // true means it is a string
661
-        if (!MathUtility::canBeInterpretedAsInteger($value)) {
662
-
663
-            $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
664
-            $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
665
-
666
-            if (Tca::table($dataType)->field($fieldName)->isNumerical()
667
-                && !Tca::table($dataType)->field($fieldName)->hasRelation()
668
-            ) {
669
-                $isSuitable = false;
670
-            }
671
-        }
672
-
673
-        return $isSuitable;
674
-    }
675
-
676
-    /**
677
-     * Computes the constraint for matches and returns it.
678
-     *
679
-     * @param Query $query
680
-     * @param Matcher $matcher
681
-     * @param string $operator
682
-     * @return ConstraintInterface|null
683
-     */
684
-    protected function computeConstraint(Query $query, Matcher $matcher, $operator)
685
-    {
686
-        $result = null;
687
-
688
-        $operatorName = ucfirst($operator);
689
-        $getCriteria = sprintf('get%s', $operatorName);
690
-        $criteria = $matcher->$getCriteria();
691
-
692
-        if (!empty($criteria)) {
693
-            $constraints = array();
694
-
695
-            foreach ($criteria as $criterion) {
696
-
697
-                $fieldNameAndPath = $criterion['fieldNameAndPath'];
698
-                $operand = $criterion['operand'];
699
-
700
-                // Compute a few variables...
701
-                // $dataType is generally equals to $this->dataType but not always... if fieldName is a path.
702
-                $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
703
-                $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
704
-                $fieldPath = $this->getFieldPathResolver()->stripFieldName($fieldNameAndPath, $this->dataType);
705
-
706
-                if (Tca::table($dataType)->field($fieldName)->hasRelation()) {
707
-                    if (MathUtility::canBeInterpretedAsInteger($operand)) {
708
-                        $fieldNameAndPath = $fieldName . '.uid';
709
-                    } else {
710
-                        $foreignTableName = Tca::table($dataType)->field($fieldName)->getForeignTable();
711
-                        $foreignTable = Tca::table($foreignTableName);
712
-                        $fieldNameAndPath = $fieldName . '.' . $foreignTable->getLabelField();
713
-                    }
714
-
715
-                    // If different means we should restore the prepended path segment for proper SQL parser.
716
-                    // This is true for a composite field, e.g items.sys_file_metadata for categories.
717
-                    if ($fieldName !== $fieldPath) {
718
-                        $fieldNameAndPath = $fieldPath . '.' . $fieldNameAndPath;
719
-                    }
720
-                }
721
-
722
-                $constraints[] = $query->$operator($fieldNameAndPath, $criterion['operand']);
723
-            }
724
-
725
-            $getLogicalSeparator = sprintf('getLogicalSeparatorFor%s', $operatorName);
726
-            $logical = $matcher->$getLogicalSeparator();
727
-            $result = $query->$logical($constraints);
728
-        }
729
-
730
-        return $result;
731
-    }
732
-
733
-    /**
734
-     * @return \TYPO3\CMS\Core\DataHandling\DataHandler
735
-     */
736
-    protected function getDataHandler()
737
-    {
738
-        if (!$this->dataHandler) {
739
-            $this->dataHandler = GeneralUtility::makeInstance('TYPO3\CMS\Core\DataHandling\DataHandler');
740
-        }
741
-        return $this->dataHandler;
742
-    }
743
-
744
-    /**
745
-     * Handle the magic call by properly creating a Query object and returning its result.
746
-     *
747
-     * @param string $propertyName
748
-     * @param string $value
749
-     * @param string $flag
750
-     * @return array
751
-     */
752
-    protected function processMagicCall($propertyName, $value, $flag = '')
753
-    {
754
-
755
-        $fieldName = Property::name($propertyName)->of($this->dataType)->toFieldName();
756
-
757
-        /** @var $matcher Matcher */
758
-        $matcher = GeneralUtility::makeInstance('Fab\Vidi\Persistence\Matcher', array(), $this->getDataType());
759
-
760
-        $table = Tca::table($this->dataType);
761
-        if ($table->field($fieldName)->isGroup()) {
762
-
763
-            $valueParts = explode('.', $value, 2);
764
-            $fieldName = $fieldName . '.' . $valueParts[0];
765
-            $value = $valueParts[1];
766
-        }
767
-
768
-        $matcher->equals($fieldName, $value);
769
-
770
-        if ($flag == 'count') {
771
-            $result = $this->countBy($matcher);
772
-        } else {
773
-            $result = $this->findBy($matcher);
774
-        }
775
-        return $flag == 'one' && !empty($result) ? reset($result) : $result;
776
-    }
777
-
778
-    /**
779
-     * @return \Fab\Vidi\DataHandler\DataHandlerFactory
780
-     */
781
-    protected function getDataHandlerFactory()
782
-    {
783
-        return GeneralUtility::makeInstance('Fab\Vidi\DataHandler\DataHandlerFactory');
784
-    }
785
-
786
-    /**
787
-     * Returns whether the current mode is Backend
788
-     *
789
-     * @return bool
790
-     */
791
-    protected function isBackendMode()
792
-    {
793
-        return TYPO3_MODE == 'BE';
794
-    }
795
-
796
-    /**
797
-     * @return \Fab\Vidi\Resolver\FieldPathResolver
798
-     */
799
-    protected function getFieldPathResolver()
800
-    {
801
-        return GeneralUtility::makeInstance('Fab\Vidi\Resolver\FieldPathResolver');
802
-    }
803
-
804
-    /**
805
-     * @return \TYPO3\CMS\Extbase\Object\ObjectManager
806
-     */
807
-    protected function getObjectManager()
808
-    {
809
-        return GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
810
-    }
811
-
812
-    /**
813
-     * @return \Fab\Vidi\Domain\Validator\ContentValidator
814
-     */
815
-    protected function getContentValidator()
816
-    {
817
-        return GeneralUtility::makeInstance('Fab\Vidi\Domain\Validator\ContentValidator');
818
-    }
819
-
820
-    /**
821
-     * @return \Fab\Vidi\Domain\Validator\LanguageValidator
822
-     */
823
-    protected function getLanguageValidator()
824
-    {
825
-        return GeneralUtility::makeInstance('Fab\Vidi\Domain\Validator\LanguageValidator');
826
-    }
827
-
828
-    /**
829
-     * Signal that is called for post-processing the computed constraints object.
830
-     *
831
-     * @param Query $query
832
-     * @param ConstraintInterface|null $constraints
833
-     * @return ConstraintInterface|null $constraints
834
-     * @signal
835
-     */
836
-    protected function emitPostProcessConstraintsSignal(Query $query, $constraints)
837
-    {
838
-        $result = $this->getSignalSlotDispatcher()->dispatch(
839
-            'Fab\Vidi\Domain\Repository\ContentRepository',
840
-            'postProcessConstraintsObject',
841
-            array(
842
-                $query,
843
-                $constraints
844
-            )
845
-        );
846
-
847
-        return $result[1];
848
-    }
849
-
850
-    /**
851
-     * @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
852
-     */
853
-    protected function getSignalSlotDispatcher()
854
-    {
855
-        return $this->getObjectManager()->get('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
856
-    }
37
+	/**
38
+	 * Tell whether it is a raw result (array) or object being returned.
39
+	 *
40
+	 * @var bool
41
+	 */
42
+	protected $rawResult = false;
43
+
44
+	/**
45
+	 * The data type to be returned, e.g fe_users, fe_groups, tt_content, etc...
46
+	 *
47
+	 * @var string
48
+	 */
49
+	protected $dataType;
50
+
51
+	/**
52
+	 * The source field is useful in the context of MM relations to know who is the caller
53
+	 * e.g findByItems which eventually corresponds to a field name.
54
+	 *
55
+	 * @var string
56
+	 */
57
+	protected $sourceFieldName = '';
58
+
59
+	/**
60
+	 * @var array
61
+	 */
62
+	protected $errorMessages = array();
63
+
64
+	/**
65
+	 * @var QuerySettingsInterface
66
+	 */
67
+	protected $defaultQuerySettings;
68
+
69
+	/**
70
+	 * Constructor
71
+	 *
72
+	 * @param string $dataType
73
+	 */
74
+	public function __construct($dataType)
75
+	{
76
+		$this->dataType = $dataType;
77
+	}
78
+
79
+	/**
80
+	 * Returns all objects of this repository.
81
+	 *
82
+	 * @return Content[]
83
+	 */
84
+	public function findAll()
85
+	{
86
+		$query = $this->createQuery();
87
+		return $query->execute();
88
+	}
89
+
90
+	/**
91
+	 * Returns all "distinct" values for a given property.
92
+	 *
93
+	 * @param string $propertyName
94
+	 * @param Matcher $matcher
95
+	 * @return Content[]
96
+	 */
97
+	public function findDistinctValues($propertyName, Matcher $matcher = null)
98
+	{
99
+		$query = $this->createQuery();
100
+		$query->setDistinct($propertyName);
101
+
102
+		// Remove empty values from selection.
103
+		$constraint = $query->logicalNot($query->equals($propertyName, ''));
104
+
105
+		// Add some additional constraints from the Matcher object.
106
+		$matcherConstraint = null;
107
+		if (!is_null($matcher)) {
108
+			$matcherConstraint = $this->computeConstraints($query, $matcher);
109
+		}
110
+
111
+		// Assemble the final constraints or not.
112
+		if ($matcherConstraint) {
113
+			$query->logicalAnd($matcherConstraint, $constraint);
114
+			$query->matching($query->logicalAnd($matcherConstraint, $constraint));
115
+		} else {
116
+			$query->matching($constraint);
117
+		}
118
+
119
+		return $query->execute();
120
+	}
121
+
122
+	/**
123
+	 * Returns all "distinct" values for a given property.
124
+	 *
125
+	 * @param string $propertyName
126
+	 * @param Matcher $matcher
127
+	 * @return int
128
+	 */
129
+	public function countDistinctValues($propertyName, Matcher $matcher = null)
130
+	{
131
+		$query = $this->createQuery();
132
+		$query->setDistinct($propertyName);
133
+
134
+		// Remove empty values from selection.
135
+		$constraint = $query->logicalNot($query->equals($propertyName, ''));
136
+
137
+		// Add some additional constraints from the Matcher object.
138
+		$matcherConstraint = null;
139
+		if (!is_null($matcher)) {
140
+			$matcherConstraint = $this->computeConstraints($query, $matcher);
141
+		}
142
+
143
+		// Assemble the final constraints or not.
144
+		if ($matcherConstraint) {
145
+			$query->logicalAnd($matcherConstraint, $constraint);
146
+			$query->matching($query->logicalAnd($matcherConstraint, $constraint));
147
+		} else {
148
+			$query->matching($constraint);
149
+		}
150
+
151
+		return $query->count();
152
+	}
153
+
154
+	/**
155
+	 * Finds an object matching the given identifier.
156
+	 *
157
+	 * @param int $uid The identifier of the object to find
158
+	 * @return Content|null
159
+	 * @api
160
+	 */
161
+	public function findByUid($uid)
162
+	{
163
+		return $this->findByIdentifier($uid);
164
+	}
165
+
166
+	/**
167
+	 * Finds all Contents given specified matches.
168
+	 *
169
+	 * @param string $propertyName
170
+	 * @param array $values
171
+	 * @return Content[]
172
+	 */
173
+	public function findIn($propertyName, array $values)
174
+	{
175
+		$query = $this->createQuery();
176
+		$query->matching($query->in($propertyName, $values));
177
+		return $query->execute();
178
+	}
179
+
180
+	/**
181
+	 * Finds all Contents given specified matches.
182
+	 *
183
+	 * @param Matcher $matcher
184
+	 * @param Order $order The order
185
+	 * @param int $limit
186
+	 * @param int $offset
187
+	 * @return Content[]
188
+	 */
189
+	public function findBy(Matcher $matcher, Order $order = null, $limit = null, $offset = null)
190
+	{
191
+
192
+		$query = $this->createQuery();
193
+
194
+		$limit = (int)$limit; // make sure to cast
195
+		if ($limit > 0) {
196
+			$query->setLimit($limit);
197
+		}
198
+
199
+		if ($order) {
200
+			$query->setOrderings($order->getOrderings());
201
+
202
+			// Loops around the orderings adding if necessary a dummy condition
203
+			// to make sure the relations can be resolved when transforming the query to plain SQL.
204
+			foreach ($order->getOrderings() as $ordering => $direction) {
205
+				if ($this->hasForeignRelationIn($ordering)) {
206
+					$relationalField = $this->getForeignRelationFrom($ordering);
207
+					$matcher->like($relationalField . '.uid', '');
208
+				}
209
+			}
210
+		}
211
+
212
+		if ($offset) {
213
+			$query->setOffset($offset);
214
+		}
215
+
216
+		$constraints = $this->computeConstraints($query, $matcher);
217
+
218
+		if ($constraints) {
219
+			$query->matching($constraints);
220
+		}
221
+
222
+		return $query->execute();
223
+	}
224
+
225
+	/**
226
+	 * Find one Content object given specified matches.
227
+	 *
228
+	 * @param Matcher $matcher
229
+	 * @return Content
230
+	 */
231
+	public function findOneBy(Matcher $matcher)
232
+	{
233
+
234
+		$query = $this->createQuery();
235
+
236
+		$constraints = $this->computeConstraints($query, $matcher);
237
+
238
+		if ($constraints) {
239
+			$query->matching($constraints);
240
+		}
241
+
242
+		$query->setLimit(1); // only take one!
243
+
244
+		$resultSet = $query->execute();
245
+		if ($resultSet) {
246
+			$resultSet = current($resultSet);
247
+		}
248
+		return $resultSet;
249
+	}
250
+
251
+	/**
252
+	 * Count all Contents given specified matches.
253
+	 *
254
+	 * @param Matcher $matcher
255
+	 * @return int
256
+	 */
257
+	public function countBy(Matcher $matcher)
258
+	{
259
+
260
+		$query = $this->createQuery();
261
+
262
+		$constraints = $this->computeConstraints($query, $matcher);
263
+
264
+		if ($constraints) {
265
+			$query->matching($constraints);
266
+		}
267
+
268
+		return $query->count();
269
+	}
270
+
271
+	/**
272
+	 * Update a content with new information.
273
+	 *
274
+	 * @param Content $content
275
+	 * @param $language
276
+	 * @return bool
277
+	 */
278
+	public function localize($content, $language)
279
+	{
280
+
281
+		// Security check
282
+		$this->getContentValidator()->validate($content);
283
+		$this->getLanguageValidator()->validate($language);
284
+
285
+		$dataType = $content->getDataType();
286
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::LOCALIZE)->forType($dataType)->getDataHandler();
287
+
288
+		$handlerResult = $handler->processLocalize($content, $language);
289
+		$this->errorMessages = $handler->getErrorMessages();
290
+		return $handlerResult;
291
+	}
292
+
293
+	/**
294
+	 * Update a content with new information.
295
+	 *
296
+	 * @param Content $content
297
+	 * @return bool
298
+	 */
299
+	public function update($content)
300
+	{
301
+
302
+		// Security check.
303
+		$this->getContentValidator()->validate($content);
304
+
305
+		$dataType = $content->getDataType();
306
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::UPDATE)->forType($dataType)->getDataHandler();
307
+
308
+		$handlerResult = $handler->processUpdate($content);
309
+		$this->errorMessages = $handler->getErrorMessages();
310
+		return $handlerResult;
311
+	}
312
+
313
+	/**
314
+	 * Removes an object from this repository.
315
+	 *
316
+	 * @param Content $content
317
+	 * @return boolean
318
+	 */
319
+	public function remove($content)
320
+	{
321
+		$dataType = $content->getDataType();
322
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::REMOVE)->forType($dataType)->getDataHandler();
323
+
324
+		$handlerResult = $handler->processRemove($content);
325
+		$this->errorMessages = $handler->getErrorMessages();
326
+		return $handlerResult;
327
+	}
328
+
329
+	/**
330
+	 * Move a content within this repository.
331
+	 * The $target corresponds to the pid to move the records to.
332
+	 * It can also be a negative value in case of sorting. The negative value would be the uid of its predecessor.
333
+	 *
334
+	 * @param Content $content
335
+	 * @param string $target
336
+	 * @return bool
337
+	 */
338
+	public function move($content, $target)
339
+	{
340
+
341
+		// Security check.
342
+		$this->getContentValidator()->validate($content);
343
+
344
+		$dataType = $content->getDataType();
345
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::MOVE)->forType($dataType)->getDataHandler();
346
+
347
+		$handlerResult = $handler->processMove($content, $target);
348
+		$this->errorMessages = $handler->getErrorMessages();
349
+		return $handlerResult;
350
+	}
351
+
352
+	/**
353
+	 * Copy a content within this repository.
354
+	 *
355
+	 * @param Content $content
356
+	 * @return bool
357
+	 */
358
+	public function copy($content, $target)
359
+	{
360
+
361
+		// Security check.
362
+		$this->getContentValidator()->validate($content);
363
+
364
+		$dataType = $content->getDataType();
365
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::COPY)->forType($dataType)->getDataHandler();
366
+
367
+		$handlerResult = $handler->processCopy($content, $target);
368
+		$this->errorMessages = $handler->getErrorMessages();
369
+		return $handlerResult;
370
+	}
371
+
372
+	/**
373
+	 * Adds an object to this repository.
374
+	 *
375
+	 * @param object $object The object to add
376
+	 * @throws \BadMethodCallException
377
+	 * @return void
378
+	 * @api
379
+	 */
380
+	public function add($object)
381
+	{
382
+		throw new \BadMethodCallException('Repository does not support the add() method.', 1375805599);
383
+	}
384
+
385
+	/**
386
+	 * Returns the total number objects of this repository.
387
+	 *
388
+	 * @return integer The object count
389
+	 * @api
390
+	 */
391
+	public function countAll()
392
+	{
393
+		$query = $this->createQuery();
394
+		return $query->count();
395
+	}
396
+
397
+	/**
398
+	 * Removes all objects of this repository as if remove() was called for
399
+	 * all of them.
400
+	 *
401
+	 * @return void
402
+	 * @api
403
+	 */
404
+	public function removeAll()
405
+	{
406
+		// TODO: Implement removeAll() method.
407
+	}
408
+
409
+	/**
410
+	 * Finds an object matching the given identifier.
411
+	 *
412
+	 * @param mixed $identifier The identifier of the object to find
413
+	 * @return Content|null
414
+	 * @api
415
+	 */
416
+	public function findByIdentifier($identifier)
417
+	{
418
+		$query = $this->createQuery();
419
+
420
+		$result = $query->matching($query->equals('uid', $identifier))
421
+			->execute();
422
+
423
+		if (is_array($result)) {
424
+			$result = current($result);
425
+		}
426
+
427
+		return $result;
428
+	}
429
+
430
+	/**
431
+	 * Dispatches magic methods (findBy[Property]())
432
+	 *
433
+	 * @param string $methodName The name of the magic method
434
+	 * @param string $arguments The arguments of the magic method
435
+	 * @throws UnsupportedMethodException
436
+	 * @return mixed
437
+	 * @api
438
+	 */
439
+	public function __call($methodName, $arguments)
440
+	{
441
+		if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
442
+			$propertyName = strtolower(substr(substr($methodName, 6), 0, 1)) . substr(substr($methodName, 6), 1);
443
+			$result = $this->processMagicCall($propertyName, $arguments[0]);
444
+		} elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
445
+			$propertyName = strtolower(substr(substr($methodName, 9), 0, 1)) . substr(substr($methodName, 9), 1);
446
+			$result = $this->processMagicCall($propertyName, $arguments[0], 'one');
447
+		} elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
448
+			$propertyName = strtolower(substr(substr($methodName, 7), 0, 1)) . substr(substr($methodName, 7), 1);
449
+			$result = $this->processMagicCall($propertyName, $arguments[0], 'count');
450
+		} else {
451
+			throw new UnsupportedMethodException('The method "' . $methodName . '" is not supported by the repository.', 1360838010);
452
+		}
453
+		return $result;
454
+	}
455
+
456
+	/**
457
+	 * Returns a query for objects of this repository
458
+	 *
459
+	 * @return Query
460
+	 * @api
461
+	 */
462
+	public function createQuery()
463
+	{
464
+		/** @var Query $query */
465
+		$query = $this->getObjectManager()->get('Fab\Vidi\Persistence\Query', $this->dataType);
466
+		$query->setSourceFieldName($this->sourceFieldName);
467
+
468
+		if ($this->defaultQuerySettings) {
469
+			$query->setQuerySettings($this->defaultQuerySettings);
470
+		} else {
471
+
472
+			// Initialize and pass the query settings at this level.
473
+			/** @var \Fab\Vidi\Persistence\QuerySettings $querySettings */
474
+			$querySettings = $this->getObjectManager()->get('Fab\Vidi\Persistence\QuerySettings');
475
+
476
+			// Default choice for the BE.
477
+			if ($this->isBackendMode()) {
478
+				$querySettings->setIgnoreEnableFields(true);
479
+			}
480
+
481
+			$query->setQuerySettings($querySettings);
482
+		}
483
+
484
+		return $query;
485
+	}
486
+
487
+	/**
488
+	 * Sets the property names to order the result by per default.
489
+	 * Expected like this:
490
+	 * array(
491
+	 * 'foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
492
+	 * 'bar' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
493
+	 * )
494
+	 *
495
+	 * @param array $defaultOrderings The property names to order by
496
+	 * @throws \BadMethodCallException
497
+	 * @return void
498
+	 * @api
499
+	 */
500
+	public function setDefaultOrderings(array $defaultOrderings)
501
+	{
502
+		throw new \BadMethodCallException('Repository does not support the setDefaultOrderings() method.', 1375805598);
503
+	}
504
+
505
+	/**
506
+	 * Sets the default query settings to be used in this repository
507
+	 *
508
+	 * @param QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
509
+	 * @throws \BadMethodCallException
510
+	 * @return void
511
+	 * @api
512
+	 */
513
+	public function setDefaultQuerySettings(QuerySettingsInterface $defaultQuerySettings)
514
+	{
515
+		$this->defaultQuerySettings = $defaultQuerySettings;
516
+	}
517
+
518
+	/**
519
+	 * @return array
520
+	 */
521
+	public function getErrorMessages()
522
+	{
523
+		return $this->errorMessages;
524
+	}
525
+
526
+	/**
527
+	 * @param string $sourceFieldName
528
+	 * @return $this
529
+	 */
530
+	public function setSourceFieldName($sourceFieldName)
531
+	{
532
+		$this->sourceFieldName = $sourceFieldName;
533
+		return $this;
534
+	}
535
+
536
+	/**
537
+	 * @return string
538
+	 */
539
+	public function getDataType()
540
+	{
541
+		return $this->dataType;
542
+	}
543
+
544
+	/**
545
+	 * Tell whether the order has a foreign table in its expression, e.g. "metadata.title".
546
+	 *
547
+	 * @param string $ordering
548
+	 * @return bool
549
+	 */
550
+	protected function hasForeignRelationIn($ordering)
551
+	{
552
+		return strpos($ordering, '.') !== false;
553
+	}
554
+
555
+	/**
556
+	 * Extract the foreign relation of the ordering "metadata.title" -> "metadata"
557
+	 *
558
+	 * @param string $ordering
559
+	 * @return string
560
+	 */
561
+	protected function getForeignRelationFrom($ordering)
562
+	{
563
+		$parts = explode('.', $ordering);
564
+		return $parts[0];
565
+	}
566
+
567
+	/**
568
+	 * Get the constraints
569
+	 *
570
+	 * @param Query $query
571
+	 * @param Matcher $matcher
572
+	 * @return ConstraintInterface|null
573
+	 */
574
+	protected function computeConstraints(Query $query, Matcher $matcher)
575
+	{
576
+
577
+		$constraints = null;
578
+
579
+		$collectedConstraints = array();
580
+
581
+		// Search term
582
+		$constraint = $this->computeSearchTermConstraint($query, $matcher);
583
+		if ($constraint) {
584
+			$collectedConstraints[] = $constraint;
585
+		}
586
+
587
+		foreach ($matcher->getSupportedOperators() as $operator) {
588
+			$constraint = $this->computeConstraint($query, $matcher, $operator);
589
+			if ($constraint) {
590
+				$collectedConstraints[] = $constraint;
591
+			}
592
+		}
593
+
594
+		if (count($collectedConstraints) > 1) {
595
+			$logical = $matcher->getDefaultLogicalSeparator();
596
+			$constraints = $query->$logical($collectedConstraints);
597
+		} elseif (!empty($collectedConstraints)) {
598
+
599
+			// true means there is one constraint only and should become the result
600
+			$constraints = current($collectedConstraints);
601
+		}
602
+
603
+		// Trigger signal for post processing the computed constraints object.
604
+		$constraints = $this->emitPostProcessConstraintsSignal($query, $constraints);
605
+
606
+		return $constraints;
607
+	}
608
+
609
+	/**
610
+	 * Computes the search constraint and returns it.
611
+	 *
612
+	 * @param Query $query
613
+	 * @param Matcher $matcher
614
+	 * @return ConstraintInterface|null
615
+	 */
616
+	protected function computeSearchTermConstraint(Query $query, Matcher $matcher)
617
+	{
618
+
619
+		$result = null;
620
+
621
+		// Search term case
622
+		if ($matcher->getSearchTerm()) {
623
+
624
+			$fields = GeneralUtility::trimExplode(',', Tca::table($this->dataType)->getSearchFields(), true);
625
+
626
+			$constraints = array();
627
+			$likeClause = sprintf('%%%s%%', $matcher->getSearchTerm());
628
+			foreach ($fields as $fieldNameAndPath) {
629
+				if ($this->isSuitableForLike($fieldNameAndPath, $matcher->getSearchTerm())) {
630
+
631
+					$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
632
+					$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
633
+
634
+					if (Tca::table($dataType)->hasField($fieldName) && Tca::table($dataType)->field($fieldName)->hasRelation()) {
635
+						$foreignTable = Tca::table($dataType)->field($fieldName)->getForeignTable();
636
+						$fieldNameAndPath = $fieldNameAndPath . '.' . Tca::table($foreignTable)->getLabelField();
637
+					}
638
+					$constraints[] = $query->like($fieldNameAndPath, $likeClause);
639
+				}
640
+			}
641
+			$logical = $matcher->getLogicalSeparatorForSearchTerm();
642
+			$result = $query->$logical($constraints);
643
+		}
644
+
645
+		return $result;
646
+	}
647
+
648
+	/**
649
+	 * It does not make sense to have a "like" in presence of numerical field, e.g "uid".
650
+	 * Tell whether the given value makes sense for a "like" clause.
651
+	 *
652
+	 * @param string $fieldNameAndPath
653
+	 * @param string $value
654
+	 * @return bool
655
+	 */
656
+	protected function isSuitableForLike($fieldNameAndPath, $value)
657
+	{
658
+		$isSuitable = true;
659
+
660
+		// true means it is a string
661
+		if (!MathUtility::canBeInterpretedAsInteger($value)) {
662
+
663
+			$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
664
+			$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
665
+
666
+			if (Tca::table($dataType)->field($fieldName)->isNumerical()
667
+				&& !Tca::table($dataType)->field($fieldName)->hasRelation()
668
+			) {
669
+				$isSuitable = false;
670
+			}
671
+		}
672
+
673
+		return $isSuitable;
674
+	}
675
+
676
+	/**
677
+	 * Computes the constraint for matches and returns it.
678
+	 *
679
+	 * @param Query $query
680
+	 * @param Matcher $matcher
681
+	 * @param string $operator
682
+	 * @return ConstraintInterface|null
683
+	 */
684
+	protected function computeConstraint(Query $query, Matcher $matcher, $operator)
685
+	{
686
+		$result = null;
687
+
688
+		$operatorName = ucfirst($operator);
689
+		$getCriteria = sprintf('get%s', $operatorName);
690
+		$criteria = $matcher->$getCriteria();
691
+
692
+		if (!empty($criteria)) {
693
+			$constraints = array();
694
+
695
+			foreach ($criteria as $criterion) {
696
+
697
+				$fieldNameAndPath = $criterion['fieldNameAndPath'];
698
+				$operand = $criterion['operand'];
699
+
700
+				// Compute a few variables...
701
+				// $dataType is generally equals to $this->dataType but not always... if fieldName is a path.
702
+				$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
703
+				$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
704
+				$fieldPath = $this->getFieldPathResolver()->stripFieldName($fieldNameAndPath, $this->dataType);
705
+
706
+				if (Tca::table($dataType)->field($fieldName)->hasRelation()) {
707
+					if (MathUtility::canBeInterpretedAsInteger($operand)) {
708
+						$fieldNameAndPath = $fieldName . '.uid';
709
+					} else {
710
+						$foreignTableName = Tca::table($dataType)->field($fieldName)->getForeignTable();
711
+						$foreignTable = Tca::table($foreignTableName);
712
+						$fieldNameAndPath = $fieldName . '.' . $foreignTable->getLabelField();
713
+					}
714
+
715
+					// If different means we should restore the prepended path segment for proper SQL parser.
716
+					// This is true for a composite field, e.g items.sys_file_metadata for categories.
717
+					if ($fieldName !== $fieldPath) {
718
+						$fieldNameAndPath = $fieldPath . '.' . $fieldNameAndPath;
719
+					}
720
+				}
721
+
722
+				$constraints[] = $query->$operator($fieldNameAndPath, $criterion['operand']);
723
+			}
724
+
725
+			$getLogicalSeparator = sprintf('getLogicalSeparatorFor%s', $operatorName);
726
+			$logical = $matcher->$getLogicalSeparator();
727
+			$result = $query->$logical($constraints);
728
+		}
729
+
730
+		return $result;
731
+	}
732
+
733
+	/**
734
+	 * @return \TYPO3\CMS\Core\DataHandling\DataHandler
735
+	 */
736
+	protected function getDataHandler()
737
+	{
738
+		if (!$this->dataHandler) {
739
+			$this->dataHandler = GeneralUtility::makeInstance('TYPO3\CMS\Core\DataHandling\DataHandler');
740
+		}
741
+		return $this->dataHandler;
742
+	}
743
+
744
+	/**
745
+	 * Handle the magic call by properly creating a Query object and returning its result.
746
+	 *
747
+	 * @param string $propertyName
748
+	 * @param string $value
749
+	 * @param string $flag
750
+	 * @return array
751
+	 */
752
+	protected function processMagicCall($propertyName, $value, $flag = '')
753
+	{
754
+
755
+		$fieldName = Property::name($propertyName)->of($this->dataType)->toFieldName();
756
+
757
+		/** @var $matcher Matcher */
758
+		$matcher = GeneralUtility::makeInstance('Fab\Vidi\Persistence\Matcher', array(), $this->getDataType());
759
+
760
+		$table = Tca::table($this->dataType);
761
+		if ($table->field($fieldName)->isGroup()) {
762
+
763
+			$valueParts = explode('.', $value, 2);
764
+			$fieldName = $fieldName . '.' . $valueParts[0];
765
+			$value = $valueParts[1];
766
+		}
767
+
768
+		$matcher->equals($fieldName, $value);
769
+
770
+		if ($flag == 'count') {
771
+			$result = $this->countBy($matcher);
772
+		} else {
773
+			$result = $this->findBy($matcher);
774
+		}
775
+		return $flag == 'one' && !empty($result) ? reset($result) : $result;
776
+	}
777
+
778
+	/**
779
+	 * @return \Fab\Vidi\DataHandler\DataHandlerFactory
780
+	 */
781
+	protected function getDataHandlerFactory()
782
+	{
783
+		return GeneralUtility::makeInstance('Fab\Vidi\DataHandler\DataHandlerFactory');
784
+	}
785
+
786
+	/**
787
+	 * Returns whether the current mode is Backend
788
+	 *
789
+	 * @return bool
790
+	 */
791
+	protected function isBackendMode()
792
+	{
793
+		return TYPO3_MODE == 'BE';
794
+	}
795
+
796
+	/**
797
+	 * @return \Fab\Vidi\Resolver\FieldPathResolver
798
+	 */
799
+	protected function getFieldPathResolver()
800
+	{
801
+		return GeneralUtility::makeInstance('Fab\Vidi\Resolver\FieldPathResolver');
802
+	}
803
+
804
+	/**
805
+	 * @return \TYPO3\CMS\Extbase\Object\ObjectManager
806
+	 */
807
+	protected function getObjectManager()
808
+	{
809
+		return GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
810
+	}
811
+
812
+	/**
813
+	 * @return \Fab\Vidi\Domain\Validator\ContentValidator
814
+	 */
815
+	protected function getContentValidator()
816
+	{
817
+		return GeneralUtility::makeInstance('Fab\Vidi\Domain\Validator\ContentValidator');
818
+	}
819
+
820
+	/**
821
+	 * @return \Fab\Vidi\Domain\Validator\LanguageValidator
822
+	 */
823
+	protected function getLanguageValidator()
824
+	{
825
+		return GeneralUtility::makeInstance('Fab\Vidi\Domain\Validator\LanguageValidator');
826
+	}
827
+
828
+	/**
829
+	 * Signal that is called for post-processing the computed constraints object.
830
+	 *
831
+	 * @param Query $query
832
+	 * @param ConstraintInterface|null $constraints
833
+	 * @return ConstraintInterface|null $constraints
834
+	 * @signal
835
+	 */
836
+	protected function emitPostProcessConstraintsSignal(Query $query, $constraints)
837
+	{
838
+		$result = $this->getSignalSlotDispatcher()->dispatch(
839
+			'Fab\Vidi\Domain\Repository\ContentRepository',
840
+			'postProcessConstraintsObject',
841
+			array(
842
+				$query,
843
+				$constraints
844
+			)
845
+		);
846
+
847
+		return $result[1];
848
+	}
849
+
850
+	/**
851
+	 * @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
852
+	 */
853
+	protected function getSignalSlotDispatcher()
854
+	{
855
+		return $this->getObjectManager()->get('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
856
+	}
857 857
 
858 858
 }
Please login to merge, or discard this patch.
Classes/Persistence/Matcher.php 1 patch
Indentation   +466 added lines, -466 removed lines patch added patch discarded remove patch
@@ -20,470 +20,470 @@
 block discarded – undo
20 20
 class Matcher
21 21
 {
22 22
 
23
-    /**
24
-     * The logical OR
25
-     */
26
-    const LOGICAL_OR = 'logicalOr';
27
-
28
-    /**
29
-     * The logical AND
30
-     */
31
-    const LOGICAL_AND = 'logicalAnd';
32
-
33
-    /**
34
-     * @var string
35
-     */
36
-    protected $dataType = '';
37
-
38
-    /**
39
-     * @var string
40
-     */
41
-    protected $searchTerm = '';
42
-
43
-    /**
44
-     * @var array
45
-     */
46
-    protected $supportedOperators = [
47
-        '=' => 'equals',
48
-        'in' => 'in',
49
-        'like' => 'like',
50
-        '>' => 'greaterThan',
51
-        '>=' => 'greaterThanOrEqual',
52
-        '<' => 'lessThan',
53
-        '<=' => 'lessThanOrEqual'
54
-    ];
55
-
56
-    /**
57
-     * @var array
58
-     */
59
-    protected $equals = [];
60
-
61
-    /**
62
-     * @var array
63
-     */
64
-    protected $greaterThan = [];
65
-
66
-    /**
67
-     * @var array
68
-     */
69
-    protected $greaterThanOrEqual = [];
70
-
71
-    /**
72
-     * @var array
73
-     */
74
-    protected $lessThan = [];
75
-
76
-    /**
77
-     * @var array
78
-     */
79
-    protected $lessThanOrEqual = [];
80
-
81
-    /**
82
-     * @var array
83
-     */
84
-    protected $in = [];
85
-
86
-    /**
87
-     * @var array
88
-     */
89
-    protected $like = [];
90
-
91
-    /**
92
-     * @var string
93
-     */
94
-    protected $defaultLogicalSeparator = self::LOGICAL_AND;
95
-
96
-    /**
97
-     * @var string
98
-     */
99
-    protected $logicalSeparatorForEquals = self::LOGICAL_AND;
100
-
101
-    /**
102
-     * @var string
103
-     */
104
-    protected $logicalSeparatorForGreaterThan = self::LOGICAL_AND;
105
-
106
-    /**
107
-     * @var string
108
-     */
109
-    protected $logicalSeparatorForGreaterThanOrEqual = self::LOGICAL_AND;
110
-
111
-    /**
112
-     * @var string
113
-     */
114
-    protected $logicalSeparatorForLessThan = self::LOGICAL_AND;
115
-
116
-    /**
117
-     * @var string
118
-     */
119
-    protected $logicalSeparatorForLessThanOrEqual = self::LOGICAL_AND;
120
-
121
-    /**
122
-     * @var string
123
-     */
124
-    protected $logicalSeparatorForIn = self::LOGICAL_AND;
125
-
126
-    /**
127
-     * @var string
128
-     */
129
-    protected $logicalSeparatorForLike = self::LOGICAL_AND;
130
-
131
-    /**
132
-     * @var string
133
-     */
134
-    protected $logicalSeparatorForSearchTerm = self::LOGICAL_OR;
135
-
136
-    /**
137
-     * Constructs a new Matcher
138
-     *
139
-     * @param array $matches associative [$field => $value]
140
-     * @param string $dataType which corresponds to an entry of the TCA (table name).
141
-     * @return \Fab\Vidi\Persistence\Matcher
142
-     */
143
-    public function __construct($matches = [], $dataType = '')
144
-    {
145
-        $this->dataType = $dataType;
146
-        $this->matches = $matches;
147
-    }
148
-
149
-    /**
150
-     * @param string $searchTerm
151
-     * @return \Fab\Vidi\Persistence\Matcher
152
-     */
153
-    public function setSearchTerm($searchTerm)
154
-    {
155
-        $this->searchTerm = $searchTerm;
156
-        return $this;
157
-    }
158
-
159
-    /**
160
-     * @return string
161
-     */
162
-    public function getSearchTerm()
163
-    {
164
-        return $this->searchTerm;
165
-    }
166
-
167
-    /**
168
-     * @return array
169
-     */
170
-    public function getEquals()
171
-    {
172
-        return $this->equals;
173
-    }
174
-
175
-    /**
176
-     * @param $fieldNameAndPath
177
-     * @param $operand
178
-     * @return $this
179
-     */
180
-    public function equals($fieldNameAndPath, $operand)
181
-    {
182
-        $this->equals[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
183
-        return $this;
184
-    }
185
-
186
-    /**
187
-     * @return array
188
-     */
189
-    public function getGreaterThan()
190
-    {
191
-        return $this->greaterThan;
192
-    }
193
-
194
-    /**
195
-     * @param $fieldNameAndPath
196
-     * @param $operand
197
-     * @return $this
198
-     */
199
-    public function greaterThan($fieldNameAndPath, $operand)
200
-    {
201
-        $this->greaterThan[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
202
-        return $this;
203
-    }
204
-
205
-    /**
206
-     * @return array
207
-     */
208
-    public function getGreaterThanOrEqual()
209
-    {
210
-        return $this->greaterThanOrEqual;
211
-    }
212
-
213
-    /**
214
-     * @param $fieldNameAndPath
215
-     * @param $operand
216
-     * @return $this
217
-     */
218
-    public function greaterThanOrEqual($fieldNameAndPath, $operand)
219
-    {
220
-        $this->greaterThanOrEqual[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
221
-        return $this;
222
-    }
223
-
224
-    /**
225
-     * @return array
226
-     */
227
-    public function getLessThan()
228
-    {
229
-        return $this->lessThan;
230
-    }
231
-
232
-    /**
233
-     * @param $fieldNameAndPath
234
-     * @param $operand
235
-     * @return $this
236
-     */
237
-    public function lessThan($fieldNameAndPath, $operand)
238
-    {
239
-        $this->lessThan[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
240
-        return $this;
241
-    }
242
-
243
-    /**
244
-     * @return array
245
-     */
246
-    public function getLessThanOrEqual()
247
-    {
248
-        return $this->lessThanOrEqual;
249
-    }
250
-
251
-    /**
252
-     * @param $fieldNameAndPath
253
-     * @param $operand
254
-     * @return $this
255
-     */
256
-    public function lessThanOrEqual($fieldNameAndPath, $operand)
257
-    {
258
-        $this->lessThanOrEqual[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
259
-        return $this;
260
-    }
261
-
262
-    /**
263
-     * @return array
264
-     */
265
-    public function getLike()
266
-    {
267
-        return $this->like;
268
-    }
269
-
270
-    /**
271
-     * @param $fieldNameAndPath
272
-     * @param $operand
273
-     * @return $this
274
-     */
275
-    public function in($fieldNameAndPath, $operand)
276
-    {
277
-        $this->in[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
278
-        return $this;
279
-    }
280
-
281
-    /**
282
-     * @return array
283
-     */
284
-    public function getIn()
285
-    {
286
-        return $this->in;
287
-    }
288
-
289
-    /**
290
-     * @param $fieldNameAndPath
291
-     * @param $operand
292
-     * @param bool $addWildCard
293
-     * @return $this
294
-     */
295
-    public function like($fieldNameAndPath, $operand, $addWildCard = TRUE)
296
-    {
297
-        $wildCardSymbol = $addWildCard ? '%' : '';
298
-        $this->like[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $wildCardSymbol . $operand . $wildCardSymbol];
299
-        return $this;
300
-    }
301
-
302
-    /**
303
-     * @return array
304
-     */
305
-    public function getDefaultLogicalSeparator()
306
-    {
307
-        return $this->defaultLogicalSeparator;
308
-    }
309
-
310
-    /**
311
-     * @param string $defaultLogicalSeparator
312
-     * @return $this
313
-     */
314
-    public function setDefaultLogicalSeparator($defaultLogicalSeparator)
315
-    {
316
-        $this->defaultLogicalSeparator = $defaultLogicalSeparator;
317
-        return $this;
318
-    }
319
-
320
-    /**
321
-     * @return string
322
-     */
323
-    public function getLogicalSeparatorForEquals()
324
-    {
325
-        return $this->logicalSeparatorForEquals;
326
-    }
327
-
328
-    /**
329
-     * @param string $logicalSeparatorForEquals
330
-     * @return $this
331
-     */
332
-    public function setLogicalSeparatorForEquals($logicalSeparatorForEquals)
333
-    {
334
-        $this->logicalSeparatorForEquals = $logicalSeparatorForEquals;
335
-        return $this;
336
-    }
337
-
338
-    /**
339
-     * @return string
340
-     */
341
-    public function getLogicalSeparatorForGreaterThan()
342
-    {
343
-        return $this->logicalSeparatorForGreaterThan;
344
-    }
345
-
346
-    /**
347
-     * @param string $logicalSeparatorForGreaterThan
348
-     * @return $this
349
-     */
350
-    public function setLogicalSeparatorForGreaterThan($logicalSeparatorForGreaterThan)
351
-    {
352
-        $this->logicalSeparatorForGreaterThan = $logicalSeparatorForGreaterThan;
353
-        return $this;
354
-    }
355
-
356
-    /**
357
-     * @return string
358
-     */
359
-    public function getLogicalSeparatorForGreaterThanOrEqual()
360
-    {
361
-        return $this->logicalSeparatorForGreaterThanOrEqual;
362
-    }
363
-
364
-    /**
365
-     * @param string $logicalSeparatorForGreaterThanOrEqual
366
-     * @return $this
367
-     */
368
-    public function setLogicalSeparatorForGreaterThanOrEqual($logicalSeparatorForGreaterThanOrEqual)
369
-    {
370
-        $this->logicalSeparatorForGreaterThanOrEqual = $logicalSeparatorForGreaterThanOrEqual;
371
-        return $this;
372
-    }
373
-
374
-    /**
375
-     * @return string
376
-     */
377
-    public function getLogicalSeparatorForLessThan()
378
-    {
379
-        return $this->logicalSeparatorForLessThan;
380
-    }
381
-
382
-    /**
383
-     * @param string $logicalSeparatorForLessThan
384
-     * @return $this
385
-     */
386
-    public function setLogicalSeparatorForLessThan($logicalSeparatorForLessThan)
387
-    {
388
-        $this->logicalSeparatorForLessThan = $logicalSeparatorForLessThan;
389
-        return $this;
390
-    }
391
-
392
-    /**
393
-     * @return string
394
-     */
395
-    public function getLogicalSeparatorForLessThanOrEqual()
396
-    {
397
-        return $this->logicalSeparatorForLessThanOrEqual;
398
-    }
399
-
400
-    /**
401
-     * @param string $logicalSeparatorForLessThanOrEqual
402
-     * @return $this
403
-     */
404
-    public function setLogicalSeparatorForLessThanOrEqual($logicalSeparatorForLessThanOrEqual)
405
-    {
406
-        $this->logicalSeparatorForLessThanOrEqual = $logicalSeparatorForLessThanOrEqual;
407
-        return $this;
408
-    }
409
-
410
-    /**
411
-     * @return string
412
-     */
413
-    public function getLogicalSeparatorForIn()
414
-    {
415
-        return $this->logicalSeparatorForIn;
416
-    }
417
-
418
-    /**
419
-     * @param string $logicalSeparatorForIn
420
-     * @return $this
421
-     */
422
-    public function setLogicalSeparatorForIn($logicalSeparatorForIn)
423
-    {
424
-        $this->logicalSeparatorForIn = $logicalSeparatorForIn;
425
-        return $this;
426
-    }
427
-
428
-    /**
429
-     * @return string
430
-     */
431
-    public function getLogicalSeparatorForLike()
432
-    {
433
-        return $this->logicalSeparatorForLike;
434
-    }
435
-
436
-    /**
437
-     * @param string $logicalSeparatorForLike
438
-     * @return $this
439
-     */
440
-    public function setLogicalSeparatorForLike($logicalSeparatorForLike)
441
-    {
442
-        $this->logicalSeparatorForLike = $logicalSeparatorForLike;
443
-        return $this;
444
-    }
445
-
446
-    /**
447
-     * @return string
448
-     */
449
-    public function getLogicalSeparatorForSearchTerm()
450
-    {
451
-        return $this->logicalSeparatorForSearchTerm;
452
-    }
453
-
454
-    /**
455
-     * @param string $logicalSeparatorForSearchTerm
456
-     * @return $this
457
-     */
458
-    public function setLogicalSeparatorForSearchTerm($logicalSeparatorForSearchTerm)
459
-    {
460
-        $this->logicalSeparatorForSearchTerm = $logicalSeparatorForSearchTerm;
461
-        return $this;
462
-    }
463
-
464
-    /**
465
-     * @return array
466
-     */
467
-    public function getSupportedOperators()
468
-    {
469
-        return $this->supportedOperators;
470
-    }
471
-
472
-    /**
473
-     * @return string
474
-     */
475
-    public function getDataType()
476
-    {
477
-        return $this->dataType;
478
-    }
479
-
480
-    /**
481
-     * @param string $dataType
482
-     * @return $this
483
-     */
484
-    public function setDataType($dataType)
485
-    {
486
-        $this->dataType = $dataType;
487
-        return $this;
488
-    }
23
+	/**
24
+	 * The logical OR
25
+	 */
26
+	const LOGICAL_OR = 'logicalOr';
27
+
28
+	/**
29
+	 * The logical AND
30
+	 */
31
+	const LOGICAL_AND = 'logicalAnd';
32
+
33
+	/**
34
+	 * @var string
35
+	 */
36
+	protected $dataType = '';
37
+
38
+	/**
39
+	 * @var string
40
+	 */
41
+	protected $searchTerm = '';
42
+
43
+	/**
44
+	 * @var array
45
+	 */
46
+	protected $supportedOperators = [
47
+		'=' => 'equals',
48
+		'in' => 'in',
49
+		'like' => 'like',
50
+		'>' => 'greaterThan',
51
+		'>=' => 'greaterThanOrEqual',
52
+		'<' => 'lessThan',
53
+		'<=' => 'lessThanOrEqual'
54
+	];
55
+
56
+	/**
57
+	 * @var array
58
+	 */
59
+	protected $equals = [];
60
+
61
+	/**
62
+	 * @var array
63
+	 */
64
+	protected $greaterThan = [];
65
+
66
+	/**
67
+	 * @var array
68
+	 */
69
+	protected $greaterThanOrEqual = [];
70
+
71
+	/**
72
+	 * @var array
73
+	 */
74
+	protected $lessThan = [];
75
+
76
+	/**
77
+	 * @var array
78
+	 */
79
+	protected $lessThanOrEqual = [];
80
+
81
+	/**
82
+	 * @var array
83
+	 */
84
+	protected $in = [];
85
+
86
+	/**
87
+	 * @var array
88
+	 */
89
+	protected $like = [];
90
+
91
+	/**
92
+	 * @var string
93
+	 */
94
+	protected $defaultLogicalSeparator = self::LOGICAL_AND;
95
+
96
+	/**
97
+	 * @var string
98
+	 */
99
+	protected $logicalSeparatorForEquals = self::LOGICAL_AND;
100
+
101
+	/**
102
+	 * @var string
103
+	 */
104
+	protected $logicalSeparatorForGreaterThan = self::LOGICAL_AND;
105
+
106
+	/**
107
+	 * @var string
108
+	 */
109
+	protected $logicalSeparatorForGreaterThanOrEqual = self::LOGICAL_AND;
110
+
111
+	/**
112
+	 * @var string
113
+	 */
114
+	protected $logicalSeparatorForLessThan = self::LOGICAL_AND;
115
+
116
+	/**
117
+	 * @var string
118
+	 */
119
+	protected $logicalSeparatorForLessThanOrEqual = self::LOGICAL_AND;
120
+
121
+	/**
122
+	 * @var string
123
+	 */
124
+	protected $logicalSeparatorForIn = self::LOGICAL_AND;
125
+
126
+	/**
127
+	 * @var string
128
+	 */
129
+	protected $logicalSeparatorForLike = self::LOGICAL_AND;
130
+
131
+	/**
132
+	 * @var string
133
+	 */
134
+	protected $logicalSeparatorForSearchTerm = self::LOGICAL_OR;
135
+
136
+	/**
137
+	 * Constructs a new Matcher
138
+	 *
139
+	 * @param array $matches associative [$field => $value]
140
+	 * @param string $dataType which corresponds to an entry of the TCA (table name).
141
+	 * @return \Fab\Vidi\Persistence\Matcher
142
+	 */
143
+	public function __construct($matches = [], $dataType = '')
144
+	{
145
+		$this->dataType = $dataType;
146
+		$this->matches = $matches;
147
+	}
148
+
149
+	/**
150
+	 * @param string $searchTerm
151
+	 * @return \Fab\Vidi\Persistence\Matcher
152
+	 */
153
+	public function setSearchTerm($searchTerm)
154
+	{
155
+		$this->searchTerm = $searchTerm;
156
+		return $this;
157
+	}
158
+
159
+	/**
160
+	 * @return string
161
+	 */
162
+	public function getSearchTerm()
163
+	{
164
+		return $this->searchTerm;
165
+	}
166
+
167
+	/**
168
+	 * @return array
169
+	 */
170
+	public function getEquals()
171
+	{
172
+		return $this->equals;
173
+	}
174
+
175
+	/**
176
+	 * @param $fieldNameAndPath
177
+	 * @param $operand
178
+	 * @return $this
179
+	 */
180
+	public function equals($fieldNameAndPath, $operand)
181
+	{
182
+		$this->equals[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
183
+		return $this;
184
+	}
185
+
186
+	/**
187
+	 * @return array
188
+	 */
189
+	public function getGreaterThan()
190
+	{
191
+		return $this->greaterThan;
192
+	}
193
+
194
+	/**
195
+	 * @param $fieldNameAndPath
196
+	 * @param $operand
197
+	 * @return $this
198
+	 */
199
+	public function greaterThan($fieldNameAndPath, $operand)
200
+	{
201
+		$this->greaterThan[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
202
+		return $this;
203
+	}
204
+
205
+	/**
206
+	 * @return array
207
+	 */
208
+	public function getGreaterThanOrEqual()
209
+	{
210
+		return $this->greaterThanOrEqual;
211
+	}
212
+
213
+	/**
214
+	 * @param $fieldNameAndPath
215
+	 * @param $operand
216
+	 * @return $this
217
+	 */
218
+	public function greaterThanOrEqual($fieldNameAndPath, $operand)
219
+	{
220
+		$this->greaterThanOrEqual[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
221
+		return $this;
222
+	}
223
+
224
+	/**
225
+	 * @return array
226
+	 */
227
+	public function getLessThan()
228
+	{
229
+		return $this->lessThan;
230
+	}
231
+
232
+	/**
233
+	 * @param $fieldNameAndPath
234
+	 * @param $operand
235
+	 * @return $this
236
+	 */
237
+	public function lessThan($fieldNameAndPath, $operand)
238
+	{
239
+		$this->lessThan[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
240
+		return $this;
241
+	}
242
+
243
+	/**
244
+	 * @return array
245
+	 */
246
+	public function getLessThanOrEqual()
247
+	{
248
+		return $this->lessThanOrEqual;
249
+	}
250
+
251
+	/**
252
+	 * @param $fieldNameAndPath
253
+	 * @param $operand
254
+	 * @return $this
255
+	 */
256
+	public function lessThanOrEqual($fieldNameAndPath, $operand)
257
+	{
258
+		$this->lessThanOrEqual[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
259
+		return $this;
260
+	}
261
+
262
+	/**
263
+	 * @return array
264
+	 */
265
+	public function getLike()
266
+	{
267
+		return $this->like;
268
+	}
269
+
270
+	/**
271
+	 * @param $fieldNameAndPath
272
+	 * @param $operand
273
+	 * @return $this
274
+	 */
275
+	public function in($fieldNameAndPath, $operand)
276
+	{
277
+		$this->in[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
278
+		return $this;
279
+	}
280
+
281
+	/**
282
+	 * @return array
283
+	 */
284
+	public function getIn()
285
+	{
286
+		return $this->in;
287
+	}
288
+
289
+	/**
290
+	 * @param $fieldNameAndPath
291
+	 * @param $operand
292
+	 * @param bool $addWildCard
293
+	 * @return $this
294
+	 */
295
+	public function like($fieldNameAndPath, $operand, $addWildCard = TRUE)
296
+	{
297
+		$wildCardSymbol = $addWildCard ? '%' : '';
298
+		$this->like[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $wildCardSymbol . $operand . $wildCardSymbol];
299
+		return $this;
300
+	}
301
+
302
+	/**
303
+	 * @return array
304
+	 */
305
+	public function getDefaultLogicalSeparator()
306
+	{
307
+		return $this->defaultLogicalSeparator;
308
+	}
309
+
310
+	/**
311
+	 * @param string $defaultLogicalSeparator
312
+	 * @return $this
313
+	 */
314
+	public function setDefaultLogicalSeparator($defaultLogicalSeparator)
315
+	{
316
+		$this->defaultLogicalSeparator = $defaultLogicalSeparator;
317
+		return $this;
318
+	}
319
+
320
+	/**
321
+	 * @return string
322
+	 */
323
+	public function getLogicalSeparatorForEquals()
324
+	{
325
+		return $this->logicalSeparatorForEquals;
326
+	}
327
+
328
+	/**
329
+	 * @param string $logicalSeparatorForEquals
330
+	 * @return $this
331
+	 */
332
+	public function setLogicalSeparatorForEquals($logicalSeparatorForEquals)
333
+	{
334
+		$this->logicalSeparatorForEquals = $logicalSeparatorForEquals;
335
+		return $this;
336
+	}
337
+
338
+	/**
339
+	 * @return string
340
+	 */
341
+	public function getLogicalSeparatorForGreaterThan()
342
+	{
343
+		return $this->logicalSeparatorForGreaterThan;
344
+	}
345
+
346
+	/**
347
+	 * @param string $logicalSeparatorForGreaterThan
348
+	 * @return $this
349
+	 */
350
+	public function setLogicalSeparatorForGreaterThan($logicalSeparatorForGreaterThan)
351
+	{
352
+		$this->logicalSeparatorForGreaterThan = $logicalSeparatorForGreaterThan;
353
+		return $this;
354
+	}
355
+
356
+	/**
357
+	 * @return string
358
+	 */
359
+	public function getLogicalSeparatorForGreaterThanOrEqual()
360
+	{
361
+		return $this->logicalSeparatorForGreaterThanOrEqual;
362
+	}
363
+
364
+	/**
365
+	 * @param string $logicalSeparatorForGreaterThanOrEqual
366
+	 * @return $this
367
+	 */
368
+	public function setLogicalSeparatorForGreaterThanOrEqual($logicalSeparatorForGreaterThanOrEqual)
369
+	{
370
+		$this->logicalSeparatorForGreaterThanOrEqual = $logicalSeparatorForGreaterThanOrEqual;
371
+		return $this;
372
+	}
373
+
374
+	/**
375
+	 * @return string
376
+	 */
377
+	public function getLogicalSeparatorForLessThan()
378
+	{
379
+		return $this->logicalSeparatorForLessThan;
380
+	}
381
+
382
+	/**
383
+	 * @param string $logicalSeparatorForLessThan
384
+	 * @return $this
385
+	 */
386
+	public function setLogicalSeparatorForLessThan($logicalSeparatorForLessThan)
387
+	{
388
+		$this->logicalSeparatorForLessThan = $logicalSeparatorForLessThan;
389
+		return $this;
390
+	}
391
+
392
+	/**
393
+	 * @return string
394
+	 */
395
+	public function getLogicalSeparatorForLessThanOrEqual()
396
+	{
397
+		return $this->logicalSeparatorForLessThanOrEqual;
398
+	}
399
+
400
+	/**
401
+	 * @param string $logicalSeparatorForLessThanOrEqual
402
+	 * @return $this
403
+	 */
404
+	public function setLogicalSeparatorForLessThanOrEqual($logicalSeparatorForLessThanOrEqual)
405
+	{
406
+		$this->logicalSeparatorForLessThanOrEqual = $logicalSeparatorForLessThanOrEqual;
407
+		return $this;
408
+	}
409
+
410
+	/**
411
+	 * @return string
412
+	 */
413
+	public function getLogicalSeparatorForIn()
414
+	{
415
+		return $this->logicalSeparatorForIn;
416
+	}
417
+
418
+	/**
419
+	 * @param string $logicalSeparatorForIn
420
+	 * @return $this
421
+	 */
422
+	public function setLogicalSeparatorForIn($logicalSeparatorForIn)
423
+	{
424
+		$this->logicalSeparatorForIn = $logicalSeparatorForIn;
425
+		return $this;
426
+	}
427
+
428
+	/**
429
+	 * @return string
430
+	 */
431
+	public function getLogicalSeparatorForLike()
432
+	{
433
+		return $this->logicalSeparatorForLike;
434
+	}
435
+
436
+	/**
437
+	 * @param string $logicalSeparatorForLike
438
+	 * @return $this
439
+	 */
440
+	public function setLogicalSeparatorForLike($logicalSeparatorForLike)
441
+	{
442
+		$this->logicalSeparatorForLike = $logicalSeparatorForLike;
443
+		return $this;
444
+	}
445
+
446
+	/**
447
+	 * @return string
448
+	 */
449
+	public function getLogicalSeparatorForSearchTerm()
450
+	{
451
+		return $this->logicalSeparatorForSearchTerm;
452
+	}
453
+
454
+	/**
455
+	 * @param string $logicalSeparatorForSearchTerm
456
+	 * @return $this
457
+	 */
458
+	public function setLogicalSeparatorForSearchTerm($logicalSeparatorForSearchTerm)
459
+	{
460
+		$this->logicalSeparatorForSearchTerm = $logicalSeparatorForSearchTerm;
461
+		return $this;
462
+	}
463
+
464
+	/**
465
+	 * @return array
466
+	 */
467
+	public function getSupportedOperators()
468
+	{
469
+		return $this->supportedOperators;
470
+	}
471
+
472
+	/**
473
+	 * @return string
474
+	 */
475
+	public function getDataType()
476
+	{
477
+		return $this->dataType;
478
+	}
479
+
480
+	/**
481
+	 * @param string $dataType
482
+	 * @return $this
483
+	 */
484
+	public function setDataType($dataType)
485
+	{
486
+		$this->dataType = $dataType;
487
+		return $this;
488
+	}
489 489
 }
Please login to merge, or discard this patch.