Completed
Push — MbhSoft-feature/pid-check ( e7aab5 )
by Torben
04:02
created

initializeSaveRegistrationAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
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\Utility\MessageType;
18
use DERHANSEN\SfEventMgt\Utility\Page;
19
use DERHANSEN\SfEventMgt\Utility\RegistrationResult;
20
use TYPO3\CMS\Core\Utility\ArrayUtility;
21
use TYPO3\CMS\Core\Utility\GeneralUtility;
22
use TYPO3\CMS\Core\Utility\HttpUtility;
23
use TYPO3\CMS\Extbase\Mvc\RequestInterface;
24
use TYPO3\CMS\Extbase\Mvc\ResponseInterface;
25
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
26
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
27
use TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter;
28
use TYPO3\CMS\Fluid\View\StandaloneView;
29
30
/**
31
 * EventController
32
 *
33
 * @author Torben Hansen <[email protected]>
34
 */
35
class EventController extends AbstractController
36
{
37
    /**
38
     * Assign contentObjectData and pageData to earch view
39
     *
40
     * @param \TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view
41
     */
42
    protected function initializeView(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view)
43
    {
44
        $view->assign('contentObjectData', $this->configurationManager->getContentObject()->data);
45
        if (is_object($GLOBALS['TSFE'])) {
46
            $view->assign('pageData', $GLOBALS['TSFE']->page);
47
        }
48
        parent::initializeView($view);
49
    }
50
51
    /**
52
     * Properties in this array will be ignored by overwriteDemandObject()
53
     *
54
     * @var array
55
     */
56
    protected $ignoredSettingsForOverwriteDemand = ['storagepage', 'orderfieldallowed'];
57
58
    /**
59
     * Initializes the current action
60
     */
61
    public function initializeAction()
62
    {
63
        $typoScriptFrontendController = $this->getTypoScriptFrontendController();
64
        if ($typoScriptFrontendController !== null) {
65
            static $cacheTagsSet = false;
66
67
            if (!$cacheTagsSet) {
68
                $typoScriptFrontendController->addCacheTags(['tx_sfeventmgt']);
69
                $cacheTagsSet = true;
70
            }
71
        }
72
    }
73
74
    /**
75
     * Creates an event demand object with the given settings
76
     *
77
     * @param array $settings The settings
78
     *
79
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand
80
     */
81
    public function createEventDemandObjectFromSettings(array $settings)
82
    {
83
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand */
84
        $demand = $this->objectManager->get(EventDemand::class);
85
        $demand->setDisplayMode($settings['displayMode']);
86
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
87
        $demand->setCategoryConjunction($settings['categoryConjunction']);
88
        $demand->setCategory($settings['category']);
89
        $demand->setIncludeSubcategories($settings['includeSubcategories']);
90
        $demand->setTopEventRestriction((int)$settings['topEventRestriction']);
91
        $demand->setOrderField($settings['orderField']);
92
        $demand->setOrderFieldAllowed($settings['orderFieldAllowed']);
93
        $demand->setOrderDirection($settings['orderDirection']);
94
        $demand->setQueryLimit($settings['queryLimit']);
95
        $demand->setLocation($settings['location']);
96
        $demand->setOrganisator($settings['organisator']);
97
98
        return $demand;
99
    }
100
101
    /**
102
     * Creates a foreign record demand object with the given settings
103
     *
104
     * @param array $settings The settings
105
     *
106
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand
107
     */
108
    public function createForeignRecordDemandObjectFromSettings(array $settings)
109
    {
110
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand $demand */
111
        $demand = $this->objectManager->get(ForeignRecordDemand::class);
112
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
113
        $demand->setRestrictForeignRecordsToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
114
115
        return $demand;
116
    }
117
118
    /**
119
     * Creates a category demand object with the given settings
120
     *
121
     * @param array $settings The settings
122
     *
123
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand
124
     */
125
    public function createCategoryDemandObjectFromSettings(array $settings)
126
    {
127
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand $demand */
128
        $demand = $this->objectManager->get(CategoryDemand::class);
129
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
130
        $demand->setRestrictToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
131
        $demand->setCategories($settings['categoryMenu']['categories']);
132
        $demand->setIncludeSubcategories($settings['categoryMenu']['includeSubcategories']);
133
134
        return $demand;
135
    }
136
137
    /**
138
     * Overwrites a given demand object by an propertyName =>  $propertyValue array
139
     *
140
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand Demand
141
     * @param array $overwriteDemand OwerwriteDemand
142
     *
143
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand
144
     */
145
    protected function overwriteEventDemandObject(EventDemand $demand, array $overwriteDemand)
146
    {
147
        foreach ($this->ignoredSettingsForOverwriteDemand as $property) {
148
            unset($overwriteDemand[$property]);
149
        }
150
151
        foreach ($overwriteDemand as $propertyName => $propertyValue) {
152
            if (in_array(strtolower($propertyName), $this->ignoredSettingsForOverwriteDemand, true)) {
153
                continue;
154
            }
155
            \TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($demand, $propertyName, $propertyValue);
156
        }
157
158
        return $demand;
159
    }
160
161
    /**
162
     * Hook into request processing and catch exceptions
163
     *
164
     * @param RequestInterface $request
165
     * @param ResponseInterface $response
166
     * @throws \Exception
167
     */
168
    public function processRequest(RequestInterface $request, ResponseInterface $response)
169
    {
170
        try {
171
            parent::processRequest($request, $response);
172
        } catch (\Exception $exception) {
173
            $this->handleKnownExceptionsElseThrowAgain($exception);
174
        }
175
    }
176
177
    /**
178
     * Handle known exceptions
179
     *
180
     * @param \Exception $exception
181
     * @throws \Exception
182
     */
183
    private function handleKnownExceptionsElseThrowAgain(\Exception $exception)
184
    {
185
        $previousException = $exception->getPrevious();
186
        $actions = ['detailAction', 'registrationAction', 'icalDownloadAction'];
187
        if (in_array($this->actionMethodName, $actions, true)
188
            && $previousException instanceof \TYPO3\CMS\Extbase\Property\Exception
189
        ) {
190
            $this->handleEventNotFoundError($this->settings);
191
        } else {
192
            throw $exception;
193
        }
194
    }
195
196
    /**
197
     * Initialize list action and set format
198
     *
199
     * @return void
200
     */
201
    public function initializeListAction()
202
    {
203
        if (isset($this->settings['list']['format'])) {
204
            $this->request->setFormat($this->settings['list']['format']);
205
        }
206
    }
207
208
    /**
209
     * List view
210
     *
211
     * @param array $overwriteDemand OverwriteDemand
212
     *
213
     * @return void
214
     */
215
    public function listAction(array $overwriteDemand = [])
216
    {
217
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
218
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
219
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
220
        if ($this->isOverwriteDemand($overwriteDemand)) {
221
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
222
        }
223
        $events = $this->eventRepository->findDemanded($eventDemand);
224
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
225
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
226
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
227
228
        $values = [
229
            'events' => $events,
230
            'categories' => $categories,
231
            'locations' => $locations,
232
            'organisators' => $organisators,
233
            'overwriteDemand' => $overwriteDemand,
234
            'eventDemand' => $eventDemand
235
        ];
236
237
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
238
        $this->view->assignMultiple($values);
239
240
        $this->addPageCacheTagsByEventDemandObject($eventDemand);
241
    }
242
243
    /**
244
     * Calendar view
245
     *
246
     * @param array $overwriteDemand OverwriteDemand
247
     *
248
     * @return void
249
     */
250
    public function calendarAction(array $overwriteDemand = [])
251
    {
252
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
253
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
254
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
255
        if ($this->isOverwriteDemand($overwriteDemand)) {
256
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
257
        }
258
259
        // Set month/year to demand if not given
260
        if (!$eventDemand->getMonth()) {
261
            $currentMonth = date('n');
262
            $eventDemand->setMonth($currentMonth);
263
        } else {
264
            $currentMonth = $eventDemand->getMonth();
265
        }
266
        if (!$eventDemand->getYear()) {
267
            $currentYear = date('Y');
268
            $eventDemand->setYear($currentYear);
269
        } else {
270
            $currentYear = $eventDemand->getYear();
271
        }
272
273
        // Set demand from calendar date range instead of month / year
274
        if ((bool)$this->settings['calendar']['includeEventsForEveryDayOfAllCalendarWeeks']) {
275
            $eventDemand = $this->changeEventDemandToFullMonthDateRange($eventDemand);
276
        }
277
278
        $events = $this->eventRepository->findDemanded($eventDemand);
279
        $weeks = $this->calendarService->getCalendarArray(
280
            $currentMonth,
281
            $currentYear,
282
            strtotime('today midnight'),
283
            (int)$this->settings['calendar']['firstDayOfWeek'],
284
            $events
285
        );
286
287
        $values = [
288
            'weeks' => $weeks,
289
            'categories' => $this->categoryRepository->findDemanded($categoryDemand),
290
            'locations' => $this->locationRepository->findDemanded($foreignRecordDemand),
291
            'organisators' => $this->organisatorRepository->findDemanded($foreignRecordDemand),
292
            'eventDemand' => $eventDemand,
293
            'overwriteDemand' => $overwriteDemand,
294
            'currentPageId' => $GLOBALS['TSFE']->id,
295
            'firstDayOfMonth' => \DateTime::createFromFormat('d.m.Y', sprintf('1.%s.%s', $currentMonth, $currentYear)),
296
            'previousMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '-1 month'),
297
            'nextMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '+1 month')
298
        ];
299
300
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
301
        $this->view->assignMultiple($values);
302
    }
303
304
    /**
305
     * Changes the given event demand object to select a date range for a calendar month including days of the previous
306
     * month for the first week and they days for the next month for the last week
307
     *
308
     * @param EventDemand $eventDemand
309
     * @return EventDemand
310
     */
311
    protected function changeEventDemandToFullMonthDateRange(EventDemand $eventDemand)
312
    {
313
        $calendarDateRange = $this->calendarService->getCalendarDateRange(
314
            $eventDemand->getMonth(),
315
            $eventDemand->getYear(),
316
            $this->settings['calendar']['firstDayOfWeek']
317
        );
318
319
        $eventDemand->setMonth(0);
320
        $eventDemand->setYear(0);
321
322
        $startDate = new \DateTime();
323
        $startDate->setTimestamp($calendarDateRange['firstDayOfCalendar']);
324
        $endDate = new \DateTime();
325
        $endDate->setTimestamp($calendarDateRange['lastDayOfCalendar']);
326
        $endDate->setTime(23, 59, 59);
327
328
        $searchDemand = new SearchDemand();
329
        $searchDemand->setStartDate($startDate);
330
        $searchDemand->setEndDate($endDate);
331
        $eventDemand->setSearchDemand($searchDemand);
332
333
        return $eventDemand;
334
    }
335
336
    /**
337
     * Detail view for an event
338
     *
339
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
340
     * @return mixed string|void
341
     */
342
    public function detailAction(Event $event = null)
343
    {
344
        $event = $this->evaluateSingleEventSetting($event);
345
        if (is_a($event, Event::class) && $this->settings['detail']['checkPidOfEventRecord']) {
346
            $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...
347
        }
348
349
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
350
            return $this->handleEventNotFoundError($this->settings);
351
        }
352
        $values = ['event' => $event];
353
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
354
        $this->view->assignMultiple($values);
355
        if ($event !== null) {
356
            $this->addCacheTagsByEventRecords([$event]);
357
        }
358
    }
