Completed
Push — feature/spam-protection ( be04ad )
by Torben
02:50
created

removePossibleSpamCheckFieldsFromArguments()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
cc 4
nc 5
nop 0
1
<?php
2
namespace DERHANSEN\SfEventMgt\Controller;
3
4
/*
5
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE.txt file that was distributed with this source code.
9
 */
10
11
use DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand;
12
use DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand;
13
use DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand;
14
use DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand;
15
use DERHANSEN\SfEventMgt\Domain\Model\Event;
16
use DERHANSEN\SfEventMgt\Domain\Model\Registration;
17
use DERHANSEN\SfEventMgt\Service\EventCacheService;
18
use DERHANSEN\SfEventMgt\Utility\MessageType;
19
use DERHANSEN\SfEventMgt\Utility\Page;
20
use DERHANSEN\SfEventMgt\Utility\RegistrationResult;
21
use TYPO3\CMS\Core\Utility\ArrayUtility;
22
use TYPO3\CMS\Core\Utility\GeneralUtility;
23
use TYPO3\CMS\Core\Utility\HttpUtility;
24
use TYPO3\CMS\Extbase\Mvc\RequestInterface;
25
use TYPO3\CMS\Extbase\Mvc\ResponseInterface;
26
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
27
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
28
use TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter;
29
use TYPO3\CMS\Fluid\View\StandaloneView;
30
31
/**
32
 * EventController
33
 *
34
 * @author Torben Hansen <[email protected]>
35
 */
