Completed
Pull Request — master (#450)
by
unknown
02:09
created

IndexRepository::getStoragePageIds()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.2728
c 0
b 0
f 0
cc 5
nc 7
nop 0
1
<?php
2
3
/**
4
 * Index repository.
5
 */
6
declare(strict_types=1);
7
8
namespace HDNET\Calendarize\Domain\Repository;
9
10
use Exception;
11
use HDNET\Calendarize\Domain\Model\Index;
12
use HDNET\Calendarize\Domain\Model\Request\OptionRequest;
13
use HDNET\Calendarize\Utility\ConfigurationUtility;
14
use HDNET\Calendarize\Utility\DateTimeUtility;
15
use HDNET\Calendarize\Utility\ExtensionConfigurationUtility;
16
use TYPO3\CMS\Core\Database\ConnectionPool;
17
use TYPO3\CMS\Core\Utility\GeneralUtility;
18
use TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager;
19
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
20
use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
21
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
22
23
/**
24
 * Index repository.
25
 */
26
class IndexRepository extends AbstractRepository
27
{
28
    /**
29
     * Default orderings for index records.
30
     *
31
     * @var array
32
     */
33
    protected $defaultOrderings = [
34
        'start_date' => QueryInterface::ORDER_ASCENDING,
35
        'start_time' => QueryInterface::ORDER_ASCENDING,
36
    ];
37
38
    /**
39
     * Index types for selection.
40
     *
41
     * @var array
42
     */
43
    protected $indexTypes = [];
44
45
    /**
46
     * Override page ids.
47
     *
48
     * @var array
49
     */
50
    protected $overridePageIds;
51
52
    /**
53
     * Create query.
54
     *
55
     * @return QueryInterface
56
     */
57
    public function createQuery()
58
    {
59
        $query = parent::createQuery();
60
        $query->getQuerySettings()->setLanguageMode($this->getIndexLanguageMode());
61
62
        return $query;
63
    }
64
65
    /**
66
     * Set the index types.
67
     *
68
     * @param array $types
69
     */
70
    public function setIndexTypes(array $types)
71
    {
72
        $this->indexTypes = $types;
73
    }
74
75
    /**
76
     * Override page IDs.
77
     *
78
     * @param array $overridePageIds
79
     */
80
    public function setOverridePageIds($overridePageIds)
81
    {
82
        $this->overridePageIds = $overridePageIds;
83
    }
84
85
    /**
86
     * Select indecies for Backend.
87
     *
88
     * @param OptionRequest $options
89
     *
90
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
91
     */
92
    public function findAllForBackend(OptionRequest $options)
93
    {
94
        $query = $this->createQuery();
95
        $query->getQuerySettings()->setIgnoreEnableFields(true);
96
        $query->getQuerySettings()->setRespectSysLanguage(false);
97
        $query->getQuerySettings()->setLanguageOverlayMode(false);
98
        $query->getQuerySettings()->setLanguageMode('ignore');
99
100
        // Notice Selection without any language handling
101
        unset($GLOBALS['TCA']['tx_calendarize_domain_model_index']['ctrl']['languageField'], $GLOBALS['TCA']['tx_calendarize_domain_model_index']['ctrl']['transOrigPointerField']);
102
103
        if ('asc' === $options->getDirection()) {
104
            $query->setOrderings([
105
                'start_date' => QueryInterface::ORDER_ASCENDING,
106
                'start_time' => QueryInterface::ORDER_ASCENDING,
107
            ]);
108
        } else {
109
            $query->setOrderings([
110
                'start_date' => QueryInterface::ORDER_DESCENDING,
111
                'start_time' => QueryInterface::ORDER_DESCENDING,
112
            ]);
113
        }
114
115
        if ((int)$options->getPid() > 0) {
116
            $query->matching($query->equals('pid', (int)$options->getPid()));
117
        }
118
119
        return $query->execute();
120
    }
121
122
    /**
123
     * Find List.
124
     *
125
     * @param int        $limit
126
     * @param int|string $listStartTime
127
     * @param int        $startOffsetHours
128
     * @param int        $overrideStartDate
129
     * @param int        $overrideEndDate
130
     *
131
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
132
     */
133
    public function findList(
134
        $limit = 0,
135
        $listStartTime = 0,
136
        $startOffsetHours = 0,
137
        $overrideStartDate = 0,
138
        $overrideEndDate = 0
139
    ) {
140
        if ($overrideStartDate > 0) {
141
            $startTimestamp = $overrideStartDate;
142
        } else {
143
            $now = DateTimeUtility::getNow();
144
            if ('now' !== $listStartTime) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of 'now' (string) and $listStartTime (integer) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
145
                $now->setTime(0, 0, 0);
146
            }
147
            $now->modify($startOffsetHours . ' hours');
148
            $startTimestamp = $now->getTimestamp();
149
        }
150
        $endTimestamp = null;
151
        if ($overrideEndDate > 0) {
152
            $endTimestamp = $overrideEndDate;
153
        }
154
155
        $result = $this->findByTimeSlot($startTimestamp, $endTimestamp);
156
        if ($limit > 0) {
157
            $query = $result->getQuery();
158
            $query->setLimit($limit);
159
            $result = $query->execute();
160
        }
161
162
        return $result;
163
    }
164
165
    /**
166
     * Find by custom search.
167
     *
168
     * @param \DateTime $startDate
169
     * @param \DateTime $endDate
170
     * @param array     $customSearch
171
     * @param int       $limit
172
     *
173
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
174
     */
175
    public function findBySearch(\DateTime $startDate = null, \DateTime $endDate = null, array $customSearch = [], int $limit = 0)
176
    {
177
        $arguments = [
178
            'indexIds' => [],
179
            'startDate' => $startDate,
180
            'endDate' => $endDate,
181
            'customSearch' => $customSearch,
182
            'indexTypes' => $this->indexTypes,
183
            'emptyPreResult' => false,
184
        ];
185
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__ . 'Pre', $arguments);
186
187
        $query = $this->createQuery();
188
        $constraints = $this->getDefaultConstraints($query);
189
190
        if ($limit > 0) {
191
            $query->setLimit($limit);
192
        }
193
194
        $this->addTimeFrameConstraints(
195
            $constraints,
196
            $query,
197
            $arguments['startDate'] instanceof \DateTime ? DateTimeUtility::getDayStart($arguments['startDate'])->getTimestamp() : null,
198
            $arguments['endDate'] instanceof \DateTime ? DateTimeUtility::getDayEnd($arguments['endDate'])->getTimestamp() : null
199
        );
200
201
        if ($arguments['indexIds']) {
202
            $indexIds = [];
203
            $tabledIndexIds = [];
204
            foreach ($arguments['indexIds'] as $key => $indexId) {
205
                if (is_int($key)) {
206
                    // Plain integers (= deprecated old way, stays in for compatibility)
207
                    $indexIds[] = $indexId;
208
                } elseif (is_string($key) && is_array($indexId)) {
209
                    // Table based values with array of foreign uids
210
                    $tabledIndexIds[] = [
211
                        'table' => $key,
212
                        'indexIds' => $indexId
213
                    ];
214
                } elseif (is_string($key) && is_int($indexId)) {
215
                    // Table based single return value
216
                    $tabledIndexIds[] = [
217
                         'table' => $key,
218
                         'indexIds' => [$indexId]
219
                    ];
220
                }
221
            }
222
            $foreignIdConstraints = [];
223
            // Old way, just accept foreignUids as provided, not checking the table.
224
            // This has a caveat solved with the $tabledIndexIds
225
            if ($indexIds) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $indexIds of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
226
                $foreignIdConstraints[] = $query->in('foreignUid', $indexIds);
227
            }
228
            if ($tabledIndexIds) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $tabledIndexIds of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
229
                // Handle each table individually on the filters
230
                // allowing for uids to be table specific.
231
                // If 1,3,5 on table_a are ok and 4,5,7 on table_b are ok,
232
                // don't show uid 1 from table_b
233
                foreach ($tabledIndexIds as $tabledIndexId) {
234
                    if ($tabledIndexId['indexIds']) {
235
                        // This table has used filters and returned some allowed uids.
236
                        // Providing non-existing values e.g.: -1 will remove everything
237
                        // unless other elements have found elements with the filters
238
                        $foreignIdConstraints[] = $query->logicalAnd([
239
                            $query->equals('foreignTable', $tabledIndexId['table']),
240
                            $query->in('foreignUid', $tabledIndexId['indexIds'])
241
                        ]);
242
                    }
243
                }
244
            }