359
360
    /**
361
     * Error handling if event is not found
362
     *
363
     * @param array $settings
364
     * @return string
365
     */
366
    protected function handleEventNotFoundError($settings)
367
    {
368
        if (empty($settings['event']['errorHandling'])) {
369
            return null;
370
        }
371
372
        $configuration = GeneralUtility::trimExplode(',', $settings['event']['errorHandling'], true);
373
374
        switch ($configuration[0]) {
375
            case 'redirectToListView':
376
                $listPid = (int)$settings['listPid'] > 0 ? (int)$settings['listPid'] : 1;
377
                $this->redirect('list', null, null, null, $listPid);
378
                break;
379
            case 'pageNotFoundHandler':
380
                $GLOBALS['TSFE']->pageNotFoundAndExit('Event not found.');
381
                break;
382
            case 'showStandaloneTemplate':
383
                if (isset($configuration[2])) {
384
                    $statusCode = constant(HttpUtility::class . '::HTTP_STATUS_' . $configuration[2]);
385
                    HttpUtility::setResponseCode($statusCode);
386
                }
387
                $standaloneTemplate = $this->objectManager->get(StandaloneView::class);
388
                $standaloneTemplate->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($configuration[1]));
389
390
                return $standaloneTemplate->render();
391
                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...
392
            default:
393
        }