36
class EventController extends AbstractController
37
{
38
    /**
39
     * @var EventCacheService
40
     */
41
    protected $eventCacheService = null;
42
43
    /**
44
     * @param EventCacheService $cacheService
45
     */
46
    public function injectEventCacheService(EventCacheService $cacheService)
47
    {
48
        $this->eventCacheService = $cacheService;
49
    }
50
51
    /**
52
     * Assign contentObjectData and pageData to earch view
53
     *
54
     * @param \TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view
55
     */
56
    protected function initializeView(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view)
57
    {
58
        $view->assign('contentObjectData', $this->configurationManager->getContentObject()->data);
59
        if (is_object($GLOBALS['TSFE'])) {
60
            $view->assign('pageData', $GLOBALS['TSFE']->page);
61
        }
62
        parent::initializeView($view);
63
    }
64
65
    /**
66
     * Initializes the current action
67
     */
68
    public function initializeAction()
69
    {
70
        $typoScriptFrontendController = $this->getTypoScriptFrontendController();
71
        if ($typoScriptFrontendController !== null) {
72
            static $cacheTagsSet = false;
73
74
            if (!$cacheTagsSet) {
75
                $typoScriptFrontendController->addCacheTags(['tx_sfeventmgt']);
76
                $cacheTagsSet = true;
77
            }
78
        }
79
    }
80
81
    /**
82
     * Creates an event demand object with the given settings
83
     *
84
     * @param array $settings The settings
85
     *
86
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand
87
     */
88
    public function createEventDemandObjectFromSettings(array $settings)
89
    {
90
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand */
91
        $demand = $this->objectManager->get(EventDemand::class);
92
        $demand->setDisplayMode($settings['displayMode']);
93
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
94
        $demand->setCategoryConjunction($settings['categoryConjunction']);
95
        $demand->setCategory($settings['category']);
96
        $demand->setIncludeSubcategories($settings['includeSubcategories']);
97
        $demand->setTopEventRestriction((int)$settings['topEventRestriction']);
98
        $demand->setOrderField($settings['orderField']);
99
        $demand->setOrderFieldAllowed($settings['orderFieldAllowed']);
100
        $demand->setOrderDirection($settings['orderDirection']);
101
        $demand->setQueryLimit($settings['queryLimit']);
102
        $demand->setLocation($settings['location']);
103
        $demand->setOrganisator($settings['organisator']);
104
        $demand->setSpeaker($settings['speaker']);
105
106
        return $demand;
107
    }
108
109
    /**
110
     * Creates a foreign record demand object with the given settings
111
     *
112
     * @param array $settings The settings
113
     *
114
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand
115
     */
116
    public function createForeignRecordDemandObjectFromSettings(array $settings)
117
    {
118
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand $demand */
119
        $demand = $this->objectManager->get(ForeignRecordDemand::class);
120
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
121
        $demand->setRestrictForeignRecordsToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
122
123
        return $demand;
124
    }
125
126
    /**
127
     * Creates a category demand object with the given settings
128
     *
129
     * @param array $settings The settings
130
     *
131
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand
132
     */
133
    public function createCategoryDemandObjectFromSettings(array $settings)
134
    {
135
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand $demand */
136
        $demand = $this->objectManager->get(CategoryDemand::class);
137
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
138
        $demand->setRestrictToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
139
        $demand->setCategories($settings['categoryMenu']['categories']);
140
        $demand->setIncludeSubcategories($settings['categoryMenu']['includeSubcategories']);
141
142
        return $demand;
143
    }
144
145
    /**
146
     * Hook into request processing and catch exceptions
147
     *
148
     * @param RequestInterface $request
149
     * @param ResponseInterface $response
150
     * @throws \Exception
151
     */
152
    public function processRequest(RequestInterface $request, ResponseInterface $response)
153
    {
154
        try {
155
            parent::processRequest($request, $response);
156
        } catch (\Exception $exception) {
157
            $this->handleKnownExceptionsElseThrowAgain($exception);
158
        }
159
    }
160
161
    /**
162
     * Handle known exceptions
163
     *
164
     * @param \Exception $exception
165
     * @throws \Exception
166
     */
167
    private function handleKnownExceptionsElseThrowAgain(\Exception $exception)
168
    {
169
        $previousException = $exception->getPrevious();
170
        $actions = ['detailAction', 'registrationAction', 'icalDownloadAction'];
171
        if (in_array($this->actionMethodName, $actions, true)
172
            && $previousException instanceof \TYPO3\CMS\Extbase\Property\Exception
173
        ) {
174
            $this->handleEventNotFoundError($this->settings);
175
        } else {
176
            throw $exception;
177
        }
178
    }
179
180
    /**
181
     * Initialize list action and set format
182
     *
183
     * @return void
184
     */
185
    public function initializeListAction()
186
    {
187
        if (isset($this->settings['list']['format'])) {
188
            $this->request->setFormat($this->settings['list']['format']);
189
        }
190
    }
191
192
    /**
193
     * List view
194
     *
195
     * @param array $overwriteDemand OverwriteDemand
196
     *
197
     * @return void
198
     */
199
    public function listAction(array $overwriteDemand = [])
200
    {
201
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
202
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
203
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
204
        if ($this->isOverwriteDemand($overwriteDemand)) {
205
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
206
        }
207
        $events = $this->eventRepository->findDemanded($eventDemand);
208
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
209
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
210
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
211
        $speakers = $this->speakerRepository->findDemanded($foreignRecordDemand);
212
213
        $values = [
214
            'events' => $events,
215
            'categories' => $categories,
216
            'locations' => $locations,
217
            'organisators' => $organisators,
218
            'speakers' => $speakers,
219
            'overwriteDemand' => $overwriteDemand,
220
            'eventDemand' => $eventDemand
221
        ];
222
223
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
224
        $this->view->assignMultiple($values);
225
226
        $this->eventCacheService->addPageCacheTagsByEventDemandObject($eventDemand);
227
    }
228
229
    /**
230
     * Calendar view
231
     *
232
     * @param array $overwriteDemand OverwriteDemand
233
     *
234
     * @return void
235
     */
236
    public function calendarAction(array $overwriteDemand = [])
237
    {
238
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
239
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
240
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
241
        if ($this->isOverwriteDemand($overwriteDemand)) {
242
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
243
        }
244
245
        // Set month/year to demand if not given
246
        if (!$eventDemand->getMonth()) {
247
            $currentMonth = date('n');
248
            $eventDemand->setMonth($currentMonth);
249
        } else {
250
            $currentMonth = $eventDemand->getMonth();
251
        }
252
        if (!$eventDemand->getYear()) {
253
            $currentYear = date('Y');
254
            $eventDemand->setYear($currentYear);
255
        } else {
256
            $currentYear = $eventDemand->getYear();
257
        }
258
259
        // Set demand from calendar date range instead of month / year
260
        if ((bool)$this->settings['calendar']['includeEventsForEveryDayOfAllCalendarWeeks']) {
261
            $eventDemand = $this->changeEventDemandToFullMonthDateRange($eventDemand);
262
        }
263
264
        $events = $this->eventRepository->findDemanded($eventDemand);
265
        $weeks = $this->calendarService->getCalendarArray(
266
            $currentMonth,
267
            $currentYear,
268
            strtotime('today midnight'),
269
            (int)$this->settings['calendar']['firstDayOfWeek'],
270
            $events
271
        );
272
273
        $values = [
274
            'events' => $events,
275
            'weeks' => $weeks,
276
            'categories' => $this->categoryRepository->findDemanded($categoryDemand),
277
            'locations' => $this->locationRepository->findDemanded($foreignRecordDemand),
278
            'organisators' => $this->organisatorRepository->findDemanded($foreignRecordDemand),
279
            'eventDemand' => $eventDemand,
280
            'overwriteDemand' => $overwriteDemand,
281
            'currentPageId' => $GLOBALS['TSFE']->id,
282
            'firstDayOfMonth' => \DateTime::createFromFormat('d.m.Y', sprintf('1.%s.%s', $currentMonth, $currentYear)),
283
            'previousMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '-1 month'),
284
            'nextMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '+1 month')
285
        ];
286
287
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
288
        $this->view->assignMultiple($values);
289
    }
290
291
    /**
292
     * Changes the given event demand object to select a date range for a calendar month including days of the previous
293
     * month for the first week and they days for the next month for the last week
294
     *
295
     * @param EventDemand $eventDemand
296
     * @return EventDemand
297
     */
298
    protected function changeEventDemandToFullMonthDateRange(EventDemand $eventDemand)
299
    {
300
        $calendarDateRange = $this->calendarService->getCalendarDateRange(
301
            $eventDemand->getMonth(),
302
            $eventDemand->getYear(),
303
            $this->settings['calendar']['firstDayOfWeek']
304
        );
305
306
        $eventDemand->setMonth(0);
307
        $eventDemand->setYear(0);
308
309
        $startDate = new \DateTime();
310
        $startDate->setTimestamp($calendarDateRange['firstDayOfCalendar']);
311
        $endDate = new \DateTime();
312
        $endDate->setTimestamp($calendarDateRange['lastDayOfCalendar']);
313
        $endDate->setTime(23, 59, 59);
314
315
        $searchDemand = new SearchDemand();
316
        $searchDemand->setStartDate($startDate);
317
        $searchDemand->setEndDate($endDate);
318
        $eventDemand->setSearchDemand($searchDemand);
319
320
        return $eventDemand;
321
    }
322
323
    /**
324
     * Detail view for an event
325
     *
326
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
327
     * @return mixed string|void
328
     */
329
    public function detailAction(Event $event = null)
330
    {
331
        $event = $this->evaluateSingleEventSetting($event);
332
        $event = $this->evaluateIsShortcutSetting($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->evaluateIsShortcutSetting($event) on line 332 can also be of type object; however, DERHANSEN\SfEventMgt\Con...uateIsShortcutSetting() does only seem to accept object<DERHANSEN\SfEvent...omain\Model\Event>|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...
333
        if (is_a($event, Event::class) && $this->settings['detail']['checkPidOfEventRecord']) {
334
            $event = $this->checkPidOfEventRecord($event);
0 ignored issues
show
Documentation introduced by
$event is of type null|object, but the function expects a object<DERHANSEN\SfEventMgt\Domain\Model\Event>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
335
        }
336
337
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
338
            return $this->handleEventNotFoundError($this->settings);
339
        }
340
        $values = ['event' => $event];
341
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
342
        $this->view->assignMultiple($values);
343
        if ($event !== null) {
344
            $this->eventCacheService->addCacheTagsByEventRecords([$event]);
345
        }
346
    }
347
348
    /**
349
     * Error handling if event is not found
350
     *
351
     * @param array $settings
352
     * @return string
353
     */
354
    protected function handleEventNotFoundError($settings)
355
    {
356
        if (empty($settings['event']['errorHandling'])) {
357
            return null;
358
        }
359
360
        $configuration = GeneralUtility::trimExplode(',', $settings['event']['errorHandling'], true);
361
362
        switch ($configuration[0]) {
363
            case 'redirectToListView':
364
                $listPid = (int)$settings['listPid'] > 0 ? (int)$settings['listPid'] : 1;
365
                $this->redirect('list', null, null, null, $listPid);
366
                break;
367
            case 'pageNotFoundHandler':
368
                $GLOBALS['TSFE']->pageNotFoundAndExit('Event not found.');
369
                break;
370
            case 'showStandaloneTemplate':
371
                if (isset($configuration[2])) {
372
                    $statusCode = constant(HttpUtility::class . '::HTTP_STATUS_' . $configuration[2]);
373
                    HttpUtility::setResponseCode($statusCode);
374
                }
375
                $standaloneTemplate = $this->objectManager->get(StandaloneView::class);
376
                $standaloneTemplate->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($configuration[1]));
377
378
                return $standaloneTemplate->render();
379
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
380
            default:
381
        }
382
    }
