Completed
Push — master ( c73141...490d99 )
by Tim
04:55 queued 02:37
created

IndexRepository::findByEvent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 8
nc 1
nop 1
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\Persistence\QueryInterface;
19
20
/**
21
 * Index repository.
22
 */
23
class IndexRepository extends AbstractRepository
24
{
25
    /**
26
     * Default orderings for index records.
27
     *
28
     * @var array
29
     */
30
    protected $defaultOrderings = [
31
        'start_date' => QueryInterface::ORDER_ASCENDING,
32
        'start_time' => QueryInterface::ORDER_ASCENDING,
33
    ];
34
35
    /**
36
     * Index types for selection.
37
     *
38
     * @var array
39
     */
40
    protected $indexTypes = [];
41
42
    /**
43
     * Override page ids.
44
     *
45
     * @var array
46
     */
47
    protected $overridePageIds = [];
48
49
    /**
50
     * Set the index types.
51
     *
52
     * @param array $types
53
     */
54
    public function setIndexTypes(array $types)
55
    {
56
        $this->indexTypes = $types;
57
    }
58
59
    /**
60
     * Override page IDs.
61
     *
62
     * @param array $overridePageIds
63
     */
64
    public function setOverridePageIds($overridePageIds)
65
    {
66
        $this->overridePageIds = $overridePageIds;
67
    }
68
69
    /**
70
     * Find List.
71
     *
72
     * @param int        $limit
73
     * @param int|string $listStartTime
74
     * @param int        $startOffsetHours
75
     * @param int        $overrideStartDate
76
     * @param int        $overrideEndDate
77
     *
78
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
79
     */
80
    public function findList(
81
        $limit = 0,
82
        $listStartTime = 0,
83
        $startOffsetHours = 0,
84
        $overrideStartDate = 0,
85
        $overrideEndDate = 0
86
    ) {
87
        if ($overrideStartDate > 0) {
88
            $startTimestamp = $overrideStartDate;
89
        } else {
90
            $now = DateTimeUtility::getNow();
91
            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...
92
                $now->setTime(0, 0, 0);
93
            }
94
            $now->modify($startOffsetHours . ' hours');
95
            $startTimestamp = $now->getTimestamp();
96
        }
97
        $endTimestamp = null;
98
        if ($overrideEndDate > 0) {
99
            $endTimestamp = $overrideEndDate;
100
        }
101
102
        $result = $this->findByTimeSlot($startTimestamp, $endTimestamp);
103
        if ($limit > 0) {
104
            $query = $result->getQuery();
105
            $query->setLimit($limit);
106
            $result = $query->execute();
107
        }
108
109
        return $result;
110
    }
111
112
    /**
113
     * Find by custom search.
114
     *
115
     * @param \DateTime $startDate
116
     * @param \DateTime $endDate
117
     * @param array     $customSearch
118
     *
119
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
120
     */
121
    public function findBySearch(\DateTime $startDate = null, \DateTime $endDate = null, array $customSearch = [])
122
    {
123
        $arguments = [
124
            'indexIds' => [],
125
            'startDate' => $startDate,
126
            'endDate' => $endDate,
127
            'customSearch' => $customSearch,
128
            'indexTypes' => $this->indexTypes,
129
            'emptyPreResult' => false,
130
        ];
131
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__ . 'Pre', $arguments);
132
133
        $query = $this->createQuery();
134
        $constraints = $this->getDefaultConstraints($query);
135
136
        $this->addTimeFrameConstraints(
137
            $constraints,
138
            $query,
139
            $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...
140
            $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...
141
        );
142
143
        if ($arguments['indexIds']) {
144
            $constraints[] = $query->in('foreign_uid', $arguments['indexIds']);
145
        }
146
        $result = [
147
            'result' => $arguments['emptyPreResult'] ? [] : $this->matchAndExecute($query, $constraints),
148
        ];
149
150
        $result = $this->callSignal(__CLASS__, __FUNCTION__ . 'Post', $result);
151
152
        return $result['result'];
153
    }
154
    /**
155
     * Find Past Events
156
     * 
157
     * @param int       $limit
158
     * @param string    $sort
159
     * 
160
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
161
     */
