Completed
Push — master ( 36bbbe...f30a93 )
by Tim
02:07
created

IndexRepository::findAllForBackend()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nc 1
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\Utility\DateTimeUtility;
13
use HDNET\Calendarize\Utility\ExtensionConfigurationUtility;
14
use TYPO3\CMS\Core\Utility\GeneralUtility;
15
use TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager;
16
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
17
use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
18
use TYPO3\CMS\Extbase\Object\ObjectManager;
19
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
20
21
/**
22
 * Index repository.
23
 */
24
class IndexRepository extends AbstractRepository
25
{
26
    /**
27
     * Default orderings for index records.
28
     *
29
     * @var array
30
     */
31
    protected $defaultOrderings = [
32
        'start_date' => QueryInterface::ORDER_ASCENDING,
33
        'start_time' => QueryInterface::ORDER_ASCENDING,
34
    ];
35
36
    /**
37
     * Index types for selection.
38
     *
39
     * @var array
40
     */
41
    protected $indexTypes = [];
42
43
    /**
44
     * Override page ids.
45
     *
46
     * @var array
47
     */
48
    protected $overridePageIds = [];
49
50
    /**
51
     * @return QueryInterface
52
     */
53
    public function createQuery()
54
    {
55
        $query = parent::createQuery();
56
        $query->getQuerySettings()->setLanguageMode($this->getIndexLanguageMode());
57
58
        return $query;
59
    }
60
61
    /**
62
     * Set the index types.
63
     *
64
     * @param array $types
65
     */
66
    public function setIndexTypes(array $types)
67
    {
68
        $this->indexTypes = $types;
69
    }
70
71
    /**
72
     * Override page IDs.
73
     *
74
     * @param array $overridePageIds
75
     */
76
    public function setOverridePageIds($overridePageIds)
77
    {
78
        $this->overridePageIds = $overridePageIds;
79
    }
80
81
    /**
82
     * Select indecies for Backend.
83
     *
84
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
85
     */
86
    public function findAllForBackend()
87
    {
88
        $query = $this->createQuery();
89
        $query->getQuerySettings()->setRespectSysLanguage(false);
90
91
        return $query->execute();
92
    }
93
94
    /**
95
     * Find List.
96
     *
97
     * @param int        $limit
98
     * @param int|string $listStartTime
99
     * @param int        $startOffsetHours
100
     * @param int        $overrideStartDate
101
     * @param int        $overrideEndDate
102
     *
103
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
104
     */
105
    public function findList(
106
        $limit = 0,
107
        $listStartTime = 0,
108
        $startOffsetHours = 0,
109
        $overrideStartDate = 0,
110
        $overrideEndDate = 0
111
    ) {
112
        if ($overrideStartDate > 0) {
113
            $startTimestamp = $overrideStartDate;
114
        } else {
115
            $now = DateTimeUtility::getNow();
116
            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...
117
                $now->setTime(0, 0, 0);
118
            }
119
            $now->modify($startOffsetHours . ' hours');
120
            $startTimestamp = $now->getTimestamp();
121
        }
122
        $endTimestamp = null;
123
        if ($overrideEndDate > 0) {
124
            $endTimestamp = $overrideEndDate;
125
        }
126
127
        $result = $this->findByTimeSlot($startTimestamp, $endTimestamp);
128
        if ($limit > 0) {
129
            $query = $result->getQuery();
130
            $query->setLimit($limit);
131
            $result = $query->execute();
132
        }
133
134
        return $result;
135
    }
136
137
    /**
138
     * Find by custom search.
139
     *
140
     * @param \DateTime $startDate
141
     * @param \DateTime $endDate
142
     * @param array     $customSearch
143
     * @param int       $limit
144
     *
145
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
146
     */
147
    public function findBySearch(\DateTime $startDate = null, \DateTime $endDate = null, array $customSearch = [], int $limit = 0)
