Completed
Push — master ( f30a93...2b3d30 )
by Tim
02:07
created

IndexRepository::findQuarter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
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 quarter.
326
     *
327
     * @param int $year
328
     * @param int $quarter
329
     *
330
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
331
     */
332
    public function findQuarter(int $year, int $quarter)
333
    {
334
        $startMonth = 1 + (3 * ($quarter - 1));
335
336
        return $this->findByTimeSlot(\mktime(0, 0, 0, $startMonth, 1, $year), \mktime(0, 0, 0, $startMonth + 3, 1, $year) - 1);
337
    }
338
339
    /**
340
     * find Month.
341
     *
342
     * @param int $year
343
     * @param int $month
344
     *
345
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
346
     */
347
    public function findMonth(int $year, int $month)
348
    {
349
        $startTime = \mktime(0, 0, 0, $month, 1, $year);
350
        $endTime = \mktime(0, 0, 0, $month + 1, 1, $year) - 1;
351
352
        return $this->findByTimeSlot($startTime, $endTime);
353
    }
354
355
    /**
356
     * find Week.
357
     *
358
     * @param int $year
359
     * @param int $week
360
     * @param int $weekStart See documentation for settings.weekStart
361
     *
362
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
363
     */
364
    public function findWeek($year, $week, $weekStart = 1)
365
    {
366
        $weekStart = (int) $weekStart;
367
        $daysShift = DateTimeUtility::SECONDS_DAY * ($weekStart - 1);
368
        $firstDay = DateTimeUtility::convertWeekYear2DayMonthYear($week, $year);
369
        $timezone = DateTimeUtility::getTimeZone();
370
        $firstDay->setTimezone($timezone);
371
        $timeStampStart = $firstDay->getTimestamp() + $daysShift;
372
373
        return $this->findByTimeSlot($timeStampStart, $timeStampStart + DateTimeUtility::SECONDS_WEEK - 1);
374
    }
375
376
    /**
377
     * Find different types and locations.
378
     *
379
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
380
     */
381
    public function findDifferentTypesAndLocations()
382
    {
383
        $query = $this->createQuery();
384
385
        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...
386
            ->statement('SELECT *'
387
                . 'FROM tx_calendarize_domain_model_index '
388
                . 'GROUP BY pid,foreign_table')
389
            ->execute();
390
    }
391
392
    /**
393
     * find day.
394
     *
395
     * @param int $year
396
     * @param int $month
397
     * @param int $day
398
     *
399
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
400
     */
401
    public function findDay(int $year, int $month, int $day)
402
    {
403
        $startTime = \mktime(0, 0, 0, $month, $day, $year);
404
405
        return $this->findByTimeSlot($startTime, $startTime + DateTimeUtility::SECONDS_DAY - 1);
406
    }
407
408
    /**
409
     * Set the default sorting direction.
410
     *
411
     * @param string $direction
412
     * @param string $field
413
     */
414
    public function setDefaultSortingDirection($direction, $field = '')
415
    {
416
        $this->defaultOrderings = $this->getSorting($direction, $field);
417
    }
418
419
    /**
420
     * Find by time slot.
421
     *
422
     * @param int      $startTime
423
     * @param int|null $endTime   null means open end
424
     *
425
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
426
     */
427
    public function findByTimeSlot($startTime, $endTime = null)
428
    {
429
        $query = $this->createQuery();
430
        $constraints = $this->getDefaultConstraints($query);
431
        $this->addTimeFrameConstraints($constraints, $query, $startTime, $endTime);
432
433
        return $this->matchAndExecute($query, $constraints);
434
    }
435
436
    /**
437
     * Find all indices by the given Event model.
438
     *
439
     * @param DomainObjectInterface $event
440
     *
441
     * @throws Exception
442
     *
443
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
444
     */
445
    public function findByEvent(DomainObjectInterface $event)
446
    {
447
        $query = $this->createQuery();
448
449
        $uniqueRegisterKey = ExtensionConfigurationUtility::getUniqueRegisterKeyForModel($event);
450
451
        $this->setIndexTypes([$uniqueRegisterKey]);
452
        $constraints = $this->getDefaultConstraints($query);
453
        $constraints[] = $query->equals('foreignUid', $event->getUid());
454
        $query->matching($query->logicalAnd($constraints));
455
456
        return $query->execute();
457
    }
458
459
    /**
460
     * Get index language mode.
461
     *
462
     * @return string
463
     */
464
    protected function getIndexLanguageMode()
465
    {
466
        static $mode;
467
        if (null !== $mode) {
468
            return $mode;
469
        }
470
471
        $objectManager = new ObjectManager();
472
        /** @var ConfigurationManagerInterface $config */
473
        $config = $objectManager->get(ConfigurationManagerInterface::class);
474
        $pluginConfig = $config->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS);
475
476
        $mode = isset($pluginConfig['indexLanguageMode']) ? (string) $pluginConfig['indexLanguageMode'] : 'strict';
477
478
        return $mode;
479
    }
