Completed
Push — master ( 3efc81...a16fdb )
by Fabien
03:51
created
Classes/Domain/Repository/ContentRepository.php 2 patches
Doc Comments   +5 added lines, -4 removed lines patch added patch discarded remove patch
@@ -286,7 +286,7 @@  discard block
 block discarded – undo
286 286
      * Update a content with new information.
287 287
      *
288 288
      * @param Content $content
289
-     * @param $language
289
+     * @param integer $language
290 290
      * @return bool
291 291
      */
292 292
     public function localize($content, $language): bool
@@ -367,6 +367,7 @@  discard block
 block discarded – undo
367 367
      * Copy a content within this repository.
368 368
      *
369 369
      * @param Content $content
370
+     * @param string $target
370 371
      * @return bool
371 372
      */
372 373
     public function copy($content, $target): bool
@@ -518,7 +519,7 @@  discard block
 block discarded – undo
518 519
     /**
519 520
      * Sets the default query settings to be used in this repository
520 521
      *
521
-     * @param QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
522
+     * @param QuerySettings $defaultQuerySettings The query settings to be used by default
522 523
      * @return void
523 524
      * @api
524 525
      */
@@ -838,7 +839,7 @@  discard block
 block discarded – undo
838 839
     }
839 840
 
840 841
     /**
841
-     * @return ContentValidator|object
842
+     * @return ContentValidator
842 843
      */
843 844
     protected function getContentValidator(): ContentValidator
844 845
     {
@@ -846,7 +847,7 @@  discard block
 block discarded – undo
846 847
     }
847 848
 
848 849
     /**
849
-     * @return LanguageValidator|object
850
+     * @return LanguageValidator
850 851
      */
851 852
     protected function getLanguageValidator(): LanguageValidator