162
163
    public function findByPast(
164
        $limit,
165
        $sort
166
    ) {
167
        //create Query
168
        $query = $this->createQuery();
169
        //Get actual datetime
170
        $now = DateTimeUtility::getNow()->getTimestamp();
171
        
172
        $constraints = [];
0 ignored issues
show
Unused Code introduced by
$constraints is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
173
        $constraints = $this->getDefaultConstraints($query);
174
        $constraints[] = $query->lessThanOrEqual('startDate', $now);
175
        $sort = QueryInterface::ORDER_ASCENDING === $sort ? QueryInterface::ORDER_ASCENDING : QueryInterface::ORDER_DESCENDING;
176
        $query->setOrderings($this->getSorting($sort));
177
        $query->setLimit($limit);
178
179
        return $this->matchAndExecute($query, $constraints);
180
181
    }
182
183
    /**
184
     * Find by traversing information.
185
     *
186
     * @param Index      $index
187
     * @param bool|true  $future
188
     * @param bool|false $past
189
     * @param int        $limit
190
     * @param string     $sort
191
     * @param bool       $useIndexTime
192
     *
193
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
194
     */
195
    public function findByTraversing(
196
        Index $index,
197
        $future = true,
198
        $past = false,
199
        $limit = 100,
200
        $sort = QueryInterface::ORDER_ASCENDING,
201
        $useIndexTime = false
202
    ) {
203
        if (!$future && !$past) {
204
            return [];
205
        }
206
        $query = $this->createQuery();
207
208
        $now = DateTimeUtility::getNow()
209
            ->getTimestamp();
210
        if ($useIndexTime) {
211
            $now = $index->getStartDate()->getTimestamp();
212
        }
213
214
        $constraints = [];
215
        $constraints[] = $query->logicalNot($query->equals('uid', $index->getUid()));
216
        $constraints[] = $query->equals('foreignTable', $index->getForeignTable());
217
        $constraints[] = $query->equals('foreignUid', $index->getForeignUid());
218
        if (!$future) {
219
            $constraints[] = $query->lessThanOrEqual('startDate', $now);
220
        }
221
        if (!$past) {
222
            $constraints[] = $query->greaterThanOrEqual('startDate', $now);
223
        }
224
225
        $query->setLimit($limit);
226
        $sort = QueryInterface::ORDER_ASCENDING === $sort ? QueryInterface::ORDER_ASCENDING : QueryInterface::ORDER_DESCENDING;
227
        $query->setOrderings($this->getSorting($sort));
228
229
        return $this->matchAndExecute($query, $constraints);
230
    }
231
232
    /**
233
     * Find by traversing information.
234
     *
235
     * @param DomainObjectInterface $event
236
     * @param bool|true             $future
237
     * @param bool|false            $past
238
     * @param int                   $limit
239
     * @param string                $sort
240
     *
241
     * @throws Exception
242
     *
243
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
244
     */
245
    public function findByEventTraversing(
246
        DomainObjectInterface $event,
247
        $future = true,
248
        $past = false,
249
        $limit = 100,
250
        $sort = QueryInterface::ORDER_ASCENDING
251
    ) {
252
        if (!$future && !$past) {
253
            return [];
254
        }
255
        $query = $this->createQuery();
256
257
        $uniqueRegisterKey = ExtensionConfigurationUtility::getUniqueRegisterKeyForModel($event);
258
259
        $this->setIndexTypes([$uniqueRegisterKey]);
260
261
        $now = DateTimeUtility::getNow()
262
            ->getTimestamp();
263
264
        $constraints = [];
265
266
        $constraints[] = $query->equals('foreignUid', $event->getUid());
267
        if (!$future) {
268
            $constraints[] = $query->lessThanOrEqual('startDate', $now);
269
        }
270
        if (!$past) {
271
            $constraints[] = $query->greaterThanOrEqual('startDate', $now);
272
        }
273
274
        $query->setLimit($limit);
275
        $sort = QueryInterface::ORDER_ASCENDING === $sort ? QueryInterface::ORDER_ASCENDING : QueryInterface::ORDER_DESCENDING;
276
        $query->setOrderings($this->getSorting($sort));
277
278
        return $this->matchAndExecute($query, $constraints);
279
    }
280
281
    /**
282
     * find Year.
283
     *
284
     * @param int $year
285
     *
286
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
287
     */
288
    public function findYear($year)