148
    {
149
        $arguments = [
150
            'indexIds' => [],
151
            'startDate' => $startDate,
152
            'endDate' => $endDate,
153
            'customSearch' => $customSearch,
154
            'indexTypes' => $this->indexTypes,
155
            'emptyPreResult' => false,
156
        ];
157
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__ . 'Pre', $arguments);
158
159
        $query = $this->createQuery();
160
        $constraints = $this->getDefaultConstraints($query);
161
162
        if ($limit > 0) {
163
            $query->setLimit($limit);
164
        }
165
166
        $this->addTimeFrameConstraints(
167
            $constraints,
168
            $query,
169
            $arguments['startDate'] instanceof \DateTime ? DateTimeUtility::getDayStart($arguments['startDate']) : null,
0 ignored issues
show
Bug introduced by
It seems like $arguments['startDate'] ...ts['startDate']) : null can also be of type object<DateTime>; however, HDNET\Calendarize\Domain...dTimeFrameConstraints() does only seem to accept integer|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
170
            $arguments['endDate'] instanceof \DateTime ? DateTimeUtility::getDayEnd($arguments['endDate']) : null
0 ignored issues
show
Bug introduced by
It seems like $arguments['endDate'] in...ents['endDate']) : null can also be of type object<DateTime>; however, HDNET\Calendarize\Domain...dTimeFrameConstraints() does only seem to accept integer|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
171
        );
172
173
        if ($arguments['indexIds']) {
174
            $constraints[] = $query->in('foreign_uid', $arguments['indexIds']);
175
        }
176
        if ($arguments['emptyPreResult']) {
177
            $constraints[] = $query->equals('uid', '-1');
178
        }
179
        $result = [
180
            'result' => $this->matchAndExecute($query, $constraints),
181
        ];
182
183
        $result = $this->callSignal(__CLASS__, __FUNCTION__ . 'Post', $result);
184
185
        return $result['result'];
186
    }
187
188
    /**
189
     * Find Past Events.
190
     *
191
     * @param int    $limit
192
     * @param string $sort
193
     *
194
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
195
     */
196
    public function findByPast(
197
        $limit,
198
        $sort
199
    ) {
200
        //create Query
201
        $query = $this->createQuery();
202
        //Get actual datetime
203
        $now = DateTimeUtility::getNow()->getTimestamp();
204
205
        $constraints = $this->getDefaultConstraints($query);
206
        $constraints[] = $query->lessThanOrEqual('startDate', $now);
207
        $sort = QueryInterface::ORDER_ASCENDING === $sort ? QueryInterface::ORDER_ASCENDING : QueryInterface::ORDER_DESCENDING;
208
        $query->setOrderings($this->getSorting($sort));
209
        $query->setLimit($limit);
210
211
        return $this->matchAndExecute($query, $constraints);
212
    }
213
214
    /**
215
     * Find by traversing information.
216
     *
217
     * @param Index      $index
218
     * @param bool|true  $future
219
     * @param bool|false $past
220
     * @param int        $limit
221
     * @param string     $sort
222
     * @param bool       $useIndexTime
223
     *
224
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
225
     */
226
    public function findByTraversing(
227
        Index $index,
228
        $future = true,
229
        $past = false,
230
        $limit = 100,
231
        $sort = QueryInterface::ORDER_ASCENDING,
232
        $useIndexTime = false
233
    ) {
234
        if (!$future && !$past) {
235
            return [];
236
        }
237
        $query = $this->createQuery();
238
239
        $now = DateTimeUtility::getNow()
240
            ->getTimestamp();
241
        if ($useIndexTime) {
242
            $now = $index->getStartDate()->getTimestamp();
243
        }
244
245
        $constraints = [];
246
        $constraints[] = $query->logicalNot($query->equals('uid', $index->getUid()));
247
        $constraints[] = $query->equals('foreignTable', $index->getForeignTable());
248
        $constraints[] = $query->equals('foreignUid', $index->getForeignUid());
249
        if (!$future) {
250
            $constraints[] = $query->lessThanOrEqual('startDate', $now);
251
        }
252
        if (!$past) {
253
            $constraints[] = $query->greaterThanOrEqual('startDate', $now);
254
        }
255
256
        $query->setLimit($limit);
257
        $sort = QueryInterface::ORDER_ASCENDING === $sort ? QueryInterface::ORDER_ASCENDING : QueryInterface::ORDER_DESCENDING;
258
        $query->setOrderings($this->getSorting($sort));
259
260
        return $this->matchAndExecute($query, $constraints);
261
    }