245
            if (count($foreignIdConstraints) > 1) {
246
                // Multiple valid tables should be grouped by "OR"
247
                // so it's either table_a with uids 1,3,4 OR table_b with uids 1,5,7
248
                $foreignIdConstraint = $query->logicalOr($foreignIdConstraints);
249
            } else {
250
                // Single constraint or no constraint should just be simply added
251
                $foreignIdConstraint = array_shift($foreignIdConstraints);
252
            }
253
            // If any foreignUid constraint survived, use it on the query
254
            if ($foreignIdConstraint) {
255
                $constraints[] = $foreignIdConstraint;
256
            }
257
        }
258
        if ($arguments['emptyPreResult']) {
259
            $constraints[] = $query->equals('uid', '-1');
260
        }
261
        $result = [
262
            'result' => $this->matchAndExecute($query, $constraints),
263
        ];
264
265
        $result = $this->callSignal(__CLASS__, __FUNCTION__ . 'Post', $result);
266
267
        return $result['result'];
268
    }
269
270
    /**
271
     * Find Past Events.
272
     *
273
     * @param int    $limit
274
     * @param string $sort
275
     *
276
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
277
     */
278
    public function findByPast(
279
        $limit,
280
        $sort
281
    ) {
282
        //create Query
283
        $query = $this->createQuery();
284
        //Get actual datetime
285
        $now = DateTimeUtility::getNow()->getTimestamp();
286
287
        $constraints = $this->getDefaultConstraints($query);
288
        $constraints[] = $query->lessThanOrEqual('startDate', $now);
289
        $sort = QueryInterface::ORDER_ASCENDING === $sort ? QueryInterface::ORDER_ASCENDING : QueryInterface::ORDER_DESCENDING;
290
        $query->setOrderings($this->getSorting($sort));
291
        $query->setLimit($limit);
292
293
        return $this->matchAndExecute($query, $constraints);
294
    }
