Completed
Push — development ( 11da13...e9292e )
by Torben
03:28
created

EventController::overwriteEventDemandObject()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 6
cts 6
cp 1
rs 9.7666
c 0
b 0
f 0
cc 4
nc 6
nop 2
crap 4
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
     * Initializes the current action
53
     */
54
    public function initializeAction()
55
    {
56
        $typoScriptFrontendController = $this->getTypoScriptFrontendController();
57
        if ($typoScriptFrontendController !== null) {
58
            static $cacheTagsSet = false;
59
60
            if (!$cacheTagsSet) {
61
                $typoScriptFrontendController->addCacheTags(['tx_sfeventmgt']);
62
                $cacheTagsSet = true;
63
            }
64
        }
65
    }
66
67
    /**
68
     * Creates an event demand object with the given settings
69
     *
70
     * @param array $settings The settings
71
     *
72
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand
73
     */
74
    public function createEventDemandObjectFromSettings(array $settings)
75
    {
76
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand */
77
        $demand = $this->objectManager->get(EventDemand::class);
78
        $demand->setDisplayMode($settings['displayMode']);
79
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
80
        $demand->setCategoryConjunction($settings['categoryConjunction']);
81
        $demand->setCategory($settings['category']);
82
        $demand->setIncludeSubcategories($settings['includeSubcategories']);
83
        $demand->setTopEventRestriction((int)$settings['topEventRestriction']);
84
        $demand->setOrderField($settings['orderField']);
85
        $demand->setOrderFieldAllowed($settings['orderFieldAllowed']);
86
        $demand->setOrderDirection($settings['orderDirection']);
87
        $demand->setQueryLimit($settings['queryLimit']);
88
        $demand->setLocation($settings['location']);
89
        $demand->setOrganisator($settings['organisator']);
90
91
        return $demand;
92
    }
93
94
    /**
95
     * Creates a foreign record demand object with the given settings
96
     *
97
     * @param array $settings The settings
98
     *
99
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand
100
     */
101
    public function createForeignRecordDemandObjectFromSettings(array $settings)
102
    {
103
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand $demand */
104
        $demand = $this->objectManager->get(ForeignRecordDemand::class);
105
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
106
        $demand->setRestrictForeignRecordsToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
107
108
        return $demand;
109
    }
110
111
    /**
112
     * Creates a category demand object with the given settings
113
     *
114
     * @param array $settings The settings
115
     *
116
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand
117
     */
118
    public function createCategoryDemandObjectFromSettings(array $settings)
119
    {
120
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand $demand */
121
        $demand = $this->objectManager->get(CategoryDemand::class);
122
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
123
        $demand->setRestrictToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
124
        $demand->setCategories($settings['categoryMenu']['categories']);
125
        $demand->setIncludeSubcategories($settings['categoryMenu']['includeSubcategories']);
126
127
        return $demand;
128
    }
129
130
    /**
131
     * Hook into request processing and catch exceptions
132
     *
133
     * @param RequestInterface $request
134
     * @param ResponseInterface $response
135
     * @throws \Exception
136
     */
137 1
    public function processRequest(RequestInterface $request, ResponseInterface $response)
138
    {
139
        try {
140 1
            parent::processRequest($request, $response);
141 1
        } catch (\Exception $exception) {
142 1
            $this->handleKnownExceptionsElseThrowAgain($exception);
143 1
        }
144 1
    }
145 1
146 1
    /**
147 1
     * Handle known exceptions
148 1
     *
149 1
     * @param \Exception $exception
150 1
     * @throws \Exception
151
     */
152
    private function handleKnownExceptionsElseThrowAgain(\Exception $exception)
153
    {
154
        $previousException = $exception->getPrevious();
155
        $actions = ['detailAction', 'registrationAction', 'icalDownloadAction'];
156
        if (in_array($this->actionMethodName, $actions, true)
157
            && $previousException instanceof \TYPO3\CMS\Extbase\Property\Exception
158
        ) {
159
            $this->handleEventNotFoundError($this->settings);
160
        } else {
161
            throw $exception;
162
        }
163
    }
164
165
    /**
166
     * Initialize list action and set format
167
     *
168
     * @return void
169
     */
170
    public function initializeListAction()
171
    {
172
        if (isset($this->settings['list']['format'])) {
173
            $this->request->setFormat($this->settings['list']['format']);
174
        }
175
    }
