EventRepository   F
last analyzed

Complexity

Total Complexity 72

Size/Duplication

Total Lines 379
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 166
c 1
b 0
f 0
dl 0
loc 379
rs 2.64
wmc 72

19 Methods

Rating   Name   Duplication   Size   Complexity  
A setCategoryConstraint() 0 20 6
A initializeObject() 0 4 1
A findDemanded() 0 37 2
A setStoragePageConstraint() 0 8 2
A injectEventDispatcher() 0 3 1
A setQueryLimitFromDemand() 0 4 2
A findByUidIncludeHidden() 0 6 1
A setLocationConstraint() 0 4 3
A setLocationCityConstraint() 0 7 3
A setTopEventConstraint() 0 4 2
A getCategoryConstraint() 0 21 5
A setYearMonthDayRestriction() 0 24 4
A setLocationCountryConstraint() 0 7 3
B setStartEndDateConstraint() 0 25 8
A setSpeakerConstraint() 0 4 3
A setOrganisatorConstraint() 0 7 3
B setDisplayModeConstraint() 0 49 11
A setSearchConstraint() 0 19 6
A setOrderingsFromDemand() 0 10 6

How to fix   Complexity   

Complex Class

Complex classes like EventRepository often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EventRepository, and based on these observations, apply Extract Interface, too.

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\Event\ModifyEventQueryConstraintsEvent;
16
use DERHANSEN\SfEventMgt\Service\CategoryService;
17
use Psr\EventDispatcher\EventDispatcherInterface;
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
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...
20
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...
21
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...
22
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...
23
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...
24
use UnexpectedValueException;
25
26
class EventRepository extends Repository
27
{
28
    protected $defaultOrderings = [
29
        'startdate' => QueryInterface::ORDER_ASCENDING,
30
    ];
31
32
    protected EventDispatcherInterface $eventDispatcher;
33
34
    public function injectEventDispatcher(EventDispatcherInterface $eventDispatcher): void
35
    {
36
        $this->eventDispatcher = $eventDispatcher;
37
    }
38
39
    /**
40
     * Disable the use of storage records, because the StoragePage can be set
41
     * in the plugin
42
     */
43
    public function initializeObject(): void
44
    {
45
        $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...
46
        $this->defaultQuerySettings->setRespectStoragePage(false);
47
    }
48
49
    /**
50
     * Returns the objects of this repository matching the given demand
51
     */
52
    public function findDemanded(EventDemand $eventDemand): QueryResultInterface
53
    {
54
        $constraints = [];
55
        $query = $this->createQuery();
56
        $query->getQuerySettings()->setIgnoreEnableFields($eventDemand->getIgnoreEnableFields());
57
58
        $this->setStoragePageConstraint($query, $eventDemand, $constraints);
59
        $this->setDisplayModeConstraint($query, $eventDemand, $constraints);
60
        $this->setCategoryConstraint($query, $eventDemand, $constraints);
61
        $this->setLocationConstraint($query, $eventDemand, $constraints);
62
        $this->setLocationCityConstraint($query, $eventDemand, $constraints);
63
        $this->setLocationCountryConstraint($query, $eventDemand, $constraints);
64
        $this->setSpeakerConstraint($query, $eventDemand, $constraints);
65
        $this->setOrganisatorConstraint($query, $eventDemand, $constraints);
66
        $this->setStartEndDateConstraint($query, $eventDemand, $constraints);
67
        $this->setSearchConstraint($query, $eventDemand, $constraints);
68
        $this->setTopEventConstraint($query, $eventDemand, $constraints);
69
        $this->setYearMonthDayRestriction($query, $eventDemand, $constraints);
70
71
        $modifyEventQueryConstraintsEvent = new ModifyEventQueryConstraintsEvent(
72
            $constraints,
73
            $query,
74
            $eventDemand,
75
            $this
76
        );
77
        $this->eventDispatcher->dispatch($modifyEventQueryConstraintsEvent);
78
        $constraints = $modifyEventQueryConstraintsEvent->getConstraints();
79
80
        $this->setOrderingsFromDemand($query, $eventDemand);
81
82
        if (count($constraints) > 0) {
83
            $query->matching($query->logicalAnd(...$constraints));
84
        }
85
86
        $this->setQueryLimitFromDemand($query, $eventDemand);
87
88
        return $query->execute();
89
    }
90
91
    /**
92
     * Returns the event with the given UID and also respects the hidden state
93
     *
94
     * @param int $uid
95
     * @return object
96
     */
97
    public function findByUidIncludeHidden(int $uid): object
98
    {
99
        $query = $this->createQuery();
100
        $query->getQuerySettings()->setIgnoreEnableFields(true);
101
        $query->matching($query->equals('uid', $uid));
102
        return $query->execute()->getFirst();
103
    }
104
105
    /**
106
     * Sets a query limit to the given query for the given demand
107
     */
108
    protected function setQueryLimitFromDemand(QueryInterface $query, EventDemand $eventDemand): void
109
    {
110
        if ($eventDemand->getQueryLimit() > 0) {
111
            $query->setLimit($eventDemand->getQueryLimit());
112
        }
113
    }
114
115
    /**
116
     * Sets the ordering to the given query for the given demand
117
     */
118
    protected function setOrderingsFromDemand(QueryInterface $query, EventDemand $eventDemand): void
119
    {
120
        $orderings = [];
121
        $orderFieldAllowed = GeneralUtility::trimExplode(',', $eventDemand->getOrderFieldAllowed(), true);
122
        if ($eventDemand->getOrderField() !== '' && $eventDemand->getOrderDirection() !== '' &&
123
            !empty($orderFieldAllowed) && in_array($eventDemand->getOrderField(), $orderFieldAllowed, true)) {
124
            $orderings[$eventDemand->getOrderField()] = ((strtolower($eventDemand->getOrderDirection()) === 'desc') ?
125
                QueryInterface::ORDER_DESCENDING :
126
                QueryInterface::ORDER_ASCENDING);
127
            $query->setOrderings($orderings);
128
        }
129
    }
130
131
    /**
132
     * Sets the storagePage constraint to the given constraints array
133
     */
134
    protected function setStoragePageConstraint(
135
        QueryInterface $query,
136
        EventDemand $eventDemand,
137
        array &$constraints
138
    ): void {
139
        if ($eventDemand->getStoragePage() !== '') {
140
            $pidList = GeneralUtility::intExplode(',', $eventDemand->getStoragePage(), true);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Core\Utility\G...alUtility::intExplode() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

140
            $pidList = /** @scrutinizer ignore-deprecated */ GeneralUtility::intExplode(',', $eventDemand->getStoragePage(), true);
Loading history...
141
            $constraints['storagePage'] = $query->in('pid', $pidList);
142
        }
143
    }
144
145
    /**
146
     * Sets the displayMode constraint to the given constraints array
147
     */
148
    protected function setDisplayModeConstraint(
149
        QueryInterface $query,
150
        EventDemand $eventDemand,
151
        array &$constraints
152
    ): void {
153
        switch ($eventDemand->getDisplayMode()) {
154
            case 'future':
155
                $constraints['displayMode'] = $query->greaterThan('startdate', $eventDemand->getCurrentDateTime());
156
                break;
157
            case 'current_future':
158
                $constraints['displayMode'] = $query->logicalOr(
159
                    $query->greaterThan('startdate', $eventDemand->getCurrentDateTime()),
160
                    $query->greaterThanOrEqual('enddate', $eventDemand->getCurrentDateTime()),
161
                );
162
                break;
163
            case 'past':
164
                $constraints['displayMode'] = $query->logicalAnd(
165
                    $query->greaterThan('enddate', 0),
166
                    $query->lessThanOrEqual('enddate', $eventDemand->getCurrentDateTime()),
167
                );
168
                break;
169
            case 'time_restriction':
170
                $includeCurrentConstraint = null;
171
                if (!empty($eventDemand->getTimeRestrictionLow())) {
172
                    $timeRestriction = strtotime($eventDemand->getTimeRestrictionLow());
173
                    $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...
174
175
                    if ($eventDemand->getIncludeCurrent()) {
176
                        $includeCurrentConstraint = $query->logicalAnd(
177
                            $query->lessThan('startdate', $timeRestriction),
178
                            $query->greaterThan('enddate', $timeRestriction),
179
                        );
180
                    }
181
                }
182
                if (!empty($eventDemand->getTimeRestrictionHigh())) {
183
                    $timeRestrictionHigh = strtotime($eventDemand->getTimeRestrictionHigh());
184
                    $timeRestrictionConstraints['timeRestrictionHigh'] = $query->lessThanOrEqual('startdate', $timeRestrictionHigh);
185
                }
186
                if (isset($timeRestrictionConstraints)) {
187
                    if ($eventDemand->getIncludeCurrent() && $includeCurrentConstraint) {
188
                        $constraints['displayMode'] = $query->logicalOr(
189
                            $includeCurrentConstraint,
190
                            $query->logicalAnd(...$timeRestrictionConstraints),
191
                        );
192
                    } else {
193
                        $constraints['displayMode'] = $query->logicalAnd(...$timeRestrictionConstraints);
194
                    }
195
                }
196
                break;
197
        }
198
    }
199
200
    /**
201
     * Sets the category constraint to the given constraints array
202
     */
203
    protected function setCategoryConstraint(QueryInterface $query, EventDemand $eventDemand, array &$constraints): void
204
    {
205
        // If no category constraint is set, categories should not be respected in the query
206
        if ($eventDemand->getCategoryConjunction() === '') {
207
            return;
208
        }
209
210
        if ($eventDemand->getCategory() !== '') {
211
            $categoryConstraints = [];
212
            if ($eventDemand->getIncludeSubcategories()) {
213
                $categoryList = CategoryService::getCategoryListWithChilds($eventDemand->getCategory());
214
                $categories = GeneralUtility::intExplode(',', $categoryList, true);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Core\Utility\G...alUtility::intExplode() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

214
                $categories = /** @scrutinizer ignore-deprecated */ GeneralUtility::intExplode(',', $categoryList, true);
Loading history...
215
            } else {
216
                $categories = GeneralUtility::intExplode(',', $eventDemand->getCategory(), true);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Core\Utility\G...alUtility::intExplode() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

216
                $categories = /** @scrutinizer ignore-deprecated */ GeneralUtility::intExplode(',', $eventDemand->getCategory(), true);
Loading history...
217
            }
218
            foreach ($categories as $category) {
219
                $categoryConstraints[] = $query->contains('category', $category);
220
            }
221
            if (count($categoryConstraints) > 0) {
222
                $constraints['category'] = $this->getCategoryConstraint($query, $eventDemand, $categoryConstraints);
223
            }
224
        }
225
    }
226
227
    /**
228
     * Returns the category constraint depending on the category conjunction configured in eventDemand
229
     */
230
    public function getCategoryConstraint(
231
        QueryInterface $query,
232
        EventDemand $eventDemand,
233
        array $categoryConstraints
234
    ): ConstraintInterface {
235
        switch (strtolower($eventDemand->getCategoryConjunction())) {
236
            case 'and':
237
                $constraint = $query->logicalAnd(...$categoryConstraints);
238
                break;
239
            case 'notor':
240
                $constraint = $query->logicalNot($query->logicalOr(...$categoryConstraints));
241
                break;
242
            case 'notand':
243
                $constraint = $query->logicalNot($query->logicalAnd(...$categoryConstraints));
244
                break;
245
            case 'or':
246
            default:
247
                $constraint = $query->logicalOr(...$categoryConstraints);
248
        }
249
250
        return $constraint;
251
    }
252
253
    /**
254
     * Sets the location constraint to the given constraints array
255
     */
256
    protected function setLocationConstraint(QueryInterface $query, EventDemand $eventDemand, array &$constraints): void
257
    {
258
        if ($eventDemand->getLocation() !== null && $eventDemand->getLocation() !== '') {
259
            $constraints['location'] = $query->equals('location', $eventDemand->getLocation());
260
        }
261
    }
262
263
    /**
264
     * Sets the location.city constraint to the given constraints array
265
     */
266
    protected function setLocationCityConstraint(
267
        QueryInterface $query,
268
        EventDemand $eventDemand,
269
        array &$constraints
270
    ): void {
271
        if ($eventDemand->getLocationCity() !== null && $eventDemand->getLocationCity() !== '') {
272
            $constraints['locationCity'] = $query->equals('location.city', $eventDemand->getLocationCity());
273
        }
274
    }
275
276
    /**
277
     * Sets the location.country constraint to the given constraints array
278
     */
279
    protected function setLocationCountryConstraint(
280
        QueryInterface $query,
281
        EventDemand $eventDemand,
282
        array &$constraints
283
    ): void {
284
        if ($eventDemand->getLocationCountry() !== null && $eventDemand->getLocationCountry() !== '') {
285
            $constraints['locationCountry'] = $query->equals('location.country', $eventDemand->getLocationCountry());
286
        }
287
    }
288
289
    /**
290
     * Sets the speaker constraint to the given constraints array
291
     */
292
    protected function setSpeakerConstraint(QueryInterface $query, EventDemand $eventDemand, array &$constraints): void
293
    {
294
        if ($eventDemand->getSpeaker() !== null && $eventDemand->getSpeaker() !== '') {
295
            $constraints['speaker'] = $query->contains('speaker', $eventDemand->getSpeaker());
296
        }
297
    }
298
299
    /**
300
     * Sets the organisator constraint to the given constraints array
301
     */
302
    protected function setOrganisatorConstraint(
303
        QueryInterface $query,
304
        EventDemand $eventDemand,
305
        array &$constraints
306
    ): void {
307
        if ($eventDemand->getOrganisator() !== null && $eventDemand->getOrganisator() !== '') {
308
            $constraints['organisator'] = $query->equals('organisator', $eventDemand->getOrganisator());
309
        }
310
    }
311
312
    /**
313
     * Sets the start- and enddate constraint to the given constraints array
314
     */
315
    protected function setStartEndDateConstraint(
316
        QueryInterface $query,
317
        EventDemand $eventDemand,
318
        array &$constraints
319
    ): void {
320
        if ($eventDemand->getSearchDemand() && $eventDemand->getSearchDemand()->getStartDate() !== null &&
321
            $eventDemand->getSearchDemand()->getEndDate() !== null
322
        ) {
323
            /* StartDate and EndDate  - Search for events between two given dates */
324
            $begin = $eventDemand->getSearchDemand()->getStartDate();
325
            $end = $eventDemand->getSearchDemand()->getEndDate();
326
            $constraints['startEndDate'] = $query->logicalOr(
327
                $query->between('startdate', $begin, $end),
328
                $query->between('enddate', $begin, $end),
329
                $query->logicalAnd(
330
                    $query->greaterThanOrEqual('enddate', $begin),
331
                    $query->lessThanOrEqual('startdate', $begin),
332
                ),
333
            );
334
        } elseif ($eventDemand->getSearchDemand() && $eventDemand->getSearchDemand()->getStartDate() !== null) {
335
            /* StartDate - Search for events beginning at a given date */
336
            $constraints['startDate'] = $query->greaterThanOrEqual('startdate', $eventDemand->getSearchDemand()->getStartDate());
337
        } elseif ($eventDemand->getSearchDemand() && $eventDemand->getSearchDemand()->getEndDate() !== null) {
338
            /* EndDate - Search for events ending on a given date */
339
            $constraints['endDate'] = $query->lessThanOrEqual('enddate', $eventDemand->getSearchDemand()->getEndDate());
340
        }
341
    }
342
343
    /**
344
     * Sets the search constraint to the given constraints array
345
     */
346
    protected function setSearchConstraint(QueryInterface $query, EventDemand $eventDemand, array &$constraints): void
347
    {
348
        if ($eventDemand->getSearchDemand() &&
349
            $eventDemand->getSearchDemand()->getSearch() !== null &&
350
            $eventDemand->getSearchDemand()->getSearch() !== ''
351
        ) {
352
            $searchFields = GeneralUtility::trimExplode(',', $eventDemand->getSearchDemand()->getFields(), true);
353
            $searchConstraints = [];
354
355
            if (count($searchFields) === 0) {
356
                throw new UnexpectedValueException('No search fields defined', 1318497755);
357
            }
358
359
            $searchSubject = $eventDemand->getSearchDemand()->getSearch();
360
            foreach ($searchFields as $field) {
361
                $searchConstraints[] = $query->like($field, '%' . addcslashes($searchSubject, '_%') . '%');
362
            }
363
364
            $constraints['search'] = $query->logicalOr(...$searchConstraints);
365
        }
366
    }
367
368
    /**
369
     * Sets the topEvent constraint to the given constraints array
370
     */
371
    protected function setTopEventConstraint(QueryInterface $query, EventDemand $eventDemand, array &$constraints): void
372
    {
373
        if ($eventDemand->getTopEventRestriction() > 0) {
374
            $constraints['topEvent'] = $query->equals('topEvent', (bool)($eventDemand->getTopEventRestriction() - 1));
375
        }
376
    }
377
378
    /**
379
     * Sets the restriction for year, year/month or year/month/day to the given constraints array
380
     */
381
    protected function setYearMonthDayRestriction(
382
        QueryInterface $query,
383
        EventDemand $eventDemand,
384
        array &$constraints
385
    ): void {
386
        if ($eventDemand->getYear() > 0) {
387
            if ($eventDemand->getMonth() > 0) {
388
                if ($eventDemand->getDay() > 0) {
389
                    $begin = mktime(0, 0, 0, $eventDemand->getMonth(), $eventDemand->getDay(), $eventDemand->getYear());
390
                    $end = mktime(23, 59, 59, $eventDemand->getMonth(), $eventDemand->getDay(), $eventDemand->getYear());
391
                } else {
392
                    $begin = mktime(0, 0, 0, $eventDemand->getMonth(), 1, $eventDemand->getYear());
393
                    $end = mktime(23, 59, 59, ($eventDemand->getMonth() + 1), 0, $eventDemand->getYear());
394
                }
395
            } else {
396
                $begin = mktime(0, 0, 0, 1, 1, $eventDemand->getYear());
397
                $end = mktime(23, 59, 59, 12, 31, $eventDemand->getYear());
398
            }
399
            $constraints['yearMonthDay'] = $query->logicalOr(
400
                $query->between('startdate', $begin, $end),
401
                $query->between('enddate', $begin, $end),
402
                $query->logicalAnd(
403
                    $query->greaterThanOrEqual('enddate', $begin),
404
                    $query->lessThanOrEqual('startdate', $begin),
405
                ),
406
            );
407
        }
408
    }
409
}
410