852 853
     {
Please login to merge, or discard this patch.
Indentation   +854 added lines, -854 removed lines patch added patch discarded remove patch
@@ -38,859 +38,859 @@
 block discarded – undo
38 38
 class ContentRepository implements RepositoryInterface
39 39
 {
40 40
 
41
-    /**
42
-     * Tell whether it is a raw result (array) or object being returned.
43
-     *
44
-     * @var bool
45
-     */
46
-    protected $rawResult = false;
47
-
48
-    /**
49
-     * The data type to be returned, e.g fe_users, fe_groups, tt_content, etc...
50
-     *
51
-     * @var string
52
-     */
53
-    protected $dataType;
54
-
55
-    /**
56
-     * The source field is useful in the context of MM relations to know who is the caller
57
-     * e.g findByItems which eventually corresponds to a field name.
58
-     *
59
-     * @var string
60
-     */
61
-    protected $sourceFieldName = '';
62
-
63
-    /**
64
-     * @var array
65
-     */
66
-    protected $errorMessages = [];
67
-
68
-    /**
69
-     * @var QuerySettingsInterface
70
-     */
71
-    protected $defaultQuerySettings;
72
-
73
-    /**
74
-     * @var DataHandler
75
-     */
76
-    protected $dataHandler;
77
-
78
-    /**
79
-     * Constructor
80
-     *
81
-     * @param string $dataType
82
-     */
83
-    public function __construct($dataType)
84
-    {
85
-        $this->dataType = $dataType;
86
-    }
87
-
88
-    /**
89
-     * Returns all objects of this repository.
90
-     *
91
-     * @return Content[]
92
-     */
93
-    public function findAll()
94
-    {
95
-        $query = $this->createQuery();
96
-        return $query->execute();
97
-    }
98
-
99
-    /**
100
-     * Returns all "distinct" values for a given property.
101
-     *
102
-     * @param string $propertyName
103
-     * @param Matcher $matcher
104
-     * @param Order|null $order
105
-     * @return Content[]
106
-     */
107
-    public function findDistinctValues($propertyName, Matcher $matcher = null, Order $order = null): array
108
-    {
109
-        $query = $this->createQuery();
110
-        $query->setDistinct($propertyName);
111
-
112
-        // Remove empty values from selection.
113
-        $constraint = $query->logicalNot($query->equals($propertyName, ''));
114
-
115
-        // Add some additional constraints from the Matcher object.
116
-        $matcherConstraint = null;
117
-        if ($matcher !== null) {
118
-            $matcherConstraint = $this->computeConstraints($query, $matcher);
119
-        }
120
-
121
-        // Assemble the final constraints or not.
122
-        if ($matcherConstraint) {
123
-            $query->logicalAnd($matcherConstraint, $constraint);
124
-            $query->matching($query->logicalAnd($matcherConstraint, $constraint));
125
-        } else {
126
-            $query->matching($constraint);
127
-        }
128
-
129
-        if ($order) {
130
-            $query->setOrderings($order->getOrderings());
131
-        }
132
-
133
-        return $query->execute();
134
-    }
135
-
136
-    /**
137
-     * Returns all "distinct" values for a given property.
138
-     *
139
-     * @param string $propertyName
140
-     * @param Matcher $matcher
141
-     * @return int
142
-     */
143
-    public function countDistinctValues($propertyName, Matcher $matcher = null): int
144
-    {
145
-        $query = $this->createQuery();
146
-        $query->setDistinct($propertyName);
147
-
148
-        // Remove empty values from selection.
149
-        $constraint = $query->logicalNot($query->equals($propertyName, ''));
150
-
151
-        // Add some additional constraints from the Matcher object.
152
-        $matcherConstraint = null;
153
-        if (!is_null($matcher)) {
154
-            $matcherConstraint = $this->computeConstraints($query, $matcher);
155
-        }
156
-
157
-        // Assemble the final constraints or not.
158
-        if ($matcherConstraint) {
159
-            $query->logicalAnd($matcherConstraint, $constraint);
160
-            $query->matching($query->logicalAnd($matcherConstraint, $constraint));
161
-        } else {
162
-            $query->matching($constraint);
163
-        }
164
-
165
-        return $query->count();
166
-    }
167
-
168
-    /**
169
-     * Finds an object matching the given identifier.
170
-     *
171
-     * @param int $uid The identifier of the object to find
172
-     * @return Content|null
173
-     * @api
174
-     */
175
-    public function findByUid($uid)
176
-    {
177
-        return $this->findByIdentifier($uid);
178
-    }
179
-
180
-    /**
181
-     * Finds all Contents given specified matches.
182
-     *
183
-     * @param string $propertyName
184
-     * @param array $values
185
-     * @return Content[]
186
-     */
187
-    public function findIn($propertyName, array $values): array
188
-    {
189
-        $query = $this->createQuery();
190
-        $query->matching($query->in($propertyName, $values));
191
-        return $query->execute();
192
-    }
193
-
194
-    /**
195
-     * Finds all Contents given specified matches.
196
-     *
197
-     * @param Matcher $matcher
198
-     * @param Order $order The order
199
-     * @param int $limit
200
-     * @param int $offset
201
-     * @return Content[]
202
-     */
203
-    public function findBy(Matcher $matcher, Order $order = null, $limit = null, $offset = null): array
204
-    {
205
-
206
-        $query = $this->createQuery();
207
-
208
-        $limit = (int)$limit; // make sure to cast
209
-        if ($limit > 0) {
210
-            $query->setLimit($limit);
211
-        }
212
-
213
-        if ($order) {
214
-            $query->setOrderings($order->getOrderings());
215
-
216
-            // Loops around the orderings adding if necessary a dummy condition
217
-            // to make sure the relations can be resolved when transforming the query to plain SQL.
218
-            foreach ($order->getOrderings() as $ordering => $direction) {
219
-                if ($this->hasForeignRelationIn($ordering)) {
220
-                    $relationalField = $this->getForeignRelationFrom($ordering);
221
-                    $matcher->like($relationalField . '.uid', '');
222
-                }
223
-            }
224
-        }
225
-
226
-        if ($offset) {
227
-            $query->setOffset($offset);
228
-        }
229
-
230
-        $constraints = $this->computeConstraints($query, $matcher);
231
-
232
-        if ($constraints) {
233
-            $query->matching($constraints);
234
-        }
235
-
236
-        return $query->execute();
237
-    }
238
-
239
-    /**
240
-     * Find one Content object given specified matches.
241
-     *
242
-     * @param Matcher $matcher
243
-     * @return Content
244
-     */
245
-    public function findOneBy(Matcher $matcher): Content
246
-    {
247
-
248
-        $query = $this->createQuery();
249
-
250
-        $constraints = $this->computeConstraints($query, $matcher);
251
-
252
-        if ($constraints) {
253
-            $query->matching($constraints);
254
-        }
255
-
256
-        $query->setLimit(1); // only take one!
257
-
258
-        $resultSet = $query->execute();
259
-        if ($resultSet) {
260
-            $resultSet = current($resultSet);
261
-        }
262
-        return $resultSet;
263
-    }
264
-
265
-    /**
266
-     * Count all Contents given specified matches.
267
-     *
268
-     * @param Matcher $matcher
269
-     * @return int
270
-     */
271
-    public function countBy(Matcher $matcher): int
272
-    {
273
-
274
-        $query = $this->createQuery();
275
-
276
-        $constraints = $this->computeConstraints($query, $matcher);
277
-
278
-        if ($constraints) {
279
-            $query->matching($constraints);
280
-        }
281
-
282
-        return $query->count();
283
-    }
284
-
285
-    /**
286
-     * Update a content with new information.
287
-     *
288
-     * @param Content $content
289
-     * @param $language
290
-     * @return bool
291
-     */
292
-    public function localize($content, $language): bool
293
-    {
294
-
295
-        // Security check
296
-        $this->getContentValidator()->validate($content);
297
-        $this->getLanguageValidator()->validate($language);
298
-
299
-        $dataType = $content->getDataType();
300
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::LOCALIZE)->forType($dataType)->getDataHandler();
301
-
302
-        $handlerResult = $handler->processLocalize($content, $language);
303
-        $this->errorMessages = $handler->getErrorMessages();
304
-        return $handlerResult;
305
-    }
306
-
307
-    /**
308
-     * Update a content with new information.
309
-     *
310
-     * @param Content $content
311
-     * @return bool
312
-     */
313
-    public function update($content)
314
-    {
315
-
316
-        // Security check.
317
-        $this->getContentValidator()->validate($content);
318
-
319
-        $dataType = $content->getDataType();
320
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::UPDATE)->forType($dataType)->getDataHandler();
321
-
322
-        $handlerResult = $handler->processUpdate($content);
323
-        $this->errorMessages = $handler->getErrorMessages();
324
-        return $handlerResult;
325
-    }
326
-
327
-    /**
328
-     * Removes an object from this repository.
329
-     *
330
-     * @param Content $content
331
-     * @return boolean
332
-     */
333
-    public function remove($content)
334
-    {
335
-        $dataType = $content->getDataType();
336
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::REMOVE)->forType($dataType)->getDataHandler();
337
-
338
-        $handlerResult = $handler->processRemove($content);
339
-        $this->errorMessages = $handler->getErrorMessages();
340
-        return $handlerResult;
341
-    }
342
-
343
-    /**
344
-     * Move a content within this repository.
345
-     * The $target corresponds to the pid to move the records to.
346
-     * It can also be a negative value in case of sorting. The negative value would be the uid of its predecessor.
347
-     *
348
-     * @param Content $content
349
-     * @param string $target
350
-     * @return bool
351
-     */
352
-    public function move($content, $target): bool
353
-    {
354
-
355
-        // Security check.
356
-        $this->getContentValidator()->validate($content);
357
-
358
-        $dataType = $content->getDataType();
359
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::MOVE)->forType($dataType)->getDataHandler();
360
-
361
-        $handlerResult = $handler->processMove($content, $target);
362
-        $this->errorMessages = $handler->getErrorMessages();
363
-        return $handlerResult;
364
-    }
365
-
366
-    /**
367
-     * Copy a content within this repository.
368
-     *
369
-     * @param Content $content
370
-     * @return bool
371
-     */
372
-    public function copy($content, $target): bool
373
-    {
374
-
375
-        // Security check.
376
-        $this->getContentValidator()->validate($content);
377
-
378
-        $dataType = $content->getDataType();
379
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::COPY)->forType($dataType)->getDataHandler();
380
-
381
-        $handlerResult = $handler->processCopy($content, $target);
382
-        $this->errorMessages = $handler->getErrorMessages();
383
-        return $handlerResult;
384
-    }
385
-
386
-    /**
387
-     * Adds an object to this repository.
388
-     *
389
-     * @param object $object The object to add
390
-     * @return void
391
-     * @api
392
-     */
393
-    public function add($object)
394
-    {
395
-        throw new \BadMethodCallException('Repository does not support the add() method.', 1375805599);
396
-    }
397
-
398
-    /**
399
-     * Returns the total number objects of this repository.
400
-     *
401
-     * @return integer The object count
402
-     * @api
403
-     */
404
-    public function countAll()
405
-    {
406
-        $query = $this->createQuery();
407
-        return $query->count();
408
-    }
409
-
410
-    /**
411
-     * Removes all objects of this repository as if remove() was called for
412
-     * all of them.
413
-     *
414
-     * @return void
415
-     * @api
416
-     */
417
-    public function removeAll()
418
-    {
419
-        // TODO: Implement removeAll() method.
420
-    }
421
-
422
-    /**
423
-     * Finds an object matching the given identifier.
424
-     *
425
-     * @param mixed $identifier The identifier of the object to find
426
-     * @return Content|null
427
-     * @api
428
-     */
429
-    public function findByIdentifier($identifier)
430
-    {
431
-        $query = $this->createQuery();
432
-
433
-        $result = $query->matching(
434
-            $query->equals('uid', $identifier)
435
-        )
436
-            ->execute();
437
-
438
-        if (is_array($result)) {
439
-            $result = current($result);
440
-        }
441
-
442
-        return $result;
443
-    }
444
-
445
-    /**
446
-     * Dispatches magic methods (findBy[Property]())
447
-     *
448
-     * @param string $methodName The name of the magic method
449
-     * @param string $arguments The arguments of the magic method
450
-     * @return mixed
451
-     * @api
452
-     */
453
-    public function __call($methodName, $arguments)
454
-    {
455
-        if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
456
-            $propertyName = strtolower(substr(substr($methodName, 6), 0, 1)) . substr(substr($methodName, 6), 1);
457
-            $result = $this->processMagicCall($propertyName, $arguments[0]);
458
-        } elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
459
-            $propertyName = strtolower(substr(substr($methodName, 9), 0, 1)) . substr(substr($methodName, 9), 1);
460
-            $result = $this->processMagicCall($propertyName, $arguments[0], 'one');
461
-        } elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
462
-            $propertyName = strtolower(substr(substr($methodName, 7), 0, 1)) . substr(substr($methodName, 7), 1);
463
-            $result = $this->processMagicCall($propertyName, $arguments[0], 'count');
464
-        } else {
465
-            throw new UnsupportedMethodException('The method "' . $methodName . '" is not supported by the repository.', 1360838010);
466
-        }
467
-        return $result;
468
-    }
469
-
470
-    /**
471
-     * Returns a query for objects of this repository
472
-     *
473
-     * @return Query
474
-     * @api
475
-     */
476
-    public function createQuery()
477
-    {
478
-        /** @var Query $query */
479
-        $query = $this->getObjectManager()->get(Query::class, $this->dataType);
480
-        $query->setSourceFieldName($this->sourceFieldName);
481
-
482
-        if ($this->defaultQuerySettings) {
483
-            $query->setQuerySettings($this->defaultQuerySettings);
484
-        } else {
485
-
486
-            // Initialize and pass the query settings at this level.
487
-            /** @var QuerySettings $querySettings */
488
-            $querySettings = $this->getObjectManager()->get(QuerySettings::class);
489
-
490
-            // Default choice for the BE.
491
-            if ($this->isBackendMode()) {
492
-                $querySettings->setIgnoreEnableFields(true);
493
-            }
494
-
495
-            $query->setQuerySettings($querySettings);
496
-        }
497
-
498
-        return $query;
499
-    }
500
-
501
-    /**
502
-     * Sets the property names to order the result by per default.
503
-     * Expected like this:
504
-     * array(
505
-     * 'foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
506
-     * 'bar' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
507
-     * )
508
-     *
509
-     * @param array $defaultOrderings The property names to order by
510
-     * @return void
511
-     * @api
512
-     */
513
-    public function setDefaultOrderings(array $defaultOrderings)
514
-    {
515
-        throw new \BadMethodCallException('Repository does not support the setDefaultOrderings() method.', 1375805598);
516
-    }
517
-
518
-    /**
519
-     * Sets the default query settings to be used in this repository
520
-     *
521
-     * @param QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
522
-     * @return void
523
-     * @api
524
-     */
525
-    public function setDefaultQuerySettings(QuerySettingsInterface $defaultQuerySettings)
526
-    {
527
-        $this->defaultQuerySettings = $defaultQuerySettings;
528
-    }
529
-
530
-    /**
531
-     * @return void
532
-     */
533
-    public function resetDefaultQuerySettings(): void
534
-    {
535
-        $this->defaultQuerySettings = null;
536
-    }
537
-
538
-
539
-    /**
540
-     * @return array
541
-     */
542
-    public function getErrorMessages(): array
543
-    {
544
-        return $this->errorMessages;
545
-    }
546
-
547
-    /**
548
-     * @param string $sourceFieldName
549
-     * @return $this
550
-     */
551
-    public function setSourceFieldName($sourceFieldName): self
552
-    {
553
-        $this->sourceFieldName = $sourceFieldName;
554
-        return $this;
555
-    }
556
-
557
-    /**
558
-     * @return string
559
-     */
560
-    public function getDataType(): string
561
-    {
562
-        return $this->dataType;
563
-    }
564
-
565
-    /**
566
-     * Tell whether the order has a foreign table in its expression, e.g. "metadata.title".
567
-     *
568
-     * @param string $ordering
569
-     * @return bool
570
-     */
571
-    protected function hasForeignRelationIn($ordering): bool
572
-    {
573
-        return strpos($ordering, '.') !== false;
574
-    }
575
-
576
-    /**
577
-     * Extract the foreign relation of the ordering "metadata.title" -> "metadata"
578
-     *
579
-     * @param string $ordering
580
-     * @return string
581
-     */
582
-    protected function getForeignRelationFrom($ordering): string
583
-    {
584
-        $parts = explode('.', $ordering);
585
-        return $parts[0];
586
-    }
587
-
588
-    /**
589
-     * Get the constraints
590
-     *
591
-     * @param Query $query
592
-     * @param Matcher $matcher
593
-     * @return ConstraintInterface|null
594
-     */
595
-    protected function computeConstraints(Query $query, Matcher $matcher): ?ConstraintInterface
596
-    {
597
-        $constraints = null;
598
-
599
-        $collectedConstraints = [];
600
-
601
-        // Search term
602
-        $constraint = $this->computeSearchTermConstraint($query, $matcher);
603
-        if ($constraint) {
604
-            $collectedConstraints[] = $constraint;
605
-        }
606
-
607
-        foreach ($matcher->getSupportedOperators() as $operator) {
608
-            $constraint = $this->computeConstraint($query, $matcher, $operator);
609
-            if ($constraint) {
610
-                $collectedConstraints[] = $constraint;
611
-            }
612
-        }
613
-
614
-        if (count($collectedConstraints) > 1) {
615
-            $logical = $matcher->getDefaultLogicalSeparator();
616
-            $constraints = $query->$logical($collectedConstraints);
617
-        } elseif (!empty($collectedConstraints)) {
618
-
619
-            // true means there is one constraint only and should become the result
620
-            $constraints = current($collectedConstraints);
621
-        }
622
-
623
-        // Trigger signal for post processing the computed constraints object.
624
-        $constraints = $this->emitPostProcessConstraintsSignal($query, $constraints);
625
-
626
-        return $constraints;
627
-    }
628
-
629
-    /**
630
-     * Computes the search constraint and returns it.
631
-     *
632
-     * @param Query $query
633
-     * @param Matcher $matcher
634
-     * @return ConstraintInterface|null
635
-     */
636
-    protected function computeSearchTermConstraint(Query $query, Matcher $matcher): ?ConstraintInterface
637
-    {
638
-
639
-        $result = null;
640
-
641
-        // Search term case
642
-        if ($matcher->getSearchTerm()) {
643
-
644
-            $fields = GeneralUtility::trimExplode(',', Tca::table($this->dataType)->getSearchFields(), true);
645
-
646
-            $constraints = [];
647
-            $likeClause = sprintf('%%%s%%', $matcher->getSearchTerm());
648
-            foreach ($fields as $fieldNameAndPath) {
649
-                if ($this->isSuitableForLike($fieldNameAndPath, $matcher->getSearchTerm())) {
650
-
651
-                    $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
652
-                    $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
653
-
654
-                    if (Tca::table($dataType)->hasField($fieldName) && Tca::table($dataType)->field($fieldName)->hasRelation()) {
655
-                        $foreignTable = Tca::table($dataType)->field($fieldName)->getForeignTable();
656
-                        $fieldNameAndPath = $fieldNameAndPath . '.' . Tca::table($foreignTable)->getLabelField();
657
-                    }
658
-                    $constraints[] = $query->like($fieldNameAndPath, $likeClause);
659
-                }
660
-            }
661
-            $logical = $matcher->getLogicalSeparatorForSearchTerm();
662
-            $result = $query->$logical($constraints);
663
-        }
664
-
665
-        return $result;
666
-    }
667
-
668
-    /**
669
-     * It does not make sense to have a "like" in presence of numerical field, e.g "uid".
670
-     * Tell whether the given value makes sense for a "like" clause.
671
-     *
672
-     * @param string $fieldNameAndPath
673
-     * @param string $value
674
-     * @return bool
675
-     */
676
-    protected function isSuitableForLike($fieldNameAndPath, $value): bool
677
-    {
678
-        $isSuitable = true;
679
-
680
-        // true means it is a string
681
-        if (!MathUtility::canBeInterpretedAsInteger($value)) {
682
-
683
-            $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
684
-            $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
685
-
686
-            if (Tca::table($dataType)->field($fieldName)->isNumerical()
687
-                && !Tca::table($dataType)->field($fieldName)->hasRelation()
688
-            ) {
689
-                $isSuitable = false;
690
-            }
691
-        }
692
-
693
-        return $isSuitable;
694
-    }
695
-
696
-    /**
697
-     * Computes the constraint for matches and returns it.
698
-     *
699
-     * @param Query $query
700
-     * @param Matcher $matcher
701
-     * @param string $operator
702
-     * @return ConstraintInterface|null
703
-     */
704
-    protected function computeConstraint(Query $query, Matcher $matcher, $operator): ?ConstraintInterface
705
-    {
706
-        $result = null;
707
-
708
-        $operatorName = ucfirst($operator);
709
-        $getCriteria = sprintf('get%s', $operatorName);
710
-        $criteria = $matcher->$getCriteria();
711
-
712
-        if (!empty($criteria)) {
713
-            $constraints = [];
714
-
715
-            foreach ($criteria as $criterion) {
716
-
717
-                $fieldNameAndPath = $criterion['fieldNameAndPath'];
718
-                $operand = $criterion['operand'];
719
-
720
-                // Compute a few variables...
721
-                // $dataType is generally equals to $this->dataType but not always... if fieldName is a path.
722
-                $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
723
-                $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
724
-                $fieldPath = $this->getFieldPathResolver()->stripFieldName($fieldNameAndPath, $this->dataType);
725
-
726
-                if (Tca::table($dataType)->field($fieldName)->hasRelation()) {
727
-                    if (MathUtility::canBeInterpretedAsInteger($operand)) {
728
-                        $fieldNameAndPath = $fieldName . '.uid';
729
-                    } else {
730
-                        $foreignTableName = Tca::table($dataType)->field($fieldName)->getForeignTable();
731
-                        $foreignTable = Tca::table($foreignTableName);
732
-                        $fieldNameAndPath = $fieldName . '.' . $foreignTable->getLabelField();
733
-                    }
734
-
735
-                    // If different means we should restore the prepended path segment for proper SQL parser.
736
-                    // This is true for a composite field, e.g items.sys_file_metadata for categories.
737
-                    if ($fieldName !== $fieldPath) {
738
-                        $fieldNameAndPath = $fieldPath . '.' . $fieldNameAndPath;
739
-                    }
740
-                }
741
-
742
-                if (strpos($operator, 'not') === 0) {
743
-                    $strippedOperator = strtolower(substr($operator, 3));
744
-                    $constraints[] = $query->logicalNot($query->$strippedOperator($fieldNameAndPath, $criterion['operand']));
745
-                } else {
746
-                    $constraints[] = $query->$operator($fieldNameAndPath, $criterion['operand']);
747
-                }
748
-            }
749
-
750
-            $getLogicalSeparator = sprintf('getLogicalSeparatorFor%s', $operatorName);
751
-            $logical = method_exists($matcher, $getLogicalSeparator)
752
-                ? $matcher->$getLogicalSeparator()
753
-                : $matcher->getDefaultLogicalSeparator();
754
-
755
-            $result = $query->$logical($constraints);
756
-        }
757
-
758
-        return $result;
759
-    }
760
-
761
-    /**
762
-     * @return DataHandler
763
-     */
764
-    protected function getDataHandler(): DataHandler
765
-    {
766
-        if (!$this->dataHandler) {
767
-            $this->dataHandler = GeneralUtility::makeInstance(DataHandler::class);
768
-        }
769
-        return $this->dataHandler;
770
-    }
771
-
772
-    /**
773
-     * Handle the magic call by properly creating a Query object and returning its result.
774
-     *
775
-     * @param string $propertyName
776
-     * @param string $value
777
-     * @param string $flag
778
-     * @return array
779
-     */
780
-    protected function processMagicCall($propertyName, $value, $flag = ''): array
781
-    {
782
-
783
-        $fieldName = Property::name($propertyName)->of($this->dataType)->toFieldName();
784
-
785
-        /** @var $matcher Matcher */
786
-        $matcher = GeneralUtility::makeInstance(Matcher::class, [], $this->getDataType());
787
-
788
-        $table = Tca::table($this->dataType);
789
-        if ($table->field($fieldName)->isGroup()) {
790
-
791
-            $valueParts = explode('.', $value, 2);
792
-            $fieldName = $fieldName . '.' . $valueParts[0];
793
-            $value = $valueParts[1];
794
-        }
795
-
796
-        $matcher->equals($fieldName, $value);
797
-
798
-        if ($flag === 'count') {
799
-            $result = $this->countBy($matcher);
800
-        } else {
801
-            $result = $this->findBy($matcher);
802
-        }
803
-        return $flag === 'one' && !empty($result) ? reset($result) : $result;
804
-    }
805
-
806
-    /**
807
-     * @return DataHandlerFactory|object
808
-     */
809
-    protected function getDataHandlerFactory()
810
-    {
811
-        return GeneralUtility::makeInstance(DataHandlerFactory::class);
812
-    }
813
-
814
-    /**
815
-     * Returns whether the current mode is Backend
816
-     *
817
-     * @return bool
818
-     */
819
-    protected function isBackendMode(): bool
820
-    {
821
-        return TYPO3_MODE === 'BE';
822
-    }
823
-
824
-    /**
825
-     * @return FieldPathResolver|object
826
-     */
827
-    protected function getFieldPathResolver()
828
-    {
829
-        return GeneralUtility::makeInstance(FieldPathResolver::class);
830
-    }
831
-
832
-    /**
833
-     * @return ObjectManager|object
834
-     */
835
-    protected function getObjectManager(): ObjectManager
836
-    {
837
-        return GeneralUtility::makeInstance(ObjectManager::class);
838
-    }
839
-
840
-    /**
841
-     * @return ContentValidator|object
842
-     */
843
-    protected function getContentValidator(): ContentValidator
844
-    {
845
-        return GeneralUtility::makeInstance(ContentValidator::class);
846
-    }
847
-
848
-    /**
849
-     * @return LanguageValidator|object
850
-     */
851
-    protected function getLanguageValidator(): LanguageValidator
852
-    {
853
-        return GeneralUtility::makeInstance(LanguageValidator::class);
854
-    }
855
-
856
-    /**
857
-     * Signal that is called for post-processing the computed constraints object.
858
-     *
859
-     * @param Query $query
860
-     * @param ConstraintInterface|null $constraints
861
-     * @return ConstraintInterface|null $constraints
862
-     * @signal
863
-     */
864
-    protected function emitPostProcessConstraintsSignal(Query $query, $constraints): ?ConstraintInterface
865
-    {
866
-        /** @var ConstraintContainer $constraintContainer */
867
-        $constraintContainer = GeneralUtility::makeInstance(ConstraintContainer::class);
868
-        $result = $this->getSignalSlotDispatcher()->dispatch(
869
-            self::class,
870
-            'postProcessConstraintsObject',
871
-            [
872
-                $query,
873
-                $constraints,
874
-                $constraintContainer
875
-            ]
876
-        );
877
-
878
-        // Backward compatibility.
879
-        $processedConstraints = $result[1];
880
-
881
-        // New way to transmit the constraints.
882
-        if ($constraintContainer->getConstraint()) {
883
-            $processedConstraints = $constraintContainer->getConstraint();
884
-        }
885
-        return $processedConstraints;
886
-    }
887
-
888
-    /**
889
-     * @return Dispatcher
890
-     */
891
-    protected function getSignalSlotDispatcher(): Dispatcher
892
-    {
893
-        return $this->getObjectManager()->get(Dispatcher::class);
894
-    }
41
+	/**
42
+	 * Tell whether it is a raw result (array) or object being returned.
43
+	 *
44
+	 * @var bool
45
+	 */
46
+	protected $rawResult = false;
47
+
48
+	/**
49
+	 * The data type to be returned, e.g fe_users, fe_groups, tt_content, etc...
50
+	 *
51
+	 * @var string
52
+	 */
53
+	protected $dataType;
54
+
55
+	/**
56
+	 * The source field is useful in the context of MM relations to know who is the caller
57
+	 * e.g findByItems which eventually corresponds to a field name.
58
+	 *
59
+	 * @var string
60
+	 */
61
+	protected $sourceFieldName = '';
62
+
63
+	/**
64
+	 * @var array
65
+	 */
66
+	protected $errorMessages = [];
67
+
68
+	/**
69
+	 * @var QuerySettingsInterface
70
+	 */
71
+	protected $defaultQuerySettings;
72
+
73
+	/**
74
+	 * @var DataHandler
75
+	 */
76
+	protected $dataHandler;
77
+
78
+	/**
79
+	 * Constructor
80
+	 *
81
+	 * @param string $dataType
82
+	 */
83
+	public function __construct($dataType)
84
+	{
85
+		$this->dataType = $dataType;
86
+	}
87
+
88
+	/**
89
+	 * Returns all objects of this repository.
90
+	 *
91
+	 * @return Content[]
92
+	 */
93
+	public function findAll()
94
+	{
95
+		$query = $this->createQuery();
96
+		return $query->execute();
97
+	}
98
+
99
+	/**
100
+	 * Returns all "distinct" values for a given property.
101
+	 *
102
+	 * @param string $propertyName
103
+	 * @param Matcher $matcher
104
+	 * @param Order|null $order
105
+	 * @return Content[]
106
+	 */
107
+	public function findDistinctValues($propertyName, Matcher $matcher = null, Order $order = null): array
108
+	{
109
+		$query = $this->createQuery();
110
+		$query->setDistinct($propertyName);
111
+
112
+		// Remove empty values from selection.
113
+		$constraint = $query->logicalNot($query->equals($propertyName, ''));
114
+
115
+		// Add some additional constraints from the Matcher object.
116
+		$matcherConstraint = null;
117
+		if ($matcher !== null) {
118
+			$matcherConstraint = $this->computeConstraints($query, $matcher);
119
+		}
120
+
121
+		// Assemble the final constraints or not.
122
+		if ($matcherConstraint) {
123
+			$query->logicalAnd($matcherConstraint, $constraint);
124
+			$query->matching($query->logicalAnd($matcherConstraint, $constraint));
125
+		} else {
126
+			$query->matching($constraint);
127
+		}
128
+
129
+		if ($order) {
130
+			$query->setOrderings($order->getOrderings());
131
+		}
132
+
133
+		return $query->execute();
134
+	}
135
+
136
+	/**
137
+	 * Returns all "distinct" values for a given property.
138
+	 *
139
+	 * @param string $propertyName
140
+	 * @param Matcher $matcher
141
+	 * @return int
142
+	 */
143
+	public function countDistinctValues($propertyName, Matcher $matcher = null): int
144
+	{
145
+		$query = $this->createQuery();
146
+		$query->setDistinct($propertyName);
147
+
148
+		// Remove empty values from selection.
149
+		$constraint = $query->logicalNot($query->equals($propertyName, ''));
150
+
151
+		// Add some additional constraints from the Matcher object.
152
+		$matcherConstraint = null;
153
+		if (!is_null($matcher)) {
154
+			$matcherConstraint = $this->computeConstraints($query, $matcher);
155
+		}
156
+
157
+		// Assemble the final constraints or not.
158
+		if ($matcherConstraint) {
159
+			$query->logicalAnd($matcherConstraint, $constraint);
160
+			$query->matching($query->logicalAnd($matcherConstraint, $constraint));
161
+		} else {
162
+			$query->matching($constraint);
163
+		}
164
+
165
+		return $query->count();
166
+	}
167
+
168
+	/**
169
+	 * Finds an object matching the given identifier.
170
+	 *
171
+	 * @param int $uid The identifier of the object to find
172
+	 * @return Content|null
173
+	 * @api
174
+	 */
175
+	public function findByUid($uid)
176
+	{
177
+		return $this->findByIdentifier($uid);
178
+	}
179
+
180
+	/**
181
+	 * Finds all Contents given specified matches.
182
+	 *
183
+	 * @param string $propertyName
184
+	 * @param array $values
185
+	 * @return Content[]
186
+	 */
187
+	public function findIn($propertyName, array $values): array
188
+	{
189
+		$query = $this->createQuery();
190
+		$query->matching($query->in($propertyName, $values));
191
+		return $query->execute();
192
+	}
193
+
194
+	/**
195
+	 * Finds all Contents given specified matches.
196
+	 *
197
+	 * @param Matcher $matcher
198
+	 * @param Order $order The order
199
+	 * @param int $limit
200
+	 * @param int $offset
201
+	 * @return Content[]
202
+	 */
203
+	public function findBy(Matcher $matcher, Order $order = null, $limit = null, $offset = null): array
204
+	{
205
+
206
+		$query = $this->createQuery();
207
+
208
+		$limit = (int)$limit; // make sure to cast
209
+		if ($limit > 0) {
210
+			$query->setLimit($limit);
211
+		}
212
+
213
+		if ($order) {
214
+			$query->setOrderings($order->getOrderings());
215
+
216
+			// Loops around the orderings adding if necessary a dummy condition
217
+			// to make sure the relations can be resolved when transforming the query to plain SQL.
218
+			foreach ($order->getOrderings() as $ordering => $direction) {
219
+				if ($this->hasForeignRelationIn($ordering)) {
220
+					$relationalField = $this->getForeignRelationFrom($ordering);
221
+					$matcher->like($relationalField . '.uid', '');
222
+				}
223
+			}
224
+		}
225
+
226
+		if ($offset) {
227
+			$query->setOffset($offset);
228
+		}
229
+
230
+		$constraints = $this->computeConstraints($query, $matcher);
231
+
232
+		if ($constraints) {
233
+			$query->matching($constraints);
234
+		}
235
+
236
+		return $query->execute();
237
+	}
238
+
239
+	/**
240
+	 * Find one Content object given specified matches.
241
+	 *
242
+	 * @param Matcher $matcher
243
+	 * @return Content
244
+	 */
245
+	public function findOneBy(Matcher $matcher): Content
246
+	{
247
+
248
+		$query = $this->createQuery();
249
+
250
+		$constraints = $this->computeConstraints($query, $matcher);
251
+
252
+		if ($constraints) {
253
+			$query->matching($constraints);
254
+		}
255
+
256
+		$query->setLimit(1); // only take one!
257
+
258
+		$resultSet = $query->execute();
259
+		if ($resultSet) {
260
+			$resultSet = current($resultSet);
261
+		}
262
+		return $resultSet;
263
+	}
264
+
265
+	/**
266
+	 * Count all Contents given specified matches.
267
+	 *
268
+	 * @param Matcher $matcher
269
+	 * @return int
270
+	 */
271
+	public function countBy(Matcher $matcher): int
272
+	{
273
+
274
+		$query = $this->createQuery();
275
+
276
+		$constraints = $this->computeConstraints($query, $matcher);
277
+
278
+		if ($constraints) {
279
+			$query->matching($constraints);
280
+		}
281
+
282
+		return $query->count();
283
+	}
284
+
285
+	/**
286
+	 * Update a content with new information.
287
+	 *
288
+	 * @param Content $content
289
+	 * @param $language
290
+	 * @return bool
291
+	 */
292
+	public function localize($content, $language): bool
293
+	{
294
+
295
+		// Security check
296
+		$this->getContentValidator()->validate($content);
297
+		$this->getLanguageValidator()->validate($language);
298
+
299
+		$dataType = $content->getDataType();
300
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::LOCALIZE)->forType($dataType)->getDataHandler();
301
+
302
+		$handlerResult = $handler->processLocalize($content, $language);
303
+		$this->errorMessages = $handler->getErrorMessages();
304
+		return $handlerResult;
305
+	}
306
+
307
+	/**
308
+	 * Update a content with new information.
309
+	 *
310
+	 * @param Content $content
311
+	 * @return bool
312
+	 */
313
+	public function update($content)
314
+	{
315
+
316
+		// Security check.
317
+		$this->getContentValidator()->validate($content);
318
+
319
+		$dataType = $content->getDataType();
320
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::UPDATE)->forType($dataType)->getDataHandler();
321
+
322
+		$handlerResult = $handler->processUpdate($content);
323
+		$this->errorMessages = $handler->getErrorMessages();
324
+		return $handlerResult;
325
+	}
326
+
327
+	/**
328
+	 * Removes an object from this repository.
329
+	 *
330
+	 * @param Content $content
331
+	 * @return boolean
332
+	 */
333
+	public function remove($content)
334
+	{
335
+		$dataType = $content->getDataType();
336
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::REMOVE)->forType($dataType)->getDataHandler();
337
+
338
+		$handlerResult = $handler->processRemove($content);
339
+		$this->errorMessages = $handler->getErrorMessages();
340
+		return $handlerResult;
341
+	}
342
+
343
+	/**
344
+	 * Move a content within this repository.
345
+	 * The $target corresponds to the pid to move the records to.
346
+	 * It can also be a negative value in case of sorting. The negative value would be the uid of its predecessor.
347
+	 *
348
+	 * @param Content $content
349
+	 * @param string $target
350
+	 * @return bool
351
+	 */
352
+	public function move($content, $target): bool
353
+	{
354
+
355
+		// Security check.
356
+		$this->getContentValidator()->validate($content);
357
+
358
+		$dataType = $content->getDataType();
359
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::MOVE)->forType($dataType)->getDataHandler();
360
+
361
+		$handlerResult = $handler->processMove($content, $target);
362
+		$this->errorMessages = $handler->getErrorMessages();
363
+		return $handlerResult;
364
+	}
365
+
366
+	/**
367
+	 * Copy a content within this repository.
368
+	 *
369
+	 * @param Content $content
370
+	 * @return bool
371
+	 */
372
+	public function copy($content, $target): bool
373
+	{
374
+
375
+		// Security check.
376
+		$this->getContentValidator()->validate($content);
377
+
378
+		$dataType = $content->getDataType();
379
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::COPY)->forType($dataType)->getDataHandler();
380
+
381
+		$handlerResult = $handler->processCopy($content, $target);
382
+		$this->errorMessages = $handler->getErrorMessages();
383
+		return $handlerResult;
384
+	}
385
+
386
+	/**
387
+	 * Adds an object to this repository.
388
+	 *
389
+	 * @param object $object The object to add
390
+	 * @return void
391
+	 * @api
392
+	 */
393
+	public function add($object)
394
+	{
395
+		throw new \BadMethodCallException('Repository does not support the add() method.', 1375805599);
396
+	}
397
+
398
+	/**
399
+	 * Returns the total number objects of this repository.
400
+	 *
401
+	 * @return integer The object count
402
+	 * @api
403
+	 */
404
+	public function countAll()
405
+	{
406
+		$query = $this->createQuery();
407
+		return $query->count();
408
+	}
409
+
410
+	/**
411
+	 * Removes all objects of this repository as if remove() was called for
412
+	 * all of them.
413
+	 *
414
+	 * @return void
415
+	 * @api
416
+	 */
417
+	public function removeAll()
418
+	{
419
+		// TODO: Implement removeAll() method.
420
+	}
421
+
422
+	/**
423
+	 * Finds an object matching the given identifier.
424
+	 *
425
+	 * @param mixed $identifier The identifier of the object to find
426
+	 * @return Content|null
427
+	 * @api
428
+	 */
429
+	public function findByIdentifier($identifier)
430
+	{
431
+		$query = $this->createQuery();
432
+
433
+		$result = $query->matching(
434
+			$query->equals('uid', $identifier)
435
+		)
436
+			->execute();
437
+
438
+		if (is_array($result)) {
439
+			$result = current($result);
440
+		}
441
+
442
+		return $result;
443
+	}
444
+
445
+	/**
446
+	 * Dispatches magic methods (findBy[Property]())
447
+	 *
448
+	 * @param string $methodName The name of the magic method
449
+	 * @param string $arguments The arguments of the magic method
450
+	 * @return mixed
451
+	 * @api
452
+	 */
453
+	public function __call($methodName, $arguments)
454
+	{
455
+		if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
456
+			$propertyName = strtolower(substr(substr($methodName, 6), 0, 1)) . substr(substr($methodName, 6), 1);
457
+			$result = $this->processMagicCall($propertyName, $arguments[0]);
458
+		} elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
459
+			$propertyName = strtolower(substr(substr($methodName, 9), 0, 1)) . substr(substr($methodName, 9), 1);
460
+			$result = $this->processMagicCall($propertyName, $arguments[0], 'one');
461
+		} elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
462
+			$propertyName = strtolower(substr(substr($methodName, 7), 0, 1)) . substr(substr($methodName, 7), 1);
463
+			$result = $this->processMagicCall($propertyName, $arguments[0], 'count');
464
+		} else {
465
+			throw new UnsupportedMethodException('The method "' . $methodName . '" is not supported by the repository.', 1360838010);
466
+		}
467
+		return $result;
468
+	}
469
+
470
+	/**
471
+	 * Returns a query for objects of this repository
472
+	 *
473
+	 * @return Query
474
+	 * @api
475
+	 */
476
+	public function createQuery()
477
+	{
478
+		/** @var Query $query */
479
+		$query = $this->getObjectManager()->get(Query::class, $this->dataType);
480
+		$query->setSourceFieldName($this->sourceFieldName);
481
+
482
+		if ($this->defaultQuerySettings) {
483
+			$query->setQuerySettings($this->defaultQuerySettings);
484
+		} else {
485
+
486
+			// Initialize and pass the query settings at this level.
487
+			/** @var QuerySettings $querySettings */
488
+			$querySettings = $this->getObjectManager()->get(QuerySettings::class);
489
+
490
+			// Default choice for the BE.
491
+			if ($this->isBackendMode()) {
492
+				$querySettings->setIgnoreEnableFields(true);
493
+			}
494
+
495
+			$query->setQuerySettings($querySettings);
496
+		}
497
+
498
+		return $query;
499
+	}
500
+
501
+	/**
502
+	 * Sets the property names to order the result by per default.
503
+	 * Expected like this:
504
+	 * array(
505
+	 * 'foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
506
+	 * 'bar' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
507
+	 * )
508
+	 *
509
+	 * @param array $defaultOrderings The property names to order by
510
+	 * @return void
511
+	 * @api
512
+	 */
513
+	public function setDefaultOrderings(array $defaultOrderings)
514
+	{
515
+		throw new \BadMethodCallException('Repository does not support the setDefaultOrderings() method.', 1375805598);
516
+	}
517
+
518
+	/**
519
+	 * Sets the default query settings to be used in this repository
520
+	 *
521
+	 * @param QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
522
+	 * @return void
523
+	 * @api
524
+	 */
525
+	public function setDefaultQuerySettings(QuerySettingsInterface $defaultQuerySettings)
526
+	{
527
+		$this->defaultQuerySettings = $defaultQuerySettings;
528
+	}
529
+
530
+	/**
531
+	 * @return void
532
+	 */
533
+	public function resetDefaultQuerySettings(): void
534
+	{
535
+		$this->defaultQuerySettings = null;
536
+	}
537
+
538
+
539
+	/**
540
+	 * @return array
541
+	 */
542
+	public function getErrorMessages(): array
543
+	{
544
+		return $this->errorMessages;
545
+	}
546
+
547
+	/**
548
+	 * @param string $sourceFieldName
549
+	 * @return $this
550
+	 */
551
+	public function setSourceFieldName($sourceFieldName): self
552
+	{
553
+		$this->sourceFieldName = $sourceFieldName;
554
+		return $this;
555
+	}
556
+
557
+	/**
558
+	 * @return string
559
+	 */
560
+	public function getDataType(): string
561
+	{
562
+		return $this->dataType;
563
+	}
564
+
565
+	/**
566
+	 * Tell whether the order has a foreign table in its expression, e.g. "metadata.title".
567
+	 *
568
+	 * @param string $ordering
569
+	 * @return bool
570
+	 */
571
+	protected function hasForeignRelationIn($ordering): bool
572
+	{
573
+		return strpos($ordering, '.') !== false;
574
+	}
575
+
576
+	/**
577
+	 * Extract the foreign relation of the ordering "metadata.title" -> "metadata"
578
+	 *
579
+	 * @param string $ordering
580
+	 * @return string
581
+	 */
582
+	protected function getForeignRelationFrom($ordering): string
583
+	{
584
+		$parts = explode('.', $ordering);
585
+		return $parts[0];
586
+	}
587
+
588
+	/**
589
+	 * Get the constraints
590
+	 *
591
+	 * @param Query $query
592
+	 * @param Matcher $matcher
593
+	 * @return ConstraintInterface|null
594
+	 */
595
+	protected function computeConstraints(Query $query, Matcher $matcher): ?ConstraintInterface
596
+	{
597
+		$constraints = null;
598
+
599
+		$collectedConstraints = [];
600
+
601
+		// Search term
602
+		$constraint = $this->computeSearchTermConstraint($query, $matcher);
603
+		if ($constraint) {
604
+			$collectedConstraints[] = $constraint;
605
+		}
606
+
607
+		foreach ($matcher->getSupportedOperators() as $operator) {
608
+			$constraint = $this->computeConstraint($query, $matcher, $operator);
609
+			if ($constraint) {
610
+				$collectedConstraints[] = $constraint;
611
+			}
612
+		}
613
+
614
+		if (count($collectedConstraints) > 1) {
615
+			$logical = $matcher->getDefaultLogicalSeparator();
616
+			$constraints = $query->$logical($collectedConstraints);
617
+		} elseif (!empty($collectedConstraints)) {
618
+
619
+			// true means there is one constraint only and should become the result
620
+			$constraints = current($collectedConstraints);
621
+		}
622
+
623
+		// Trigger signal for post processing the computed constraints object.
624
+		$constraints = $this->emitPostProcessConstraintsSignal($query, $constraints);
625
+
626
+		return $constraints;
627
+	}
628
+
629
+	/**
630
+	 * Computes the search constraint and returns it.
631
+	 *
632
+	 * @param Query $query
633
+	 * @param Matcher $matcher
634
+	 * @return ConstraintInterface|null
635
+	 */
636
+	protected function computeSearchTermConstraint(Query $query, Matcher $matcher): ?ConstraintInterface
637
+	{
638
+
639
+		$result = null;
640
+
641
+		// Search term case
642
+		if ($matcher->getSearchTerm()) {
643
+
644
+			$fields = GeneralUtility::trimExplode(',', Tca::table($this->dataType)->getSearchFields(), true);
645
+
646
+			$constraints = [];
647
+			$likeClause = sprintf('%%%s%%', $matcher->getSearchTerm());
648
+			foreach ($fields as $fieldNameAndPath) {
649
+				if ($this->isSuitableForLike($fieldNameAndPath, $matcher->getSearchTerm())) {
650
+
651
+					$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
652
+					$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
653
+
654
+					if (Tca::table($dataType)->hasField($fieldName) && Tca::table($dataType)->field($fieldName)->hasRelation()) {
655
+						$foreignTable = Tca::table($dataType)->field($fieldName)->getForeignTable();
656
+						$fieldNameAndPath = $fieldNameAndPath . '.' . Tca::table($foreignTable)->getLabelField();
657
+					}
658
+					$constraints[] = $query->like($fieldNameAndPath, $likeClause);
659
+				}
660
+			}
661
+			$logical = $matcher->getLogicalSeparatorForSearchTerm();
662
+			$result = $query->$logical($constraints);
663
+		}
664
+
665
+		return $result;
666
+	}
667
+
668
+	/**
669
+	 * It does not make sense to have a "like" in presence of numerical field, e.g "uid".
670
+	 * Tell whether the given value makes sense for a "like" clause.
671
+	 *
672
+	 * @param string $fieldNameAndPath
673
+	 * @param string $value
674
+	 * @return bool
675
+	 */
676
+	protected function isSuitableForLike($fieldNameAndPath, $value): bool
677
+	{
678
+		$isSuitable = true;
679
+
680
+		// true means it is a string
681
+		if (!MathUtility::canBeInterpretedAsInteger($value)) {
682
+
683
+			$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
684
+			$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
685
+
686
+			if (Tca::table($dataType)->field($fieldName)->isNumerical()
687
+				&& !Tca::table($dataType)->field($fieldName)->hasRelation()
688
+			) {
689
+				$isSuitable = false;
690
+			}
691
+		}
692
+
693
+		return $isSuitable;
694
+	}
695
+
696
+	/**
697
+	 * Computes the constraint for matches and returns it.
698
+	 *
699
+	 * @param Query $query
700
+	 * @param Matcher $matcher
701
+	 * @param string $operator
702
+	 * @return ConstraintInterface|null
703
+	 */
704
+	protected function computeConstraint(Query $query, Matcher $matcher, $operator): ?ConstraintInterface
705
+	{
706
+		$result = null;
707
+
708
+		$operatorName = ucfirst($operator);
709
+		$getCriteria = sprintf('get%s', $operatorName);
710
+		$criteria = $matcher->$getCriteria();
711
+
712
+		if (!empty($criteria)) {
713
+			$constraints = [];
714
+
715
+			foreach ($criteria as $criterion) {
716
+
717
+				$fieldNameAndPath = $criterion['fieldNameAndPath'];
718
+				$operand = $criterion['operand'];
719
+
720
+				// Compute a few variables...
721
+				// $dataType is generally equals to $this->dataType but not always... if fieldName is a path.
722
+				$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
723
+				$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
724
+				$fieldPath = $this->getFieldPathResolver()->stripFieldName($fieldNameAndPath, $this->dataType);
725
+
726
+				if (Tca::table($dataType)->field($fieldName)->hasRelation()) {
727
+					if (MathUtility::canBeInterpretedAsInteger($operand)) {
728
+						$fieldNameAndPath = $fieldName . '.uid';
729
+					} else {
730
+						$foreignTableName = Tca::table($dataType)->field($fieldName)->getForeignTable();
731
+						$foreignTable = Tca::table($foreignTableName);
732
+						$fieldNameAndPath = $fieldName . '.' . $foreignTable->getLabelField();
733
+					}
734
+
735
+					// If different means we should restore the prepended path segment for proper SQL parser.
736
+					// This is true for a composite field, e.g items.sys_file_metadata for categories.
737
+					if ($fieldName !== $fieldPath) {
738
+						$fieldNameAndPath = $fieldPath . '.' . $fieldNameAndPath;
739
+					}
740
+				}
741
+
742
+				if (strpos($operator, 'not') === 0) {
743
+					$strippedOperator = strtolower(substr($operator, 3));
744
+					$constraints[] = $query->logicalNot($query->$strippedOperator($fieldNameAndPath, $criterion['operand']));
745
+				} else {
746
+					$constraints[] = $query->$operator($fieldNameAndPath, $criterion['operand']);
747
+				}
748
+			}
749
+
750
+			$getLogicalSeparator = sprintf('getLogicalSeparatorFor%s', $operatorName);
751
+			$logical = method_exists($matcher, $getLogicalSeparator)
752
+				? $matcher->$getLogicalSeparator()
753
+				: $matcher->getDefaultLogicalSeparator();
754
+
755
+			$result = $query->$logical($constraints);
756
+		}
757
+
758
+		return $result;
759
+	}
760
+
761
+	/**
762
+	 * @return DataHandler
763
+	 */
764
+	protected function getDataHandler(): DataHandler
765
+	{
766
+		if (!$this->dataHandler) {
767
+			$this->dataHandler = GeneralUtility::makeInstance(DataHandler::class);
768
+		}
769
+		return $this->dataHandler;
770
+	}
771
+
772
+	/**
773
+	 * Handle the magic call by properly creating a Query object and returning its result.
774
+	 *
775
+	 * @param string $propertyName
776
+	 * @param string $value
777
+	 * @param string $flag
778
+	 * @return array
779
+	 */
780
+	protected function processMagicCall($propertyName, $value, $flag = ''): array
781
+	{
782
+
783
+		$fieldName = Property::name($propertyName)->of($this->dataType)->toFieldName();
784
+
785
+		/** @var $matcher Matcher */
786
+		$matcher = GeneralUtility::makeInstance(Matcher::class, [], $this->getDataType());
787
+
788
+		$table = Tca::table($this->dataType);
789
+		if ($table->field($fieldName)->isGroup()) {
790
+
791
+			$valueParts = explode('.', $value, 2);
792
+			$fieldName = $fieldName . '.' . $valueParts[0];
793
+			$value = $valueParts[1];
794
+		}
795
+
796
+		$matcher->equals($fieldName, $value);
797
+
798
+		if ($flag === 'count') {
799
+			$result = $this->countBy($matcher);
800
+		} else {
801
+			$result = $this->findBy($matcher);
802
+		}
803
+		return $flag === 'one' && !empty($result) ? reset($result) : $result;
804
+	}
805
+
806
+	/**
807
+	 * @return DataHandlerFactory|object
808
+	 */
809
+	protected function getDataHandlerFactory()
810
+	{
811
+		return GeneralUtility::makeInstance(DataHandlerFactory::class);
812
+	}
813
+
814
+	/**
815
+	 * Returns whether the current mode is Backend
816
+	 *
817
+	 * @return bool
818
+	 */
819
+	protected function isBackendMode(): bool
820
+	{
821
+		return TYPO3_MODE === 'BE';
822
+	}
823
+
824
+	/**
825
+	 * @return FieldPathResolver|object
826
+	 */
827
+	protected function getFieldPathResolver()
828
+	{
829
+		return GeneralUtility::makeInstance(FieldPathResolver::class);
830
+	}
831
+
832
+	/**
833
+	 * @return ObjectManager|object
834
+	 */
835
+	protected function getObjectManager(): ObjectManager
836
+	{
837
+		return GeneralUtility::makeInstance(ObjectManager::class);
838
+	}
839
+
840
+	/**
841
+	 * @return ContentValidator|object
842
+	 */
843
+	protected function getContentValidator(): ContentValidator
844
+	{
845
+		return GeneralUtility::makeInstance(ContentValidator::class);
846
+	}
847
+
848
+	/**
849
+	 * @return LanguageValidator|object
850
+	 */
851
+	protected function getLanguageValidator(): LanguageValidator
852
+	{
853
+		return GeneralUtility::makeInstance(LanguageValidator::class);
854
+	}
855
+
856
+	/**
857
+	 * Signal that is called for post-processing the computed constraints object.
858
+	 *
859
+	 * @param Query $query
860
+	 * @param ConstraintInterface|null $constraints
861
+	 * @return ConstraintInterface|null $constraints
862
+	 * @signal
863
+	 */
864
+	protected function emitPostProcessConstraintsSignal(Query $query, $constraints): ?ConstraintInterface
865
+	{
866
+		/** @var ConstraintContainer $constraintContainer */
867
+		$constraintContainer = GeneralUtility::makeInstance(ConstraintContainer::class);
868
+		$result = $this->getSignalSlotDispatcher()->dispatch(
869
+			self::class,
870
+			'postProcessConstraintsObject',
871
+			[
872
+				$query,
873
+				$constraints,
874
+				$constraintContainer
875
+			]
876
+		);
877
+
878
+		// Backward compatibility.
879
+		$processedConstraints = $result[1];
880
+
881
+		// New way to transmit the constraints.
882
+		if ($constraintContainer->getConstraint()) {
883
+			$processedConstraints = $constraintContainer->getConstraint();
884
+		}
885
+		return $processedConstraints;
886
+	}
887
+
888
+	/**
889
+	 * @return Dispatcher
890
+	 */
891
+	protected function getSignalSlotDispatcher(): Dispatcher
892
+	{
893
+		return $this->getObjectManager()->get(Dispatcher::class);
894
+	}
895 895
 