176 1
177
    /**
178
     * List view
179 1
     *
180 1
     * @param array $overwriteDemand OverwriteDemand
181 1
     *
182 1
     * @return void
183 1
     */
184 1
    public function listAction(array $overwriteDemand = [])
185
    {
186
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
187
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
188
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
189
        if ($this->isOverwriteDemand($overwriteDemand)) {
190
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
191
        }
192
        $events = $this->eventRepository->findDemanded($eventDemand);
193
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
194
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
195 2
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
196
197 2
        $values = [
198 2
            'events' => $events,
199 2
            'categories' => $categories,
200
            'locations' => $locations,
201 2
            'organisators' => $organisators,
202 2
            'overwriteDemand' => $overwriteDemand,
203 2
            'eventDemand' => $eventDemand
204 2
        ];
205
206
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
207
        $this->view->assignMultiple($values);
208
209
        $this->addPageCacheTagsByEventDemandObject($eventDemand);
210
    }
211
212
    /**
213
     * Calendar view
214
     *
215
     * @param array $overwriteDemand OverwriteDemand
216
     *
217
     * @return void
218
     */
219
    public function calendarAction(array $overwriteDemand = [])
220
    {
221
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
222
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
223
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
224
        if ($this->isOverwriteDemand($overwriteDemand)) {
225
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
226 3
        }
227
228 3
        // Set month/year to demand if not given
229 3
        if (!$eventDemand->getMonth()) {
230 3
            $currentMonth = date('n');
231 3
            $eventDemand->setMonth($currentMonth);
232 1
        } else {
233 1
            $currentMonth = $eventDemand->getMonth();
234 3
        }
235 3
        if (!$eventDemand->getYear()) {
236 3
            $currentYear = date('Y');
237 3
            $eventDemand->setYear($currentYear);
238 3
        } else {
239 3
            $currentYear = $eventDemand->getYear();
240 3
        }
241 3
242
        // Set demand from calendar date range instead of month / year
243
        if ((bool)$this->settings['calendar']['includeEventsForEveryDayOfAllCalendarWeeks']) {
244
            $eventDemand = $this->changeEventDemandToFullMonthDateRange($eventDemand);
245
        }
246
247
        $events = $this->eventRepository->findDemanded($eventDemand);
248
        $weeks = $this->calendarService->getCalendarArray(
249
            $currentMonth,
250 1
            $currentYear,
251
            strtotime('today midnight'),
252 1
            (int)$this->settings['calendar']['firstDayOfWeek'],
253 1
            $events
254
        );
255
256
        $values = [
257
            'weeks' => $weeks,
258
            'categories' => $this->categoryRepository->findDemanded($categoryDemand),
259
            'locations' => $this->locationRepository->findDemanded($foreignRecordDemand),
260
            'organisators' => $this->organisatorRepository->findDemanded($foreignRecordDemand),
261
            'eventDemand' => $eventDemand,
262 1
            'overwriteDemand' => $overwriteDemand,
263
            'currentPageId' => $GLOBALS['TSFE']->id,
264 1
            'firstDayOfMonth' => \DateTime::createFromFormat('d.m.Y', sprintf('1.%s.%s', $currentMonth, $currentYear)),
265 1
            'previousMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '-1 month'),
266
            'nextMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '+1 month')
267
        ];
268
269
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
270
        $this->view->assignMultiple($values);
271
    }
272
273
    /**
274
     * Changes the given event demand object to select a date range for a calendar month including days of the previous
275 1
     * month for the first week and they days for the next month for the last week
276
     *
277 1
     * @param EventDemand $eventDemand
278
     * @return EventDemand
279
     */
280 1
    protected function changeEventDemandToFullMonthDateRange(EventDemand $eventDemand)
281
    {
282 1
        $calendarDateRange = $this->calendarService->getCalendarDateRange(
283 1
            $eventDemand->getMonth(),
284 1
            $eventDemand->getYear(),
285
            $this->settings['calendar']['firstDayOfWeek']
286
        );
287
288
        $eventDemand->setMonth(0);
289
        $eventDemand->setYear(0);
290
291 1
        $startDate = new \DateTime();
292
        $startDate->setTimestamp($calendarDateRange['firstDayOfCalendar']);
293 1
        $endDate = new \DateTime();
294 1
        $endDate->setTimestamp($calendarDateRange['lastDayOfCalendar']);
295 1
        $endDate->setTime(23, 59, 59);
296 1
297 1
        $searchDemand = new SearchDemand();
298 1
        $searchDemand->setStartDate($startDate);
299 1
        $searchDemand->setEndDate($endDate);
300 1
        $eventDemand->setSearchDemand($searchDemand);
301
302
        return $eventDemand;
303
    }
