EventRepository::setSpeakerConstraint()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 2
nc 2
nop 3
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
7
 *
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
namespace DERHANSEN\SfEventMgt\Domain\Repository;
13
14
use DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand;
15
use DERHANSEN\SfEventMgt\Domain\Model\Event;
16
use DERHANSEN\SfEventMgt\Event\ModifyEventQueryConstraintsEvent;
17
use DERHANSEN\SfEventMgt\Service\CategoryService;
18
use Psr\EventDispatcher\EventDispatcherInterface;
19
use TYPO3\CMS\Core\Utility\GeneralUtility;
20
use TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Persis...Qom\ConstraintInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Persis...eric\Typo3QuerySettings was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Persistence\QueryInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Persistence\QueryResultInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use TYPO3\CMS\Extbase\Persistence\Repository;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Persistence\Repository was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use UnexpectedValueException;
26
27
/**
28
 * @extends Repository<Event>
29
 */
30
class EventRepository extends Repository
31
{
32
    protected $defaultOrderings = [
33
        'startdate' => QueryInterface::ORDER_ASCENDING,
34
    ];
35
36
    protected EventDispatcherInterface $eventDispatcher;
37
38
    public function injectEventDispatcher(EventDispatcherInterface $eventDispatcher): void
39
    {
40
        $this->eventDispatcher = $eventDispatcher;
41
    }
42
43
    /**
44
     * Disable the use of storage records, because the StoragePage can be set
45
     * in the plugin
46
     */
47
    public function initializeObject(): void
48
    {
49
        $this->defaultQuerySettings = GeneralUtility::makeInstance(Typo3QuerySettings::class);
0 ignored issues
show
Bug Best Practice introduced by
The property defaultQuerySettings does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
50
        $this->defaultQuerySettings->setRespectStoragePage(false);
51
    }
52
53
    /**
54
     * Returns the objects of this repository matching the given demand
55
     */
56
    public function findDemanded(EventDemand $eventDemand): QueryResultInterface
57
    {
58
        $constraints = [];
59
        $query = $this->createQuery();
60
        $query->getQuerySettings()->setIgnoreEnableFields($eventDemand->getIgnoreEnableFields());
61
62
        $this->setStoragePageConstraint($query, $eventDemand, $constraints);
63
        $this->setDisplayModeConstraint($query, $eventDemand, $constraints);
64
        $this->setCategoryConstraint($query, $eventDemand, $constraints);
65
        $this->setLocationConstraint($query, $eventDemand, $constraints);
66
        $this->setLocationCityConstraint($query, $eventDemand, $constraints);
67
        $this->setLocationCountryConstraint($query, $eventDemand, $constraints);
68
        $this->setSpeakerConstraint($query, $eventDemand, $constraints);
69
        $this->setOrganisatorConstraint($query, $eventDemand, $constraints);
70
        $this->setStartEndDateConstraint($query, $eventDemand, $constraints);
71
        $this->setSearchConstraint($query, $eventDemand, $constraints);
72
        $this->setTopEventConstraint($query, $eventDemand, $constraints);
73
        $this->setYearMonthDayRestriction($query, $eventDemand, $constraints);
74
75
        $modifyEventQueryConstraintsEvent = new ModifyEventQueryConstraintsEvent(
76
            $constraints,
77
            $query,
78
            $eventDemand,
79
            $this
80
        );
81
        $this->eventDispatcher->dispatch($modifyEventQueryConstraintsEvent);
82
        $constraints = $modifyEventQueryConstraintsEvent->getConstraints();
83
84
        $this->setOrderingsFromDemand($query, $eventDemand);
85
86
        if (count($constraints) > 0) {
87
            $query->matching($query->logicalAnd(...$constraints));
88
        }
89
90
        $this->setQueryLimitFromDemand($query, $eventDemand);
91
92
        return $query->execute();
93
    }
94
95
    /**
96
     * Returns the event with the given UID and also respects the hidden state
97
     */
98
    public function findByUidIncludeHidden(int $uid): ?Event
99
    {
100
        $query = $this->createQuery();
101
        $query->getQuerySettings()->setIgnoreEnableFields(true);
102
        return $query->matching(
103
            $query->logicalAnd(
104
                $query->equals('uid', $uid),
105
                $query->equals('deleted', 0)
106
            )
107
        )->execute()->getFirst();
108
    }
109
110
    /**
111
     * Sets a query limit to the given query for the given demand
112
     */
113
    protected function setQueryLimitFromDemand(QueryInterface $query, EventDemand $eventDemand): void
114
    {
115
        if ($eventDemand->getQueryLimit() > 0) {
116
            $query->setLimit($eventDemand->getQueryLimit());
117
        }
118
    }
119
120
    /**
121
     * Sets the ordering to the given query for the given demand
122
     */
123
    protected function setOrderingsFromDemand(QueryInterface $query, EventDemand $eventDemand): void
124
    {
125
        $orderings = [];
126
        $orderFieldAllowed = GeneralUtility::trimExplode(',', $eventDemand->getOrderFieldAllowed(), true);
127
        if ($eventDemand->getOrderField() !== '' && $eventDemand->getOrderDirection() !== '' &&
128
            !empty($orderFieldAllowed) && in_array($eventDemand->getOrderField(), $orderFieldAllowed, true)) {
129
            $orderings[$eventDemand->getOrderField()] = ((strtolower($eventDemand->getOrderDirection()) === 'desc') ?
130
                QueryInterface::ORDER_DESCENDING :
131
                QueryInterface::ORDER_ASCENDING);
132
            $query->setOrderings($orderings);
133
        }
134
    }
135
136
    /**
137
     * Sets the storagePage constraint to the given constraints array
138
     */
139
    protected function setStoragePageConstraint(
140
        QueryInterface $query,
141
        EventDemand $eventDemand,
142
        array &$constraints
143
    ): void {
144
        if ($eventDemand->getStoragePage() !== '') {
145
            $pidList = GeneralUtility::intExplode(',', $eventDemand->getStoragePage(), true);
146
            $constraints['storagePage'] = $query->in('pid', $pidList);
147
        }
148
    }
149
150
    /**
151
     * Sets the displayMode constraint to the given constraints array
152
     */
153
    protected function setDisplayModeConstraint(
154
        QueryInterface $query,
155
        EventDemand $eventDemand,
156
        array &$constraints
157
    ): void {
158
        switch ($eventDemand->getDisplayMode()) {
159
            case 'future':
160
                $constraints['displayMode'] = $query->greaterThan('startdate', $eventDemand->getCurrentDateTime());
161
                break;
162
            case 'current_future':
163
                $constraints['displayMode'] = $query->logicalOr(
164
                    $query->greaterThan('startdate', $eventDemand->getCurrentDateTime()),
165
                    $query->greaterThanOrEqual('enddate', $eventDemand->getCurrentDateTime()),
166
                );
167
                break;
168
            case 'past':
169
                $constraints['displayMode'] = $query->logicalAnd(
170
                    $query->greaterThan('enddate', 0),
171
                    $query->lessThanOrEqual('enddate', $eventDemand->getCurrentDateTime()),
172
                );
173
                break;
174
            case 'time_restriction':
175
                $includeCurrentConstraint = null;
176
                if (!empty($eventDemand->getTimeRestrictionLow())) {
177
                    $timeRestriction = strtotime($eventDemand->getTimeRestrictionLow());
178
                    $timeRestrictionConstraints['timeRestrictionLow'] = $query->greaterThanOrEqual('startdate', $timeRestriction);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$timeRestrictionConstraints was never initialized. Although not strictly required by PHP, it is generally a good practice to add $timeRestrictionConstraints = array(); before regardless.
Loading history...
179
180
                    if ($eventDemand->getIncludeCurrent()) {
181
                        $includeCurrentConstraint = $query->logicalAnd(
182
                            $query->lessThan('startdate', $timeRestriction),
183
                            $query->greaterThan('enddate', $timeRestriction),
184
                        );
185
                    }
186
                }
187
                if (!empty($eventDemand->getTimeRestrictionHigh())) {
188
                    $timeRestrictionHigh = strtotime($eventDemand->getTimeRestrictionHigh());
189
                    $timeRestrictionConstraints['timeRestrictionHigh'] = $query->lessThanOrEqual('startdate', $timeRestrictionHigh);
190
                }
191
                if (isset($timeRestrictionConstraints)) {
192
                    if ($eventDemand->getIncludeCurrent() && $includeCurrentConstraint) {
193
                        $constraints['displayMode'] = $query->logicalOr(
194
                            $includeCurrentConstraint,
195
                            $query->logicalAnd(...$timeRestrictionConstraints),
196
                        );
197
                    } else {
198
                        $constraints['displayMode'] = $query->logicalAnd(...$timeRestrictionConstraints);
199
                    }
200
                }
201
                break;
202
        }
203
    }
204
205
    /**
206
     * Sets the category constraint to the given constraints array
207
     */
208
    protected function setCategoryConstraint(QueryInterface $query, EventDemand $eventDemand, array &$constraints): void
209
    {
210
        // If no category constraint is set, categories should not be respected in the query
211
        if ($eventDemand->getCategoryConjunction() === '') {
212
            return;
213
        }
214
215
        if ($eventDemand->getCategory() !== '') {
216
            $categoryConstraints = [];
217
            if ($eventDemand->getIncludeSubcategories()) {
218
                $categoryList = CategoryService::getCategoryListWithChilds($eventDemand->getCategory());
219
                $categories = GeneralUtility::intExplode(',', $categoryList, true);
220
            } else {
221
                $categories = GeneralUtility::intExplode(',', $eventDemand->getCategory(), true);
222
            }
223
            foreach ($categories as $category) {
224
                $categoryConstraints[] = $query->contains('category', $category);
225
            }
226
            if (count($categoryConstraints) > 0) {
227
                $constraints['category'] = $this->getCategoryConstraint($query, $eventDemand, $categoryConstraints);
228
            }
229
        }
230
    }
231
232
    /**
233
     * Returns the category constraint depending on the category conjunction configured in eventDemand
234
     */
235
    public function getCategoryConstraint(
236
        QueryInterface $query,
237
        EventDemand $eventDemand,
238
        array $categoryConstraints
239
    ): ConstraintInterface {
240
        switch (strtolower($eventDemand->getCategoryConjunction())) {
241
            case 'and':
242
                $constraint = $query->logicalAnd(...$categoryConstraints);
243
                break;
244
            case 'notor':
245
                $constraint = $query->logicalNot($query->logicalOr(...$categoryConstraints));
246
                break;
247
            case 'notand':
248
                $constraint = $query->logicalNot($query->logicalAnd(...$categoryConstraints));
249
                break;
250
            case 'or':
251
            default:
252
                $constraint = $query->logicalOr(...$categoryConstraints);
253
        }
254
255
        return $constraint;
256
    }
257
258
    /**
259
     * Sets the location constraint to the given constraints array
260
     */
261
    protected function setLocationConstraint(QueryInterface $query, EventDemand $eventDemand, array &$constraints): void
262
    {
263
        if ($eventDemand->getLocation() !== null && $eventDemand->getLocation() !== '') {
264
            $constraints['location'] = $query->equals('location', $eventDemand->getLocation());
265
        }
266
    }
267
268
    /**
269
     * Sets the location.city constraint to the given constraints array
270
     */
271
    protected function setLocationCityConstraint(
272
        QueryInterface $query,
273
        EventDemand $eventDemand,
274
        array &$constraints
275
    ): void {
276
        if ($eventDemand->getLocationCity() !== null && $eventDemand->getLocationCity() !== '') {
277
            $constraints['locationCity'] = $query->equals('location.city', $eventDemand->getLocationCity());
278
        }
279
    }
280
281
    /**
282
     * Sets the location.country constraint to the given constraints array
283
     */
284
    protected function setLocationCountryConstraint(
285
        QueryInterface $query,
286
        EventDemand $eventDemand,
287
        array &$constraints
288
    ): void {
289
        if ($eventDemand->getLocationCountry() !== null && $eventDemand->getLocationCountry() !== '') {
290
            $constraints['locationCountry'] = $query->equals('location.country', $eventDemand->getLocationCountry());
291
        }
292
    }
293
294
    /**
295
     * Sets the speaker constraint to the given constraints array
296
     */
297
    protected function setSpeakerConstraint(QueryInterface $query, EventDemand $eventDemand, array &$constraints): void
298
    {
299
        if ($eventDemand->getSpeaker() !== null && $eventDemand->getSpeaker() !== '') {
300
            $constraints['speaker'] = $query->contains('speaker', $eventDemand->getSpeaker());
301
        }
302
    }
303
304
    /**
305
     * Sets the organisator constraint to the given constraints array
306
     */
307
    protected function setOrganisatorConstraint(
308
        QueryInterface $query,
309
        EventDemand $eventDemand,
310
        array &$constraints
311
    ): void {
312
        if ($eventDemand->getOrganisator() !== null && $eventDemand->getOrganisator() !== '') {
313
            $constraints['organisator'] = $query->equals('organisator', $eventDemand->getOrganisator());
314
        }
315
    }
316
317
    /**
318
     * Sets the start- and enddate constraint to the given constraints array
319
     */
320
    protected function setStartEndDateConstraint(
321
        QueryInterface $query,
322
        EventDemand $eventDemand,
323
        array &$constraints
324
    ): void {
325
        if ($eventDemand->getSearchDemand() && $eventDemand->getSearchDemand()->getStartDate() !== null &&
326
            $eventDemand->getSearchDemand()->getEndDate() !== null
327
        ) {
328
            /* StartDate and EndDate  - Search for events between two given dates */
329
            $begin = $eventDemand->getSearchDemand()->getStartDate();
330
            $end = $eventDemand->getSearchDemand()->getEndDate();
331
            $constraints['startEndDate'] = $query->logicalOr(
332
                $query->between('startdate', $begin, $end),
333
                $query->between('enddate', $begin, $end),
334
                $query->logicalAnd(
335
                    $query->greaterThanOrEqual('enddate', $begin),
336
                    $query->lessThanOrEqual('startdate', $begin),
337
                ),
338
            );
339
        } elseif ($eventDemand->getSearchDemand() && $eventDemand->getSearchDemand()->getStartDate() !== null) {
340
            /* StartDate - Search for events beginning at a given date */
341
            $constraints['startDate'] = $query->greaterThanOrEqual('startdate', $eventDemand->getSearchDemand()->getStartDate());
342
        } elseif ($eventDemand->getSearchDemand() && $eventDemand->getSearchDemand()->getEndDate() !== null) {
343
            /* EndDate - Search for events ending on a given date */
344
            $constraints['endDate'] = $query->lessThanOrEqual('enddate', $eventDemand->getSearchDemand()->getEndDate());
345
        }
346
    }
347
348
    /**
349
     * Sets the search constraint to the given constraints array
350
     */
351
    protected function setSearchConstraint(QueryInterface $query, EventDemand $eventDemand, array &$constraints): void
352
    {
353
        if ($eventDemand->getSearchDemand() &&
354
            $eventDemand->getSearchDemand()->getSearch() !== null &&
355
            $eventDemand->getSearchDemand()->getSearch() !== ''
356
        ) {
357
            $searchFields = GeneralUtility::trimExplode(',', $eventDemand->getSearchDemand()->getFields(), true);
358
            $searchConstraints = [];
359
360
            if (count($searchFields) === 0) {
361
                throw new UnexpectedValueException('No search fields defined', 1318497755);
362
            }
363
364
            $searchSubject = $eventDemand->getSearchDemand()->getSearch();
365
            foreach ($searchFields as $field) {
366
                $searchConstraints[] = $query->like($field, '%' . addcslashes($searchSubject, '_%') . '%');
367
            }
368
369
            $constraints['search'] = $query->logicalOr(...$searchConstraints);
370
        }
371
    }
372
373
    /**
374
     * Sets the topEvent constraint to the given constraints array
375
     */
376
    protected function setTopEventConstraint(QueryInterface $query, EventDemand $eventDemand, array &$constraints): void
377
    {
378
        if ($eventDemand->getTopEventRestriction() > 0) {
379
            $constraints['topEvent'] = $query->equals('topEvent', (bool)($eventDemand->getTopEventRestriction() - 1));
380
        }
381
    }
382
383
    /**
384
     * Sets the restriction for year, year/month or year/month/day to the given constraints array
385
     */
386
    protected function setYearMonthDayRestriction(
387
        QueryInterface $query,
388
        EventDemand $eventDemand,
389
        array &$constraints
390
    ): void {
391
        if ($eventDemand->getYear() > 0) {
392
            if ($eventDemand->getMonth() > 0) {
393
                if ($eventDemand->getDay() > 0) {
394
                    $begin = mktime(0, 0, 0, $eventDemand->getMonth(), $eventDemand->getDay(), $eventDemand->getYear());
395
                    $end = mktime(23, 59, 59, $eventDemand->getMonth(), $eventDemand->getDay(), $eventDemand->getYear());
396
                } else {
397
                    $begin = mktime(0, 0, 0, $eventDemand->getMonth(), 1, $eventDemand->getYear());
398
                    $end = mktime(23, 59, 59, ($eventDemand->getMonth() + 1), 0, $eventDemand->getYear());
399
                }
400
            } else {
401
                $begin = mktime(0, 0, 0, 1, 1, $eventDemand->getYear());
402
                $end = mktime(23, 59, 59, 12, 31, $eventDemand->getYear());
403
            }
404
            $constraints['yearMonthDay'] = $query->logicalOr(
405
                $query->between('startdate', $begin, $end),
406
                $query->between('enddate', $begin, $end),
407
                $query->logicalAnd(
408
                    $query->greaterThanOrEqual('enddate', $begin),
409
                    $query->lessThanOrEqual('startdate', $begin),
410
                ),
411
            );
412
        }
413
    }
414
}
415