383
384
    /**
385
     * Initiates the iCalendar download for the given event
386
     *
387
     * @param Event $event The event
388
     *
389
     * @return string|false
390
     */
391
    public function icalDownloadAction(Event $event = null)
392
    {
393
        if (is_a($event, Event::class) && $this->settings['detail']['checkPidOfEventRecord']) {
394
            $event = $this->checkPidOfEventRecord($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 394 can be null; however, DERHANSEN\SfEventMgt\Con...checkPidOfEventRecord() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
395
        }
396
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
397
            return $this->handleEventNotFoundError($this->settings);
398
        }
399
        $this->icalendarService->downloadiCalendarFile($event);
0 ignored issues
show
Bug introduced by
It seems like $event can be null; however, downloadiCalendarFile() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
400
        exit();
401
    }
402
403
    /**
404
     * Registration view for an event
405
     *
406
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
407
     *
408
     * @return mixed string|void
409
     */
410
    public function registrationAction(Event $event = null)
411
    {
412
        $event = $this->evaluateSingleEventSetting($event);
413
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
414
            $event = $this->checkPidOfEventRecord($event);
0 ignored issues
show
Documentation introduced by
$event is of type null|object, but the function expects a object<DERHANSEN\SfEventMgt\Domain\Model\Event>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
415
        }