304
305
    /**
306
     * Detail view for an event
307
     *
308
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
309
     * @return mixed string|void
310
     */
311 11
    public function detailAction(Event $event = null)
312
    {
313 11
        $event = $this->evaluateSingleEventSetting($event);
314 11
        if (is_a($event, Event::class) && $this->settings['detail']['checkPidOfEventRecord']) {
315 11
            $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...
316
        }
317
318 11
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
319 4
            return $this->handleEventNotFoundError($this->settings);
320 4
        }
321 4
        $values = ['event' => $event];
322 4
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
323 4
        $this->view->assignMultiple($values);
324 4
        if ($event !== null) {
325
            $this->addCacheTagsByEventRecords([$event]);
326 4
        }
327 4
    }
328 4
329 4
    /**
330
     * Error handling if event is not found
331 4
     *
332 4
     * @param array $settings
333 4
     * @return string
334 4
     */
335 4
    protected function handleEventNotFoundError($settings)
336 4
    {
337 4
        if (empty($settings['event']['errorHandling'])) {
338 4
            return null;
339
        }
340
341 4
        $configuration = GeneralUtility::trimExplode(',', $settings['event']['errorHandling'], true);
342
343
        switch ($configuration[0]) {
344 4
            case 'redirectToListView':
345 1
                $listPid = (int)$settings['listPid'] > 0 ? (int)$settings['listPid'] : 1;
346 1
                $this->redirect('list', null, null, null, $listPid);
347 1
                break;
348 3
            case 'pageNotFoundHandler':
349 3
                $GLOBALS['TSFE']->pageNotFoundAndExit('Event not found.');
350
                break;
351 4
            case 'showStandaloneTemplate':
352
                if (isset($configuration[2])) {
353
                    $statusCode = constant(HttpUtility::class . '::HTTP_STATUS_' . $configuration[2]);
354 4
                    HttpUtility::setResponseCode($statusCode);
355 3
                }
356 3
                $standaloneTemplate = $this->objectManager->get(StandaloneView::class);
357 3
                $standaloneTemplate->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($configuration[1]));
358 3
359
                return $standaloneTemplate->render();
360 3
                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...
361 3
            default:
362 3
        }
363 3
    }
364 3
365
    /**
366 3
     * Initiates the iCalendar download for the given event
367 3
     *
368
     * @param Event $event The event
369
     *
370 4
     * @return string|false
371 1
     */
372 1
    public function icalDownloadAction(Event $event = null)
373
    {
374
        if (is_a($event, Event::class) && $this->settings['detail']['checkPidOfEventRecord']) {
375 4
            $event = $this->checkPidOfEventRecord($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 375 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...
376 4
        }
377
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
378 11
            return $this->handleEventNotFoundError($this->settings);
379 1
        }
380 1
        $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...
381 1
        exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method icalDownloadAction() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
382 1
    }
383
384 1
    /**
385 1
     * Registration view for an event
386 1
     *
387 1
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
388 1
     *
389 10
     * @return mixed string|void
390 10
     */
391 10
    public function registrationAction(Event $event = null)
392 10
    {
393 10
        $event = $this->evaluateSingleEventSetting($event);
394 10
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
395
            $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...
396 11
        }
397
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
398
            return $this->handleEventNotFoundError($this->settings);
399
        }
400
        if ($event->getRestrictPaymentMethods()) {
401
            $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...
402
        } else {
403
            $paymentMethods = $this->paymentService->getPaymentMethods();
404
        }
405 9
406
        $values = [
407
            'event' => $event,
408 9
            'paymentMethods' => $paymentMethods,
409 1
        ];
410 1
411 1
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
412 8
        $this->view->assignMultiple($values);
413
    }
414
415
    /**
416 8
     * Processes incoming registrations fields and adds field values to arguments
417 1
     *
418 1
     * @return void
419 1
     */
420 7
    protected function setRegistrationFieldValuesToArguments()