295
296
    /**
297
     * Find by traversing information.
298
     *
299
     * @param Index      $index
300
     * @param bool|true  $future
301
     * @param bool|false $past
302
     * @param int        $limit
303
     * @param string     $sort
304
     * @param bool       $useIndexTime
305
     *
306
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
307
     */
308
    public function findByTraversing(
309
        Index $index,
310
        $future = true,
311
        $past = false,
312
        $limit = 100,
313
        $sort = QueryInterface::ORDER_ASCENDING,
314
        $useIndexTime = false
315
    ) {
316
        if (!$future && !$past) {
317
            return [];
318
        }
319
        $query = $this->createQuery();
320
321
        $now = DateTimeUtility::getNow()
322
            ->getTimestamp();
323
        if ($useIndexTime) {
324
            $now = $index->getStartDate()->getTimestamp();
325
        }
326
327
        $constraints = [];
328
        $constraints[] = $query->logicalNot($query->equals('uid', $index->getUid()));
329
        $constraints[] = $query->equals('foreignTable', $index->getForeignTable());
330
        $constraints[] = $query->equals('foreignUid', $index->getForeignUid());
331
        if (!$future) {
332
            $constraints[] = $query->lessThanOrEqual('startDate', $now);
333
        }
334
        if (!$past) {
335
            $constraints[] = $query->greaterThanOrEqual('startDate', $now);
336
        }
337
338
        $query->setLimit($limit);
339
        $sort = QueryInterface::ORDER_ASCENDING === $sort ? QueryInterface::ORDER_ASCENDING : QueryInterface::ORDER_DESCENDING;
340
        $query->setOrderings($this->getSorting($sort));
341
342
        return $this->matchAndExecute($query, $constraints);
343
    }
344
345
    /**
346
     * Find by traversing information.
347
     *
348
     * @param DomainObjectInterface $event
349
     * @param bool|true             $future
350
     * @param bool|false            $past
351
     * @param int                   $limit
352
     * @param string                $sort
353
     *
354
     * @throws Exception
355
     *
356
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
357
     */