896 896
 }
Please login to merge, or discard this patch.
Classes/Utility/BackendUtility.php 2 patches
Indentation   +102 added lines, -102 removed lines patch added patch discarded remove patch
@@ -18,115 +18,115 @@
 block discarded – undo
18 18
 class BackendUtility
19 19
 {
20 20
 
21
-    /*******************************************
21
+	/*******************************************
22 22
      *
23 23
      * SQL-related, selecting records, searching
24 24
      *
25 25
      *******************************************/
26
-    /**
27
-     * Returns the WHERE clause " AND NOT [tablename].[deleted-field]" if a deleted-field
28
-     * is configured in $GLOBALS['TCA'] for the tablename, $table
29
-     * This function should ALWAYS be called in the backend for selection on tables which
30
-     * are configured in $GLOBALS['TCA'] since it will ensure consistent selection of records,
31
-     * even if they are marked deleted (in which case the system must always treat them as non-existent!)
32
-     * In the frontend a function, ->enableFields(), is known to filter hidden-field, start- and endtime
33
-     * and fe_groups as well. But that is a job of the frontend, not the backend. If you need filtering
34
-     * on those fields as well in the backend you can use ->BEenableFields() though.
35
-     *
36
-     * @param string $table Table name present in $GLOBALS['TCA']
37
-     * @param string $withLogicalSeparator Table alias if any
38
-     * @return string WHERE clause for filtering out deleted records, eg " AND tablename.deleted=0
39
-     */
40
-    public static function deleteClause($table, $withLogicalSeparator = ' AND')
41
-    {
42
-        if (empty($GLOBALS['TCA'][$table]['ctrl']['delete'])) {
43
-            return '';
44
-        }
45
-        $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
46
-            ->getQueryBuilderForTable($table)
47
-            ->expr();
48
-        return $withLogicalSeparator . ' ' . $expressionBuilder->eq(
49
-                $table . '.' . $GLOBALS['TCA'][$table]['ctrl']['delete'],
50
-                0
51
-            );
52
-    }
53
-    /**
54
-     * Backend implementation of enableFields()
55
-     * Notice that "fe_groups" is not selected for - only disabled, starttime and endtime.
56
-     * Notice that deleted-fields are NOT filtered - you must ALSO call deleteClause in addition.
57
-     * $GLOBALS["SIM_ACCESS_TIME"] is used for date.
58
-     *
59
-     * @param string $table The table from which to return enableFields WHERE clause. Table name must have a 'ctrl' section in $GLOBALS['TCA'].
60
-     * @param bool $inv Means that the query will select all records NOT VISIBLE records (inverted selection)
61
-     * @return string WHERE clause part
62
-     */
63
-    public static function BEenableFields($table, $inv = false)
64
-    {
65
-        $ctrl = $GLOBALS['TCA'][$table]['ctrl'];
66
-        $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
67
-            ->getConnectionForTable($table)
68
-            ->getExpressionBuilder();
69
-        $query = $expressionBuilder->andX();
70
-        $invQuery = $expressionBuilder->orX();
26
+	/**
27
+	 * Returns the WHERE clause " AND NOT [tablename].[deleted-field]" if a deleted-field
28
+	 * is configured in $GLOBALS['TCA'] for the tablename, $table
29
+	 * This function should ALWAYS be called in the backend for selection on tables which
30
+	 * are configured in $GLOBALS['TCA'] since it will ensure consistent selection of records,
31
+	 * even if they are marked deleted (in which case the system must always treat them as non-existent!)
32
+	 * In the frontend a function, ->enableFields(), is known to filter hidden-field, start- and endtime
33
+	 * and fe_groups as well. But that is a job of the frontend, not the backend. If you need filtering
34
+	 * on those fields as well in the backend you can use ->BEenableFields() though.
35
+	 *
36
+	 * @param string $table Table name present in $GLOBALS['TCA']
37
+	 * @param string $withLogicalSeparator Table alias if any
38
+	 * @return string WHERE clause for filtering out deleted records, eg " AND tablename.deleted=0
39
+	 */
40
+	public static function deleteClause($table, $withLogicalSeparator = ' AND')
41
+	{
42
+		if (empty($GLOBALS['TCA'][$table]['ctrl']['delete'])) {
43
+			return '';
44
+		}
45
+		$expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
46
+			->getQueryBuilderForTable($table)
47
+			->expr();
48
+		return $withLogicalSeparator . ' ' . $expressionBuilder->eq(
49
+				$table . '.' . $GLOBALS['TCA'][$table]['ctrl']['delete'],
50
+				0
51
+			);
52
+	}
53
+	/**
54
+	 * Backend implementation of enableFields()
55
+	 * Notice that "fe_groups" is not selected for - only disabled, starttime and endtime.
56
+	 * Notice that deleted-fields are NOT filtered - you must ALSO call deleteClause in addition.
57
+	 * $GLOBALS["SIM_ACCESS_TIME"] is used for date.
58
+	 *
59
+	 * @param string $table The table from which to return enableFields WHERE clause. Table name must have a 'ctrl' section in $GLOBALS['TCA'].
60
+	 * @param bool $inv Means that the query will select all records NOT VISIBLE records (inverted selection)
61
+	 * @return string WHERE clause part
62
+	 */
63
+	public static function BEenableFields($table, $inv = false)
64
+	{
65
+		$ctrl = $GLOBALS['TCA'][$table]['ctrl'];
66
+		$expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
67
+			->getConnectionForTable($table)
68
+			->getExpressionBuilder();
69
+		$query = $expressionBuilder->andX();
70
+		$invQuery = $expressionBuilder->orX();
71 71
 
72
-        if (is_array($ctrl)) {
73
-            if (is_array($ctrl['enablecolumns'])) {
74
-                if ($ctrl['enablecolumns']['disabled'] ?? false) {
75
-                    $field = $table . '.' . $ctrl['enablecolumns']['disabled'];
76
-                    $query->add($expressionBuilder->eq($field, 0));
77
-                    $invQuery->add($expressionBuilder->neq($field, 0));
78
-                }
79
-                if ($ctrl['enablecolumns']['starttime'] ?? false) {
80
-                    $field = $table . '.' . $ctrl['enablecolumns']['starttime'];
81
-                    $query->add($expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME']));
82
-                    $invQuery->add(
83
-                        $expressionBuilder->andX(
84
-                            $expressionBuilder->neq($field, 0),
85
-                            $expressionBuilder->gt($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
86
-                        )
87
-                    );
88
-                }
89
-                if ($ctrl['enablecolumns']['endtime'] ?? false) {
90
-                    $field = $table . '.' . $ctrl['enablecolumns']['endtime'];
91
-                    $query->add(
92
-                        $expressionBuilder->orX(
93
-                            $expressionBuilder->eq($field, 0),
94
-                            $expressionBuilder->gt($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
95
-                        )
96
-                    );
97
-                    $invQuery->add(
98
-                        $expressionBuilder->andX(
99
-                            $expressionBuilder->neq($field, 0),
100
-                            $expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
101
-                        )
102
-                    );
103
-                }
104
-            }
105
-        }
72
+		if (is_array($ctrl)) {
73
+			if (is_array($ctrl['enablecolumns'])) {
74
+				if ($ctrl['enablecolumns']['disabled'] ?? false) {
75
+					$field = $table . '.' . $ctrl['enablecolumns']['disabled'];
76
+					$query->add($expressionBuilder->eq($field, 0));
77
+					$invQuery->add($expressionBuilder->neq($field, 0));
78
+				}
79
+				if ($ctrl['enablecolumns']['starttime'] ?? false) {
80
+					$field = $table . '.' . $ctrl['enablecolumns']['starttime'];
81
+					$query->add($expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME']));
82
+					$invQuery->add(
83
+						$expressionBuilder->andX(
84
+							$expressionBuilder->neq($field, 0),
85
+							$expressionBuilder->gt($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
86
+						)
87
+					);
88
+				}
89
+				if ($ctrl['enablecolumns']['endtime'] ?? false) {
90
+					$field = $table . '.' . $ctrl['enablecolumns']['endtime'];
91
+					$query->add(
92
+						$expressionBuilder->orX(
93
+							$expressionBuilder->eq($field, 0),
94
+							$expressionBuilder->gt($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
95
+						)
96
+					);
97
+					$invQuery->add(
98
+						$expressionBuilder->andX(
99
+							$expressionBuilder->neq($field, 0),
100
+							$expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
101
+						)
102
+					);
103
+				}
104
+			}
105
+		}
106 106
 
107
-        if ($query->count() === 0) {
108
-            return '';
109
-        }
107
+		if ($query->count() === 0) {
108
+			return '';
109
+		}
110 110
 
111
-        return ' AND ' . ($inv ? $invQuery : $query);
112
-    }
111
+		return ' AND ' . ($inv ? $invQuery : $query);
112
+	}
113 113
 
114
-    /**
115
-     * Returns the URL to a given module
116
-     *
117
-     * @param string $moduleName Name of the module
118
-     * @param array $urlParameters URL parameters that should be added as key value pairs
119
-     * @return string Calculated URL
120
-     */
121
-    public static function getModuleUrl($moduleName, $urlParameters = [])
122
-    {
123
-        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
124
-        try {
125
-            $uri = $uriBuilder->buildUriFromRoute($moduleName, $urlParameters);
126
-        } catch (\TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException $e) {
127
-            $uri = $uriBuilder->buildUriFromRoutePath($moduleName, $urlParameters);
128
-        }
129
-        return (string)$uri;
130
-    }
114
+	/**
115
+	 * Returns the URL to a given module
116
+	 *
117
+	 * @param string $moduleName Name of the module
118
+	 * @param array $urlParameters URL parameters that should be added as key value pairs
119
+	 * @return string Calculated URL
120
+	 */
121
+	public static function getModuleUrl($moduleName, $urlParameters = [])
122
+	{
123
+		$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
124
+		try {
125
+			$uri = $uriBuilder->buildUriFromRoute($moduleName, $urlParameters);
126
+		} catch (\TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException $e) {
127
+			$uri = $uriBuilder->buildUriFromRoutePath($moduleName, $urlParameters);
128
+		}
129
+		return (string)$uri;
130
+	}
131 131
 
132 132
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -45,8 +45,8 @@  discard block
 block discarded – undo
45 45
         $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
46 46
             ->getQueryBuilderForTable($table)
47 47
             ->expr();
48
-        return $withLogicalSeparator . ' ' . $expressionBuilder->eq(
49
-                $table . '.' . $GLOBALS['TCA'][$table]['ctrl']['delete'],
48
+        return $withLogicalSeparator.' '.$expressionBuilder->eq(
49
+                $table.'.'.$GLOBALS['TCA'][$table]['ctrl']['delete'],
50 50
                 0
51 51
             );
52 52
     }
@@ -72,12 +72,12 @@  discard block
 block discarded – undo
72 72
         if (is_array($ctrl)) {
73 73
             if (is_array($ctrl['enablecolumns'])) {
74 74
                 if ($ctrl['enablecolumns']['disabled'] ?? false) {
75
-                    $field = $table . '.' . $ctrl['enablecolumns']['disabled'];
75
+                    $field = $table.'.'.$ctrl['enablecolumns']['disabled'];
76 76
                     $query->add($expressionBuilder->eq($field, 0));
77 77
                     $invQuery->add($expressionBuilder->neq($field, 0));
78 78
                 }
79 79
                 if ($ctrl['enablecolumns']['starttime'] ?? false) {
80
-                    $field = $table . '.' . $ctrl['enablecolumns']['starttime'];
80
+                    $field = $table.'.'.$ctrl['enablecolumns']['starttime'];
81 81
                     $query->add($expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME']));
82 82
                     $invQuery->add(
83 83
                         $expressionBuilder->andX(
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
                     );
88 88
                 }
89 89
                 if ($ctrl['enablecolumns']['endtime'] ?? false) {
90
-                    $field = $table . '.' . $ctrl['enablecolumns']['endtime'];
90
+                    $field = $table.'.'.$ctrl['enablecolumns']['endtime'];
91 91
                     $query->add(
92 92
                         $expressionBuilder->orX(
93 93
                             $expressionBuilder->eq($field, 0),
@@ -108,7 +108,7 @@  discard block
 block discarded – undo
108 108
             return '';
109 109
         }
110 110
 
111
-        return ' AND ' . ($inv ? $invQuery : $query);
111
+        return ' AND '.($inv ? $invQuery : $query);
112 112
     }
113 113
 
114 114
     /**
Please login to merge, or discard this patch.
Classes/Tca/GridService.php 2 patches
Indentation   +703 added lines, -703 removed lines patch added patch discarded remove patch
@@ -22,708 +22,708 @@
 block discarded – undo
22 22
 class GridService extends AbstractTca
23 23
 {
24 24
 
25
-    /**
26
-     * @var array
27
-     */
28
-    protected $tca;
29
-
30
-    /**
31
-     * @var string
32
-     */
33
-    protected $tableName;
34
-
35
-    /**
36
-     * All fields available in the Grid.
37
-     *
38
-     * @var array
39
-     */
40
-    protected $fields;
41
-
42
-    /**
43
-     * All fields regardless whether they have been excluded or not.
44
-     *
45
-     * @var array
46
-     */
47
-    protected $allFields;
48
-
49
-    /**
50
-     * @var array
51
-     */
52
-    protected $instances;
53
-
54
-    /**
55
-     * @var array
56
-     */
57
-    protected $facets;
58
-
59
-    /**
60
-     * __construct
61
-     *
62
-     * @param string $tableName
63
-     */
64
-    public function __construct($tableName)
65
-    {
66
-
67
-        $this->tableName = $tableName;
68
-
69
-        if (empty($GLOBALS['TCA'][$this->tableName])) {
70
-            throw new InvalidKeyInArrayException('No TCA existence for table name: ' . $this->tableName, 1356945108);
71
-        }
72
-
73
-        $this->tca = $GLOBALS['TCA'][$this->tableName]['grid'];
74
-    }
75
-
76
-    /**
77
-     * Returns an array containing column names.
78
-     *
79
-     * @return array
80
-     */
81
-    public function getFieldNames(): array
82
-    {
83
-        $fields = $this->getFields();
84
-        return array_keys($fields);
85
-    }
86
-
87
-    /**
88
-     * Returns an array containing column names.
89
-     *
90
-     * @return array
91
-     */
92
-    public function getAllFieldNames(): array
93
-    {
94
-        $allFields = $this->getAllFields();
95
-        return array_keys($allFields);
96
-    }
97
-
98
-    /**
99
-     * Get the label key.
100
-     *
101
-     * @param string $fieldNameAndPath
102
-     * @return string
103
-     */
104
-    public function getLabelKey($fieldNameAndPath): string
105
-    {
106
-
107
-        $field = $this->getField($fieldNameAndPath);
108
-
109
-        // First option is to get the label from the Grid TCA.
110
-        $rawLabel = '';
111
-        if (isset($field['label'])) {
112
-            $rawLabel = $field['label'];
113
-        }
114
-
115
-        // Second option is to fetch the label from the Column Renderer object.
116
-        if (!$rawLabel && $this->hasRenderers($fieldNameAndPath)) {
117
-            $renderers = $this->getRenderers($fieldNameAndPath);
118
-            /** @var $renderer ColumnRendererInterface */
119
-            foreach ($renderers as $renderer) {
120
-                if (isset($renderer['label'])) {
121
-                    $rawLabel = $renderer['label'];
122
-                    break;
123
-                }
124
-            }
125
-        }
126
-        return $rawLabel;
127
-    }
128
-
129
-    /**
130
-     * Get the translation of a label given a column name.
131
-     *
132
-     * @param string $fieldNameAndPath
133
-     * @return string
134
-     */
135
-    public function getLabel($fieldNameAndPath)
136
-    {
137
-        $label = '';
138
-        if ($this->hasLabel($fieldNameAndPath)) {
139
-            $labelKey = $this->getLabelKey($fieldNameAndPath);
140
-            try {
141
-                $label = $this->getLanguageService()->sL($labelKey);
142
-            } catch (\InvalidArgumentException $e) {
143
-            }
144
-            if (empty($label)) {
145
-                $label = $labelKey;
146
-            }
147
-        } else {
148
-
149
-            // Important to notice the label can contains a path, e.g. metadata.categories and must be resolved.
150
-            $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->tableName);
151
-            $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->tableName);
152
-            $table = Tca::table($dataType);
153
-
154
-            if ($table->hasField($fieldName) && $table->field($fieldName)->hasLabel()) {
155
-                $label = $table->field($fieldName)->getLabel();
156
-            }
157
-        }
158
-
159
-        return $label;
160
-    }
161
-
162
-    /**
163
-     * Returns the field name given its position.
164
-     *
165
-     * @param string $position the position of the field in the grid
166
-     * @return int
167
-     */
168
-    public function getFieldNameByPosition($position): int
169
-    {
170
-        $fields = array_keys($this->getFields());
171
-        if (empty($fields[$position])) {
172
-            throw new InvalidKeyInArrayException('No field exist for position: ' . $position, 1356945119);
173
-        }
174
-
175
-        return $fields[$position];
176
-    }
177
-
178
-    /**
179
-     * Returns a field name.
180
-     *
181
-     * @param string $fieldName
182
-     * @return array
183
-     */
184
-    public function getField($fieldName): array
185
-    {
186
-        $fields = $this->getFields();
187
-        return $fields[$fieldName];
188
-    }
189
-
190
-    /**
191
-     * Returns an array containing column names for the Grid.
192
-     *
193
-     * @return array
194
-     */
195
-    public function getFields(): array
196
-    {
197
-        // Cache this operation since it can take some time.
198
-        if ($this->fields === null) {
199
-
200
-            // Fetch all available fields first.
201
-            $fields = $this->getAllFields();
202
-
203
-            if ($this->isBackendMode()) {
204
-
205
-                // Then remove the not allowed.
206
-                $fields = $this->filterByIncludedFields($fields);
207
-                $fields = $this->filterByBackendUser($fields);
208
-                $fields = $this->filterByExcludedFields($fields);
209
-            }
210
-
211
-            $this->fields = $fields;
212
-        }
213
-
214
-        return $this->fields;
215
-    }
216
-
217
-    /**
218
-     * Remove fields according to Grid configuration.
219
-     *
220
-     * @param $fields
221
-     * @return array
222
-     */
223
-    protected function filterByIncludedFields($fields): array
224
-    {
225
-
226
-        $filteredFields = $fields;
227
-        $includedFields = $this->getIncludedFields();
228
-        if (count($includedFields) > 0) {
229
-            $filteredFields = [];
230
-            foreach ($fields as $fieldNameAndPath => $configuration) {
231
-                if (in_array($fieldNameAndPath, $includedFields, true) || !Tca::table($this->tableName)->hasField($fieldNameAndPath)) {
232
-                    $filteredFields[$fieldNameAndPath] = $configuration;
233
-                }
234
-            }
235
-        }
236
-        return $filteredFields;
237
-    }
238
-
239
-    /**
240
-     * Remove fields according to BE User permission.
241
-     *
242
-     * @param $fields
243
-     * @return array
244
-     */
245
-    protected function filterByBackendUser($fields): array
246
-    {
247
-        if (!$this->getBackendUser()->isAdmin()) {
248
-            foreach ($fields as $fieldName => $field) {
249
-                if (Tca::table($this->tableName)->hasField($fieldName) && !Tca::table($this->tableName)->field($fieldName)->hasAccess()) {
250
-                    unset($fields[$fieldName]);
251
-                }
252
-            }
253
-        }
254
-        return $fields;
255
-    }
256
-
257
-    /**
258
-     * Remove fields according to Grid configuration.
259
-     *
260
-     * @param $fields
261
-     * @return array
262
-     */
263
-    protected function filterByExcludedFields($fields): array
264
-    {
265
-
266
-        // Unset excluded fields.
267
-        foreach ($this->getExcludedFields() as $excludedField) {
268
-            if (isset($fields[$excludedField])) {
269
-                unset($fields[$excludedField]);
270
-            }
271
-        }
272
-
273
-        return $fields;
274
-    }
275
-
276
-    /**
277
-     * Returns an array containing column names for the Grid.
278
-     *
279
-     * @return array
280
-     */
281
-    public function getAllFields(): array
282
-    {
283
-
284
-        // Cache this operation since it can take some time.
285
-        if ($this->allFields === null) {
286
-
287
-            $fields = is_array($this->tca['columns']) ? $this->tca['columns'] : [];
288
-            $gridFieldNames = array_keys($fields);
289
-
290
-            // Fetch all fields of the TCA and merge it back to the fields configured for Grid.
291
-            $tableFieldNames = Tca::table($this->tableName)->getFields();
292
-
293
-            // Just remove system fields from the Grid.
294
-            foreach ($tableFieldNames as $key => $fieldName) {
295
-                if (in_array($fieldName, Tca::getSystemFields())) {
296
-                    unset($tableFieldNames[$key]);
297
-                }
298
-            }
299
-
300
-            $additionalFields = array_diff($tableFieldNames, $gridFieldNames);
301
-
302
-            if (!empty($additionalFields)) {
303
-
304
-                // Pop out last element of the key
305
-                // Idea is to place new un-configured columns in between. By default, they will be hidden.
306
-                end($fields);
307
-                $lastColumnKey = key($fields);
308
-                $lastColumn = array_pop($fields);
309
-
310
-                // Feed up the grid fields with un configured elements
311
-                foreach ($additionalFields as $additionalField) {
312
-                    $fields[$additionalField] = array(
313
-                        'visible' => false
314
-                    );
315
-
316
-                    // Try to guess the format of the field.
317
-                    $fieldType = Tca::table($this->tableName)->field($additionalField)->getType();
318
-                    if ($fieldType === FieldType::DATE) {
319
-                        $fields[$additionalField]['format'] = 'Fab\Vidi\Formatter\Date';
320
-                    } elseif ($fieldType === FieldType::DATETIME) {
321
-                        $fields[$additionalField]['format'] = 'Fab\Vidi\Formatter\Datetime';
322
-                    }
323
-                }
324
-                $fields[$lastColumnKey] = $lastColumn;
325
-            }
326
-
327
-            $this->allFields = $fields;
328
-        }
329
-
330
-        return $this->allFields;
331
-    }
332
-
333
-    /**
334
-     * Tell whether the field exists in the grid or not.
335
-     *
336
-     * @param string $fieldName
337
-     * @return bool
338
-     */
339
-    public function hasField($fieldName): bool
340
-    {
341
-        $fields = $this->getFields();
342
-        return isset($fields[$fieldName]);
343
-    }
344
-
345
-    /**
346
-     * Tell whether the facet exists in the grid or not.
347
-     *
348
-     * @param string $facetName
349
-     * @return bool
350
-     */
351
-    public function hasFacet($facetName): bool
352
-    {
353
-        $facets = $this->getFacets();
354
-        return isset($facets[$facetName]);
355
-    }
356
-
357
-    /**
358
-     * Returns an array containing facets fields.
359
-     *
360
-     * @return FacetInterface[]
361
-     */
362
-    public function getFacets(): array
363
-    {
364
-        if ($this->facets === null) {
365
-            $this->facets = [];
366
-
367
-            if (is_array($this->tca['facets'])) {
368
-                foreach ($this->tca['facets'] as $key => $facetNameOrArray) {
369
-                    if (is_array($facetNameOrArray)) {
370
-
371
-                        $name = $facetNameOrArray['name'] ?? '';
372
-
373
-                        $label = isset($facetNameOrArray['label'])
374
-                            ? $this->getLanguageService()->sL($facetNameOrArray['label'])
375
-                            : '';
376
-
377
-                        $suggestions = $facetNameOrArray['suggestions'] ?? [];
378
-                        $configuration = $facetNameOrArray['configuration'] ?? [];
379
-
380
-                        /** @var FacetInterface $facetObject */
381
-                        $facetObject = GeneralUtility::makeInstance($key, $name, $label, $suggestions, $configuration);
382
-                        $this->facets[$facetObject->getName()] = $facetObject;
383
-                    } else {
384
-                        $this->facets[$facetNameOrArray] = $this->instantiateStandardFacet($facetNameOrArray);
385
-                    }
386
-                }
387
-            }
388
-        }
389
-        return $this->facets;
390
-    }
391
-
392
-    /**
393
-     * Returns the "sortable" value of the column.
394
-     *
395
-     * @param string $fieldName
396
-     * @return int|string
397
-     */
398
-    public function isSortable($fieldName)
399
-    {
400
-        $defaultValue = true;
401
-        $hasSortableField = Tca::table($this->tableName)->hasSortableField();
402
-        if ($hasSortableField) {
403
-            $isSortable = false;
404
-        } else {
405
-            $isSortable = $this->get($fieldName, 'sortable', $defaultValue);
406
-        }
407
-        return $isSortable;
408
-    }
409
-
410
-    /**
411
-     * Returns the "canBeHidden" value of the column.
412
-     *
413
-     * @param string $fieldName
414
-     * @return bool
415
-     */
416
-    public function canBeHidden($fieldName): bool
417
-    {
418
-        $defaultValue = true;
419
-        return $this->get($fieldName, 'canBeHidden', $defaultValue);
420
-    }
421
-
422
-    /**
423
-     * Returns the "width" value of the column.
424
-     *
425
-     * @param string $fieldName
426
-     * @return int|string
427
-     */
428
-    public function getWidth($fieldName)
429
-    {
430
-        $defaultValue = 'auto';
431
-        return $this->get($fieldName, 'width', $defaultValue);
432
-    }
433
-
434
-    /**
435
-     * Returns the "visible" value of the column.
436
-     *
437
-     * @param string $fieldName
438
-     * @return bool
439
-     */
440
-    public function isVisible($fieldName): bool
441
-    {
442
-        $defaultValue = true;
443
-        return $this->get($fieldName, 'visible', $defaultValue);
444
-    }
445
-
446
-    /**
447
-     * Returns the "editable" value of the column.
448
-     *
449
-     * @param string $columnName
450
-     * @return bool
451
-     */
452
-    public function isEditable($columnName): bool
453
-    {
454
-        $defaultValue = false;
455
-        return $this->get($columnName, 'editable', $defaultValue);
456
-    }
457
-
458
-    /**
459
-     * Returns the "localized" value of the column.
460
-     *
461
-     * @param string $columnName
462
-     * @return bool
463
-     */
464
-    public function isLocalized($columnName): bool
465
-    {
466
-        $defaultValue = true;
467
-        return $this->get($columnName, 'localized', $defaultValue);
468
-    }
469
-
470
-    /**
471
-     *
472
-     * Returns the "html" value of the column.
473
-     *
474
-     * @param string $fieldName
475
-     * @return string
476
-     */
477
-    public function getHeader($fieldName): string
478
-    {
479
-        $defaultValue = '';
480
-        return $this->get($fieldName, 'html', $defaultValue);
481
-    }
482
-
483
-    /**
484
-     * Fetch a possible from a Grid Renderer. If no value is found, returns null
485
-     *
486
-     * @param string $fieldName
487
-     * @param string $key
488
-     * @param mixed $defaultValue
489
-     * @return null|mixed
490
-     */
491
-    public function get($fieldName, $key, $defaultValue = null)
492
-    {
493
-        $value = $defaultValue;
494
-
495
-        $field = $this->getField($fieldName);
496
-        if (isset($field[$key])) {
497
-            $value = $field[$key];
498
-        } elseif ($this->hasRenderers($fieldName)) {
499
-            $renderers = $this->getRenderers($fieldName);
500
-            foreach ($renderers as $rendererConfiguration) {
501
-                if (isset($rendererConfiguration[$key])) {
502
-                    $value = $rendererConfiguration[$key];
503
-                }
504
-            }
505
-        }
506
-        return $value;
507
-    }
508
-
509
-    /**
510
-     * Returns whether the column has a renderer.
511
-     *
512
-     * @param string $fieldName
513
-     * @return bool
514
-     */
515
-    public function hasRenderers($fieldName): bool
516
-    {
517
-        $field = $this->getField($fieldName);
518
-        return empty($field['renderer']) && empty($field['renderers']) ? false : true;
519
-    }
520
-
521
-    /**
522
-     * Returns a renderer.
523
-     *
524
-     * @param string $fieldName
525
-     * @return array
526
-     */
527
-    public function getRenderers($fieldName): array
528
-    {
529
-        $field = $this->getField($fieldName);
530
-        $renderers = [];
531
-        if (!empty($field['renderer'])) {
532
-            $renderers = $this->convertRendererToArray($field['renderer'], $field);
533
-        } elseif (!empty($field['renderers']) && is_array($field['renderers'])) {
534
-            foreach ($field['renderers'] as $renderer) {
535
-                $rendererNameAndConfiguration = $this->convertRendererToArray($renderer, $field);
536
-                $renderers = array_merge($renderers, $rendererNameAndConfiguration);
537
-            }
538
-        }
539
-
540
-        return $renderers;
541
-    }
542
-
543
-    /**
544
-     * @param string $renderer
545
-     * @return array
546
-     */
547
-    protected function convertRendererToArray($renderer, array $field): array
548
-    {
549
-        $result = [];
550
-        if (is_string($renderer)) {
551
-            $configuration = empty($field['rendererConfiguration'])
552
-                ? []
553
-                : $field['rendererConfiguration'];
554
-
555
-            /** @var ColumnRendererInterface $rendererObject */
556
-            $rendererObject = GeneralUtility::makeInstance($renderer);
557
-
558
-            $result[$renderer] = array_merge($rendererObject->getConfiguration(), $configuration);
559
-            // TODO: throw alert message because this is not compatible anymore as of TYPO3 8.7.7
560
-        } elseif ($renderer instanceof ColumnRendererInterface) {
561
-            /** @var ColumnRendererInterface $renderer */
562
-            $result[get_class($renderer)] = $renderer->getConfiguration();
563
-        }
564
-        return $result;
565
-    }
566
-
567
-    /**
568
-     * Returns the class names applied to a cell
569
-     *
570
-     * @param string $fieldName
571
-     * @return bool
572
-     */
573
-    public function getClass($fieldName): bool
574
-    {
575
-        $field = $this->getField($fieldName);
576
-        return isset($field['class']) ? $field['class'] : '';
577
-    }
578
-
579
-    /**
580
-     * Returns whether the column has a label.
581
-     *
582
-     * @param string $fieldNameAndPath
583
-     * @return bool
584
-     */
585
-    public function hasLabel($fieldNameAndPath): bool
586
-    {
587
-        $field = $this->getField($fieldNameAndPath);
588
-
589
-        $hasLabel = empty($field['label']) ? false : true;
590
-
591
-        if (!$hasLabel && $this->hasRenderers($fieldNameAndPath)) {
592
-            $renderers = $this->getRenderers($fieldNameAndPath);
593
-            /** @var $renderer ColumnRendererInterface */
594
-            foreach ($renderers as $renderer) {
595
-                if (isset($renderer['label'])) {
596
-                    $hasLabel = true;
597
-                    break;
598
-                }
599
-            }
600
-        }
601
-        return $hasLabel;
602
-    }
603
-
604
-    /**
605
-     * @return array
606
-     */
607
-    public function getTca(): array
608
-    {
609
-        return $this->tca;
610
-    }
611
-
612
-    /**
613
-     * @return array
614
-     */
615
-    public function getIncludedFields(): array
616
-    {
617
-        return empty($this->tca['included_fields']) ? [] : GeneralUtility::trimExplode(',', $this->tca['included_fields'], true);
618
-    }
619
-
620
-    /**
621
-     * Return excluded fields from configuration + preferences.
622
-     *
623
-     * @return array
624
-     */
625
-    public function getExcludedFields(): array
626
-    {
627
-        $configurationFields = $this->getExcludedFieldsFromConfiguration();
628
-        $preferencesFields = $this->getExcludedFieldsFromPreferences();
629
-
630
-        return array_merge($configurationFields, $preferencesFields);
631
-    }
632
-
633
-    /**
634
-     * Fetch excluded fields from configuration.
635
-     *
636
-     * @return array
637
-     */
638
-    protected function getExcludedFieldsFromConfiguration(): array
639
-    {
640
-        $excludedFields = [];
641
-        if (!empty($this->tca['excluded_fields'])) {
642
-            $excludedFields = GeneralUtility::trimExplode(',', $this->tca['excluded_fields'], true);
643
-        } elseif (!empty($this->tca['export']['excluded_fields'])) { // only for export for legacy reason.
644
-            $excludedFields = GeneralUtility::trimExplode(',', $this->tca['export']['excluded_fields'], true);
645
-        }
646
-        return $excludedFields;
647
-
648
-    }
649
-
650
-    /**
651
-     * Fetch excluded fields from preferences.
652
-     *
653
-     * @return array
654
-     */
655
-    protected function getExcludedFieldsFromPreferences(): array
656
-    {
657
-        $excludedFields = $this->getModulePreferences()->get(ConfigurablePart::EXCLUDED_FIELDS, $this->tableName);
658
-        return is_array($excludedFields) ? $excludedFields : [];
659
-    }
660
-
661
-    /**
662
-     * @return array
663
-     */
664
-    public function areFilesIncludedInExport(): array
665
-    {
666
-        $isIncluded = true;
667
-
668
-        if (isset($this->tca['export']['include_files'])) {
669
-            $isIncluded = $this->tca['export']['include_files'];
670
-        }
671
-        return $isIncluded;
672
-    }
673
-
674
-    /**
675
-     * Returns a "facet" service instance.
676
-     *
677
-     * @param string|FacetInterface $facetName
678
-     * @return StandardFacet
679
-     */
680
-    protected function instantiateStandardFacet($facetName): StandardFacet
681
-    {
682
-        $label = $this->getLabel($facetName);
683
-
684
-        /** @var StandardFacet $facetName */
685
-        $facet = GeneralUtility::makeInstance(StandardFacet::class, $facetName, $label);
686
-
687
-        if (!$facet instanceof StandardFacet) {
688
-            throw new \RuntimeException('I could not instantiate a facet for facet name "' . $facetName . '""', 1445856345);
689
-        }
690
-        return $facet;
691
-    }
692
-
693
-    /**
694
-     * Returns a "facet" service instance.
695
-     *
696
-     * @param string|FacetInterface $facetName
697
-     * @return FacetInterface
698
-     */
699
-    public function facet($facetName = ''): FacetInterface
700
-    {
701
-        $facets = $this->getFacets();
702
-        return $facets[$facetName];
703
-    }
704
-
705
-    /**
706
-     * @return \Fab\Vidi\Resolver\FieldPathResolver|object
707
-     */
708
-    protected function getFieldPathResolver()
709
-    {
710
-        return GeneralUtility::makeInstance(\Fab\Vidi\Resolver\FieldPathResolver::class);
711
-    }
712
-
713
-    /**
714
-     * @return ModulePreferences|object
715
-     */
716
-    protected function getModulePreferences()
717
-    {
718
-        return GeneralUtility::makeInstance(ModulePreferences::class);
719
-    }
720
-
721
-    /**
722
-     * @return \TYPO3\CMS\Lang\LanguageService|object
723
-     */
724
-    protected function getLanguageService(): \TYPO3\CMS\Lang\LanguageService
725
-    {
726
-        return GeneralUtility::makeInstance(\TYPO3\CMS\Lang\LanguageService::class);
727
-    }
25
+	/**
26
+	 * @var array
27
+	 */
28
+	protected $tca;
29
+
30
+	/**
31
+	 * @var string
32
+	 */
33
+	protected $tableName;
34
+
35
+	/**
36
+	 * All fields available in the Grid.
37
+	 *
38
+	 * @var array
39
+	 */
40
+	protected $fields;
41
+
42
+	/**
43
+	 * All fields regardless whether they have been excluded or not.
44
+	 *
45
+	 * @var array
46
+	 */
47
+	protected $allFields;
48
+
49
+	/**
50
+	 * @var array
51
+	 */
52
+	protected $instances;
53
+
54
+	/**
55
+	 * @var array
56
+	 */
57
+	protected $facets;
58
+
59
+	/**
60
+	 * __construct
61
+	 *
62
+	 * @param string $tableName
63
+	 */
64
+	public function __construct($tableName)
65
+	{
66
+
67
+		$this->tableName = $tableName;
68
+
69
+		if (empty($GLOBALS['TCA'][$this->tableName])) {
70
+			throw new InvalidKeyInArrayException('No TCA existence for table name: ' . $this->tableName, 1356945108);
71
+		}
72
+
73
+		$this->tca = $GLOBALS['TCA'][$this->tableName]['grid'];
74
+	}
75
+
76
+	/**
77
+	 * Returns an array containing column names.
78
+	 *
79
+	 * @return array
80
+	 */
81
+	public function getFieldNames(): array
82
+	{
83
+		$fields = $this->getFields();
84
+		return array_keys($fields);
85
+	}
86
+
87
+	/**
88
+	 * Returns an array containing column names.
89
+	 *
90
+	 * @return array
91
+	 */
92
+	public function getAllFieldNames(): array
93
+	{
94
+		$allFields = $this->getAllFields();
95
+		return array_keys($allFields);
96
+	}
97
+
98
+	/**
99
+	 * Get the label key.
100
+	 *
101
+	 * @param string $fieldNameAndPath
102
+	 * @return string
103
+	 */
104
+	public function getLabelKey($fieldNameAndPath): string
105
+	{
106
+
107
+		$field = $this->getField($fieldNameAndPath);
108
+
109
+		// First option is to get the label from the Grid TCA.
110
+		$rawLabel = '';
111
+		if (isset($field['label'])) {
112
+			$rawLabel = $field['label'];
113
+		}
114
+
115
+		// Second option is to fetch the label from the Column Renderer object.
116
+		if (!$rawLabel && $this->hasRenderers($fieldNameAndPath)) {
117
+			$renderers = $this->getRenderers($fieldNameAndPath);
118
+			/** @var $renderer ColumnRendererInterface */
119
+			foreach ($renderers as $renderer) {
120
+				if (isset($renderer['label'])) {
121
+					$rawLabel = $renderer['label'];
122
+					break;
123
+				}
124
+			}
125
+		}
126
+		return $rawLabel;
127
+	}
128
+
129
+	/**
130
+	 * Get the translation of a label given a column name.
131
+	 *
132
+	 * @param string $fieldNameAndPath
133
+	 * @return string
134
+	 */
135
+	public function getLabel($fieldNameAndPath)
136
+	{
137
+		$label = '';
138
+		if ($this->hasLabel($fieldNameAndPath)) {
139
+			$labelKey = $this->getLabelKey($fieldNameAndPath);
140
+			try {
141
+				$label = $this->getLanguageService()->sL($labelKey);
142
+			} catch (\InvalidArgumentException $e) {
143
+			}
144
+			if (empty($label)) {
145
+				$label = $labelKey;
146
+			}
147
+		} else {
148
+
149
+			// Important to notice the label can contains a path, e.g. metadata.categories and must be resolved.
150
+			$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->tableName);
151
+			$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->tableName);
152
+			$table = Tca::table($dataType);
153
+
154
+			if ($table->hasField($fieldName) && $table->field($fieldName)->hasLabel()) {
155
+				$label = $table->field($fieldName)->getLabel();
156
+			}
157
+		}
158
+
159
+		return $label;
160
+	}
161
+
162
+	/**
163
+	 * Returns the field name given its position.
164
+	 *
165
+	 * @param string $position the position of the field in the grid
166
+	 * @return int
167
+	 */
168
+	public function getFieldNameByPosition($position): int
169
+	{
170
+		$fields = array_keys($this->getFields());
171
+		if (empty($fields[$position])) {
172
+			throw new InvalidKeyInArrayException('No field exist for position: ' . $position, 1356945119);
173
+		}
174
+
175
+		return $fields[$position];
176
+	}
177
+
178
+	/**
179
+	 * Returns a field name.
180
+	 *
181
+	 * @param string $fieldName
182
+	 * @return array
183
+	 */
184
+	public function getField($fieldName): array
185
+	{
186
+		$fields = $this->getFields();
187
+		return $fields[$fieldName];
188
+	}
189
+
190
+	/**
191
+	 * Returns an array containing column names for the Grid.
192
+	 *
193
+	 * @return array
194
+	 */
195
+	public function getFields(): array
196
+	{
197
+		// Cache this operation since it can take some time.
198
+		if ($this->fields === null) {
199
+
200
+			// Fetch all available fields first.
201
+			$fields = $this->getAllFields();
202
+
203
+			if ($this->isBackendMode()) {
204
+
205
+				// Then remove the not allowed.
206
+				$fields = $this->filterByIncludedFields($fields);
207
+				$fields = $this->filterByBackendUser($fields);
208
+				$fields = $this->filterByExcludedFields($fields);
209
+			}
210
+
211
+			$this->fields = $fields;
212
+		}
213
+
214
+		return $this->fields;
215
+	}
216
+
217
+	/**
218
+	 * Remove fields according to Grid configuration.
219
+	 *
220
+	 * @param $fields
221
+	 * @return array
222
+	 */
223
+	protected function filterByIncludedFields($fields): array
224
+	{
225
+
226
+		$filteredFields = $fields;
227
+		$includedFields = $this->getIncludedFields();
228
+		if (count($includedFields) > 0) {
229
+			$filteredFields = [];
230
+			foreach ($fields as $fieldNameAndPath => $configuration) {
231
+				if (in_array($fieldNameAndPath, $includedFields, true) || !Tca::table($this->tableName)->hasField($fieldNameAndPath)) {
232
+					$filteredFields[$fieldNameAndPath] = $configuration;
233
+				}
234
+			}
235
+		}
236
+		return $filteredFields;
237
+	}
238
+
239
+	/**
240
+	 * Remove fields according to BE User permission.
241
+	 *
242
+	 * @param $fields
243
+	 * @return array
244
+	 */
245
+	protected function filterByBackendUser($fields): array
246
+	{
247
+		if (!$this->getBackendUser()->isAdmin()) {
248
+			foreach ($fields as $fieldName => $field) {
249
+				if (Tca::table($this->tableName)->hasField($fieldName) && !Tca::table($this->tableName)->field($fieldName)->hasAccess()) {
250
+					unset($fields[$fieldName]);
251
+				}
252
+			}
253
+		}
254
+		return $fields;
255
+	}
256
+
257
+	/**
258
+	 * Remove fields according to Grid configuration.
259
+	 *
260
+	 * @param $fields
261
+	 * @return array
262
+	 */
263
+	protected function filterByExcludedFields($fields): array
264
+	{
265
+
266
+		// Unset excluded fields.
267
+		foreach ($this->getExcludedFields() as $excludedField) {
268
+			if (isset($fields[$excludedField])) {
269
+				unset($fields[$excludedField]);
270
+			}
271
+		}
272
+
273
+		return $fields;
274
+	}
275
+
276
+	/**
277
+	 * Returns an array containing column names for the Grid.
278
+	 *
279
+	 * @return array
280
+	 */
281
+	public function getAllFields(): array
282
+	{
283
+
284
+		// Cache this operation since it can take some time.
285
+		if ($this->allFields === null) {
286
+
287
+			$fields = is_array($this->tca['columns']) ? $this->tca['columns'] : [];
288
+			$gridFieldNames = array_keys($fields);
289
+
290
+			// Fetch all fields of the TCA and merge it back to the fields configured for Grid.
291
+			$tableFieldNames = Tca::table($this->tableName)->getFields();
292
+
293
+			// Just remove system fields from the Grid.
294
+			foreach ($tableFieldNames as $key => $fieldName) {
295
+				if (in_array($fieldName, Tca::getSystemFields())) {
296
+					unset($tableFieldNames[$key]);
297
+				}
298
+			}
299
+
300
+			$additionalFields = array_diff($tableFieldNames, $gridFieldNames);
301
+
302
+			if (!empty($additionalFields)) {
303
+
304
+				// Pop out last element of the key
305
+				// Idea is to place new un-configured columns in between. By default, they will be hidden.
306
+				end($fields);
307
+				$lastColumnKey = key($fields);
308
+				$lastColumn = array_pop($fields);
309
+
310
+				// Feed up the grid fields with un configured elements
311
+				foreach ($additionalFields as $additionalField) {
312
+					$fields[$additionalField] = array(
313
+						'visible' => false
314
+					);
315
+
316
+					// Try to guess the format of the field.
317
+					$fieldType = Tca::table($this->tableName)->field($additionalField)->getType();
318
+					if ($fieldType === FieldType::DATE) {
319
+						$fields[$additionalField]['format'] = 'Fab\Vidi\Formatter\Date';
320
+					} elseif ($fieldType === FieldType::DATETIME) {
321
+						$fields[$additionalField]['format'] = 'Fab\Vidi\Formatter\Datetime';
322
+					}
323
+				}
324
+				$fields[$lastColumnKey] = $lastColumn;
325
+			}
326
+
327
+			$this->allFields = $fields;
328
+		}
329
+
330
+		return $this->allFields;
331
+	}
332
+
333
+	/**
334
+	 * Tell whether the field exists in the grid or not.
335
+	 *
336
+	 * @param string $fieldName
337
+	 * @return bool
338
+	 */
339
+	public function hasField($fieldName): bool
340
+	{
341
+		$fields = $this->getFields();
342
+		return isset($fields[$fieldName]);
343
+	}
344
+
345
+	/**
346
+	 * Tell whether the facet exists in the grid or not.
347
+	 *
348
+	 * @param string $facetName
349
+	 * @return bool
350
+	 */
351
+	public function hasFacet($facetName): bool
352
+	{
353
+		$facets = $this->getFacets();
354
+		return isset($facets[$facetName]);
355
+	}
356
+
357
+	/**
358
+	 * Returns an array containing facets fields.
359
+	 *
360
+	 * @return FacetInterface[]
361
+	 */
362
+	public function getFacets(): array
363
+	{
364
+		if ($this->facets === null) {
365
+			$this->facets = [];
366
+
367
+			if (is_array($this->tca['facets'])) {
368
+				foreach ($this->tca['facets'] as $key => $facetNameOrArray) {
369
+					if (is_array($facetNameOrArray)) {
370
+
371
+						$name = $facetNameOrArray['name'] ?? '';
372
+
373
+						$label = isset($facetNameOrArray['label'])
374
+							? $this->getLanguageService()->sL($facetNameOrArray['label'])
375
+							: '';
376
+
377
+						$suggestions = $facetNameOrArray['suggestions'] ?? [];
378
+						$configuration = $facetNameOrArray['configuration'] ?? [];
379
+
380
+						/** @var FacetInterface $facetObject */
381
+						$facetObject = GeneralUtility::makeInstance($key, $name, $label, $suggestions, $configuration);
382
+						$this->facets[$facetObject->getName()] = $facetObject;
383
+					} else {
384
+						$this->facets[$facetNameOrArray] = $this->instantiateStandardFacet($facetNameOrArray);
385
+					}
386
+				}
387
+			}
388
+		}
389
+		return $this->facets;
390
+	}
391
+
392
+	/**
393
+	 * Returns the "sortable" value of the column.
394
+	 *
395
+	 * @param string $fieldName
396
+	 * @return int|string
397
+	 */
398
+	public function isSortable($fieldName)
399
+	{
400
+		$defaultValue = true;
401
+		$hasSortableField = Tca::table($this->tableName)->hasSortableField();
402
+		if ($hasSortableField) {
403
+			$isSortable = false;
404
+		} else {
405
+			$isSortable = $this->get($fieldName, 'sortable', $defaultValue);
406
+		}
407
+		return $isSortable;
408
+	}
409
+
410
+	/**
411
+	 * Returns the "canBeHidden" value of the column.
412
+	 *
413
+	 * @param string $fieldName
414
+	 * @return bool
415
+	 */
416
+	public function canBeHidden($fieldName): bool
417
+	{
418
+		$defaultValue = true;
419
+		return $this->get($fieldName, 'canBeHidden', $defaultValue);
420
+	}
421
+
422
+	/**
423
+	 * Returns the "width" value of the column.
424
+	 *
425
+	 * @param string $fieldName
426
+	 * @return int|string
427
+	 */
428
+	public function getWidth($fieldName)
429
+	{
430
+		$defaultValue = 'auto';
431
+		return $this->get($fieldName, 'width', $defaultValue);
432
+	}
433
+
434
+	/**
435
+	 * Returns the "visible" value of the column.
436
+	 *
437
+	 * @param string $fieldName
438
+	 * @return bool
439
+	 */
440
+	public function isVisible($fieldName): bool
441
+	{
442
+		$defaultValue = true;
443
+		return $this->get($fieldName, 'visible', $defaultValue);
444
+	}
445
+
446
+	/**
447
+	 * Returns the "editable" value of the column.
448
+	 *
449
+	 * @param string $columnName
450
+	 * @return bool
451
+	 */
452
+	public function isEditable($columnName): bool
453
+	{
454
+		$defaultValue = false;
455
+		return $this->get($columnName, 'editable', $defaultValue);
456
+	}
457
+
458
+	/**
459
+	 * Returns the "localized" value of the column.
460
+	 *
461
+	 * @param string $columnName
462
+	 * @return bool
463
+	 */
464
+	public function isLocalized($columnName): bool
465
+	{
466
+		$defaultValue = true;
467
+		return $this->get($columnName, 'localized', $defaultValue);
468
+	}
469
+
470
+	/**
471
+	 *
472
+	 * Returns the "html" value of the column.
473
+	 *
474
+	 * @param string $fieldName
475
+	 * @return string
476
+	 */
477
+	public function getHeader($fieldName): string
478
+	{
479
+		$defaultValue = '';
480
+		return $this->get($fieldName, 'html', $defaultValue);
481
+	}
482
+
483
+	/**
484
+	 * Fetch a possible from a Grid Renderer. If no value is found, returns null
485
+	 *
486
+	 * @param string $fieldName
487
+	 * @param string $key
488
+	 * @param mixed $defaultValue
489
+	 * @return null|mixed
490
+	 */
491
+	public function get($fieldName, $key, $defaultValue = null)
492
+	{
493
+		$value = $defaultValue;
494
+
495
+		$field = $this->getField($fieldName);
496
+		if (isset($field[$key])) {
497
+			$value = $field[$key];
498
+		} elseif ($this->hasRenderers($fieldName)) {
499
+			$renderers = $this->getRenderers($fieldName);
500
+			foreach ($renderers as $rendererConfiguration) {
501
+				if (isset($rendererConfiguration[$key])) {
502
+					$value = $rendererConfiguration[$key];
503
+				}
504
+			}
505
+		}
506
+		return $value;
507
+	}
508
+
509
+	/**
510
+	 * Returns whether the column has a renderer.
511
+	 *
512
+	 * @param string $fieldName
513
+	 * @return bool
514
+	 */
515
+	public function hasRenderers($fieldName): bool
516
+	{
517
+		$field = $this->getField($fieldName);
518
+		return empty($field['renderer']) && empty($field['renderers']) ? false : true;
519
+	}
520
+
521
+	/**
522
+	 * Returns a renderer.
523
+	 *
524
+	 * @param string $fieldName
525
+	 * @return array
526
+	 */
527
+	public function getRenderers($fieldName): array
528
+	{
529
+		$field = $this->getField($fieldName);
530
+		$renderers = [];
531
+		if (!empty($field['renderer'])) {
532
+			$renderers = $this->convertRendererToArray($field['renderer'], $field);
533
+		} elseif (!empty($field['renderers']) && is_array($field['renderers'])) {
534
+			foreach ($field['renderers'] as $renderer) {
535
+				$rendererNameAndConfiguration = $this->convertRendererToArray($renderer, $field);
536
+				$renderers = array_merge($renderers, $rendererNameAndConfiguration);
537
+			}
538
+		}
539
+
540
+		return $renderers;
541
+	}
542
+
543
+	/**
544
+	 * @param string $renderer
545
+	 * @return array
546
+	 */
547
+	protected function convertRendererToArray($renderer, array $field): array
548
+	{
549
+		$result = [];
550
+		if (is_string($renderer)) {
551
+			$configuration = empty($field['rendererConfiguration'])
552
+				? []
553
+				: $field['rendererConfiguration'];
554
+
555
+			/** @var ColumnRendererInterface $rendererObject */
556
+			$rendererObject = GeneralUtility::makeInstance($renderer);
557
+
558
+			$result[$renderer] = array_merge($rendererObject->getConfiguration(), $configuration);
559
+			// TODO: throw alert message because this is not compatible anymore as of TYPO3 8.7.7
560
+		} elseif ($renderer instanceof ColumnRendererInterface) {
561
+			/** @var ColumnRendererInterface $renderer */
562
+			$result[get_class($renderer)] = $renderer->getConfiguration();
563
+		}
564
+		return $result;
565
+	}
566
+
567
+	/**
568
+	 * Returns the class names applied to a cell
569
+	 *
570
+	 * @param string $fieldName
571
+	 * @return bool
572
+	 */
573
+	public function getClass($fieldName): bool
574
+	{
575
+		$field = $this->getField($fieldName);
576
+		return isset($field['class']) ? $field['class'] : '';
577
+	}
578
+
579
+	/**
580
+	 * Returns whether the column has a label.
581
+	 *
582
+	 * @param string $fieldNameAndPath
583
+	 * @return bool
584
+	 */
585
+	public function hasLabel($fieldNameAndPath): bool
586
+	{
587
+		$field = $this->getField($fieldNameAndPath);
588
+
589
+		$hasLabel = empty($field['label']) ? false : true;
590
+
591
+		if (!$hasLabel && $this->hasRenderers($fieldNameAndPath)) {
592
+			$renderers = $this->getRenderers($fieldNameAndPath);
593
+			/** @var $renderer ColumnRendererInterface */
594
+			foreach ($renderers as $renderer) {
595
+				if (isset($renderer['label'])) {
596
+					$hasLabel = true;
597
+					break;
598
+				}
599
+			}
600
+		}
601
+		return $hasLabel;
602
+	}
603
+
604
+	/**
605
+	 * @return array
606
+	 */
607
+	public function getTca(): array
608
+	{
609
+		return $this->tca;
610
+	}
611
+
612
+	/**
613
+	 * @return array
614
+	 */
615
+	public function getIncludedFields(): array
616
+	{
617
+		return empty($this->tca['included_fields']) ? [] : GeneralUtility::trimExplode(',', $this->tca['included_fields'], true);
618
+	}
619
+
620
+	/**
621
+	 * Return excluded fields from configuration + preferences.
622
+	 *
623
+	 * @return array
624
+	 */
625
+	public function getExcludedFields(): array
626
+	{
627
+		$configurationFields = $this->getExcludedFieldsFromConfiguration();
628
+		$preferencesFields = $this->getExcludedFieldsFromPreferences();
629
+
630
+		return array_merge($configurationFields, $preferencesFields);
631
+	}
632
+
633
+	/**
634
+	 * Fetch excluded fields from configuration.
635
+	 *
636
+	 * @return array
637
+	 */
638
+	protected function getExcludedFieldsFromConfiguration(): array
639
+	{
640
+		$excludedFields = [];
641
+		if (!empty($this->tca['excluded_fields'])) {
642
+			$excludedFields = GeneralUtility::trimExplode(',', $this->tca['excluded_fields'], true);
643
+		} elseif (!empty($this->tca['export']['excluded_fields'])) { // only for export for legacy reason.
644
+			$excludedFields = GeneralUtility::trimExplode(',', $this->tca['export']['excluded_fields'], true);
645
+		}
646
+		return $excludedFields;
647
+
648
+	}
649
+
650
+	/**
651
+	 * Fetch excluded fields from preferences.
652
+	 *
653
+	 * @return array
654
+	 */
655
+	protected function getExcludedFieldsFromPreferences(): array
656
+	{
657
+		$excludedFields = $this->getModulePreferences()->get(ConfigurablePart::EXCLUDED_FIELDS, $this->tableName);
658
+		return is_array($excludedFields) ? $excludedFields : [];
659
+	}
660
+
661
+	/**
662
+	 * @return array
663
+	 */
664
+	public function areFilesIncludedInExport(): array
665
+	{
666
+		$isIncluded = true;
667
+
668
+		if (isset($this->tca['export']['include_files'])) {
669
+			$isIncluded = $this->tca['export']['include_files'];
670
+		}
671
+		return $isIncluded;
672
+	}
673
+
674
+	/**
675
+	 * Returns a "facet" service instance.
676
+	 *
677
+	 * @param string|FacetInterface $facetName
678
+	 * @return StandardFacet
679
+	 */
680
+	protected function instantiateStandardFacet($facetName): StandardFacet
681
+	{
682
+		$label = $this->getLabel($facetName);
683
+
684
+		/** @var StandardFacet $facetName */
685
+		$facet = GeneralUtility::makeInstance(StandardFacet::class, $facetName, $label);
686
+
687
+		if (!$facet instanceof StandardFacet) {
688
+			throw new \RuntimeException('I could not instantiate a facet for facet name "' . $facetName . '""', 1445856345);
689
+		}
690
+		return $facet;
691
+	}
692
+
693
+	/**
694
+	 * Returns a "facet" service instance.
695
+	 *
696
+	 * @param string|FacetInterface $facetName
697
+	 * @return FacetInterface
698
+	 */
699
+	public function facet($facetName = ''): FacetInterface
700
+	{
701
+		$facets = $this->getFacets();
702
+		return $facets[$facetName];
703
+	}
704
+
705
+	/**
706
+	 * @return \Fab\Vidi\Resolver\FieldPathResolver|object
707
+	 */
708
+	protected function getFieldPathResolver()
709
+	{
710
+		return GeneralUtility::makeInstance(\Fab\Vidi\Resolver\FieldPathResolver::class);
711
+	}
712
+
713
+	/**
714
+	 * @return ModulePreferences|object
715
+	 */
716
+	protected function getModulePreferences()
717
+	{
718
+		return GeneralUtility::makeInstance(ModulePreferences::class);
719
+	}
720
+
721
+	/**
722
+	 * @return \TYPO3\CMS\Lang\LanguageService|object
723
+	 */
724
+	protected function getLanguageService(): \TYPO3\CMS\Lang\LanguageService
725
+	{
726
+		return GeneralUtility::makeInstance(\TYPO3\CMS\Lang\LanguageService::class);
727
+	}
728 728
 
729 729
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -67,7 +67,7 @@  discard block
 block discarded – undo
67 67
         $this->tableName = $tableName;
68 68
 
69 69
         if (empty($GLOBALS['TCA'][$this->tableName])) {
70
-            throw new InvalidKeyInArrayException('No TCA existence for table name: ' . $this->tableName, 1356945108);
70
+            throw new InvalidKeyInArrayException('No TCA existence for table name: '.$this->tableName, 1356945108);
71 71
         }
72 72
 
73 73
         $this->tca = $GLOBALS['TCA'][$this->tableName]['grid'];
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
     {
170 170
         $fields = array_keys($this->getFields());
171 171
         if (empty($fields[$position])) {
172
-            throw new InvalidKeyInArrayException('No field exist for position: ' . $position, 1356945119);
172
+            throw new InvalidKeyInArrayException('No field exist for position: '.$position, 1356945119);
173 173
         }
174 174
 
175 175
         return $fields[$position];
@@ -685,7 +685,7 @@  discard block
 block discarded – undo
685 685
         $facet = GeneralUtility::makeInstance(StandardFacet::class, $facetName, $label);
686 686
 
687 687
         if (!$facet instanceof StandardFacet) {
688
-            throw new \RuntimeException('I could not instantiate a facet for facet name "' . $facetName . '""', 1445856345);
688
+            throw new \RuntimeException('I could not instantiate a facet for facet name "'.$facetName.'""', 1445856345);
689 689
         }
690 690
         return $facet;
691 691
     }
Please login to merge, or discard this patch.
Classes/Persistence/Matcher.php 2 patches
Indentation   +495 added lines, -495 removed lines patch added patch discarded remove patch
@@ -13,499 +13,499 @@
 block discarded – undo
13 13
  */
14 14
 class Matcher
15 15
 {
16
-    /**
17
-     * The logical OR
18
-     */
19
-    const LOGICAL_OR = 'logicalOr';
20
-
21
-    /**
22
-     * The logical AND
23
-     */
24
-    const LOGICAL_AND = 'logicalAnd';
25
-
26
-    /**
27
-     * @var string
28
-     */
29
-    protected $dataType = '';
30
-
31
-    /**
32
-     * @var string
33
-     */
34
-    protected $searchTerm = '';
35
-
36
-    /**
37
-     * @var array
38
-     */
39
-    protected $supportedOperators = [
40
-        '=' => 'equals',
41
-        '!=' => 'notEquals',
42
-        'in' => 'in',
43
-        'like' => 'like',
44
-        '>' => 'greaterThan',
45
-        '>=' => 'greaterThanOrEqual',
46
-        '<' => 'lessThan',
47
-        '<=' => 'lessThanOrEqual',
48
-    ];
49
-
50
-    /**
51
-     * @var array
52
-     */
53
-    protected $equals = [];
54
-
55
-    /**
56
-     * @var array
57
-     */
58
-    protected $notEquals = [];
59
-
60
-    /**
61
-     * @var array
62
-     */
63
-    protected $greaterThan = [];
64
-
65
-    /**
66
-     * @var array
67
-     */
68
-    protected $greaterThanOrEqual = [];
69
-
70
-    /**
71
-     * @var array
72
-     */
73
-    protected $lessThan = [];
74
-
75
-    /**
76
-     * @var array
77
-     */
78
-    protected $lessThanOrEqual = [];
79
-
80
-    /**
81
-     * @var array
82
-     */
83
-    protected $in = [];
84
-
85
-    /**
86
-     * @var array
87
-     */
88
-    protected $like = [];
89
-
90
-    /**
91
-     * @var array
92
-     */
93
-    protected $matches = [];
94
-
95
-    /**
96
-     * @var string
97
-     */
98
-    protected $defaultLogicalSeparator = self::LOGICAL_AND;
99
-
100
-    /**
101
-     * @var string
102
-     */
103
-    protected $logicalSeparatorForEquals = self::LOGICAL_AND;
104
-
105
-    /**
106
-     * @var string
107
-     */
108
-    protected $logicalSeparatorForGreaterThan = self::LOGICAL_AND;
109
-
110
-    /**
111
-     * @var string
112
-     */
113
-    protected $logicalSeparatorForGreaterThanOrEqual = self::LOGICAL_AND;
114
-
115
-    /**
116
-     * @var string
117
-     */
118
-    protected $logicalSeparatorForLessThan = self::LOGICAL_AND;
119
-
120
-    /**
121
-     * @var string
122
-     */
123
-    protected $logicalSeparatorForLessThanOrEqual = self::LOGICAL_AND;
124
-
125
-    /**
126
-     * @var string
127
-     */
128
-    protected $logicalSeparatorForIn = self::LOGICAL_AND;
129
-
130
-    /**
131
-     * @var string
132
-     */
133
-    protected $logicalSeparatorForLike = self::LOGICAL_AND;
134
-
135
-    /**
136
-     * @var string
137
-     */
138
-    protected $logicalSeparatorForSearchTerm = self::LOGICAL_OR;
139
-
140
-    /**
141
-     * Constructs a new Matcher
142
-     *
143
-     * @param array $matches associative [$field => $value]
144
-     * @param string $dataType which corresponds to an entry of the TCA (table name).
145
-     */
146
-    public function __construct($matches = [], $dataType = '')
147
-    {
148
-        $this->dataType = $dataType;
149
-        $this->matches = $matches;
150
-    }
151
-
152
-    /**
153
-     * @param string $searchTerm
154
-     * @return \Fab\Vidi\Persistence\Matcher
155
-     */
156
-    public function setSearchTerm($searchTerm): Matcher
157
-    {
158
-        $this->searchTerm = $searchTerm;
159
-        return $this;
160
-    }
161
-
162
-    /**
163
-     * @return string
164
-     */
165
-    public function getSearchTerm(): string
166
-    {
167
-        return $this->searchTerm;
168
-    }
169
-
170
-    /**
171
-     * @return array
172
-     */
173
-    public function getEquals(): array
174
-    {
175
-        return $this->equals;
176
-    }
177
-
178
-    /**
179
-     * @param $fieldNameAndPath
180
-     * @param $operand
181
-     * @return $this
182
-     */
183
-    public function equals($fieldNameAndPath, $operand): self
184
-    {
185
-        $this->equals[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
186
-        return $this;
187
-    }
188
-
189
-    /**
190
-     * @return array
191
-     */
192
-    public function getNotEquals(): array
193
-    {
194
-        return $this->notEquals;
195
-    }
196
-
197
-    /**
198
-     * @param $fieldNameAndPath
199
-     * @param $operand
200
-     * @return $this
201
-     */
202
-    public function notEquals($fieldNameAndPath, $operand): self
203
-    {
204
-        $this->notEquals[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
205
-        return $this;
206
-    }
207
-
208
-    /**
209
-     * @return array
210
-     */
211
-    public function getGreaterThan(): array
212
-    {
213
-        return $this->greaterThan;
214
-    }
215
-
216
-    /**
217
-     * @param $fieldNameAndPath
218
-     * @param $operand
219
-     * @return $this
220
-     */
221
-    public function greaterThan($fieldNameAndPath, $operand): self
222
-    {
223
-        $this->greaterThan[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
224
-        return $this;
225
-    }
226
-
227
-    /**
228
-     * @return array
229
-     */
230
-    public function getGreaterThanOrEqual(): array
231
-    {
232
-        return $this->greaterThanOrEqual;
233
-    }
234
-
235
-    /**
236
-     * @param $fieldNameAndPath
237
-     * @param $operand
238
-     * @return $this
239
-     */
240
-    public function greaterThanOrEqual($fieldNameAndPath, $operand): self
241
-    {
242
-        $this->greaterThanOrEqual[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
243
-        return $this;
244
-    }
245
-
246
-    /**
247
-     * @return array
248
-     */
249
-    public function getLessThan(): array
250
-    {
251
-        return $this->lessThan;
252
-    }
253
-
254
-    /**
255
-     * @param $fieldNameAndPath
256
-     * @param $operand
257
-     * @return $this
258
-     */
259
-    public function lessThan($fieldNameAndPath, $operand): self
260
-    {
261
-        $this->lessThan[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
262
-        return $this;
263
-    }
264
-
265
-    /**
266
-     * @return array
267
-     */
268
-    public function getLessThanOrEqual(): array
269
-    {
270
-        return $this->lessThanOrEqual;
271
-    }
272
-
273
-    /**
274
-     * @param $fieldNameAndPath
275
-     * @param $operand
276
-     * @return $this
277
-     */
278
-    public function lessThanOrEqual($fieldNameAndPath, $operand): self
279
-    {
280
-        $this->lessThanOrEqual[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
281
-        return $this;
282
-    }
283
-
284
-    /**
285
-     * @return array
286
-     */
287
-    public function getLike(): array
288
-    {
289
-        return $this->like;
290
-    }
291
-
292
-    /**
293
-     * @param $fieldNameAndPath
294
-     * @param $operand
295
-     * @return $this
296
-     */
297
-    public function in($fieldNameAndPath, $operand): self
298
-    {
299
-        $this->in[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
300
-        return $this;
301
-    }
302
-
303
-    /**
304
-     * @return array
305
-     */
306
-    public function getIn(): array
307
-    {
308
-        return $this->in;
309
-    }
310
-
311
-    /**
312
-     * @param $fieldNameAndPath
313
-     * @param $operand
314
-     * @param bool $addWildCard
315
-     * @return $this
316
-     */
317
-    public function like($fieldNameAndPath, $operand, $addWildCard = true): self
318
-    {
319
-        $wildCardSymbol = $addWildCard ? '%' : '';
320
-        $this->like[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $wildCardSymbol . $operand . $wildCardSymbol];
321
-        return $this;
322
-    }
323
-
324
-    /**
325
-     * @return string
326
-     */
327
-    public function getDefaultLogicalSeparator(): string
328
-    {
329
-        return $this->defaultLogicalSeparator;
330
-    }
331
-
332
-    /**
333
-     * @param string $defaultLogicalSeparator
334
-     * @return $this
335
-     */
336
-    public function setDefaultLogicalSeparator($defaultLogicalSeparator): self
337
-    {
338
-        $this->defaultLogicalSeparator = $defaultLogicalSeparator;
339
-        return $this;
340
-    }
341
-
342
-    /**
343
-     * @return string
344
-     */
345
-    public function getLogicalSeparatorForEquals(): string
346
-    {
347
-        return $this->logicalSeparatorForEquals;
348
-    }
349
-
350
-    /**
351
-     * @param string $logicalSeparatorForEquals
352
-     * @return $this
353
-     */
354
-    public function setLogicalSeparatorForEquals($logicalSeparatorForEquals): self
355
-    {
356
-        $this->logicalSeparatorForEquals = $logicalSeparatorForEquals;
357
-        return $this;
358
-    }
359
-
360
-    /**
361
-     * @return string
362
-     */
363
-    public function getLogicalSeparatorForGreaterThan(): string
364
-    {
365
-        return $this->logicalSeparatorForGreaterThan;
366
-    }
367
-
368
-    /**
369
-     * @param string $logicalSeparatorForGreaterThan
370
-     * @return $this
371
-     */
372
-    public function setLogicalSeparatorForGreaterThan($logicalSeparatorForGreaterThan): self
373
-    {
374
-        $this->logicalSeparatorForGreaterThan = $logicalSeparatorForGreaterThan;
375
-        return $this;
376
-    }
377
-
378
-    /**
379
-     * @return string
380
-     */
381
-    public function getLogicalSeparatorForGreaterThanOrEqual(): string
382
-    {
383
-        return $this->logicalSeparatorForGreaterThanOrEqual;
384
-    }
385
-
386
-    /**
387
-     * @param string $logicalSeparatorForGreaterThanOrEqual
388
-     * @return $this
389
-     */
390
-    public function setLogicalSeparatorForGreaterThanOrEqual($logicalSeparatorForGreaterThanOrEqual): self
391
-    {
392
-        $this->logicalSeparatorForGreaterThanOrEqual = $logicalSeparatorForGreaterThanOrEqual;
393
-        return $this;
394
-    }
395
-
396
-    /**
397
-     * @return string
398
-     */
399
-    public function getLogicalSeparatorForLessThan(): string
400
-    {
401
-        return $this->logicalSeparatorForLessThan;
402
-    }
403
-
404
-    /**
405
-     * @param string $logicalSeparatorForLessThan
406
-     * @return $this
407
-     */
408
-    public function setLogicalSeparatorForLessThan($logicalSeparatorForLessThan): self
409
-    {
410
-        $this->logicalSeparatorForLessThan = $logicalSeparatorForLessThan;
411
-        return $this;
412
-    }
413
-
414
-    /**
415
-     * @return string
416
-     */
417
-    public function getLogicalSeparatorForLessThanOrEqual(): string
418
-    {
419
-        return $this->logicalSeparatorForLessThanOrEqual;
420
-    }
421
-
422
-    /**
423
-     * @param string $logicalSeparatorForLessThanOrEqual
424
-     * @return $this
425
-     */
426
-    public function setLogicalSeparatorForLessThanOrEqual($logicalSeparatorForLessThanOrEqual): self
427
-    {
428
-        $this->logicalSeparatorForLessThanOrEqual = $logicalSeparatorForLessThanOrEqual;
429
-        return $this;
430
-    }
431
-
432
-    /**
433
-     * @return string
434
-     */
435
-    public function getLogicalSeparatorForIn(): string
436
-    {
437
-        return $this->logicalSeparatorForIn;
438
-    }
439
-
440
-    /**
441
-     * @param string $logicalSeparatorForIn
442
-     * @return $this
443
-     */
444
-    public function setLogicalSeparatorForIn($logicalSeparatorForIn): self
445
-    {
446
-        $this->logicalSeparatorForIn = $logicalSeparatorForIn;
447
-        return $this;
448
-    }
449
-
450
-    /**
451
-     * @return string
452
-     */
453
-    public function getLogicalSeparatorForLike(): string
454
-    {
455
-        return $this->logicalSeparatorForLike;
456
-    }
457
-
458
-    /**
459
-     * @param string $logicalSeparatorForLike
460
-     * @return $this
461
-     */
462
-    public function setLogicalSeparatorForLike($logicalSeparatorForLike): self
463
-    {
464
-        $this->logicalSeparatorForLike = $logicalSeparatorForLike;
465
-        return $this;
466
-    }
467
-
468
-    /**
469
-     * @return string
470
-     */
471
-    public function getLogicalSeparatorForSearchTerm(): string
472
-    {
473
-        return $this->logicalSeparatorForSearchTerm;
474
-    }
475
-
476
-    /**
477
-     * @param string $logicalSeparatorForSearchTerm
478
-     * @return $this
479
-     */
480
-    public function setLogicalSeparatorForSearchTerm($logicalSeparatorForSearchTerm): self
481
-    {
482
-        $this->logicalSeparatorForSearchTerm = $logicalSeparatorForSearchTerm;
483
-        return $this;
484
-    }
485
-
486
-    /**
487
-     * @return array
488
-     */
489
-    public function getSupportedOperators(): array
490
-    {
491
-        return $this->supportedOperators;
492
-    }
493
-
494
-    /**
495
-     * @return string
496
-     */
497
-    public function getDataType(): string
498
-    {
499
-        return $this->dataType;
500
-    }
501
-
502
-    /**
503
-     * @param string $dataType
504
-     * @return $this
505
-     */
506
-    public function setDataType($dataType): self
507
-    {
508
-        $this->dataType = $dataType;
509
-        return $this;
510
-    }
16
+	/**
17
+	 * The logical OR
18
+	 */
19
+	const LOGICAL_OR = 'logicalOr';
20
+
21
+	/**
22
+	 * The logical AND
23
+	 */
24
+	const LOGICAL_AND = 'logicalAnd';
25
+
26
+	/**
27
+	 * @var string
28
+	 */
29
+	protected $dataType = '';
30
+
31
+	/**
32
+	 * @var string
33
+	 */
34
+	protected $searchTerm = '';
35
+
36
+	/**
37
+	 * @var array
38
+	 */
39
+	protected $supportedOperators = [
40
+		'=' => 'equals',
41
+		'!=' => 'notEquals',
42
+		'in' => 'in',
43
+		'like' => 'like',
44
+		'>' => 'greaterThan',
45
+		'>=' => 'greaterThanOrEqual',
46
+		'<' => 'lessThan',
47
+		'<=' => 'lessThanOrEqual',
48
+	];
49
+
50
+	/**
51
+	 * @var array
52
+	 */
53
+	protected $equals = [];
54
+
55
+	/**
56
+	 * @var array
57
+	 */
58
+	protected $notEquals = [];
59
+
60
+	/**
61
+	 * @var array
62
+	 */
63
+	protected $greaterThan = [];
64
+
65
+	/**
66
+	 * @var array
67
+	 */
68
+	protected $greaterThanOrEqual = [];
69
+
70
+	/**
71
+	 * @var array
72
+	 */
73
+	protected $lessThan = [];
74
+
75
+	/**
76
+	 * @var array
77
+	 */
78
+	protected $lessThanOrEqual = [];
79
+
80
+	/**
81
+	 * @var array
82
+	 */
83
+	protected $in = [];
84
+
85
+	/**
86
+	 * @var array
87
+	 */
88
+	protected $like = [];
89
+
90
+	/**
91
+	 * @var array
92
+	 */
93
+	protected $matches = [];
94
+
95
+	/**
96
+	 * @var string
97
+	 */
98
+	protected $defaultLogicalSeparator = self::LOGICAL_AND;
99
+
100
+	/**
101
+	 * @var string
102
+	 */
103
+	protected $logicalSeparatorForEquals = self::LOGICAL_AND;
104
+
105
+	/**
106
+	 * @var string
107
+	 */
108
+	protected $logicalSeparatorForGreaterThan = self::LOGICAL_AND;
109
+
110
+	/**
111
+	 * @var string
112
+	 */
113
+	protected $logicalSeparatorForGreaterThanOrEqual = self::LOGICAL_AND;
114
+
115
+	/**
116
+	 * @var string
117
+	 */
118
+	protected $logicalSeparatorForLessThan = self::LOGICAL_AND;
119
+
120
+	/**
121
+	 * @var string
122
+	 */
123
+	protected $logicalSeparatorForLessThanOrEqual = self::LOGICAL_AND;
124
+
125
+	/**
126
+	 * @var string
127
+	 */
128
+	protected $logicalSeparatorForIn = self::LOGICAL_AND;
129
+
130
+	/**
131
+	 * @var string
132
+	 */
133
+	protected $logicalSeparatorForLike = self::LOGICAL_AND;
134
+
135
+	/**
136
+	 * @var string
137
+	 */
138
+	protected $logicalSeparatorForSearchTerm = self::LOGICAL_OR;
139
+
140
+	/**
141
+	 * Constructs a new Matcher
142
+	 *
143
+	 * @param array $matches associative [$field => $value]
144
+	 * @param string $dataType which corresponds to an entry of the TCA (table name).
145
+	 */
146
+	public function __construct($matches = [], $dataType = '')
147
+	{
148
+		$this->dataType = $dataType;
149
+		$this->matches = $matches;
150
+	}
151
+
152
+	/**
153
+	 * @param string $searchTerm
154
+	 * @return \Fab\Vidi\Persistence\Matcher
155
+	 */
156
+	public function setSearchTerm($searchTerm): Matcher
157
+	{
158
+		$this->searchTerm = $searchTerm;
159
+		return $this;
160
+	}
161
+
162
+	/**
163
+	 * @return string
164
+	 */
165
+	public function getSearchTerm(): string
166
+	{
167
+		return $this->searchTerm;
168
+	}
169
+
170
+	/**
171
+	 * @return array
172
+	 */
173
+	public function getEquals(): array
174
+	{
175
+		return $this->equals;
176
+	}
177
+
178
+	/**
179
+	 * @param $fieldNameAndPath
180
+	 * @param $operand
181
+	 * @return $this
182
+	 */
183
+	public function equals($fieldNameAndPath, $operand): self
184
+	{
185
+		$this->equals[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
186
+		return $this;
187
+	}
188
+
189
+	/**
190
+	 * @return array
191
+	 */
192
+	public function getNotEquals(): array
193
+	{
194
+		return $this->notEquals;
195
+	}
196
+
197
+	/**
198
+	 * @param $fieldNameAndPath
199
+	 * @param $operand
200
+	 * @return $this
201
+	 */
202
+	public function notEquals($fieldNameAndPath, $operand): self
203
+	{
204
+		$this->notEquals[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
205
+		return $this;
206
+	}
207
+
208
+	/**
209
+	 * @return array
210
+	 */
211
+	public function getGreaterThan(): array
212
+	{
213
+		return $this->greaterThan;
214
+	}
215
+
216
+	/**
217
+	 * @param $fieldNameAndPath
218
+	 * @param $operand
219
+	 * @return $this
220
+	 */
221
+	public function greaterThan($fieldNameAndPath, $operand): self
222
+	{
223
+		$this->greaterThan[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
224
+		return $this;
225
+	}
226
+
227
+	/**
228
+	 * @return array
229
+	 */
230
+	public function getGreaterThanOrEqual(): array
231
+	{
232
+		return $this->greaterThanOrEqual;
233
+	}
234
+
235
+	/**
236
+	 * @param $fieldNameAndPath
237
+	 * @param $operand
238
+	 * @return $this
239
+	 */
240
+	public function greaterThanOrEqual($fieldNameAndPath, $operand): self
241
+	{
242
+		$this->greaterThanOrEqual[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
243
+		return $this;
244
+	}
245
+
246
+	/**
247
+	 * @return array
248
+	 */
249
+	public function getLessThan(): array
250
+	{
251
+		return $this->lessThan;
252
+	}
253
+
254
+	/**
255
+	 * @param $fieldNameAndPath
256
+	 * @param $operand
257
+	 * @return $this
258
+	 */
259
+	public function lessThan($fieldNameAndPath, $operand): self
260
+	{
261
+		$this->lessThan[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
262
+		return $this;
263
+	}
264
+
265
+	/**
266
+	 * @return array
267
+	 */
268
+	public function getLessThanOrEqual(): array
269
+	{
270
+		return $this->lessThanOrEqual;
271
+	}
272
+
273
+	/**
274
+	 * @param $fieldNameAndPath
275
+	 * @param $operand
276
+	 * @return $this
277
+	 */
278
+	public function lessThanOrEqual($fieldNameAndPath, $operand): self
279
+	{
280
+		$this->lessThanOrEqual[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
281
+		return $this;
282
+	}
283
+
284
+	/**
285
+	 * @return array
286
+	 */
287
+	public function getLike(): array
288
+	{
289
+		return $this->like;
290
+	}
291
+
292
+	/**
293
+	 * @param $fieldNameAndPath
294
+	 * @param $operand
295
+	 * @return $this
296
+	 */
297
+	public function in($fieldNameAndPath, $operand): self
298
+	{
299
+		$this->in[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $operand];
300
+		return $this;
301
+	}
302
+
303
+	/**
304
+	 * @return array
305
+	 */
306
+	public function getIn(): array
307
+	{
308
+		return $this->in;
309
+	}
310
+
311
+	/**
312
+	 * @param $fieldNameAndPath
313
+	 * @param $operand
314
+	 * @param bool $addWildCard
315
+	 * @return $this
316
+	 */
317
+	public function like($fieldNameAndPath, $operand, $addWildCard = true): self
318
+	{
319
+		$wildCardSymbol = $addWildCard ? '%' : '';
320
+		$this->like[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $wildCardSymbol . $operand . $wildCardSymbol];
321
+		return $this;
322
+	}
323
+
324
+	/**
325
+	 * @return string
326
+	 */
327
+	public function getDefaultLogicalSeparator(): string
328
+	{
329
+		return $this->defaultLogicalSeparator;
330
+	}
331
+
332
+	/**
333
+	 * @param string $defaultLogicalSeparator
334
+	 * @return $this
335
+	 */
336
+	public function setDefaultLogicalSeparator($defaultLogicalSeparator): self
337
+	{
338
+		$this->defaultLogicalSeparator = $defaultLogicalSeparator;
339
+		return $this;
340
+	}
341
+
342
+	/**
343
+	 * @return string
344
+	 */
345
+	public function getLogicalSeparatorForEquals(): string
346
+	{
347
+		return $this->logicalSeparatorForEquals;
348
+	}
349
+
350
+	/**
351
+	 * @param string $logicalSeparatorForEquals
352
+	 * @return $this
353
+	 */
354
+	public function setLogicalSeparatorForEquals($logicalSeparatorForEquals): self
355
+	{
356
+		$this->logicalSeparatorForEquals = $logicalSeparatorForEquals;
357
+		return $this;
358
+	}
359
+
360
+	/**
361
+	 * @return string
362
+	 */
363
+	public function getLogicalSeparatorForGreaterThan(): string
364
+	{
365
+		return $this->logicalSeparatorForGreaterThan;
366
+	}
367
+
368
+	/**
369
+	 * @param string $logicalSeparatorForGreaterThan
370
+	 * @return $this
371
+	 */
372
+	public function setLogicalSeparatorForGreaterThan($logicalSeparatorForGreaterThan): self
373
+	{
374
+		$this->logicalSeparatorForGreaterThan = $logicalSeparatorForGreaterThan;
375
+		return $this;
376
+	}
377
+
378
+	/**
379
+	 * @return string
380
+	 */
381
+	public function getLogicalSeparatorForGreaterThanOrEqual(): string
382
+	{
383
+		return $this->logicalSeparatorForGreaterThanOrEqual;
384
+	}
385
+
386
+	/**
387
+	 * @param string $logicalSeparatorForGreaterThanOrEqual
388
+	 * @return $this
389
+	 */
390
+	public function setLogicalSeparatorForGreaterThanOrEqual($logicalSeparatorForGreaterThanOrEqual): self
391
+	{
392
+		$this->logicalSeparatorForGreaterThanOrEqual = $logicalSeparatorForGreaterThanOrEqual;
393
+		return $this;
394
+	}
395
+
396
+	/**
397
+	 * @return string
398
+	 */
399
+	public function getLogicalSeparatorForLessThan(): string
400
+	{
401
+		return $this->logicalSeparatorForLessThan;
402
+	}
403
+
404
+	/**
405
+	 * @param string $logicalSeparatorForLessThan
406
+	 * @return $this
407
+	 */
408
+	public function setLogicalSeparatorForLessThan($logicalSeparatorForLessThan): self
409
+	{
410
+		$this->logicalSeparatorForLessThan = $logicalSeparatorForLessThan;
411
+		return $this;
412
+	}
413
+
414
+	/**
415
+	 * @return string
416
+	 */
417
+	public function getLogicalSeparatorForLessThanOrEqual(): string
418
+	{
419
+		return $this->logicalSeparatorForLessThanOrEqual;
420
+	}
421
+
422
+	/**
423
+	 * @param string $logicalSeparatorForLessThanOrEqual
424
+	 * @return $this
425
+	 */
426
+	public function setLogicalSeparatorForLessThanOrEqual($logicalSeparatorForLessThanOrEqual): self
427
+	{
428
+		$this->logicalSeparatorForLessThanOrEqual = $logicalSeparatorForLessThanOrEqual;
429
+		return $this;
430
+	}
431
+
432
+	/**
433
+	 * @return string
434
+	 */
435
+	public function getLogicalSeparatorForIn(): string
436
+	{
437
+		return $this->logicalSeparatorForIn;
438
+	}
439
+
440
+	/**
441
+	 * @param string $logicalSeparatorForIn
442
+	 * @return $this
443
+	 */
444
+	public function setLogicalSeparatorForIn($logicalSeparatorForIn): self
445
+	{
446
+		$this->logicalSeparatorForIn = $logicalSeparatorForIn;
447
+		return $this;
448
+	}
449
+
450
+	/**
451
+	 * @return string
452
+	 */
453
+	public function getLogicalSeparatorForLike(): string
454
+	{
455
+		return $this->logicalSeparatorForLike;
456
+	}
457
+
458
+	/**
459
+	 * @param string $logicalSeparatorForLike
460
+	 * @return $this
461
+	 */
462
+	public function setLogicalSeparatorForLike($logicalSeparatorForLike): self
463
+	{
464
+		$this->logicalSeparatorForLike = $logicalSeparatorForLike;
465
+		return $this;
466
+	}
467
+
468
+	/**
469
+	 * @return string
470
+	 */
471
+	public function getLogicalSeparatorForSearchTerm(): string
472
+	{
473
+		return $this->logicalSeparatorForSearchTerm;
474
+	}
475
+
476
+	/**
477
+	 * @param string $logicalSeparatorForSearchTerm
478
+	 * @return $this
479
+	 */
480
+	public function setLogicalSeparatorForSearchTerm($logicalSeparatorForSearchTerm): self
481
+	{
482
+		$this->logicalSeparatorForSearchTerm = $logicalSeparatorForSearchTerm;
483
+		return $this;
484
+	}
485
+
486
+	/**
487
+	 * @return array
488
+	 */
489
+	public function getSupportedOperators(): array
490
+	{
491
+		return $this->supportedOperators;
492
+	}
493
+
494
+	/**
495
+	 * @return string
496
+	 */
497
+	public function getDataType(): string
498
+	{
499
+		return $this->dataType;
500
+	}
501
+
502
+	/**
503
+	 * @param string $dataType
504
+	 * @return $this
505
+	 */
506
+	public function setDataType($dataType): self
507
+	{
508
+		$this->dataType = $dataType;
509
+		return $this;
510
+	}
511 511
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -317,7 +317,7 @@
 block discarded – undo
317 317
     public function like($fieldNameAndPath, $operand, $addWildCard = true): self
318 318
     {
319 319
         $wildCardSymbol = $addWildCard ? '%' : '';
320
-        $this->like[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $wildCardSymbol . $operand . $wildCardSymbol];
320
+        $this->like[] = ['fieldNameAndPath' => $fieldNameAndPath, 'operand' => $wildCardSymbol.$operand.$wildCardSymbol];
321 321
         return $this;
322 322
     }
323 323
 
Please login to merge, or discard this patch.
Classes/Facet/StandardFacet.php 1 patch
Indentation   +139 added lines, -139 removed lines patch added patch discarded remove patch
@@ -20,144 +20,144 @@
 block discarded – undo
20 20
 class StandardFacet implements FacetInterface
21 21
 {
22 22
 
23
-    /**
24
-     * @var string
25
-     */
26
-    protected $name;
27
-
28
-    /**
29
-     * @var string
30
-     */
31
-    protected $label;
32
-
33
-    /**
34
-     * @var array
35
-     */
36
-    protected $suggestions = [];
37
-
38
-    /**
39
-     * @var string
40
-     */
41
-    protected $dataType;
42
-
43
-    /**
44
-     * @var bool
45
-     */
46
-    protected $canModifyMatcher = false;
47
-
48
-    /**
49
-     * Constructor of a Generic Facet in Vidi.
50
-     *
51
-     * @param string $name
52
-     * @param string $label
53
-     * @param array $suggestions
54
-     */
55
-    public function __construct($name, $label = '', array $suggestions = [])
56
-    {
57
-        $this->name = $name;
58
-        if (empty($label)) {
59
-            $label = $this->name;
60
-        }
61
-        $this->label = $label;
62
-        $this->suggestions = $suggestions;
63
-    }
64
-
65
-    /**
66
-     * @return string
67
-     */
68
-    public function getName(): string
69
-    {
70
-        return $this->name;
71
-    }
72
-
73
-    /**
74
-     * @return string
75
-     */
76
-    public function getLabel(): string
77
-    {
78
-        if ($this->label === $this->name) {
79
-            $label = Tca::table($this->dataType)->field($this->getName())->getLabel();
80
-        } else {
81
-            try {
82
-                $label = LocalizationUtility::translate($this->label, '');
83
-            } catch (\InvalidArgumentException $e) {
84
-            }
85
-            if (empty($label)) {
86
-                $label = $this->label;
87
-            }
88
-        }
89
-
90
-        return $label;
91
-    }
92
-
93
-    /**
94
-     * @return array
95
-     */
96
-    public function getSuggestions(): array
97
-    {
98
-
99
-        $values = [];
100
-        foreach ($this->suggestions as $key => $label) {
101
-            $localizedLabel = $this->getLanguageService()->sL($label);
102
-            if (!empty($localizedLabel)) {
103
-                $label = $localizedLabel;
104
-            }
105
-
106
-            $values[] = [$key => $label];
107
-        }
108
-
109
-        return $values;
110
-    }
111
-
112
-    /**
113
-     * @return LanguageService
114
-     */
115
-    protected function getLanguageService(): LanguageService
116
-    {
117
-        /** @var LanguageService $langService */
118
-        $langService = $GLOBALS['LANG'];
119
-        if (!$langService) {
120
-            $langService = GeneralUtility::makeInstance(LanguageService::class);
121
-            $langService->init('en');
122
-        }
123
-
124
-        return $langService;
125
-    }
126
-
127
-    /**
128
-     * @return bool
129
-     */
130
-    public function hasSuggestions(): bool
131
-    {
132
-        return !empty($this->suggestions);
133
-    }
134
-
135
-    /**
136
-     * @param string $dataType
137
-     * @return $this
138
-     */
139
-    public function setDataType($dataType): self
140
-    {
141
-        $this->dataType = $dataType;
142
-        return $this;
143
-    }
144
-
145
-    /**
146
-     * @return bool
147
-     */
148
-    public function canModifyMatcher(): bool
149
-    {
150
-        return $this->canModifyMatcher;
151
-    }
152
-
153
-    /**
154
-     * @param Matcher $matcher
155
-     * @param $value
156
-     * @return Matcher
157
-     */
158
-    public function modifyMatcher(Matcher $matcher, $value): Matcher
159
-    {
160
-        return $matcher;
161
-    }
23
+	/**
24
+	 * @var string
25
+	 */
26
+	protected $name;
27
+
28
+	/**
29
+	 * @var string
30
+	 */
31
+	protected $label;
32
+
33
+	/**
34
+	 * @var array
35
+	 */
36
+	protected $suggestions = [];
37
+
38
+	/**
39
+	 * @var string
40
+	 */
41
+	protected $dataType;
42
+
43
+	/**
44
+	 * @var bool
45
+	 */
46
+	protected $canModifyMatcher = false;
47
+
48
+	/**
49
+	 * Constructor of a Generic Facet in Vidi.
50
+	 *
51
+	 * @param string $name
52
+	 * @param string $label
53
+	 * @param array $suggestions
54
+	 */
55
+	public function __construct($name, $label = '', array $suggestions = [])
56
+	{
57
+		$this->name = $name;
58
+		if (empty($label)) {
59
+			$label = $this->name;
60
+		}
61
+		$this->label = $label;
62
+		$this->suggestions = $suggestions;
63
+	}
64
+
65
+	/**
66
+	 * @return string
67
+	 */
68
+	public function getName(): string
69
+	{
70
+		return $this->name;
71
+	}
72
+
73
+	/**
74
+	 * @return string
75
+	 */
76
+	public function getLabel(): string
77
+	{
78
+		if ($this->label === $this->name) {
79
+			$label = Tca::table($this->dataType)->field($this->getName())->getLabel();
80
+		} else {
81
+			try {
82
+				$label = LocalizationUtility::translate($this->label, '');
83
+			} catch (\InvalidArgumentException $e) {
84
+			}
85
+			if (empty($label)) {
86
+				$label = $this->label;
87
+			}
88
+		}
89
+
90
+		return $label;
91
+	}
92
+
93
+	/**
94
+	 * @return array
95
+	 */
96
+	public function getSuggestions(): array
97
+	{
98
+
99
+		$values = [];
100
+		foreach ($this->suggestions as $key => $label) {
101
+			$localizedLabel = $this->getLanguageService()->sL($label);
102
+			if (!empty($localizedLabel)) {
103
+				$label = $localizedLabel;
104
+			}
105
+
106
+			$values[] = [$key => $label];
107
+		}
108
+
109
+		return $values;
110
+	}
111
+
112
+	/**
113
+	 * @return LanguageService
114
+	 */
115
+	protected function getLanguageService(): LanguageService
116
+	{
117
+		/** @var LanguageService $langService */
118
+		$langService = $GLOBALS['LANG'];
119
+		if (!$langService) {
120
+			$langService = GeneralUtility::makeInstance(LanguageService::class);
121
+			$langService->init('en');
122
+		}
123
+
124
+		return $langService;
125
+	}
126
+
127
+	/**
128
+	 * @return bool
129
+	 */
130
+	public function hasSuggestions(): bool
131
+	{
132
+		return !empty($this->suggestions);
133
+	}
134
+
135
+	/**
136
+	 * @param string $dataType
137
+	 * @return $this
138
+	 */
139
+	public function setDataType($dataType): self
140
+	{
141
+		$this->dataType = $dataType;
142
+		return $this;
143
+	}
144
+
145
+	/**
146
+	 * @return bool
147
+	 */
148
+	public function canModifyMatcher(): bool
149
+	{
150
+		return $this->canModifyMatcher;
151
+	}
152
+
153
+	/**
154
+	 * @param Matcher $matcher
155
+	 * @param $value
156
+	 * @return Matcher
157
+	 */
158
+	public function modifyMatcher(Matcher $matcher, $value): Matcher
159
+	{
160
+		return $matcher;
161
+	}
162 162
 
163 163
 }
Please login to merge, or discard this patch.
Classes/Facet/PageFacet.php 1 patch
Indentation   +168 added lines, -168 removed lines patch added patch discarded remove patch
@@ -23,173 +23,173 @@
 block discarded – undo
23 23
 class PageFacet implements FacetInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var string
28
-     */
29
-    protected $name;
30
-
31
-    /**
32
-     * @var string
33
-     */
34
-    protected $label;
35
-
36
-    /**
37
-     * @var string
38
-     */
39
-    protected $dataType;
40
-
41
-    /**
42
-     * @var bool
43
-     */
44
-    protected $canModifyMatcher = false;
45
-
46
-    /**
47
-     * Constructor of a Generic Facet in Vidi.
48
-     *
49
-     * @param string $name
50
-     * @param string $label
51
-     */
52
-    public function __construct($name, $label = '')
53
-    {
54
-        $this->name = 'pid';
55
-        $this->label = $label;
56
-    }
57
-
58
-    /**
59
-     * @return string
60
-     */
61
-    public function getName(): string
62
-    {
63
-        return $this->name;
64
-    }
65
-
66
-    /**
67
-     * @return string
68
-     */
69
-    public function getLabel(): string
70
-    {
71
-        return $this->label;
72
-    }
73
-
74
-    /**
75
-     * @return array
76
-     */
77
-    public function getSuggestions(): array
78
-    {
79
-        $values = [];
80
-        foreach ($this->getStoragePages() as $page) {
81
-            $values[] = [
82
-                $page['uid'] => sprintf('%s (%s)', $page['title'], $page['uid'])
83
-            ];
84
-        }
85
-        return $values;
86
-    }
87
-
88
-    /**
89
-     * @return array
90
-     */
91
-    protected function getStoragePages(): array
92
-    {
93
-        /** @var QueryBuilder $query */
94
-        $query = $this->getQueryBuilder('pages');
95
-        $query->getRestrictions()->removeAll();
96
-        return $query->select('*')
97
-            ->from('pages')
98
-            ->where(
99
-                sprintf(
100
-                    'uid IN (SELECT DISTINCT(pid) FROM %s WHERE 1=1 %s)',
101
-                    $this->getModuleLoader()->getDataType(),
102
-                    BackendUtility::deleteClause($this->getModuleLoader()->getDataType()
103
-                    )
104
-                ),
105
-                BackendUtility::deleteClause('pages', '')
106
-            )
107
-            ->execute()
108
-            ->fetchAll();
109
-    }
110
-
111
-    /**
112
-     * @param string $tableName
113
-     * @return object|QueryBuilder
114
-     */
115
-    protected function getQueryBuilder($tableName): QueryBuilder
116
-    {
117
-        /** @var ConnectionPool $connectionPool */
118
-        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
119
-        return $connectionPool->getQueryBuilderForTable($tableName);
120
-    }
121
-
122
-    /**
123
-     * Returns a pointer to the database.
124
-     *
125
-     * @return \Fab\Vidi\Database\DatabaseConnection
126
-     */
127
-    protected function getDatabaseConnection()
128
-    {
129
-        return $GLOBALS['TYPO3_DB'];
130
-    }
131
-
132
-    /**
133
-     * @return LanguageService
134
-     */
135
-    protected function getLanguageService(): LanguageService
136
-    {
137
-
138
-        /** @var LanguageService $langService */
139
-        $langService = $GLOBALS['LANG'];
140
-        if (!$langService) {
141
-            $langService = GeneralUtility::makeInstance(LanguageService::class);
142
-            $langService->init('en');
143
-        }
144
-
145
-        return $langService;
146
-    }
147
-
148
-    /**
149
-     * @return bool
150
-     */
151
-    public function hasSuggestions(): bool
152
-    {
153
-        return true;
154
-    }
155
-
156
-    /**
157
-     * @param string $dataType
158
-     * @return $this
159
-     */
160
-    public function setDataType($dataType): self
161
-    {
162
-        $this->dataType = $dataType;
163
-        return $this;
164
-    }
165
-
166
-    /**
167
-     * @return bool
168
-     */
169
-    public function canModifyMatcher(): bool
170
-    {
171
-        return $this->canModifyMatcher;
172
-    }
173
-
174
-    /**
175
-     * @param Matcher $matcher
176
-     * @param $value
177
-     * @return Matcher
178
-     */
179
-    public function modifyMatcher(Matcher $matcher, $value): Matcher
180
-    {
181
-        return $matcher;
182
-    }
183
-
184
-    /**
185
-     * Get the Vidi Module Loader.
186
-     *
187
-     * @return ModuleLoader|object
188
-     * @throws \InvalidArgumentException
189
-     */
190
-    protected function getModuleLoader()
191
-    {
192
-        return GeneralUtility::makeInstance(ModuleLoader::class);
193
-    }
26
+	/**
27
+	 * @var string
28
+	 */
29
+	protected $name;
30
+
31
+	/**
32
+	 * @var string
33
+	 */
34
+	protected $label;
35
+
36
+	/**
37
+	 * @var string
38
+	 */
39
+	protected $dataType;
40
+
41
+	/**
42
+	 * @var bool
43
+	 */
44
+	protected $canModifyMatcher = false;
45
+
46
+	/**
47
+	 * Constructor of a Generic Facet in Vidi.
48
+	 *
49
+	 * @param string $name
50
+	 * @param string $label
51
+	 */
52
+	public function __construct($name, $label = '')
53
+	{
54
+		$this->name = 'pid';
55
+		$this->label = $label;
56
+	}
57
+
58
+	/**
59
+	 * @return string
60
+	 */
61
+	public function getName(): string
62
+	{
63
+		return $this->name;
64
+	}
65
+
66
+	/**
67
+	 * @return string
68
+	 */
69
+	public function getLabel(): string
70
+	{
71
+		return $this->label;
72
+	}
73
+
74
+	/**
75
+	 * @return array
76
+	 */
77
+	public function getSuggestions(): array
78
+	{
79
+		$values = [];
80
+		foreach ($this->getStoragePages() as $page) {
81
+			$values[] = [
82
+				$page['uid'] => sprintf('%s (%s)', $page['title'], $page['uid'])
83
+			];
84
+		}
85
+		return $values;
86
+	}
87
+
88
+	/**
89
+	 * @return array
90
+	 */
91
+	protected function getStoragePages(): array
92
+	{
93
+		/** @var QueryBuilder $query */
94
+		$query = $this->getQueryBuilder('pages');
95
+		$query->getRestrictions()->removeAll();
96
+		return $query->select('*')
97
+			->from('pages')
98
+			->where(
99
+				sprintf(
100
+					'uid IN (SELECT DISTINCT(pid) FROM %s WHERE 1=1 %s)',
101
+					$this->getModuleLoader()->getDataType(),
102
+					BackendUtility::deleteClause($this->getModuleLoader()->getDataType()
103
+					)
104
+				),
105
+				BackendUtility::deleteClause('pages', '')
106
+			)
107
+			->execute()
108
+			->fetchAll();
109
+	}
110
+
111
+	/**
112
+	 * @param string $tableName
113
+	 * @return object|QueryBuilder
114
+	 */
115
+	protected function getQueryBuilder($tableName): QueryBuilder
116
+	{
117
+		/** @var ConnectionPool $connectionPool */
118
+		$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
119
+		return $connectionPool->getQueryBuilderForTable($tableName);
120
+	}
121
+
122
+	/**
123
+	 * Returns a pointer to the database.
124
+	 *
125
+	 * @return \Fab\Vidi\Database\DatabaseConnection
126
+	 */
127
+	protected function getDatabaseConnection()
128
+	{
129
+		return $GLOBALS['TYPO3_DB'];
130
+	}
131
+
132
+	/**
133
+	 * @return LanguageService
134
+	 */
135
+	protected function getLanguageService(): LanguageService
136
+	{
137
+
138
+		/** @var LanguageService $langService */
139
+		$langService = $GLOBALS['LANG'];
140
+		if (!$langService) {
141
+			$langService = GeneralUtility::makeInstance(LanguageService::class);
142
+			$langService->init('en');
143
+		}
144
+
145
+		return $langService;
146
+	}
147
+
148
+	/**
149
+	 * @return bool
150
+	 */
151
+	public function hasSuggestions(): bool
152
+	{
153
+		return true;
154
+	}
155
+
156
+	/**
157
+	 * @param string $dataType
158
+	 * @return $this
159
+	 */
160
+	public function setDataType($dataType): self
161
+	{
162
+		$this->dataType = $dataType;
163
+		return $this;
164
+	}
165
+
166
+	/**
167
+	 * @return bool
168
+	 */
169
+	public function canModifyMatcher(): bool
170
+	{
171
+		return $this->canModifyMatcher;
172
+	}
173
+
174
+	/**
175
+	 * @param Matcher $matcher
176
+	 * @param $value
177
+	 * @return Matcher
178
+	 */
179
+	public function modifyMatcher(Matcher $matcher, $value): Matcher
180
+	{
181
+		return $matcher;
182
+	}
183
+
184
+	/**
185
+	 * Get the Vidi Module Loader.
186
+	 *
187
+	 * @return ModuleLoader|object
188
+	 * @throws \InvalidArgumentException
189
+	 */
190
+	protected function getModuleLoader()
191
+	{
192
+		return GeneralUtility::makeInstance(ModuleLoader::class);
193
+	}
194 194
 
195 195
 }
Please login to merge, or discard this patch.
Classes/Facet/FacetSuggestionService.php 1 patch
Indentation   +106 added lines, -106 removed lines patch added patch discarded remove patch
@@ -19,111 +19,111 @@
 block discarded – undo
19 19
 class FacetSuggestionService
20 20
 {
21 21
 
22
-    /**
23
-     * Retrieve possible suggestions for a field name
24
-     *
25
-     * @param string $fieldNameAndPath
26
-     * @return array
27
-     */
28
-    public function getSuggestions($fieldNameAndPath): array
29
-    {
30
-        $values = [];
31
-
32
-        $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath);
33
-        $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath);
34
-
35
-        if (Tca::grid()->facet($fieldNameAndPath)->hasSuggestions()) {
36
-            $values = Tca::grid()->facet($fieldNameAndPath)->getSuggestions();
37
-        } else if (Tca::table($dataType)->hasField($fieldName)) {
38
-
39
-            if (Tca::table($dataType)->field($fieldName)->hasRelation()) {
40
-
41
-                // Fetch the adequate repository
42
-                $foreignTable = Tca::table($dataType)->field($fieldName)->getForeignTable();
43
-                $contentRepository = ContentRepositoryFactory::getInstance($foreignTable);
44
-                $table = Tca::table($foreignTable);
45
-
46
-                // Initialize the matcher object.
47
-                $matcher = MatcherObjectFactory::getInstance()->getMatcher([], $foreignTable);
48
-
49
-                $numberOfValues = $contentRepository->countBy($matcher);
50
-                if ($numberOfValues <= $this->getLimit()) {
51
-
52
-                    $contents = $contentRepository->findBy($matcher);
53
-
54
-                    foreach ($contents as $content) {
55
-                        $values[] = array($content->getUid() => $content[$table->getLabelField()]);
56
-                    }
57
-                }
58
-            } elseif (!Tca::table($dataType)->field($fieldName)->isTextArea()) { // We don't want suggestion if field is text area.
59
-
60
-                // Fetch the adequate repository
61
-                /** @var \Fab\Vidi\Domain\Repository\ContentRepository $contentRepository */
62
-                $contentRepository = ContentRepositoryFactory::getInstance($dataType);
63
-
64
-                // Initialize some objects related to the query
65
-                $matcher = MatcherObjectFactory::getInstance()->getMatcher([], $dataType);
66
-
67
-                // Count the number of objects.
68
-                $numberOfValues = $contentRepository->countDistinctValues($fieldName, $matcher);
69
-
70
-                // Only returns suggestion if there are not too many for the browser.
71
-                if ($numberOfValues <= $this->getLimit()) {
72
-
73
-                    // Query the repository.
74
-                    $contents = $contentRepository->findDistinctValues($fieldName, $matcher);
75
-
76
-                    foreach ($contents as $content) {
77
-
78
-                        $value = $content[$fieldName];
79
-                        $label = $content[$fieldName];
80
-                        if (Tca::table($dataType)->field($fieldName)->isSelect()) {
81
-                            $label = Tca::table($dataType)->field($fieldName)->getLabelForItem($value);
82
-                        }
83
-
84
-                        $values[] = $label;
85
-                    }
86
-                }
87
-            }
88
-        }
89
-        return $values;
90
-    }
91
-
92
-    /**
93
-     * Return from settings the suggestion limit.
94
-     *
95
-     * @return int
96
-     */
97
-    protected function getLimit(): int
98
-    {
99
-        $settings = $this->getSettings();
100
-        $suggestionLimit = (int)$settings['suggestionLimit'];
101
-        if ($suggestionLimit <= 0) {
102
-            $suggestionLimit = 1000;
103
-        }
104
-        return $suggestionLimit;
105
-    }
106
-
107
-    /**
108
-     * @return \Fab\Vidi\Resolver\FieldPathResolver|object
109
-     */
110
-    protected function getFieldPathResolver()
111
-    {
112
-        return GeneralUtility::makeInstance(\Fab\Vidi\Resolver\FieldPathResolver::class);
113
-    }
114
-
115
-    /**
116
-     * Returns the module settings.
117
-     *
118
-     * @return array
119
-     */
120
-    protected function getSettings()
121
-    {
122
-        /** @var \TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager $backendConfigurationManager */
123
-        $objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
124
-        $backendConfigurationManager = $objectManager->get('TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager');
125
-        $configuration = $backendConfigurationManager->getTypoScriptSetup();
126
-        return $configuration['module.']['tx_vidi.']['settings.'];
127
-    }
22
+	/**
23
+	 * Retrieve possible suggestions for a field name
24
+	 *
25
+	 * @param string $fieldNameAndPath
26
+	 * @return array
27
+	 */
28
+	public function getSuggestions($fieldNameAndPath): array
29
+	{
30
+		$values = [];
31
+
32
+		$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath);
33
+		$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath);
34
+
35
+		if (Tca::grid()->facet($fieldNameAndPath)->hasSuggestions()) {
36
+			$values = Tca::grid()->facet($fieldNameAndPath)->getSuggestions();
37
+		} else if (Tca::table($dataType)->hasField($fieldName)) {
38
+
39
+			if (Tca::table($dataType)->field($fieldName)->hasRelation()) {
40
+
41
+				// Fetch the adequate repository
42
+				$foreignTable = Tca::table($dataType)->field($fieldName)->getForeignTable();
43
+				$contentRepository = ContentRepositoryFactory::getInstance($foreignTable);
44
+				$table = Tca::table($foreignTable);
45
+
46
+				// Initialize the matcher object.
47
+				$matcher = MatcherObjectFactory::getInstance()->getMatcher([], $foreignTable);
48
+
49
+				$numberOfValues = $contentRepository->countBy($matcher);
50
+				if ($numberOfValues <= $this->getLimit()) {
51
+
52
+					$contents = $contentRepository->findBy($matcher);
53
+
54
+					foreach ($contents as $content) {
55
+						$values[] = array($content->getUid() => $content[$table->getLabelField()]);
56
+					}
57
+				}
58
+			} elseif (!Tca::table($dataType)->field($fieldName)->isTextArea()) { // We don't want suggestion if field is text area.
59
+
60
+				// Fetch the adequate repository
61
+				/** @var \Fab\Vidi\Domain\Repository\ContentRepository $contentRepository */
62
+				$contentRepository = ContentRepositoryFactory::getInstance($dataType);
63
+
64
+				// Initialize some objects related to the query
65
+				$matcher = MatcherObjectFactory::getInstance()->getMatcher([], $dataType);
66
+
67
+				// Count the number of objects.
68
+				$numberOfValues = $contentRepository->countDistinctValues($fieldName, $matcher);
69
+
70
+				// Only returns suggestion if there are not too many for the browser.
71
+				if ($numberOfValues <= $this->getLimit()) {
72
+
73
+					// Query the repository.
74
+					$contents = $contentRepository->findDistinctValues($fieldName, $matcher);
75
+
76
+					foreach ($contents as $content) {
77
+
78
+						$value = $content[$fieldName];
79
+						$label = $content[$fieldName];
80
+						if (Tca::table($dataType)->field($fieldName)->isSelect()) {
81
+							$label = Tca::table($dataType)->field($fieldName)->getLabelForItem($value);
82
+						}
83
+
84
+						$values[] = $label;
85
+					}
86
+				}
87
+			}
88
+		}
89
+		return $values;
90
+	}
91
+
92
+	/**
93
+	 * Return from settings the suggestion limit.
94
+	 *
95
+	 * @return int
96
+	 */
97
+	protected function getLimit(): int
98
+	{
99
+		$settings = $this->getSettings();
100
+		$suggestionLimit = (int)$settings['suggestionLimit'];
101
+		if ($suggestionLimit <= 0) {
102
+			$suggestionLimit = 1000;
103
+		}
104
+		return $suggestionLimit;
105
+	}
106
+
107
+	/**
108
+	 * @return \Fab\Vidi\Resolver\FieldPathResolver|object
109
+	 */
110
+	protected function getFieldPathResolver()
111
+	{
112
+		return GeneralUtility::makeInstance(\Fab\Vidi\Resolver\FieldPathResolver::class);
113
+	}
114
+
115
+	/**
116
+	 * Returns the module settings.
117
+	 *
118
+	 * @return array
119
+	 */
120
+	protected function getSettings()
121
+	{
122
+		/** @var \TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager $backendConfigurationManager */
123
+		$objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
124
+		$backendConfigurationManager = $objectManager->get('TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager');
125
+		$configuration = $backendConfigurationManager->getTypoScriptSetup();
126
+		return $configuration['module.']['tx_vidi.']['settings.'];
127
+	}
128 128
 
129 129
 }
Please login to merge, or discard this patch.
Classes/Facet/CompositeFacet.php 1 patch
Indentation   +159 added lines, -159 removed lines patch added patch discarded remove patch
@@ -20,164 +20,164 @@
 block discarded – undo
20 20
 class CompositeFacet implements FacetInterface
21 21
 {
22 22
 
23
-    /**
24
-     * @var string
25
-     */
26
-    protected $name;
27
-
28
-    /**
29
-     * @var string
30
-     */
31
-    protected $label;
32
-
33
-    /**
34
-     * @var array
35
-     */
36
-    protected $suggestions = [
37
-        '0' => 'LLL:EXT:vidi/Resources/Private/Language/locallang.xlf:active.0',
38
-    ];
39
-
40
-    /**
41
-     * @var array
42
-     */
43
-    protected $configuration = [];
44
-
45
-    /**
46
-     * @var string
47
-     */
48
-    protected $dataType;
49
-
50
-    /**
51
-     * @var bool
52
-     */
53
-    protected $canModifyMatcher = true;
54
-
55
-    /**
56
-     * Constructor of a Generic Facet in Vidi.
57
-     *
58
-     * @param string $name
59
-     * @param string $label
60
-     * @param array $suggestions
61
-     * @param array $configuration
62
-     */
63
-    public function __construct($name, $label = '', array $suggestions = [], $configuration = [])
64
-    {
65
-        $this->name = $name;
66
-        if (empty($label)) {
67
-            $label = $this->name;
68
-        }
69
-        $this->label = $label;
70
-        if ($suggestions) {
71
-            $this->suggestions = $suggestions;
72
-        }
73
-        if ($configuration) {
74
-            $this->configuration = $configuration;
75
-        }
76
-    }
77
-
78
-    /**
79
-     * @return string
80
-     */
81
-    public function getName(): string
82
-    {
83
-        return $this->name;
84
-    }
85
-
86
-    /**
87
-     * @return string
88
-     */
89
-    public function getLabel(): string
90
-    {
91
-        if ($this->label === $this->name) {
92
-            $label = Tca::table($this->dataType)->field($this->getName())->getLabel();
93
-        } else {
94
-            try {
95
-                $label = LocalizationUtility::translate($this->label, '');
96
-            } catch (\InvalidArgumentException $e) {
97
-            }
98
-            if (empty($label)) {
99
-                $label = $this->label;
100
-            }
101
-        }
102
-
103
-        return $label;
104
-    }
105
-
106
-    /**
107
-     * @return array
108
-     */
109
-    public function getSuggestions(): array
110
-    {
111
-
112
-        $values = [];
113
-        foreach ($this->suggestions as $key => $label) {
114
-            $localizedLabel = $this->getLanguageService()->sL($label);
115
-            if (!empty($localizedLabel)) {
116
-                $label = $localizedLabel;
117
-            }
118
-
119
-            $values[] = [$key => $label];
120
-        }
121
-
122
-        return $values;
123
-    }
124
-
125
-    /**
126
-     * @return LanguageService
127
-     */
128
-    protected function getLanguageService(): LanguageService
129
-    {
130
-        /** @var LanguageService $langService */
131
-        $langService = $GLOBALS['LANG'];
132
-        if (!$langService) {
133
-            $langService = GeneralUtility::makeInstance(LanguageService::class);
134
-            $langService->init('en');
135
-        }
136
-
137
-        return $langService;
138
-    }
139
-
140
-    /**
141
-     * @return bool
142
-     */
143
-    public function hasSuggestions(): bool
144
-    {
145
-        return !empty($this->suggestions);
146
-    }
147
-
148
-    /**
149
-     * @param string $dataType
150
-     * @return $this
151
-     */
152
-    public function setDataType($dataType): self
153
-    {
154
-        $this->dataType = $dataType;
155
-        return $this;
156
-    }
157
-
158
-    /**
159
-     * @return bool
160
-     */
161
-    public function canModifyMatcher(): bool
162
-    {
163
-        return $this->canModifyMatcher;
164
-    }
165
-
166
-    /**
167
-     * @param Matcher $matcher
168
-     * @param $value
169
-     * @return Matcher
170
-     */
171
-    public function modifyMatcher(Matcher $matcher, $value): Matcher
172
-    {
173
-        foreach ($this->configuration as $fieldNameAndPath => $operand) {
174
-            if ($operand === '*') {
175
-                $matcher->notEquals($fieldNameAndPath, '');
176
-            } else {
177
-                $matcher->equals($fieldNameAndPath, $operand);
178
-            }
179
-        }
180
-        return $matcher;
181
-    }
23
+	/**
24
+	 * @var string
25
+	 */
26
+	protected $name;
27
+
28
+	/**
29
+	 * @var string
30
+	 */
31
+	protected $label;
32
+
33
+	/**
34
+	 * @var array
35
+	 */
36
+	protected $suggestions = [
37
+		'0' => 'LLL:EXT:vidi/Resources/Private/Language/locallang.xlf:active.0',
38
+	];
39
+
40
+	/**
41
+	 * @var array
42
+	 */
43
+	protected $configuration = [];
44
+
45
+	/**
46
+	 * @var string
47
+	 */
48
+	protected $dataType;
49
+
50
+	/**
51
+	 * @var bool
52
+	 */
53
+	protected $canModifyMatcher = true;
54
+
55
+	/**
56
+	 * Constructor of a Generic Facet in Vidi.
57
+	 *
58
+	 * @param string $name
59
+	 * @param string $label
60
+	 * @param array $suggestions
61
+	 * @param array $configuration
62
+	 */
63
+	public function __construct($name, $label = '', array $suggestions = [], $configuration = [])
64
+	{
65
+		$this->name = $name;
66
+		if (empty($label)) {
67
+			$label = $this->name;
68
+		}
69
+		$this->label = $label;
70
+		if ($suggestions) {
71
+			$this->suggestions = $suggestions;
72
+		}
73
+		if ($configuration) {
74
+			$this->configuration = $configuration;
75
+		}
76
+	}
77
+
78
+	/**
79
+	 * @return string
80
+	 */
81
+	public function getName(): string
82
+	{
83
+		return $this->name;
84
+	}
85
+
86
+	/**
87
+	 * @return string
88
+	 */
89
+	public function getLabel(): string
90
+	{
91
+		if ($this->label === $this->name) {
92
+			$label = Tca::table($this->dataType)->field($this->getName())->getLabel();
93
+		} else {
94
+			try {
95
+				$label = LocalizationUtility::translate($this->label, '');
96
+			} catch (\InvalidArgumentException $e) {
97
+			}
98
+			if (empty($label)) {
99
+				$label = $this->label;
100
+			}
101
+		}
102
+
103
+		return $label;
104
+	}
105
+
106
+	/**
107
+	 * @return array
108
+	 */
109
+	public function getSuggestions(): array
110
+	{
111
+
112
+		$values = [];
113
+		foreach ($this->suggestions as $key => $label) {
114
+			$localizedLabel = $this->getLanguageService()->sL($label);
115
+			if (!empty($localizedLabel)) {
116
+				$label = $localizedLabel;
117
+			}
118
+
119
+			$values[] = [$key => $label];
120
+		}
121
+
122
+		return $values;
123
+	}
124
+
125
+	/**
126
+	 * @return LanguageService
127
+	 */
128
+	protected function getLanguageService(): LanguageService
129
+	{
130
+		/** @var LanguageService $langService */
131
+		$langService = $GLOBALS['LANG'];
132
+		if (!$langService) {
133
+			$langService = GeneralUtility::makeInstance(LanguageService::class);
134
+			$langService->init('en');
135
+		}
136
+
137
+		return $langService;
138
+	}
139
+
140
+	/**
141
+	 * @return bool
142
+	 */
143
+	public function hasSuggestions(): bool
144
+	{
145
+		return !empty($this->suggestions);
146
+	}
147
+
148
+	/**
149
+	 * @param string $dataType
150
+	 * @return $this
151
+	 */
152
+	public function setDataType($dataType): self
153
+	{
154
+		$this->dataType = $dataType;
155
+		return $this;
156
+	}
157
+
158
+	/**
159
+	 * @return bool
160
+	 */
161
+	public function canModifyMatcher(): bool
162
+	{
163
+		return $this->canModifyMatcher;
164
+	}
165
+
166
+	/**
167
+	 * @param Matcher $matcher
168
+	 * @param $value
169
+	 * @return Matcher
170
+	 */
171
+	public function modifyMatcher(Matcher $matcher, $value): Matcher
172
+	{
173
+		foreach ($this->configuration as $fieldNameAndPath => $operand) {
174
+			if ($operand === '*') {
175
+				$matcher->notEquals($fieldNameAndPath, '');
176
+			} else {
177
+				$matcher->equals($fieldNameAndPath, $operand);
178
+			}
179
+		}
180
+		return $matcher;
181
+	}
182 182
 
183 183
 }
Please login to merge, or discard this patch.