421 1
    {
422 1
        $arguments = $this->request->getArguments();
423 1
        if (!isset($arguments['registration']['fields']) || !isset($arguments['event'])) {
424 6
            return;
425 1
        }
426 1
427 1
        $registrationMvcArgument = $this->arguments->getArgument('registration');
428 5
        $propertyMapping = $registrationMvcArgument->getPropertyMappingConfiguration();
429 1
        $propertyMapping->allowProperties('fieldValues');
430 1
        $propertyMapping->allowCreationForSubProperty('fieldValues');
431 1
        $propertyMapping->allowModificationForSubProperty('fieldValues');
432 4
433 1
        // allow creation of new objects (for validation)
434 1
        $propertyMapping->setTypeConverterOptions(
435 1
            PersistentObjectConverter::class,
436 3
            [
437 1
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => true,
438 1
                PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED => true
439 1
            ]
440 2
        );
441 1
442 1
        // Set event to registration (required for validation)
443 1
        $event = $this->eventRepository->findByUid((int)$this->request->getArgument('event'));
444 1
        $propertyMapping->allowProperties('event');
445 1
        $propertyMapping->allowCreationForSubProperty('event');
446 1
        $propertyMapping->allowModificationForSubProperty('event');
447 1
        $arguments['registration']['event'] = (int)$this->request->getArgument('event');
448
449 9
        $index = 0;
450 9
        foreach ((array)$arguments['registration']['fields'] as $fieldUid => $value) {
451 9
            // Only accept registration fields of the current event
452
            if (!in_array((int)$fieldUid, $event->getRegistrationFieldsUids(), true)) {
453
                continue;
454
            }
455
456
            // allow subvalues in new property mapper
457
            $propertyMapping->forProperty('fieldValues')->allowProperties($index);
458
            $propertyMapping->forProperty('fieldValues.' . $index)->allowAllProperties();
459
            $propertyMapping->allowCreationForSubProperty('fieldValues.' . $index);
460
            $propertyMapping->allowModificationForSubProperty('fieldValues.' . $index);
461 3
462
            if (is_array($value)) {
463
                if (empty($value)) {
464 3
                    $value = '';
465
                } else {
466 3
                    $value = json_encode($value);
467 2
                }
468 2
            }
469
470 2
            /** @var Registration\Field $field */
471 2
            $field = $this->fieldRepository->findByUid((int)$fieldUid);
472 1
473 1
            $arguments['registration']['fieldValues'][$index] = [
474
                'pid' => $field->getPid(),
475
                'value' => $value,
476 2
                'field' => strval($fieldUid),
477 2
                'valueType' => $field->getValueType()
478 2
            ];
479 2
480
            $index++;
481 2
        }
482 2
483 2
        // Remove temporary "fields" field
484 2
        $arguments = ArrayUtility::removeByPath($arguments, 'registration/fields');
485 2
        $this->request->setArguments($arguments);
486
    }
487 2
488
    /**
489
     * Set date format for field dateOfBirth
490 2
     *
491 2
     * @return void
492 2
     */
493 2
    public function initializeSaveRegistrationAction()
494
    {
495
        $this->arguments->getArgument('registration')
496 3
            ->getPropertyMappingConfiguration()->forProperty('dateOfBirth')
497 3
            ->setTypeConverterOption(
498
                DateTimeConverter::class,
499
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
500
                $this->settings['registration']['formatDateOfBirth']
501
            );
502
        $this->setRegistrationFieldValuesToArguments();
503
    }
504
505
    /**
506
     * Saves the registration
507
     *
508
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
509
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
510
     * @validate $registration \DERHANSEN\SfEventMgt\Validation\Validator\RegistrationFieldValidator
511
     * @validate $registration \DERHANSEN\SfEventMgt\Validation\Validator\RegistrationValidator
512
     *
513
     * @return mixed string|void
514 3
     */
515 3
    public function saveRegistrationAction(Registration $registration, Event $event)
516 3
    {
517
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
518
            $event = $this->checkPidOfEventRecord($event);
519
        }
520
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
521
            return $this->handleEventNotFoundError($this->settings);
522
        }
523
        $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...
524
        $result = RegistrationResult::REGISTRATION_SUCCESSFUL;
525
        $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 518 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...
526 2
527
        // Save registration if no errors