358
    public function findByEventTraversing(
359
        DomainObjectInterface $event,
360
        $future = true,
361
        $past = false,
362
        $limit = 100,
363
        $sort = QueryInterface::ORDER_ASCENDING
364
    ) {
365
        if (!$future && !$past) {
366
            return [];
367
        }
368
        $query = $this->createQuery();
369
370
        $uniqueRegisterKey = ExtensionConfigurationUtility::getUniqueRegisterKeyForModel($event);
371
372
        $this->setIndexTypes([$uniqueRegisterKey]);
373
374
        $now = DateTimeUtility::getNow()
375
            ->getTimestamp();
376
377
        $constraints = [];
378
379
        $localizedUid = $event->_getProperty('_localizedUid');
380
        $selectUid = $localizedUid ? $localizedUid : $event->getUid();
381
382
        $constraints[] = $query->equals('foreignUid', $selectUid);
383
        $constraints[] = $query->in('uniqueRegisterKey', $this->indexTypes);
384
        if (!$future) {
385
            $constraints[] = $query->lessThanOrEqual('startDate', $now);
386
        }
387
        if (!$past) {
388
            $constraints[] = $query->greaterThanOrEqual('startDate', $now);
389
        }
390
391
        $query->setLimit($limit);
392
        $sort = QueryInterface::ORDER_ASCENDING === $sort ? QueryInterface::ORDER_ASCENDING : QueryInterface::ORDER_DESCENDING;
393
        $query->setOrderings($this->getSorting($sort));
394
395
        return $this->matchAndExecute($query, $constraints);
396
    }
397
398
    /**
399
     * find Year.
400
     *
401
     * @param int $year
402
     *
403
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
404
     */
405
    public function findYear(int $year)
406
    {
407
        return $this->findByTimeSlot(\mktime(0, 0, 0, 1, 1, $year), \mktime(0, 0, 0, 1, 1, $year + 1) - 1);
408
    }
409
410
    /**
411
     * find quarter.
412
     *
413
     * @param int $year
414
     * @param int $quarter
415
     *
416
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
417
     */
418
    public function findQuarter(int $year, int $quarter)
419
    {
420
        $startMonth = 1 + (3 * ($quarter - 1));
421
422
        return $this->findByTimeSlot(\mktime(0, 0, 0, $startMonth, 1, $year), \mktime(0, 0, 0, $startMonth + 3, 1, $year) - 1);
423
    }
424
425
    /**
426
     * find Month.
427
     *
428
     * @param int $year
429
     * @param int $month
430
     *
431
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
432
     */
433
    public function findMonth(int $year, int $month)
434
    {
435
        $startTime = \mktime(0, 0, 0, $month, 1, $year);
436
        $endTime = \mktime(0, 0, 0, $month + 1, 1, $year) - 1;
437
438
        return $this->findByTimeSlot($startTime, $endTime);
439
    }
440
441
    /**
442
     * find Week.
443
     *
444
     * @param int $year
445
     * @param int $week
446
     * @param int $weekStart See documentation for settings.weekStart
447
     *
448
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
449
     */
450
    public function findWeek($year, $week, $weekStart = 1)
451
    {
452
        $weekStart = (int)$weekStart;
453
        $daysShift = $weekStart - 1;
454
        $firstDay = DateTimeUtility::convertWeekYear2DayMonthYear($week, $year);
455
        $timezone = DateTimeUtility::getTimeZone();
456
        $firstDay->setTimezone($timezone);
457
        if (0 !== $daysShift) {
458
            $firstDay->modify('+' . $daysShift . ' days');
459
        }
460
        $endDate = clone $firstDay;
461
        $endDate->modify('+1 week');
462
        $endDate->modify('-1 second');
463
464
        return $this->findByTimeSlot($firstDay->getTimestamp(), $endDate->getTimestamp());
465
    }
466
467
    /**
468
     * Find different types and locations.
469
     *
470
     * @return array
471
     */
472
    public function findDifferentTypesAndLocations(): array
473
    {
474
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_calendarize_domain_model_index');
475
476
        return (array)$queryBuilder->select('unique_register_key', 'pid', 'foreign_table')->from('tx_calendarize_domain_model_index')->groupBy('pid', 'foreign_table', 'unique_register_key')->execute()->fetchAll();
477
    }