394
    }
395
396
    /**
397
     * Initiates the iCalendar download for the given event
398
     *
399
     * @param Event $event The event
400
     *
401
     * @return string|false
402
     */
403
    public function icalDownloadAction(Event $event = null)
404
    {
405
        if (is_a($event, Event::class) && $this->settings['detail']['checkPidOfEventRecord']) {
406
            $event = $this->checkPidOfEventRecord($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 406 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...
407
        }
408
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
409
            return $this->handleEventNotFoundError($this->settings);
410
        }
411
        $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...
412
413
        return false;
414
    }
415
416
    /**
417
     * Registration view for an event
418
     *
419
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
420
     *
421
     * @return mixed string|void
422
     */
423
    public function registrationAction(Event $event = null)
424
    {
425
        $event = $this->evaluateSingleEventSetting($event);
426
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
427
            $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...
428
        }
429
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
430
            return $this->handleEventNotFoundError($this->settings);
431
        }
432
        if ($event->getRestrictPaymentMethods()) {
433
            $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...
434
        } else {
435
            $paymentMethods = $this->paymentService->getPaymentMethods();
436
        }
437
438
        $values = [
439
            'event' => $event,
440
            'paymentMethods' => $paymentMethods,
441
        ];
442
443
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
444
        $this->view->assignMultiple($values);