262
263
    /**
264
     * Find by traversing information.
265
     *
266
     * @param DomainObjectInterface $event
267
     * @param bool|true             $future
268
     * @param bool|false            $past
269
     * @param int                   $limit
270
     * @param string                $sort
271
     *
272
     * @throws Exception
273
     *
274
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
275
     */
276
    public function findByEventTraversing(
277
        DomainObjectInterface $event,
278
        $future = true,
279
        $past = false,
280
        $limit = 100,
281
        $sort = QueryInterface::ORDER_ASCENDING
282
    ) {
283
        if (!$future && !$past) {
284
            return [];
285
        }
286
        $query = $this->createQuery();
287
288
        $uniqueRegisterKey = ExtensionConfigurationUtility::getUniqueRegisterKeyForModel($event);
289
290
        $this->setIndexTypes([$uniqueRegisterKey]);
291
292
        $now = DateTimeUtility::getNow()
293
            ->getTimestamp();
294
295
        $constraints = [];
296
297
        $constraints[] = $query->equals('foreignUid', $event->getUid());
298
        if (!$future) {
299
            $constraints[] = $query->lessThanOrEqual('startDate', $now);
300
        }
301
        if (!$past) {
302
            $constraints[] = $query->greaterThanOrEqual('startDate', $now);
303
        }
304
305
        $query->setLimit($limit);
306
        $sort = QueryInterface::ORDER_ASCENDING === $sort ? QueryInterface::ORDER_ASCENDING : QueryInterface::ORDER_DESCENDING;
307
        $query->setOrderings($this->getSorting($sort));
308
309
        return $this->matchAndExecute($query, $constraints);
310
    }
311
312
    /**
313
     * find Year.
314
     *
315
     * @param int $year
316
     *
317
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
318
     */
319
    public function findYear(int $year)
320
    {
321
        return $this->findByTimeSlot(\mktime(0, 0, 0, 1, 1, $year), \mktime(0, 0, 0, 1, 1, $year + 1) - 1);
322
    }
323
324
    /**
325
     * find Month.
326
     *
327
     * @param int $year
328
     * @param int $month
329
     *
330
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
331
     */
332
    public function findMonth(int $year, int $month)
333
    {
334
        $startTime = \mktime(0, 0, 0, $month, 1, $year);
335
        $endTime = \mktime(0, 0, 0, $month + 1, 1, $year) - 1;
336
337
        return $this->findByTimeSlot($startTime, $endTime);
338
    }
339
340
    /**
341
     * find Week.
342
     *
343
     * @param int $year
344
     * @param int $week
345
     * @param int $weekStart See documentation for settings.weekStart
346
     *
347
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
348
     */
349
    public function findWeek($year, $week, $weekStart = 1)
350
    {
351
        $weekStart = (int) $weekStart;
352
        $daysShift = DateTimeUtility::SECONDS_DAY * ($weekStart - 1);
353
        $firstDay = DateTimeUtility::convertWeekYear2DayMonthYear($week, $year);
354
        $timezone = DateTimeUtility::getTimeZone();
355
        $firstDay->setTimezone($timezone);
356
        $timeStampStart = $firstDay->getTimestamp() + $daysShift;
357
358
        return $this->findByTimeSlot($timeStampStart, $timeStampStart + DateTimeUtility::SECONDS_WEEK - 1);
359
    }
360
361
    /**
362
     * Find different types and locations.
363
     *
364
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
365
     */
366
    public function findDifferentTypesAndLocations()