478
479
    /**
480
     * find day.
481
     *
482
     * @param int $year
483
     * @param int $month
484
     * @param int $day
485
     *
486
     * @throws Exception
487
     *
488
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
489
     */
490
    public function findDay(int $year, int $month, int $day)
491
    {
492
        $startTime = \mktime(0, 0, 0, $month, $day, $year);
493
        $startDate = new \DateTime('@' . $startTime);
494
        $endDate = clone $startDate;
495
        $endDate->modify('+1 day');
496
        $endDate->modify('-1 second');
497
498
        return $this->findByTimeSlot($startDate->getTimestamp(), $endDate->getTimestamp());
499
    }
500
501
    /**
502
     * Set the default sorting direction.
503
     *
504
     * @param string $direction
505
     * @param string $field
506
     */
507
    public function setDefaultSortingDirection($direction, $field = '')
508
    {
509
        $this->defaultOrderings = $this->getSorting($direction, $field);
510
    }
511
512
    /**
513
     * Find by time slot.
514
     *
515
     * @param int      $startTime
516
     * @param int|null $endTime   null means open end
517
     *
518
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
519
     */
520
    public function findByTimeSlot($startTime, $endTime = null)
521
    {
522
        $query = $this->createQuery();
523
        $constraints = $this->getDefaultConstraints($query);
524
        $this->addTimeFrameConstraints($constraints, $query, $startTime, $endTime);
525
526
        $arguments = [
527
            'constraints' => $constraints,
528
            'query' => $query,
529
        ];
530
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__, $arguments);
531
        $constraints = $arguments['constraints'] ?: $constraints;
532
533
        return $this->matchAndExecute($query, $constraints);
534
    }
535
536
    /**
537
     * Find all indices by the given Event model.
538
     *
539
     * @param DomainObjectInterface $event
540
     *
541
     * @throws Exception
542
     *
543
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
544
     */
545
    public function findByEvent(DomainObjectInterface $event)
546
    {
547
        $query = $this->createQuery();
548
549
        $uniqueRegisterKey = ExtensionConfigurationUtility::getUniqueRegisterKeyForModel($event);
550
551
        $this->setIndexTypes([$uniqueRegisterKey]);
552
        $constraints = $this->getDefaultConstraints($query);
553
        $constraints[] = $query->equals('foreignUid', $event->getUid());
554
        $query->matching($query->logicalAnd($constraints));
555
556
        return $query->execute();
557
    }
558
559
    /**
560
     * Get index language mode.
561
     *
562
     * @return string
563
     */
564
    protected function getIndexLanguageMode()
565
    {
566
        static $mode;
567
        if (null !== $mode) {
568
            return $mode;
569
        }
570
571
        /** @var ConfigurationManagerInterface $config */
572
        $config = $this->objectManager->get(ConfigurationManagerInterface::class);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated with message: since TYPO3 10.4, will be removed in version 12.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
573
        $pluginConfig = $config->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS);
574
575
        $mode = isset($pluginConfig['indexLanguageMode']) ? (string)$pluginConfig['indexLanguageMode'] : 'strict';
576
577
        return $mode;
578
    }
579
580
    /**
581
     * storage page selection.
582
     *
583
     * @return array
584
     */
585
    protected function getStoragePageIds()
586
    {
587
        if ($this->overridePageIds !== null) {
588
            return $this->overridePageIds;
589
        }
590
591
        $configurationManager = $this->objectManager->get(ConfigurationManagerInterface::class);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated with message: since TYPO3 10.4, will be removed in version 12.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
592
        $frameworkConfig = $configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
593
        $storagePages = isset($frameworkConfig['persistence']['storagePid']) ? GeneralUtility::intExplode(
594
            ',',
595
            $frameworkConfig['persistence']['storagePid']
596
        ) : [];
597
        if (!empty($storagePages)) {
598
            return $storagePages;
599
        }
600
        if ($frameworkConfig instanceof BackendConfigurationManager) {
601
            return GeneralUtility::trimExplode(',', $frameworkConfig->getDefaultBackendStoragePid(), true);
602
        }
603
604
        return $storagePages;
605
    }