445
    }
446
447
    /**
448
     * Processes incoming registrations fields and adds field values to arguments
449
     *
450
     * @return void
451
     */
452
    protected function setRegistrationFieldValuesToArguments()
453
    {
454
        $arguments = $this->request->getArguments();
455
        if (!isset($arguments['registration']['fields']) || !isset($arguments['event'])) {
456
            return;
457
        }
458
459
        $registrationMvcArgument = $this->arguments->getArgument('registration');
460
        $propertyMapping = $registrationMvcArgument->getPropertyMappingConfiguration();
461
        $propertyMapping->allowProperties('fieldValues');
462
        $propertyMapping->allowCreationForSubProperty('fieldValues');
463
        $propertyMapping->allowModificationForSubProperty('fieldValues');
464
465
        // allow creation of new objects (for validation)
466
        $propertyMapping->setTypeConverterOptions(
467
            PersistentObjectConverter::class,
468
            [
469
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => true,
470
                PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED => true
471
            ]
472
        );
473
474
        // Set event to registration (required for validation)
475
        $event = $this->eventRepository->findByUid((int)$this->request->getArgument('event'));
476
        $propertyMapping->allowProperties('event');
477
        $propertyMapping->allowCreationForSubProperty('event');
478
        $propertyMapping->allowModificationForSubProperty('event');
479
        $arguments['registration']['event'] = (int)$this->request->getArgument('event');
480
481
        $index = 0;
482
        foreach ((array)$arguments['registration']['fields'] as $fieldUid => $value) {
483
            // Only accept registration fields of the current event
484
            if (!in_array((int)$fieldUid, $event->getRegistrationFieldsUids(), true)) {
485
                continue;
486
            }
487
488
            // allow subvalues in new property mapper
489
            $propertyMapping->forProperty('fieldValues')->allowProperties($index);
490
            $propertyMapping->forProperty('fieldValues.' . $index)->allowAllProperties();
491
            $propertyMapping->allowCreationForSubProperty('fieldValues.' . $index);
492
            $propertyMapping->allowModificationForSubProperty('fieldValues.' . $index);
493
494
            if (is_array($value)) {
495
                if (empty($value)) {
496
                    $value = '';
497
                } else {
498
                    $value = json_encode($value);
499
                }
500
            }
501
502
            /** @var Registration\Field $field */
503
            $field = $this->fieldRepository->findByUid((int)$fieldUid);
504
505
            $arguments['registration']['fieldValues'][$index] = [
506
                'pid' => $field->getPid(),
507
                'value' => $value,
508
                'field' => strval($fieldUid),
509
                'valueType' => $field->getValueType()
510
            ];
511
512
            $index++;
513
        }
514
515
        // Remove temporary "fields" field
516
        $arguments = ArrayUtility::removeByPath($arguments, 'registration/fields');
517
        $this->request->setArguments($arguments);
518
    }
519
520
    /**
521
     * Set date format for field dateOfBirth
522
     *
523
     * @return void
524
     */
525
    public function initializeSaveRegistrationAction()
526
    {
527
        $this->arguments->getArgument('registration')
528
            ->getPropertyMappingConfiguration()->forProperty('dateOfBirth')
529
            ->setTypeConverterOption(
530
                DateTimeConverter::class,
531
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
532
                $this->settings['registration']['formatDateOfBirth']
533
            );
534
        $this->setRegistrationFieldValuesToArguments();
535
    }
536
537
    /**
538
     * Saves the registration
539
     *
540
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
541
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
542
     * @validate $registration \DERHANSEN\SfEventMgt\Validation\Validator\RegistrationFieldValidator
543
     * @validate $registration \DERHANSEN\SfEventMgt\Validation\Validator\RegistrationValidator
544
     *
545
     * @return mixed string|void
546
     */