367
    {
368
        $query = $this->createQuery();
369
370
        return $query
0 ignored issues
show
Bug introduced by
The method statement() does not exist on TYPO3\CMS\Extbase\Persistence\QueryInterface. Did you maybe mean getStatement()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
371
            ->statement('SELECT *'
372
                . 'FROM tx_calendarize_domain_model_index '
373
                . 'GROUP BY pid,foreign_table')
374
            ->execute();
375
    }
376
377
    /**
378
     * find day.
379
     *
380
     * @param int $year
381
     * @param int $month
382
     * @param int $day
383
     *
384
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
385
     */
386
    public function findDay(int $year, int $month, int $day)
387
    {
388
        $startTime = \mktime(0, 0, 0, $month, $day, $year);
389
390
        return $this->findByTimeSlot($startTime, $startTime + DateTimeUtility::SECONDS_DAY - 1);
391
    }
392
393
    /**
394
     * Set the default sorting direction.
395
     *
396
     * @param string $direction
397
     * @param string $field
398
     */
399
    public function setDefaultSortingDirection($direction, $field = '')
400
    {
401
        $this->defaultOrderings = $this->getSorting($direction, $field);
402
    }
403
404
    /**
405
     * Find by time slot.
406
     *
407
     * @param int      $startTime
408
     * @param int|null $endTime   null means open end
409
     *
410
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
411
     */
412
    public function findByTimeSlot($startTime, $endTime = null)
413
    {
414
        $query = $this->createQuery();
415
        $constraints = $this->getDefaultConstraints($query);
416
        $this->addTimeFrameConstraints($constraints, $query, $startTime, $endTime);
417
418
        return $this->matchAndExecute($query, $constraints);
419
    }
420
421
    /**
422
     * Find all indices by the given Event model.
423
     *
424
     * @param DomainObjectInterface $event
425
     *
426
     * @throws Exception
427
     *
428
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
429
     */
430
    public function findByEvent(DomainObjectInterface $event)
431
    {
432
        $query = $this->createQuery();
433
434
        $uniqueRegisterKey = ExtensionConfigurationUtility::getUniqueRegisterKeyForModel($event);
435
436
        $this->setIndexTypes([$uniqueRegisterKey]);
437
        $constraints = $this->getDefaultConstraints($query);
438
        $constraints[] = $query->equals('foreignUid', $event->getUid());
439
        $query->matching($query->logicalAnd($constraints));
440
441
        return $query->execute();
442
    }
443
444
    /**
445
     * Get index language mode.
446
     *
447
     * @return string
448
     */
449
    protected function getIndexLanguageMode()
450
    {
451
        static $mode;
452
        if (null !== $mode) {
453
            return $mode;
454
        }
455
456
        $objectManager = new ObjectManager();
457
        /** @var ConfigurationManagerInterface $config */
458
        $config = $objectManager->get(ConfigurationManagerInterface::class);
459
        $pluginConfig = $config->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS);
460
461
        $mode = isset($pluginConfig['indexLanguageMode']) ? (string) $pluginConfig['indexLanguageMode'] : 'strict';
462
463
        return $mode;
464
    }
465
466
    /**
467
     * storage page selection.
468
     *
469
     * @return array
470
     */
471
    protected function getStoragePageIds()
472
    {
473
        if (!empty($this->overridePageIds)) {
474
            return $this->overridePageIds;
475
        }
476
477
        $configurationManager = $this->objectManager->get(ConfigurationManagerInterface::class);
478
        $frameworkConfig = $configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
479
        $storagePages = isset($frameworkConfig['persistence']['storagePid']) ? GeneralUtility::intExplode(
480
            ',',
481
            $frameworkConfig['persistence']['storagePid']
482
        ) : [];
483
        if (!empty($storagePages)) {
484
            return $storagePages;
485
        }
486
        if ($frameworkConfig instanceof BackendConfigurationManager) {
487
            return GeneralUtility::trimExplode(',', $frameworkConfig->getDefaultBackendStoragePid(), true);
488
        }
489
490
        return $storagePages;
491
    }