416
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
417
            return $this->handleEventNotFoundError($this->settings);
418
        }
419
        if ($event->getRestrictPaymentMethods()) {
420
            $paymentMethods = $this->paymentService->getRestrictedPaymentMethods($event);
0 ignored issues
show
Documentation introduced by
$event is of type object|null, but the function expects a object<DERHANSEN\SfEventMgt\Domain\Model\Event>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
421
        } else {
422
            $paymentMethods = $this->paymentService->getPaymentMethods();
423
        }
424
425
        $values = [
426
            'event' => $event,
427
            'paymentMethods' => $paymentMethods,
428
        ];
429
430
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
431
        $this->view->assignMultiple($values);
432
    }
433
434
    /**
435
     * Removes all possible spamcheck fields (which do not belong to the domain model) from arguments.
436
     *
437
     * @return void
438
     */
439
    protected function removePossibleSpamCheckFieldsFromArguments()
440
    {
441
        $arguments = $this->request->getArguments();
442
        if (!isset($arguments['event'])) {
443
            return;
444
        }
445
446
        // Remove a possible honeypot field
447
        $honeypotField = 'hp' . (int)$arguments['event'];
448
        if (isset($arguments['registration'][$honeypotField])) {
449
            unset($arguments['registration'][$honeypotField]);
450
        }
451
452
        // Remove a possible challenge/response field
453
        if (isset($arguments['registration']['cr-response'])) {
454
            unset($arguments['registration']['cr-response']);
455
        }
456
457
        $this->request->setArguments($arguments);
458
    }
459
460
    /**
461
     * Processes incoming registrations fields and adds field values to arguments
462
     *
463
     * @return void
464
     */
465
    protected function setRegistrationFieldValuesToArguments()
466
    {
467
        $arguments = $this->request->getArguments();
468
        if (!isset($arguments['event'])) {
469
            return;
470
        }
471
472
        /** @var Event $event */
473
        $event = $this->eventRepository->findByUid((int)$this->request->getArgument('event'));
474
        if (!$event || $event->getRegistrationFields()->count() === 0) {
475
            return;
476
        }
477
478
        $registrationMvcArgument = $this->arguments->getArgument('registration');
479
        $propertyMapping = $registrationMvcArgument->getPropertyMappingConfiguration();
480
        $propertyMapping->allowProperties('fieldValues');
481
        $propertyMapping->allowCreationForSubProperty('fieldValues');
482
        $propertyMapping->allowModificationForSubProperty('fieldValues');
483
484
        // allow creation of new objects (for validation)
485
        $propertyMapping->setTypeConverterOptions(
486
            PersistentObjectConverter::class,
487
            [
488
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => true,
489
                PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED => true
490
            ]
491
        );
492
493
        // Set event to registration (required for validation)
494
        $propertyMapping->allowProperties('event');
495
        $propertyMapping->allowCreationForSubProperty('event');
496
        $propertyMapping->allowModificationForSubProperty('event');
497
        $arguments['registration']['event'] = (int)$this->request->getArgument('event');
498
499
        $index = 0;
500
        foreach ((array)$arguments['registration']['fields'] as $fieldUid => $value) {
501
            // Only accept registration fields of the current event
502
            if (!in_array((int)$fieldUid, $event->getRegistrationFieldsUids(), true)) {
503
                continue;
504
            }
505
506
            // allow subvalues in new property mapper
507
            $propertyMapping->forProperty('fieldValues')->allowProperties($index);
508
            $propertyMapping->forProperty('fieldValues.' . $index)->allowAllProperties();
509
            $propertyMapping->allowCreationForSubProperty('fieldValues.' . $index);
510
            $propertyMapping->allowModificationForSubProperty('fieldValues.' . $index);
511
512
            if (is_array($value)) {
513
                if (empty($value)) {
514
                    $value = '';
515
                } else {
516
                    $value = json_encode($value);
517
                }
518
            }
519
520
            /** @var Registration\Field $field */
521
            $field = $this->fieldRepository->findByUid((int)$fieldUid);
522
523
            $arguments['registration']['fieldValues'][$index] = [
524
                'pid' => $field->getPid(),
525
                'value' => $value,
526
                'field' => strval($fieldUid),
527
                'valueType' => $field->getValueType()
528
            ];
529
530
            $index++;
531
        }
532
533
        // Remove temporary "fields" field
534
        if (isset($arguments['registration']['fields'])) {
535
            $arguments = ArrayUtility::removeByPath($arguments, 'registration/fields');
536
        }
537
        $this->request->setArguments($arguments);
538
    }
539
540
    /**
541
     * Set date format for field dateOfBirth
542
     *
543
     * @return void
544
     */