289
    {
290
        return $this->findByTimeSlot(\mktime(0, 0, 0, 1, 1, $year), \mktime(0, 0, 0, 1, 1, $year + 1) - 1);
291
    }
292
293
    /**
294
     * find Month.
295
     *
296
     * @param int $year
297
     * @param int $month
298
     *
299
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
300
     */
301
    public function findMonth(int $year, int $month)
302
    {
303
        $startTime = \mktime(0, 0, 0, $month, 1, $year);
304
        $endTime = \mktime(0, 0, 0, $month + 1, 1, $year) - 1;
305
306
        return $this->findByTimeSlot($startTime, $endTime);
307
    }
308
309
    /**
310
     * find Week.
311
     *
312
     * @param int $year
313
     * @param int $week
314
     * @param int $weekStart See documentation for settings.weekStart
315
     *
316
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
317
     */
318
    public function findWeek($year, $week, $weekStart = 1)
319
    {
320
        $weekStart = (int) $weekStart;
321
        $daysShift = DateTimeUtility::SECONDS_DAY * ($weekStart - 1);
322
        $firstDay = DateTimeUtility::convertWeekYear2DayMonthYear($week, $year);
323
        $timezone = DateTimeUtility::getTimeZone();
324
        $firstDay->setTimezone($timezone);
325
        $timeStampStart = $firstDay->getTimestamp() + $daysShift;
326
327
        return $this->findByTimeSlot($timeStampStart, $timeStampStart + DateTimeUtility::SECONDS_WEEK - 1);
328
    }
329
330
    /**
331
     * find day.
332
     *
333
     * @param int $year
334
     * @param int $month
335
     * @param int $day
336
     *
337
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
338
     */
339
    public function findDay($year, $month, $day)
340
    {
341
        $startTime = \mktime(0, 0, 0, $month, $day, $year);
342
343
        return $this->findByTimeSlot($startTime, $startTime + DateTimeUtility::SECONDS_DAY - 1);
344
    }
345
346
    /**
347
     * Set the default sorting direction.
348
     *
349
     * @param string $direction
350
     * @param string $field
351
     */
352
    public function setDefaultSortingDirection($direction, $field = '')
353
    {
354
        $this->defaultOrderings = $this->getSorting($direction, $field);
355
    }
356
357
    /**
358
     * Find by time slot.
359
     *
360
     * @param int      $startTime
361
     * @param int|null $endTime   null means open end
362
     *
363
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
364
     */
365
    public function findByTimeSlot($startTime, $endTime = null)
366
    {
367
        $query = $this->createQuery();
368
        $constraints = $this->getDefaultConstraints($query);
369
        $this->addTimeFrameConstraints($constraints, $query, $startTime, $endTime);
370
371
        return $this->matchAndExecute($query, $constraints);
372
    }
373
374
    /**
375
     * Find all indices by the given Event model.
376
     *
377
     * @param DomainObjectInterface $event
378
     *
379
     * @throws Exception
380
     *
381
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
382
     */
383
    public function findByEvent(DomainObjectInterface $event)
384
    {
385
        $query = $this->createQuery();
386
387
        $uniqueRegisterKey = ExtensionConfigurationUtility::getUniqueRegisterKeyForModel($event);
388
389
        $this->setIndexTypes([$uniqueRegisterKey]);
390
        $constraints = $this->getDefaultConstraints($query);
391
        $constraints[] = $query->equals('foreignUid', $event->getUid());
392
        $query->matching($query->logicalAnd($constraints));
393
394
        return $query->execute();
395
    }
396
397
    /**
398
     * storage page selection.
399
     *
400
     * @return array
401
     */
402
    protected function getStoragePageIds()
403
    {
404
        if (!empty($this->overridePageIds)) {
405
            return $this->overridePageIds;
406
        }
407
408
        $configurationManager = $this->objectManager->get(ConfigurationManagerInterface::class);
409
        $frameworkConfig = $configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
410
        $storagePages = isset($frameworkConfig['persistence']['storagePid']) ? GeneralUtility::intExplode(
411
            ',',
412
            $frameworkConfig['persistence']['storagePid']
413
        ) : [];
414
        if (!empty($storagePages)) {
415
            return $storagePages;
416
        }
417
        if ($frameworkConfig instanceof BackendConfigurationManager) {
418
            return GeneralUtility::trimExplode(',', $frameworkConfig->getDefaultBackendStoragePid(), true);
419
        }
420
421
        return $storagePages;
422
    }