547
    public function saveRegistrationAction(Registration $registration, Event $event)
548
    {
549
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
550
            $event = $this->checkPidOfEventRecord($event);
551
        }
552
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
553
            return $this->handleEventNotFoundError($this->settings);
554
        }
555
        $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...
556
        $result = RegistrationResult::REGISTRATION_SUCCESSFUL;
557
        $success = $this->registrationService->checkRegistrationSuccess($event, $registration, $result);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 550 can be null; however, DERHANSEN\SfEventMgt\Ser...ckRegistrationSuccess() 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...
558
559
        // Save registration if no errors
560
        if ($success) {
561
            $isWaitlistRegistration = $this->registrationService->isWaitlistRegistration(
562
                $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 550 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...
563
                $registration->getAmountOfRegistrations()
564
            );
565
            $linkValidity = (int)$this->settings['confirmation']['linkValidity'];
566
            if ($linkValidity === 0) {
567
                // Use 3600 seconds as default value if not set
568
                $linkValidity = 3600;
569
            }
570
            $confirmationUntil = new \DateTime();
571
            $confirmationUntil->add(new \DateInterval('PT' . $linkValidity . 'S'));
572
573
            $registration->setEvent($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 550 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...
574
            $registration->setPid($event->getPid());
575
            $registration->setConfirmationUntil($confirmationUntil);
576
            $registration->setLanguage($GLOBALS['TSFE']->config['config']['language']);
577
            $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...
578
            $registration->setWaitlist($isWaitlistRegistration);
579
            $registration->_setProperty('_languageUid', $GLOBALS['TSFE']->sys_language_uid);
580
            $this->registrationRepository->add($registration);
581
582
            // Persist registration, so we have an UID
583
            $this->objectManager->get(PersistenceManager::class)->persistAll();
584
585
            // Add new registration (or waitlist registration) to event
586
            if ($isWaitlistRegistration) {
587
                $event->addRegistrationWaitlist($registration);
588
                $messageType = MessageType::REGISTRATION_WAITLIST_NEW;
589
            } else {
590
                $event->addRegistration($registration);
591
                $messageType = MessageType::REGISTRATION_NEW;
592
            }
593
            $this->eventRepository->update($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 550 can be null; however, TYPO3\CMS\Extbase\Persistence\Repository::update() 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...
594
595
            $this->signalDispatch(__CLASS__, __FUNCTION__ . 'AfterRegistrationSaved', [$registration, $this]);
596
597
            // Send notifications to user and admin if confirmation link should be sent
598
            if (!$autoConfirmation) {
599
                $this->notificationService->sendUserMessage(
600
                    $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 550 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...
601
                    $registration,
602
                    $this->settings,
603
                    $messageType
604
                );
605
                $this->notificationService->sendAdminMessage(
606
                    $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 550 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...
607
                    $registration,
608
                    $this->settings,
609
                    $messageType
610
                );
611
            }
612
613
            // Create given amount of registrations if necessary
614
            if ($registration->getAmountOfRegistrations() > 1) {
615
                $this->registrationService->createDependingRegistrations($registration);
616
            }
617
618
            // Clear cache for configured pages
619
            $this->utilityService->clearCacheForConfiguredUids($this->settings);
620
        }
621
622
        if ($autoConfirmation && $success) {
623
            $this->redirect(
624
                'confirmRegistration',
625
                null,
626
                null,
627
                [
628
                    'reguid' => $registration->getUid(),
629
                    'hmac' => $this->hashService->generateHmac('reg-' . $registration->getUid())
630
                ]
631
            );
632
        } else {
633
            $this->redirect(
634
                'saveRegistrationResult',
635
                null,
636
                null,
637
                [
638
                    'result' => $result,
639
                    'eventuid' => $event->getUid(),
640
                    'hmac' => $this->hashService->generateHmac('event-' . $event->getUid())
641
                ]
642
            );
643
        }
644
    }
645
646
    /**
647
     * Shows the result of the saveRegistrationAction
648
     *
649
     * @param int $result Result
650
     * @param int $eventuid
651
     * @param string $hmac
652
     *
653
     * @return void
654
     */
655
    public function saveRegistrationResultAction($result, $eventuid, $hmac)
656
    {
657
        $event = null;
658
659
        switch ($result) {
660
            case RegistrationResult::REGISTRATION_SUCCESSFUL:
661
                $messageKey = 'event.message.registrationsuccessful';
662
                $titleKey = 'registrationResult.title.successful';
663
                break;
664
            case RegistrationResult::REGISTRATION_SUCCESSFUL_WAITLIST:
665
                $messageKey = 'event.message.registrationwaitlistsuccessful';
666
                $titleKey = 'registrationWaitlistResult.title.successful';
667
                break;
668
            case RegistrationResult::REGISTRATION_FAILED_EVENT_EXPIRED:
669
                $messageKey = 'event.message.registrationfailedeventexpired';
670
                $titleKey = 'registrationResult.title.failed';
671
                break;
672
            case RegistrationResult::REGISTRATION_FAILED_MAX_PARTICIPANTS:
673
                $messageKey = 'event.message.registrationfailedmaxparticipants';
674
                $titleKey = 'registrationResult.title.failed';
675
                break;
676
            case RegistrationResult::REGISTRATION_NOT_ENABLED:
677
                $messageKey = 'event.message.registrationfailednotenabled';
678
                $titleKey = 'registrationResult.title.failed';
679
                break;
680
            case RegistrationResult::REGISTRATION_FAILED_DEADLINE_EXPIRED:
681
                $messageKey = 'event.message.registrationfaileddeadlineexpired';
682
                $titleKey = 'registrationResult.title.failed';
683
                break;
684
            case RegistrationResult::REGISTRATION_FAILED_NOT_ENOUGH_FREE_PLACES:
685
                $messageKey = 'event.message.registrationfailednotenoughfreeplaces';
686
                $titleKey = 'registrationResult.title.failed';
687
                break;
688
            case RegistrationResult::REGISTRATION_FAILED_MAX_AMOUNT_REGISTRATIONS_EXCEEDED:
689
                $messageKey = 'event.message.registrationfailedmaxamountregistrationsexceeded';
690
                $titleKey = 'registrationResult.title.failed';
691
                break;
692
            case RegistrationResult::REGISTRATION_FAILED_EMAIL_NOT_UNIQUE:
693
                $messageKey = 'event.message.registrationfailedemailnotunique';
694
                $titleKey = 'registrationResult.title.failed';
695
                break;
696
            default:
697
                $messageKey = '';
698
                $titleKey = '';
699
        }
700
701
        if (!$this->hashService->validateHmac('event-' . $eventuid, $hmac)) {
702
            $messageKey = 'event.message.registrationsuccessfulwrongeventhmac';
703
            $titleKey = 'registrationResult.title.failed';
704
        } else {
705
            $event = $this->eventRepository->findByUid((int)$eventuid);
706
        }
707
708
        $this->view->assignMultiple([
709
            'messageKey' => $messageKey,
710
            'titleKey' => $titleKey,
711
            'event' => $event,
712
        ]);
713
    }
714
715
    /**
716
     * Confirms the registration if possible and sends e-mails to admin and user
717
     *
718
     * @param int $reguid UID of registration
719
     * @param string $hmac HMAC for parameters
720
     *
721
     * @return void
722
     */
723
    public function confirmRegistrationAction($reguid, $hmac)
724
    {
725
        $event = null;
726
727
        /* @var $registration Registration */
728
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkConfirmRegistration(
729
            $reguid,
730
            $hmac
731
        );
732
733
        if ($failed === false) {
734
            $registration->setConfirmed(true);
735
            $event = $registration->getEvent();
736
            $this->registrationRepository->update($registration);
737
738
            $messageType = MessageType::REGISTRATION_CONFIRMED;
739
            if ($registration->getWaitlist()) {
740
                $messageType = MessageType::REGISTRATION_WAITLIST_CONFIRMED;
741
            }
742
743
            // Send notifications to user and admin
744
            $this->notificationService->sendUserMessage(
745
                $registration->getEvent(),
746
                $registration,
747
                $this->settings,
748
                $messageType
749
            );
750
            $this->notificationService->sendAdminMessage(
751
                $registration->getEvent(),
752
                $registration,
753
                $this->settings,
754
                $messageType
755
            );
756
757
            // Confirm registrations depending on main registration if necessary
758
            if ($registration->getAmountOfRegistrations() > 1) {
759
                $this->registrationService->confirmDependingRegistrations($registration);
760
            }
761
        }
762
763
        // Redirect to payment provider if payment/redirect is enabled
764
        $paymentPid = (int)$this->settings['paymentPid'];
765
        if (!$failed && $paymentPid > 0 && $this->registrationService->redirectPaymentEnabled($registration)) {
766
            $this->uriBuilder->reset()
767
                ->setTargetPageUid($paymentPid)
768
                ->setUseCacheHash(false);
769
            $uri = $this->uriBuilder->uriFor(
770
                'redirect',
771
                [
772
                    'registration' => $registration,
773
                    'hmac' => $this->hashService->generateHmac('redirectAction-' . $registration->getUid())
774
                ],
775
                'Payment',
776
                'sfeventmgt',
777
                'Pipayment'
778
            );
779
            $this->redirectToUri($uri);
780
        }
781
782
        $values = [
783
            'messageKey' => $messageKey,
784
            'titleKey' => $titleKey,
785
            'event' => $event,
786
            'registration' => $registration,
787
        ];
788
789
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
790
        $this->view->assignMultiple($values);
791
    }
792
793
    /**
794
     * Cancels the registration if possible and sends e-mails to admin and user
795
     *
796
     * @param int $reguid UID of registration
797
     * @param string $hmac HMAC for parameters
798
     *
799
     * @return void
800
     */
801
    public function cancelRegistrationAction($reguid, $hmac)
802
    {
803
        $event = null;
804
805
        /* @var $registration Registration */
806
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkCancelRegistration($reguid, $hmac);
807
808
        if ($failed === false) {
809
            $event = $registration->getEvent();
810
811
            // Send notifications (must run before cancelling the registration)
812
            $this->notificationService->sendUserMessage(
813
                $registration->getEvent(),
814
                $registration,
815
                $this->settings,
816
                MessageType::REGISTRATION_CANCELLED
817
            );
818
            $this->notificationService->sendAdminMessage(
819
                $registration->getEvent(),
820
                $registration,
821
                $this->settings,
822
                MessageType::REGISTRATION_CANCELLED
823
            );
824
825
            // First cancel depending registrations
826
            if ($registration->getAmountOfRegistrations() > 1) {
827
                $this->registrationService->cancelDependingRegistrations($registration);
828
            }
829
830
            // Finally cancel registration
831
            $this->registrationRepository->remove($registration);
832
833
            // Dispatch signal, so waitlist registrations can be moved up
834
            $this->signalDispatch(__CLASS__, __FUNCTION__ . 'WaitlistMoveUp', [$event, $this]);
835
836
            // Clear cache for configured pages
837
            $this->utilityService->clearCacheForConfiguredUids($this->settings);
838
        }
839
840
        $values = [
841
            'messageKey' => $messageKey,
842
            'titleKey' => $titleKey,
843
            'event' => $event,
844
        ];
845
846
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
847
        $this->view->assignMultiple($values);
848
    }
849
850
    /**
851
     * Set date format for field startDate and endDate
852
     *
853
     * @return void
854
     */
855
    public function initializeSearchAction()
856
    {
857
        if ($this->settings !== null && $this->settings['search']['dateFormat']) {
858
            $this->arguments->getArgument('searchDemand')
859
                ->getPropertyMappingConfiguration()->forProperty('startDate')
860
                ->setTypeConverterOption(
861
                    DateTimeConverter::class,
862
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
863
                    $this->settings['search']['dateFormat']
864
                );
865
            $this->arguments->getArgument('searchDemand')
866
                ->getPropertyMappingConfiguration()->forProperty('endDate')
867
                ->setTypeConverterOption(
868
                    DateTimeConverter::class,
869
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
870
                    $this->settings['search']['dateFormat']
871
                );
872
        }
873
        if ($this->arguments->hasArgument('searchDemand')) {
874
            $propertyMappingConfiguration = $this->arguments->getArgument('searchDemand')
875
                ->getPropertyMappingConfiguration();
876
            $propertyMappingConfiguration->allowAllProperties();
877
            $propertyMappingConfiguration->setTypeConverterOption(
878
                PersistentObjectConverter::class,
879
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED,
880
                true
881
            );
882
        }
883
    }
884
885
    /**
886
     * Search view
887
     *
888
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand $searchDemand SearchDemand
889
     * @param array $overwriteDemand OverwriteDemand
890
     *
891
     * @return void
892
     */
893
    public function searchAction(SearchDemand $searchDemand = null, array $overwriteDemand = [])
894
    {
895
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
896
        $eventDemand->setSearchDemand($searchDemand);
0 ignored issues
show
Bug introduced by
It seems like $searchDemand defined by parameter $searchDemand on line 893 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...
897
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
898
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
899
900
        if ($searchDemand !== null) {
901
            $searchDemand->setFields($this->settings['search']['fields']);
902
903
            if ($this->settings['search']['adjustTime'] && $searchDemand->getStartDate() !== null) {
904
                $searchDemand->getStartDate()->setTime(0, 0, 0);
905
            }
906
907
            if ($this->settings['search']['adjustTime'] && $searchDemand->getEndDate() !== null) {
908
                $searchDemand->getEndDate()->setTime(23, 59, 59);
909
            }
910
        }
911
912
        if ($this->isOverwriteDemand($overwriteDemand)) {
913
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
914
        }
915
916
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
917
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
918
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
919
        $events = $this->eventRepository->findDemanded($eventDemand);
920
921
        $values = [
922
            'events' => $events,
923
            'categories' => $categories,
924
            'locations' => $locations,
925
            'organisators' => $organisators,
926
            'searchDemand' => $searchDemand,
927
            'overwriteDemand' => $overwriteDemand,
928
        ];
929
930
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
931
        $this->view->assignMultiple($values);
932
    }
933
934
    /**
935
     * Returns if a demand object can be overwritten with the given overwriteDemand array
936
     *
937
     * @param array $overwriteDemand
938
     * @return bool
939
     */
940
    protected function isOverwriteDemand($overwriteDemand)
941
    {
942
        return $this->settings['disableOverrideDemand'] != 1 && $overwriteDemand !== [];
943
    }
944
945
    /**
946
     * If no event is given and the singleEvent setting is set, the configured single event is returned
947
     *
948
     * @param Event|null $event
949
     * @return Event|null
950
     */
951
    protected function evaluateSingleEventSetting($event)
952
    {
953
        if ($event === null && (int)$this->settings['singleEvent'] > 0) {
954
            $event = $this->eventRepository->findByUid((int)$this->settings['singleEvent']);
955
        }
956
957
        return $event;
958
    }
959
960
    /**
961
     * Adds cache tags to page cache by event records.
962
     *
963
     * Following cache tags will be added to tsfe:
964
     * "tx_sfeventmgt_uid_[event:uid]"
965
     *
966
     * @param array $eventRecords array with event records
967
     */
968
    public function addCacheTagsByEventRecords(array $eventRecords)
969
    {
970
        $cacheTags = [];
971
        foreach ($eventRecords as $event) {
972
            // cache tag for each event record
973
            $cacheTags[] = 'tx_sfeventmgt_uid_' . $event->getUid();
974
        }
975
        if (count($cacheTags) > 0) {
976
            $this->getTypoScriptFrontendController()->addCacheTags($cacheTags);
977
        }
978
    }
979
980
    /**
981
     * Adds page cache tags by used storagePages.
982
     * This adds tags with the scheme tx_sfeventmgt_pid_[event:pid]
983
     *
984
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand
985
     */
986
    public function addPageCacheTagsByEventDemandObject(\DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand)
987
    {
988
        $cacheTags = [];
989
        if ($demand->getStoragePage()) {
990
            // Add cache tags for each storage page
991
            foreach (GeneralUtility::trimExplode(',', $demand->getStoragePage()) as $pageId) {
992
                $cacheTags[] = 'tx_sfeventmgt_pid_' . $pageId;
993
            }
994
        }
995
        if (count($cacheTags) > 0) {
996
            $this->getTypoScriptFrontendController()->addCacheTags($cacheTags);
997
        }
998
    }
999
1000
    /**
1001
     * Checks if the event pid could be found in the storagePage settings of the detail plugin and
1002
     * if the pid could not be found it return null instead of the event object.
1003
     *
1004
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
1005
     * @return null|\DERHANSEN\SfEventMgt\Domain\Model\Event
1006
     */
1007
    protected function checkPidOfEventRecord(Event $event)
1008
    {
1009
        $allowedStoragePages = GeneralUtility::trimExplode(
1010
            ',',
1011
            Page::extendPidListByChildren(
1012
                $this->settings['storagePage'],
1013
                $this->settings['recursive']
1014
            ),
1015
            true
1016
        );
1017
        if (count($allowedStoragePages) > 0 && !in_array($event->getPid(), $allowedStoragePages)) {
1018
            $this->signalSlotDispatcher->dispatch(
1019
                __CLASS__,
1020
                'checkPidOfEventRecordFailedInDetailAction',
1021
                [
1022
                    'event' => $event,
1023
                    'eventController' => $this
1024
                ]
1025
            );
1026
            $event = null;
1027
        }
1028
1029
        return $event;
1030
    }
1031
}
1032