545
    public function initializeSaveRegistrationAction()
546
    {
547
        $this->arguments->getArgument('registration')
548
            ->getPropertyMappingConfiguration()->forProperty('dateOfBirth')
549
            ->setTypeConverterOption(
550
                DateTimeConverter::class,
551
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
552
                $this->settings['registration']['formatDateOfBirth']
553
            );
554
        $this->removePossibleSpamCheckFieldsFromArguments();
555
        $this->setRegistrationFieldValuesToArguments();
556
    }
557
558
    /**
559
     * Saves the registration
560
     *
561
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
562
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
563
     * @validate $registration \DERHANSEN\SfEventMgt\Validation\Validator\RegistrationFieldValidator
564
     * @validate $registration \DERHANSEN\SfEventMgt\Validation\Validator\RegistrationValidator
565
     *
566
     * @return mixed string|void
567
     */
568
    public function saveRegistrationAction(Registration $registration, Event $event)
569
    {
570
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
571
            $event = $this->checkPidOfEventRecord($event);
572
        }
573
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
574
            return $this->handleEventNotFoundError($this->settings);
575
        }
576
        $autoConfirmation = (bool)$this->settings['registration']['autoConfirmation'] || $event->getEnableAutoconfirm();
0 ignored issues
show
Bug introduced by
It seems like $event is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
577
        $result = RegistrationResult::REGISTRATION_SUCCESSFUL;
578
        list($success, $result) = $this->registrationService->checkRegistrationSuccess($event, $registration, $result);
0 ignored issues
show
Bug introduced by
It seems like $event can be null; however, checkRegistrationSuccess() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
579
580
        // Save registration if no errors