606
607
    /**
608
     * Get the default constraint for the queries.
609
     *
610
     * @param QueryInterface $query
611
     *
612
     * @return array
613
     */
614
    protected function getDefaultConstraints(QueryInterface $query)
615
    {
616
        $constraints = [];
617
        if (!empty($this->indexTypes)) {
618
            $indexTypes = $this->indexTypes;
619
            $constraints[] = $query->in('uniqueRegisterKey', $indexTypes);
620
        }
621
622
        $storagePages = $this->getStoragePageIds();
623
        if (!empty($storagePages)) {
624
            $constraints[] = $query->in('pid', $storagePages);
625
        }
626
627
        $arguments = [
628
            'indexIds' => [],
629
            'indexTypes' => $this->indexTypes,
630
        ];
631
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__, $arguments);
632
633
        if ($arguments['indexIds']) {
634
            $constraints[] = $query->in('foreignUid', $arguments['indexIds']);
635
        }
636
637
        return $constraints;
638
    }
639
640
    /**
641
     * Add time frame related queries.
642
     *
643
     * @param array          $constraints
644
     * @param QueryInterface $query
645
     * @param int            $startTime
646
     * @param int|null       $endTime
647
     *
648
     * @see IndexUtility::isIndexInRange
649
     */
650
    protected function addTimeFrameConstraints(&$constraints, QueryInterface $query, $startTime = null, $endTime = null)
651
    {
652
        $arguments = [
653
            'constraints' => &$constraints,
654
            'query' => $query,
655
            'startTime' => $startTime,
656
            'endTime' => $endTime,
657
        ];
658
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__, $arguments);
659
660
        if (null === $arguments['startTime'] && null === $arguments['endTime']) {
661
            return;
662
        }
663
        if (null === $arguments['startTime']) {
664
            // Simulate start time
665
            $arguments['startTime'] = DateTimeUtility::getNow()->getTimestamp() - DateTimeUtility::SECONDS_DECADE;
666
        } elseif (null === $arguments['endTime']) {
667
            // Simulate end time
668
            $arguments['endTime'] = DateTimeUtility::getNow()->getTimestamp() + DateTimeUtility::SECONDS_DECADE;
669
        }
670
671
        if ((bool)ConfigurationUtility::get('respectTimesInTimeFrameConstraints')) {
672
            $this->addDateTimeFrameConstraints($constraints, $query, $arguments);
673
        } else {
674
            $this->addDateFrameConstraints($constraints, $query, $arguments);
675
        }
676
    }
677
678
    /**
679
     * Adds time frame constraints which respect the actual index times.
680
     * Do not call this method directly. Call IndexRepository::addTimeFrameConstraints instead.
681
     *
682
     * @param array          $constraints
683
     * @param QueryInterface $query
684
     * @param array          $arguments
685
     *
686
     * @see IndexRepository::addTimeFrameConstraints
687
     */
688
    protected function addDateTimeFrameConstraints(&$constraints, QueryInterface $query, array $arguments)
689
    {
690
        $timezone = new \DateTimeZone('UTC');
691
692
        // store values for start_date and start_time in separate variables
693
        $startDateTime = new \DateTime('@' . $arguments['startTime'], $timezone);
694
        $restrictionLowTime = DateTimeUtility::getDaySecondsOfDateTime($startDateTime);
695
        $restrictionLowDay = DateTimeUtility::resetTime($startDateTime)->format('Y-m-d');
696
697
        // store values for end_date and end_time in separate variables
698
        $endDateTime = new \DateTime('@' . $arguments['endTime'], $timezone);
699
        $restrictionHighTime = DateTimeUtility::getDaySecondsOfDateTime($endDateTime);
700
        $restrictionHighDay = DateTimeUtility::resetTime($endDateTime)->format('Y-m-d');
701
702
        $constraints[] = $query->logicalAnd([
703
            // (end_date === restrictionLowDay && end_time >= restrictionLowTime) || end_date > restrictionLowDay || (all_day === true && end_date >= restrictionLowDay)
704
            $query->logicalOr([
705
                $query->logicalAnd([
706
                    $query->equals('endDate', $restrictionLowDay),
707
                    $query->greaterThanOrEqual('endTime', $restrictionLowTime),
708
                ]),
709
                $query->greaterThan('endDate', $restrictionLowDay),
710
                $query->logicalAnd([
711
                    $query->equals('allDay', true),
712
                    $query->greaterThanOrEqual('endDate', $restrictionLowDay),
713
                ]),
714
            ]),
715
            // (start_date === restrictionHighDay && start_time <= restrictionHighTime) || start_date < restrictionHighDay || (all_day === true && start_date <= restrictionHighDay)
716
            $query->logicalOr([
717
                $query->logicalAnd([
718
                    $query->equals('startDate', $restrictionHighDay),
719
                    $query->lessThanOrEqual('startTime', $restrictionHighTime),
720
                ]),
721
                $query->lessThan('startDate', $restrictionHighDay),
722
                $query->logicalAnd([
723
                    $query->equals('allDay', true),
724
                    $query->lessThanOrEqual('startDate', $restrictionHighDay),
725
                ]),
726
            ]),
727
        ]);
728
    }