423
424
    /**
425
     * Get the default constraint for the queries.
426
     *
427
     * @param QueryInterface $query
428
     *
429
     * @return array
430
     */
431
    protected function getDefaultConstraints(QueryInterface $query)
432
    {
433
        $constraints = [];
434
        if (!empty($this->indexTypes)) {
435
            $indexTypes = $this->indexTypes;
436
            $constraints[] = $query->in('uniqueRegisterKey', $indexTypes);
437
        }
438
439
        $storagePages = $this->getStoragePageIds();
440
        if (!empty($storagePages)) {
441
            $constraints[] = $query->in('pid', $storagePages);
442
        }
443
444
        $arguments = [
445
            'indexIds' => [],
446
            'indexTypes' => $this->indexTypes,
447
        ];
448
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__, $arguments);
449
450
        if ($arguments['indexIds']) {
451
            $constraints[] = $query->in('foreign_uid', $arguments['indexIds']);
452
        }
453
454
        return $constraints;
455
    }
456
457
    /**
458
     * Add time frame related queries.
459
     *
460
     * @param array          $constraints
461
     * @param QueryInterface $query
462
     * @param int            $startTime
463
     * @param int|null       $endTime
464
     *
465
     * @see IndexUtility::isIndexInRange
466
     */
467
    protected function addTimeFrameConstraints(&$constraints, QueryInterface $query, $startTime = null, $endTime = null)
468
    {
469
        $arguments = [
470
            'constraints' => &$constraints,
471
            'query' => $query,
472
            'startTime' => $startTime,
473
            'endTime' => $endTime,
474
        ];
475
        $arguments = $this->callSignal(__CLASS__, __FUNCTION__, $arguments);
476
477
        if (null === $arguments['startTime'] && null === $arguments['endTime']) {
478
            return;
479
        }
480
        if (null === $arguments['startTime']) {
481
            // Simulate start time
482
            $arguments['startTime'] = DateTimeUtility::getNow()->getTimestamp() - DateTimeUtility::SECONDS_DECADE;
483
        } elseif (null === $arguments['endTime']) {
484
            // Simulate end time
485
            $arguments['endTime'] = DateTimeUtility::getNow()->getTimestamp() + DateTimeUtility::SECONDS_DECADE;
486
        }
487
488
        $orConstraint = [];
489
490
        // before - in
491
        $beforeIn = [
492
            $query->lessThan('start_date', $arguments['startTime']),
493
            $query->greaterThanOrEqual('end_date', $arguments['startTime']),
494
            $query->lessThan('end_date', $arguments['endTime']),
495
        ];
496
        $orConstraint[] = $query->logicalAnd($beforeIn);
497
498
        // in - in
499
        $inIn = [
500
            $query->greaterThanOrEqual('start_date', $arguments['startTime']),
501
            $query->lessThan('end_date', $arguments['endTime']),
502
        ];
503
        $orConstraint[] = $query->logicalAnd($inIn);
504
505
        // in - after
506
        $inAfter = [
507
            $query->greaterThanOrEqual('start_date', $arguments['startTime']),
508
            $query->lessThan('start_date', $arguments['endTime']),
509
            $query->greaterThanOrEqual('end_date', $arguments['endTime']),
510
        ];
511
        $orConstraint[] = $query->logicalAnd($inAfter);
512
513
        // before - after
514
        $beforeAfter = [
515
            $query->lessThan('start_date', $arguments['startTime']),
516
            $query->greaterThan('end_date', $arguments['endTime']),
517
        ];
518
        $orConstraint[] = $query->logicalAnd($beforeAfter);
519
520
        // finish
521
        $constraints[] = $query->logicalOr($orConstraint);
522
    }
523
524
    /**
525
     * Get the sorting.
526
     *
527
     * @param string $direction
528
     * @param string $field
529
     *
530
     * @return array
531
     */
532
    protected function getSorting($direction, $field = '')
533
    {
534
        if ('end' !== $field) {
535
            $field = 'start';
536
        }
537
538
        return [
539
            $field . '_date' => $direction,
540
            $field . '_time' => $direction,
541
        ];
542
    }
543
}
544