480
481
    /**
482
     * storage page selection.
483
     *
484
     * @return array
485
     */
486
    protected function getStoragePageIds()
487
    {
488
        if (!empty($this->overridePageIds)) {
489
            return $this->overridePageIds;
490
        }
491
492
        $configurationManager = $this->objectManager->get(ConfigurationManagerInterface::class);
493
        $frameworkConfig = $configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
494
        $storagePages = isset($frameworkConfig['persistence']['storagePid']) ? GeneralUtility::intExplode(
495
            ',',
496
            $frameworkConfig['persistence']['storagePid']
497
        ) : [];
498
        if (!empty($storagePages)) {
499
            return $storagePages;
500
        }
501
        if ($frameworkConfig instanceof BackendConfigurationManager) {
502
            return GeneralUtility::trimExplode(',', $frameworkConfig->getDefaultBackendStoragePid(), true);
503
        }
504
505
        return $storagePages;
506
    }
507
508
    /**
509
     * Get the default constraint for the queries.
510
     *
511
     * @param QueryInterface $query
512
     *
513
     * @return array
514
     */
515
    protected function getDefaultConstraints(QueryInterface $query)
516
    {
517
        $constraints = [];
518
        if (!empty($this->indexTypes)) {
519
            $indexTypes = $this->indexTypes;
520
            $constraints[] = $query->in('uniqueRegisterKey', $indexTypes);
521
        }
522
523
        $storagePages = $this->getStoragePageIds();
524
        if (!empty($storagePages)) {
525
            $constraints[] = $query->in('pid', $storagePages);
526
        }
527
528
        $arguments = [
529
            'indexIds' => [],
530
            'indexTypes' => $this->indexTypes,
531
        ];
532
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__, $arguments);
533
534
        if ($arguments['indexIds']) {
535
            $constraints[] = $query->in('foreign_uid', $arguments['indexIds']);
536
        }
537
538
        return $constraints;
539
    }
540
541
    /**
542
     * Add time frame related queries.
543
     *
544
     * @param array          $constraints
545
     * @param QueryInterface $query
546
     * @param int            $startTime
547
     * @param int|null       $endTime
548
     *
549
     * @see IndexUtility::isIndexInRange
550
     */
551
    protected function addTimeFrameConstraints(&$constraints, QueryInterface $query, $startTime = null, $endTime = null)
552
    {
553
        $arguments = [
554
            'constraints' => &$constraints,
555
            'query' => $query,
556
            'startTime' => $startTime,
557
            'endTime' => $endTime,
558
        ];
559
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__, $arguments);
560
561
        if (null === $arguments['startTime'] && null === $arguments['endTime']) {
562
            return;
563
        }
564
        if (null === $arguments['startTime']) {
565
            // Simulate start time
566
            $arguments['startTime'] = DateTimeUtility::getNow()->getTimestamp() - DateTimeUtility::SECONDS_DECADE;
567
        } elseif (null === $arguments['endTime']) {
568
            // Simulate end time
569
            $arguments['endTime'] = DateTimeUtility::getNow()->getTimestamp() + DateTimeUtility::SECONDS_DECADE;
570
        }
571
572
        $orConstraint = [];
573
574
        // before - in
575
        $beforeIn = [
576
            $query->lessThan('start_date', $arguments['startTime']),
577
            $query->greaterThanOrEqual('end_date', $arguments['startTime']),
578
            $query->lessThan('end_date', $arguments['endTime']),
579
        ];
580
        $orConstraint[] = $query->logicalAnd($beforeIn);
581
582
        // in - in
583
        $inIn = [
584
            $query->greaterThanOrEqual('start_date', $arguments['startTime']),
585
            $query->lessThan('end_date', $arguments['endTime']),
586
        ];
587
        $orConstraint[] = $query->logicalAnd($inIn);
588
589
        // in - after
590
        $inAfter = [
591
            $query->greaterThanOrEqual('start_date', $arguments['startTime']),
592
            $query->lessThan('start_date', $arguments['endTime']),
593
            $query->greaterThanOrEqual('end_date', $arguments['endTime']),
594
        ];
595
        $orConstraint[] = $query->logicalAnd($inAfter);
596
597
        // before - after
598
        $beforeAfter = [
599
            $query->lessThan('start_date', $arguments['startTime']),
600
            $query->greaterThan('end_date', $arguments['endTime']),
601
        ];
602
        $orConstraint[] = $query->logicalAnd($beforeAfter);
603
604
        // finish
605
        $constraints[] = $query->logicalOr($orConstraint);
606
    }
607
608
    /**
609
     * Get the sorting.
610
     *
611
     * @param string $direction
612
     * @param string $field
613
     *
614
     * @return array
615
     */
616
    protected function getSorting($direction, $field = '')
617
    {
618
        if ('end' !== $field) {
619
            $field = 'start';
620
        }
621
622
        return [
623
            $field . '_date' => $direction,
624
            $field . '_time' => $direction,
625
        ];
626
    }
627
}
628