528
        if ($success) {
529 2
            $isWaitlistRegistration = $this->registrationService->isWaitlistRegistration(
530
                $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 518 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...
531 2
                $registration->getAmountOfRegistrations()
532
            );
533 1
            $linkValidity = (int)$this->settings['confirmation']['linkValidity'];
534 1
            if ($linkValidity === 0) {
535 1
                // Use 3600 seconds as default value if not set
536 1
                $linkValidity = 3600;
537
            }
538 1
            $confirmationUntil = new \DateTime();
539 1
            $confirmationUntil->add(new \DateInterval('PT' . $linkValidity . 'S'));
540 1
541 1
            $registration->setEvent($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 518 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...
542 1
            $registration->setPid($event->getPid());
543
            $registration->setConfirmationUntil($confirmationUntil);
544 1
            $registration->setLanguage($GLOBALS['TSFE']->config['config']['language']);
545
            $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...
546
            $registration->setWaitlist($isWaitlistRegistration);
547 1
            $registration->_setProperty('_languageUid', $GLOBALS['TSFE']->sys_language_uid);
548 1
            $this->registrationRepository->add($registration);
549 1
550
            // Persist registration, so we have an UID
551
            $this->objectManager->get(PersistenceManager::class)->persistAll();
552 1
553
            // Add new registration (or waitlist registration) to event
554
            if ($isWaitlistRegistration) {
555 1
                $event->addRegistrationWaitlist($registration);
556 1
                $messageType = MessageType::REGISTRATION_WAITLIST_NEW;
557 2
            } else {
558 2
                $event->addRegistration($registration);
559 2
                $messageType = MessageType::REGISTRATION_NEW;
560
            }
561
            $this->eventRepository->update($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 518 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...
562
563
            $this->signalDispatch(__CLASS__, __FUNCTION__ . 'AfterRegistrationSaved', [$registration, $this]);
564
565
            // Send notifications to user and admin if confirmation link should be sent
566 1
            if (!$autoConfirmation) {
567
                $this->notificationService->sendUserMessage(
568 1
                    $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 518 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...
569 1
                    $registration,
570 1
                    $this->settings,
571 1
                    $messageType
572 1
                );
573 1
                $this->notificationService->sendAdminMessage(
574 1
                    $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 518 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...
575 1
                    $registration,
576 1
                    $this->settings,
577 1
                    $messageType
578 1
                );
579 1
            }
580 1
581 1
            // Create given amount of registrations if necessary
582 1
            if ($registration->getAmountOfRegistrations() > 1) {
583 1
                $this->registrationService->createDependingRegistrations($registration);
584 1
            }
585
586
            // Clear cache for configured pages
587
            $this->utilityService->clearCacheForConfiguredUids($this->settings);
588
        }
589
590
        if ($autoConfirmation && $success) {
591
            $this->redirect(
592
                'confirmRegistration',
593
                null,
594 6
                null,
595
                [
596 6
                    'reguid' => $registration->getUid(),
597 6
                    'hmac' => $this->hashService->generateHmac('reg-' . $registration->getUid())
598 6
                ]
599 6
            );
600
        } else {
601 6
            $this->redirect(
602 5
                'saveRegistrationResult',
603
                null,
604 5
                null,
605 1
                [
606 1
                    'result' => $result,
607
                    'eventuid' => $event->getUid(),
608 5
                    'hmac' => $this->hashService->generateHmac('event-' . $event->getUid())
609 1
                ]
610 1
            );
611 5
        }
612
    }
613 6
614 1
    /**
615 1
     * Shows the result of the saveRegistrationAction
616
     *
617 6
     * @param int $result Result
618 6
     * @param int $eventuid
619
     * @param string $hmac
620 6
     *
621
     * @return void
622 6
     */
623 6
    public function saveRegistrationResultAction($result, $eventuid, $hmac)
624 6
    {
625 6
        $event = null;
626 6
627 6
        switch ($result) {
628
            case RegistrationResult::REGISTRATION_SUCCESSFUL:
629
                $messageKey = 'event.message.registrationsuccessful';
630
                $titleKey = 'registrationResult.title.successful';
631
                break;
632
            case RegistrationResult::REGISTRATION_SUCCESSFUL_WAITLIST:
633
                $messageKey = 'event.message.registrationwaitlistsuccessful';
634
                $titleKey = 'registrationWaitlistResult.title.successful';
635 9
                break;
636
            case RegistrationResult::REGISTRATION_FAILED_EVENT_EXPIRED:
637 9
                $messageKey = 'event.message.registrationfailedeventexpired';
638
                $titleKey = 'registrationResult.title.failed';
639
                break;
640
            case RegistrationResult::REGISTRATION_FAILED_MAX_PARTICIPANTS:
641
                $messageKey = 'event.message.registrationfailedmaxparticipants';
642
                $titleKey = 'registrationResult.title.failed';
643
                break;
644
            case RegistrationResult::REGISTRATION_NOT_ENABLED:
645
                $messageKey = 'event.message.registrationfailednotenabled';
646
                $titleKey = 'registrationResult.title.failed';
647
                break;
648
            case RegistrationResult::REGISTRATION_FAILED_DEADLINE_EXPIRED:
649
                $messageKey = 'event.message.registrationfaileddeadlineexpired';
650
                $titleKey = 'registrationResult.title.failed';
651
                break;
652
            case RegistrationResult::REGISTRATION_FAILED_NOT_ENOUGH_FREE_PLACES:
653
                $messageKey = 'event.message.registrationfailednotenoughfreeplaces';
654
                $titleKey = 'registrationResult.title.failed';
655
                break;
656
            case RegistrationResult::REGISTRATION_FAILED_MAX_AMOUNT_REGISTRATIONS_EXCEEDED:
657
                $messageKey = 'event.message.registrationfailedmaxamountregistrationsexceeded';
658
                $titleKey = 'registrationResult.title.failed';
659
                break;
660
            case RegistrationResult::REGISTRATION_FAILED_EMAIL_NOT_UNIQUE:
661
                $messageKey = 'event.message.registrationfailedemailnotunique';
662
                $titleKey = 'registrationResult.title.failed';
663
                break;
664
            default:
665
                $messageKey = '';
666
                $titleKey = '';
667
        }
668
669
        if (!$this->hashService->validateHmac('event-' . $eventuid, $hmac)) {
670
            $messageKey = 'event.message.registrationsuccessfulwrongeventhmac';
671
            $titleKey = 'registrationResult.title.failed';
672
        } else {
673
            $event = $this->eventRepository->findByUid((int)$eventuid);
674
        }
675
676
        $this->view->assignMultiple([
677
            'messageKey' => $messageKey,
678
            'titleKey' => $titleKey,
679
            'event' => $event,
680
        ]);
681
    }
682
683
    /**
684
     * Confirms the registration if possible and sends e-mails to admin and user
685
     *
686
     * @param int $reguid UID of registration
687
     * @param string $hmac HMAC for parameters
688
     *
689
     * @return void
690
     */
691
    public function confirmRegistrationAction($reguid, $hmac)
692
    {
693
        $event = null;
694
695
        /* @var $registration Registration */
696
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkConfirmRegistration(
697
            $reguid,
698
            $hmac
699
        );
700
701
        if ($failed === false) {
702
            $registration->setConfirmed(true);
703
            $event = $registration->getEvent();
704
            $this->registrationRepository->update($registration);
705
706
            $messageType = MessageType::REGISTRATION_CONFIRMED;
707
            if ($registration->getWaitlist()) {
708
                $messageType = MessageType::REGISTRATION_WAITLIST_CONFIRMED;
709
            }
710
711
            // Send notifications to user and admin
712
            $this->notificationService->sendUserMessage(
713
                $registration->getEvent(),
714
                $registration,
715
                $this->settings,
716
                $messageType
717
            );
718
            $this->notificationService->sendAdminMessage(
719
                $registration->getEvent(),
720
                $registration,
721
                $this->settings,
722
                $messageType
723
            );
724
725
            // Confirm registrations depending on main registration if necessary
726
            if ($registration->getAmountOfRegistrations() > 1) {
727
                $this->registrationService->confirmDependingRegistrations($registration);
728
            }
729
        }
730
731
        // Redirect to payment provider if payment/redirect is enabled
732
        $paymentPid = (int)$this->settings['paymentPid'];
733
        if (!$failed && $paymentPid > 0 && $this->registrationService->redirectPaymentEnabled($registration)) {
734
            $this->uriBuilder->reset()
735
                ->setTargetPageUid($paymentPid)
736
                ->setUseCacheHash(false);
737
            $uri = $this->uriBuilder->uriFor(
738
                'redirect',
739
                [
740
                    'registration' => $registration,
741
                    'hmac' => $this->hashService->generateHmac('redirectAction-' . $registration->getUid())
742
                ],
743
                'Payment',
744
                'sfeventmgt',
745
                'Pipayment'
746
            );
747
            $this->redirectToUri($uri);
748
        }
749
750
        $values = [
751
            'messageKey' => $messageKey,
752
            'titleKey' => $titleKey,
753
            'event' => $event,
754
            'registration' => $registration,
755
        ];
756
757
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
758
        $this->view->assignMultiple($values);
759
    }
760
761
    /**
762
     * Cancels the registration if possible and sends e-mails to admin and user
763
     *
764
     * @param int $reguid UID of registration
765
     * @param string $hmac HMAC for parameters
766
     *
767
     * @return void
768
     */
769
    public function cancelRegistrationAction($reguid, $hmac)
770
    {
771
        $event = null;
772
773
        /* @var $registration Registration */
774
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkCancelRegistration($reguid, $hmac);
775
776
        if ($failed === false) {
777
            $event = $registration->getEvent();
778
779
            // Send notifications (must run before cancelling the registration)
780
            $this->notificationService->sendUserMessage(
781
                $registration->getEvent(),
782
                $registration,
783
                $this->settings,
784
                MessageType::REGISTRATION_CANCELLED
785
            );
786
            $this->notificationService->sendAdminMessage(
787
                $registration->getEvent(),
788
                $registration,
789
                $this->settings,
790
                MessageType::REGISTRATION_CANCELLED
791
            );
792
793
            // First cancel depending registrations
794
            if ($registration->getAmountOfRegistrations() > 1) {
795
                $this->registrationService->cancelDependingRegistrations($registration);
796
            }
797
798
            // Finally cancel registration
799
            $this->registrationRepository->remove($registration);
800
801
            // Dispatch signal, so waitlist registrations can be moved up
802
            $this->signalDispatch(__CLASS__, __FUNCTION__ . 'WaitlistMoveUp', [$event, $this]);
803
804
            // Clear cache for configured pages
805
            $this->utilityService->clearCacheForConfiguredUids($this->settings);
806
        }
807
808
        $values = [
809
            'messageKey' => $messageKey,
810
            'titleKey' => $titleKey,
811
            'event' => $event,
812
        ];
813
814
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
815
        $this->view->assignMultiple($values);
816
    }
817
818
    /**
819
     * Set date format for field startDate and endDate
820
     *
821
     * @return void
822
     */
823
    public function initializeSearchAction()
824
    {
825
        if ($this->settings !== null && $this->settings['search']['dateFormat']) {
826
            $this->arguments->getArgument('searchDemand')
827
                ->getPropertyMappingConfiguration()->forProperty('startDate')
828
                ->setTypeConverterOption(
829
                    DateTimeConverter::class,
830
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
831
                    $this->settings['search']['dateFormat']
832
                );
833
            $this->arguments->getArgument('searchDemand')
834
                ->getPropertyMappingConfiguration()->forProperty('endDate')
835
                ->setTypeConverterOption(
836
                    DateTimeConverter::class,
837
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
838
                    $this->settings['search']['dateFormat']
839
                );
840
        }
841
        if ($this->arguments->hasArgument('searchDemand')) {
842
            $propertyMappingConfiguration = $this->arguments->getArgument('searchDemand')
843
                ->getPropertyMappingConfiguration();
844
            $propertyMappingConfiguration->allowAllProperties();
845
            $propertyMappingConfiguration->setTypeConverterOption(
846
                PersistentObjectConverter::class,
847
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED,
848
                true
849
            );
850
        }
851
    }
852
853
    /**
854
     * Search view
855
     *
856
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand $searchDemand SearchDemand
857
     * @param array $overwriteDemand OverwriteDemand
858
     *
859
     * @return void
860
     */
861
    public function searchAction(SearchDemand $searchDemand = null, array $overwriteDemand = [])
862
    {
863
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
864
        $eventDemand->setSearchDemand($searchDemand);
0 ignored issues
show
Bug introduced by
It seems like $searchDemand defined by parameter $searchDemand on line 861 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...
865
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
866
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
867
868
        if ($searchDemand !== null) {
869
            $searchDemand->setFields($this->settings['search']['fields']);
870
871
            if ($this->settings['search']['adjustTime'] && $searchDemand->getStartDate() !== null) {
872
                $searchDemand->getStartDate()->setTime(0, 0, 0);
873
            }
874
875
            if ($this->settings['search']['adjustTime'] && $searchDemand->getEndDate() !== null) {
876
                $searchDemand->getEndDate()->setTime(23, 59, 59);
877
            }
878
        }
879
880
        if ($this->isOverwriteDemand($overwriteDemand)) {
881
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
882
        }
883
884
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
885
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
886
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
887
        $events = $this->eventRepository->findDemanded($eventDemand);
888
889
        $values = [
890
            'events' => $events,
891
            'categories' => $categories,
892
            'locations' => $locations,
893
            'organisators' => $organisators,
894
            'searchDemand' => $searchDemand,
895
            'overwriteDemand' => $overwriteDemand,
896
        ];
897
898
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
899
        $this->view->assignMultiple($values);
900
    }
901
902
    /**
903
     * Returns if a demand object can be overwritten with the given overwriteDemand array
904
     *
905
     * @param array $overwriteDemand
906
     * @return bool
907
     */
908
    protected function isOverwriteDemand($overwriteDemand)
909
    {
910
        return $this->settings['disableOverrideDemand'] != 1 && $overwriteDemand !== [];
911
    }
912
913
    /**
914
     * If no event is given and the singleEvent setting is set, the configured single event is returned
915
     *
916
     * @param Event|null $event
917
     * @return Event|null
918
     */
919
    protected function evaluateSingleEventSetting($event)
920
    {
921
        if ($event === null && (int)$this->settings['singleEvent'] > 0) {
922
            $event = $this->eventRepository->findByUid((int)$this->settings['singleEvent']);
923
        }
924
925
        return $event;
926
    }
927
928
    /**
929
     * Adds cache tags to page cache by event records.
930
     *
931
     * Following cache tags will be added to tsfe:
932
     * "tx_sfeventmgt_uid_[event:uid]"
933
     *
934
     * @param array $eventRecords array with event records
935
     */
936
    public function addCacheTagsByEventRecords(array $eventRecords)
937
    {
938
        $cacheTags = [];
939
        foreach ($eventRecords as $event) {
940
            // cache tag for each event record
941
            $cacheTags[] = 'tx_sfeventmgt_uid_' . $event->getUid();
942
        }
943
        if (count($cacheTags) > 0) {
944
            $this->getTypoScriptFrontendController()->addCacheTags($cacheTags);
945
        }
946
    }
947
948
    /**
949
     * Adds page cache tags by used storagePages.
950
     * This adds tags with the scheme tx_sfeventmgt_pid_[event:pid]
951
     *
952
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand
953
     */
954
    public function addPageCacheTagsByEventDemandObject(\DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand)
955
    {
956
        $cacheTags = [];
957
        if ($demand->getStoragePage()) {
958
            // Add cache tags for each storage page
959
            foreach (GeneralUtility::trimExplode(',', $demand->getStoragePage()) as $pageId) {
960
                $cacheTags[] = 'tx_sfeventmgt_pid_' . $pageId;
961
            }
962
        }
963
        if (count($cacheTags) > 0) {
964
            $this->getTypoScriptFrontendController()->addCacheTags($cacheTags);
965
        }
966
    }
967
968
    /**
969
     * Checks if the event pid could be found in the storagePage settings of the detail plugin and
970
     * if the pid could not be found it return null instead of the event object.
971
     *
972
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
973
     * @return null|\DERHANSEN\SfEventMgt\Domain\Model\Event
974
     */
975
    protected function checkPidOfEventRecord(Event $event)
976
    {
977
        $allowedStoragePages = GeneralUtility::trimExplode(
978
            ',',
979
            Page::extendPidListByChildren(
980
                $this->settings['storagePage'],
981
                $this->settings['recursive']
982
            ),
983
            true
984
        );
985
        if (count($allowedStoragePages) > 0 && !in_array($event->getPid(), $allowedStoragePages)) {
986
            $this->signalSlotDispatcher->dispatch(
987
                __CLASS__,
988
                'checkPidOfEventRecordFailedInDetailAction',
989
                [
990
                    'event' => $event,
991
                    'eventController' => $this
992
                ]
993
            );
994
            $event = null;
995
        }
996
997
        return $event;
998
    }
999
}
1000