729
730
    /**
731
     * Adds time frame constraints which respect only the index dates, not the actual index times.
732
     * Do not call this method directly. Call IndexRepository::addTimeFrameConstraints instead.
733
     *
734
     * @param array          $constraints
735
     * @param QueryInterface $query
736
     * @param array          $arguments
737
     *
738
     * @see IndexRepository::addTimeFrameConstraints
739
     */
740
    protected function addDateFrameConstraints(&$constraints, QueryInterface $query, array $arguments)
741
    {
742
        $orConstraint = [];
743
744
        // before - in
745
        $beforeIn = [
746
            $query->lessThan('startDate', (new \DateTime('@' . $arguments['startTime']))->format('Y-m-d')),
747
            $query->greaterThanOrEqual('endDate', (new \DateTime('@' . $arguments['endTime']))->format('Y-m-d')),
748
            $query->lessThan('endDate', (new \DateTime('@' . $arguments['endTime']))->format('Y-m-d')),
749
        ];
750
        $orConstraint[] = $query->logicalAnd($beforeIn);
751
752
        // in - in
753
        $inIn = [
754
            $query->greaterThanOrEqual('startDate', (new \DateTime('@' . $arguments['startTime']))->format('Y-m-d')),
755
            $query->lessThan('endDate', (new \DateTime('@' . $arguments['endTime']))->format('Y-m-d')),
756
        ];
757
        $orConstraint[] = $query->logicalAnd($inIn);
758
759
        // in - after
760
        $inAfter = [
761
            $query->greaterThanOrEqual('startDate', (new \DateTime('@' . $arguments['startTime']))->format('Y-m-d')),
762
            $query->lessThan('startDate', (new \DateTime('@' . $arguments['endTime']))->format('Y-m-d')),
763
            $query->greaterThanOrEqual('endDate', (new \DateTime('@' . $arguments['endTime']))->format('Y-m-d')),
764
        ];
765
        $orConstraint[] = $query->logicalAnd($inAfter);
766
767
        // before - after
768
        $beforeAfter = [
769
            $query->lessThan('startDate', (new \DateTime('@' . $arguments['startTime']))->format('Y-m-d')),
770
            $query->greaterThan('endDate', (new \DateTime('@' . $arguments['endTime']))->format('Y-m-d')),
771
        ];
772
        $orConstraint[] = $query->logicalAnd($beforeAfter);
773
774
        // finish
775
        $constraints[] = $query->logicalOr($orConstraint);
776
    }
777
778
    /**
779
     * Get the sorting.
780
     *
781
     * @param string $direction
782
     * @param string $field
783
     *
784
     * @return array
785
     */
786
    protected function getSorting($direction, $field = '')
787
    {
788
        if ('withrangelast' === $field) {
789
            return [
790
                'endDate' => $direction,
791
                'startDate' => $direction,
792
                'startTime' => $direction,
793
            ];
794
        }
795
        if ('end' !== $field) {
796
            $field = 'start';
797
        }
798
799
        return [
800
            $field . 'Date' => $direction,
801
            $field . 'Time' => $direction,
802
        ];
803
    }
804
}
805