581
        if ($success) {
582
            $isWaitlistRegistration = $this->registrationService->isWaitlistRegistration(
583
                $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 571 can be null; however, DERHANSEN\SfEventMgt\Ser...sWaitlistRegistration() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
584
                $registration->getAmountOfRegistrations()
585
            );
586
            $linkValidity = (int)$this->settings['confirmation']['linkValidity'];
587
            if ($linkValidity === 0) {
588
                // Use 3600 seconds as default value if not set
589
                $linkValidity = 3600;
590
            }
591
            $confirmationUntil = new \DateTime();
592
            $confirmationUntil->add(new \DateInterval('PT' . $linkValidity . 'S'));
593
594
            $registration->setEvent($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 571 can be null; however, DERHANSEN\SfEventMgt\Dom...egistration::setEvent() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
595
            $registration->setPid($event->getPid());
596
            $registration->setConfirmationUntil($confirmationUntil);
597
            $registration->setLanguage($GLOBALS['TSFE']->config['config']['language']);
598
            $registration->setFeUser($this->registrationService->getCurrentFeUserObject());
0 ignored issues
show
Documentation introduced by
$this->registrationServi...etCurrentFeUserObject() is of type object|null, but the function expects a object<TYPO3\CMS\Extbase...ain\Model\FrontendUser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
599
            $registration->setWaitlist($isWaitlistRegistration);
600
            $registration->_setProperty('_languageUid', $this->getSysLanguageUid());
601
            $this->registrationRepository->add($registration);
602
603
            // Persist registration, so we have an UID
604
            $this->objectManager->get(PersistenceManager::class)->persistAll();
605
606
            if ($isWaitlistRegistration) {
607
                $messageType = MessageType::REGISTRATION_WAITLIST_NEW;
608
            } else {
609
                $messageType = MessageType::REGISTRATION_NEW;
610
            }
611
612
            // Fix event in registration for language other than default language
613
            $this->registrationService->fixRegistrationEvent($registration, $event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 571 can be null; however, DERHANSEN\SfEventMgt\Ser...:fixRegistrationEvent() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
614
615
            $this->signalDispatch(__CLASS__, __FUNCTION__ . 'AfterRegistrationSaved', [$registration, $this]);
616
617
            // Send notifications to user and admin if confirmation link should be sent
618
            if (!$autoConfirmation) {
619
                $this->notificationService->sendUserMessage(
620
                    $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 571 can be null; however, DERHANSEN\SfEventMgt\Ser...vice::sendUserMessage() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
621
                    $registration,
622
                    $this->settings,
623
                    $messageType
624
                );
625
                $this->notificationService->sendAdminMessage(
626
                    $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 571 can be null; however, DERHANSEN\SfEventMgt\Ser...ice::sendAdminMessage() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
627
                    $registration,
628
                    $this->settings,
629
                    $messageType
630
                );
631
            }
632
633
            // Create given amount of registrations if necessary
634
            $createDependingRegistrations = $registration->getAmountOfRegistrations() > 1;
635
            $this->signalDispatch(
636
                __CLASS__,
637
                __FUNCTION__ . 'BeforeCreateDependingRegistrations',
638
                [$registration, &$createDependingRegistrations, $this]
639
            );
640
            if ($createDependingRegistrations) {
641
                $this->registrationService->createDependingRegistrations($registration);
642
            }
643
644
            // Flush page cache for event, since new registration has been added
645
            $this->eventCacheService->flushEventCache($event->getUid(), $event->getPid());
646
        }
647
648
        if ($autoConfirmation && $success) {
649
            $this->redirect(
650
                'confirmRegistration',
651
                null,
652
                null,
653
                [
654
                    'reguid' => $registration->getUid(),
655
                    'hmac' => $this->hashService->generateHmac('reg-' . $registration->getUid())
656
                ]
657
            );
658
        } else {
659
            $this->redirect(
660
                'saveRegistrationResult',
661
                null,
662
                null,
663
                [
664
                    'result' => $result,
665
                    'eventuid' => $event->getUid(),
666
                    'hmac' => $this->hashService->generateHmac('event-' . $event->getUid())
667
                ]
668
            );
669
        }
670
    }
671
672
    /**
673
     * Shows the result of the saveRegistrationAction
674
     *
675
     * @param int $result Result
676
     * @param int $eventuid
677
     * @param string $hmac
678
     *
679
     * @return void
680
     */
681
    public function saveRegistrationResultAction($result, $eventuid, $hmac)
682
    {
683
        $event = null;
684
685
        switch ($result) {
686
            case RegistrationResult::REGISTRATION_SUCCESSFUL:
687
                $messageKey = 'event.message.registrationsuccessful';
688
                $titleKey = 'registrationResult.title.successful';
689
                break;
690
            case RegistrationResult::REGISTRATION_SUCCESSFUL_WAITLIST:
691
                $messageKey = 'event.message.registrationwaitlistsuccessful';
692
                $titleKey = 'registrationWaitlistResult.title.successful';
693
                break;
694
            case RegistrationResult::REGISTRATION_FAILED_EVENT_EXPIRED:
695
                $messageKey = 'event.message.registrationfailedeventexpired';
696
                $titleKey = 'registrationResult.title.failed';
697
                break;
698
            case RegistrationResult::REGISTRATION_FAILED_MAX_PARTICIPANTS:
699
                $messageKey = 'event.message.registrationfailedmaxparticipants';
700
                $titleKey = 'registrationResult.title.failed';
701
                break;
702
            case RegistrationResult::REGISTRATION_NOT_ENABLED:
703
                $messageKey = 'event.message.registrationfailednotenabled';
704
                $titleKey = 'registrationResult.title.failed';
705
                break;
706
            case RegistrationResult::REGISTRATION_FAILED_DEADLINE_EXPIRED:
707
                $messageKey = 'event.message.registrationfaileddeadlineexpired';
708
                $titleKey = 'registrationResult.title.failed';
709
                break;
710
            case RegistrationResult::REGISTRATION_FAILED_NOT_ENOUGH_FREE_PLACES:
711
                $messageKey = 'event.message.registrationfailednotenoughfreeplaces';
712
                $titleKey = 'registrationResult.title.failed';
713
                break;
714
            case RegistrationResult::REGISTRATION_FAILED_MAX_AMOUNT_REGISTRATIONS_EXCEEDED:
715
                $messageKey = 'event.message.registrationfailedmaxamountregistrationsexceeded';
716
                $titleKey = 'registrationResult.title.failed';
717
                break;
718
            case RegistrationResult::REGISTRATION_FAILED_EMAIL_NOT_UNIQUE:
719
                $messageKey = 'event.message.registrationfailedemailnotunique';
720
                $titleKey = 'registrationResult.title.failed';
721
                break;
722
            default:
723
                $messageKey = '';
724
                $titleKey = '';
725
        }
726
727
        if (!$this->hashService->validateHmac('event-' . $eventuid, $hmac)) {
728
            $messageKey = 'event.message.registrationsuccessfulwrongeventhmac';
729
            $titleKey = 'registrationResult.title.failed';
730
        } else {
731
            $event = $this->eventRepository->findByUid((int)$eventuid);
732
        }
733
734
        $this->view->assignMultiple([
735
            'messageKey' => $messageKey,
736
            'titleKey' => $titleKey,
737
            'event' => $event,
738
        ]);
739
    }
740
741
    /**
742
     * Confirms the registration if possible and sends e-mails to admin and user
743
     *
744
     * @param int $reguid UID of registration
745
     * @param string $hmac HMAC for parameters
746
     *
747
     * @return void
748
     */
749
    public function confirmRegistrationAction($reguid, $hmac)
750
    {
751
        $event = null;
752
753
        /* @var $registration Registration */
754
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkConfirmRegistration(
755
            $reguid,
756
            $hmac
757
        );
758
759
        if ($failed === false) {
760
            $registration->setConfirmed(true);
761
            $event = $registration->getEvent();
762
            $this->registrationRepository->update($registration);
763
764
            $this->signalDispatch(__CLASS__, __FUNCTION__ . 'AfterRegistrationConfirmed', [$registration, $this]);
765
766
            $messageType = MessageType::REGISTRATION_CONFIRMED;
767
            if ($registration->getWaitlist()) {
768
                $messageType = MessageType::REGISTRATION_WAITLIST_CONFIRMED;
769
            }
770
771
            // Send notifications to user and admin
772
            $this->notificationService->sendUserMessage(
773
                $registration->getEvent(),
774
                $registration,
775
                $this->settings,
776
                $messageType
777
            );
778
            $this->notificationService->sendAdminMessage(
779
                $registration->getEvent(),
780
                $registration,
781
                $this->settings,
782
                $messageType
783
            );
784
785
            // Confirm registrations depending on main registration if necessary
786
            if ($registration->getAmountOfRegistrations() > 1) {
787
                $this->registrationService->confirmDependingRegistrations($registration);
788
            }
789
        }
790
791
        // Redirect to payment provider if payment/redirect is enabled
792
        $paymentPid = (int)$this->settings['paymentPid'];
793
        if (!$failed && $paymentPid > 0 && $this->registrationService->redirectPaymentEnabled($registration)) {
794
            $this->uriBuilder->reset()
795
                ->setTargetPageUid($paymentPid)
796
                ->setUseCacheHash(false);
797
            $uri = $this->uriBuilder->uriFor(
798
                'redirect',
799
                [
800
                    'registration' => $registration,
801
                    'hmac' => $this->hashService->generateHmac('redirectAction-' . $registration->getUid())
802
                ],
803
                'Payment',
804
                'sfeventmgt',
805
                'Pipayment'
806
            );
807
            $this->redirectToUri($uri);
808
        }
809
810
        $values = [
811
            'messageKey' => $messageKey,
812
            'titleKey' => $titleKey,
813
            'event' => $event,
814
            'registration' => $registration,
815
        ];
816
817
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
818
        $this->view->assignMultiple($values);
819
    }
820
821
    /**
822
     * Cancels the registration if possible and sends e-mails to admin and user
823
     *
824
     * @param int $reguid UID of registration
825
     * @param string $hmac HMAC for parameters
826
     *
827
     * @return void
828
     */
829
    public function cancelRegistrationAction($reguid, $hmac)
830
    {
831
        $event = null;
832
833
        /* @var $registration Registration */
834
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkCancelRegistration($reguid, $hmac);
835
836
        if ($failed === false) {
837
            $event = $registration->getEvent();
838
839
            // Send notifications (must run before cancelling the registration)
840
            $this->notificationService->sendUserMessage(
841
                $registration->getEvent(),
842
                $registration,
843
                $this->settings,
844
                MessageType::REGISTRATION_CANCELLED
845
            );
846
            $this->notificationService->sendAdminMessage(
847
                $registration->getEvent(),
848
                $registration,
849
                $this->settings,
850
                MessageType::REGISTRATION_CANCELLED
851
            );
852
853
            // First cancel depending registrations
854
            if ($registration->getAmountOfRegistrations() > 1) {
855
                $this->registrationService->cancelDependingRegistrations($registration);
856
            }
857
858
            // Finally cancel registration
859
            $this->registrationRepository->remove($registration);
860
861
            // Dispatch signal, so waitlist registrations can be moved up
862
            $this->signalDispatch(__CLASS__, __FUNCTION__ . 'WaitlistMoveUp', [$event, $this]);
863
864
            // Flush page cache for event, since new registration has been added
865
            $this->eventCacheService->flushEventCache($event->getUid(), $event->getPid());
866
        }
867
868
        $values = [
869
            'messageKey' => $messageKey,
870
            'titleKey' => $titleKey,
871
            'event' => $event,
872
        ];
873
874
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
875
        $this->view->assignMultiple($values);
876
    }
877
878
    /**
879
     * Set date format for field startDate and endDate
880
     *
881
     * @return void
882
     */
883
    public function initializeSearchAction()
884
    {
885
        if ($this->settings !== null && $this->settings['search']['dateFormat']) {
886
            $this->arguments->getArgument('searchDemand')
887
                ->getPropertyMappingConfiguration()->forProperty('startDate')
888
                ->setTypeConverterOption(
889
                    DateTimeConverter::class,
890
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
891
                    $this->settings['search']['dateFormat']
892
                );
893
            $this->arguments->getArgument('searchDemand')
894
                ->getPropertyMappingConfiguration()->forProperty('endDate')
895
                ->setTypeConverterOption(
896
                    DateTimeConverter::class,
897
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
898
                    $this->settings['search']['dateFormat']
899
                );
900
        }
901
        if ($this->arguments->hasArgument('searchDemand')) {
902
            $propertyMappingConfiguration = $this->arguments->getArgument('searchDemand')
903
                ->getPropertyMappingConfiguration();
904
            $propertyMappingConfiguration->allowAllProperties();
905
            $propertyMappingConfiguration->setTypeConverterOption(
906
                PersistentObjectConverter::class,
907
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED,
908
                true
909
            );
910
        }
911
    }
912
913
    /**
914
     * Search view
915
     *
916
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand $searchDemand SearchDemand
917
     * @param array $overwriteDemand OverwriteDemand
918
     *
919
     * @return void
920
     */
921
    public function searchAction(SearchDemand $searchDemand = null, array $overwriteDemand = [])
922
    {
923
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
924
        $eventDemand->setSearchDemand($searchDemand);
0 ignored issues
show
Bug introduced by
It seems like $searchDemand defined by parameter $searchDemand on line 921 can be null; however, DERHANSEN\SfEventMgt\Dom...mand::setSearchDemand() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
925
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
926
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
927
928
        if ($searchDemand !== null) {
929
            $searchDemand->setFields($this->settings['search']['fields']);
930
931
            if ($this->settings['search']['adjustTime'] && $searchDemand->getStartDate() !== null) {
932
                $searchDemand->getStartDate()->setTime(0, 0, 0);
933
            }
934
935
            if ($this->settings['search']['adjustTime'] && $searchDemand->getEndDate() !== null) {
936
                $searchDemand->getEndDate()->setTime(23, 59, 59);
937
            }
938
        }
939
940
        if ($this->isOverwriteDemand($overwriteDemand)) {
941
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
942
        }
943
944
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
945
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
946
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
947
        $speakers = $this->speakerRepository->findDemanded($foreignRecordDemand);
948
        $events = $this->eventRepository->findDemanded($eventDemand);
949
950
        $values = [
951
            'events' => $events,
952
            'categories' => $categories,
953
            'locations' => $locations,
954
            'organisators' => $organisators,
955
            'speakers' => $speakers,
956
            'searchDemand' => $searchDemand,
957
            'overwriteDemand' => $overwriteDemand,
958
        ];
959
960
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
961
        $this->view->assignMultiple($values);
962
    }
963
964
    /**
965
     * Returns if a demand object can be overwritten with the given overwriteDemand array
966
     *
967
     * @param array $overwriteDemand
968
     * @return bool
969
     */
970
    protected function isOverwriteDemand($overwriteDemand)
971
    {
972
        return $this->settings['disableOverrideDemand'] != 1 && $overwriteDemand !== [];
973
    }
974
975
    /**
976
     * If no event is given and the singleEvent setting is set, the configured single event is returned
977
     *
978
     * @param Event|null $event
979
     * @return Event|null
980
     */
981
    protected function evaluateSingleEventSetting($event)
982
    {
983
        if ($event === null && (int)$this->settings['singleEvent'] > 0) {
984
            $event = $this->eventRepository->findByUid((int)$this->settings['singleEvent']);
985
        }
986
987
        return $event;
988
    }
989
990
    /**
991
     * If no event is given and the isShortcut setting is set, the event is displayed using the "Insert Record"
992
     * content element and should be loaded from contect object data
993
     *
994
     * @param Event|null $event
995
     * @return Event|null
996
     */
997
    protected function evaluateIsShortcutSetting($event)
998
    {
999
        if ($event === null && (bool)$this->settings['detail']['isShortcut']) {
1000
            $eventRawData = $this->configurationManager->getContentObject()->data;
1001
            $event = $this->eventRepository->findByUid($eventRawData['uid']);
1002
        }
1003
1004
        return $event;
1005
    }
1006
1007
    /**
1008
     * Checks if the event pid could be found in the storagePage settings of the detail plugin and
1009
     * if the pid could not be found it return null instead of the event object.
1010
     *
1011
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
1012
     * @return null|\DERHANSEN\SfEventMgt\Domain\Model\Event
1013
     */
1014
    protected function checkPidOfEventRecord(Event $event)
1015
    {
1016
        $allowedStoragePages = GeneralUtility::trimExplode(
1017
            ',',
1018
            Page::extendPidListByChildren(
1019
                $this->settings['storagePage'],
1020
                $this->settings['recursive']
1021
            ),
1022
            true
1023
        );
1024
        if (count($allowedStoragePages) > 0 && !in_array($event->getPid(), $allowedStoragePages)) {
1025
            $this->signalSlotDispatcher->dispatch(
1026
                __CLASS__,
1027
                'checkPidOfEventRecordFailedInDetailAction',
1028
                [
1029
                    'event' => $event,
1030
                    'eventController' => $this
1031
                ]
1032
            );
1033
            $event = null;
1034
        }
1035
1036
        return $event;
1037
    }
1038
1039
    /**
1040
     * Returns the current sys_language_uid
1041
     *
1042
     * @return int
1043
     */
1044
    protected function getSysLanguageUid()
1045
    {
1046
        return $GLOBALS['TSFE']->sys_language_uid;
1047
    }
1048
}
1049