492
493
    /**
494
     * Get the default constraint for the queries.
495
     *
496
     * @param QueryInterface $query
497
     *
498
     * @return array
499
     */
500
    protected function getDefaultConstraints(QueryInterface $query)
501
    {
502
        $constraints = [];
503
        if (!empty($this->indexTypes)) {
504
            $indexTypes = $this->indexTypes;
505
            $constraints[] = $query->in('uniqueRegisterKey', $indexTypes);
506
        }
507
508
        $storagePages = $this->getStoragePageIds();
509
        if (!empty($storagePages)) {
510
            $constraints[] = $query->in('pid', $storagePages);
511
        }
512
513
        $arguments = [
514
            'indexIds' => [],
515
            'indexTypes' => $this->indexTypes,
516
        ];
517
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__, $arguments);
518
519
        if ($arguments['indexIds']) {
520
            $constraints[] = $query->in('foreign_uid', $arguments['indexIds']);
521
        }
522
523
        return $constraints;
524
    }
525
526
    /**
527
     * Add time frame related queries.
528
     *
529
     * @param array          $constraints
530
     * @param QueryInterface $query
531
     * @param int            $startTime
532
     * @param int|null       $endTime
533
     *
534
     * @see IndexUtility::isIndexInRange
535
     */
536
    protected function addTimeFrameConstraints(&$constraints, QueryInterface $query, $startTime = null, $endTime = null)
537
    {
538
        $arguments = [
539
            'constraints' => &$constraints,
540
            'query' => $query,
541
            'startTime' => $startTime,
542
            'endTime' => $endTime,
543
        ];
544
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__, $arguments);
545
546
        if (null === $arguments['startTime'] && null === $arguments['endTime']) {
547
            return;
548
        }
549
        if (null === $arguments['startTime']) {
550
            // Simulate start time
551
            $arguments['startTime'] = DateTimeUtility::getNow()->getTimestamp() - DateTimeUtility::SECONDS_DECADE;
552
        } elseif (null === $arguments['endTime']) {
553
            // Simulate end time
554
            $arguments['endTime'] = DateTimeUtility::getNow()->getTimestamp() + DateTimeUtility::SECONDS_DECADE;
555
        }
556
557
        $orConstraint = [];
558
559
        // before - in
560
        $beforeIn = [
561
            $query->lessThan('start_date', $arguments['startTime']),
562
            $query->greaterThanOrEqual('end_date', $arguments['startTime']),
563
            $query->lessThan('end_date', $arguments['endTime']),
564
        ];
565
        $orConstraint[] = $query->logicalAnd($beforeIn);
566
567
        // in - in
568
        $inIn = [
569
            $query->greaterThanOrEqual('start_date', $arguments['startTime']),
570
            $query->lessThan('end_date', $arguments['endTime']),
571
        ];
572
        $orConstraint[] = $query->logicalAnd($inIn);
573
574
        // in - after
575
        $inAfter = [
576
            $query->greaterThanOrEqual('start_date', $arguments['startTime']),
577
            $query->lessThan('start_date', $arguments['endTime']),
578
            $query->greaterThanOrEqual('end_date', $arguments['endTime']),
579
        ];
580
        $orConstraint[] = $query->logicalAnd($inAfter);
581
582
        // before - after
583
        $beforeAfter = [
584
            $query->lessThan('start_date', $arguments['startTime']),
585
            $query->greaterThan('end_date', $arguments['endTime']),
586
        ];
587
        $orConstraint[] = $query->logicalAnd($beforeAfter);
588
589
        // finish
590
        $constraints[] = $query->logicalOr($orConstraint);
591
    }
592
593
    /**
594
     * Get the sorting.
595
     *
596
     * @param string $direction
597
     * @param string $field
598
     *
599
     * @return array
600
     */
601
    protected function getSorting($direction, $field = '')
602
    {
603
        if ('end' !== $field) {
604
            $field = 'start';
605
        }
606
607
        return [
608
            $field . '_date' => $direction,
609
            $field . '_time' => $direction,
610
        ];
611
    }
612
}
613