Completed
Push — master ( e990a0...12b212 )
by Torben
03:57
created

EventController::checkPidOfEventRecord()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 0
cts 0
cp 0
rs 9.536
c 0
b 0
f 0
cc 3
nc 2
nop 1
crap 12
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 2
    /**
138
     * Overwrites a given demand object by an propertyName =>  $propertyValue array
139
     *
140 2
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand Demand
141 2
     * @param array $overwriteDemand OwerwriteDemand
142 2
     *
143 2
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand
144 2
     */
145 2
    protected function overwriteEventDemandObject(EventDemand $demand, array $overwriteDemand)
146 2
    {
147 2
        foreach ($this->ignoredSettingsForOverwriteDemand as $property) {
148 2
            unset($overwriteDemand[$property]);
149 2
        }
150 2
151 2
        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 2
    /**
178
     * Handle known exceptions
179
     *
180 2
     * @param \Exception $exception
181 2
     * @throws \Exception
182 2
     */
183 2
    private function handleKnownExceptionsElseThrowAgain(\Exception $exception)
184 2
    {
185 2
        $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 4
    /**
197
     * Initialize list action and set format
198 4
     *
199 4
     * @return void
200 4
     */
201
    public function initializeListAction()
202 4
    {
203 4
        if (isset($this->settings['list']['format'])) {
204 2
            $this->request->setFormat($this->settings['list']['format']);
205
        }
206 4
    }
207 4
208 4
    /**
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 6
            'categories' => $categories,
231
            'locations' => $locations,
232 6
            'organisators' => $organisators,
233 6
            'overwriteDemand' => $overwriteDemand,
234 6
            'eventDemand' => $eventDemand
235 6
        ];
236 2
237 2
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
238 6
        $this->view->assignMultiple($values);
239 6
240 6
        $this->addPageCacheTagsByEventDemandObject($eventDemand);
241 6
    }
242 6
243 6
    /**
244 6
     * Calendar view
245 6
     *
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 2
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
255
        if ($this->isOverwriteDemand($overwriteDemand)) {
256 2
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
257 2
        }
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 2
        if (!$eventDemand->getYear()) {
267
            $currentYear = date('Y');
268 2
            $eventDemand->setYear($currentYear);
269 2
        } 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 2
        $weeks = $this->calendarService->getCalendarArray(
280
            $currentMonth,
281 2
            $currentYear,
282
            strtotime('today midnight'),
283
            (int)$this->settings['calendar']['firstDayOfWeek'],
284 2
            $events
285
        );
286 2
287 2
        $values = [
288 2
            '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 2
            'firstDayOfMonth' => \DateTime::createFromFormat('d.m.Y', sprintf('1.%s.%s', $currentMonth, $currentYear)),
296
            'previousMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '-1 month'),
297 2
            'nextMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '+1 month')
298 2
        ];
299 2
300 2
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
301 2
        $this->view->assignMultiple($values);
302 2
    }
303 2
304 2
    /**
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 22
            $eventDemand->getYear(),
316
            $this->settings['calendar']['firstDayOfWeek']
317 22
        );
318 22
319 22
        $eventDemand->setMonth(0);
320
        $eventDemand->setYear(0);
321
322 22
        $startDate = new \DateTime();
323 8
        $startDate->setTimestamp($calendarDateRange['firstDayOfCalendar']);
324 8
        $endDate = new \DateTime();
325 8
        $endDate->setTimestamp($calendarDateRange['lastDayOfCalendar']);
326 8
        $endDate->setTime(23, 59, 59);
327 8
328 8
        $searchDemand = new SearchDemand();
329
        $searchDemand->setStartDate($startDate);
330 8
        $searchDemand->setEndDate($endDate);
331 8
        $eventDemand->setSearchDemand($searchDemand);
332 8
333 8
        return $eventDemand;
334
    }
335 8
336 8
    /**
337 8
     * Detail view for an event
338 8
     *
339 8
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
340 8
     * @return mixed string|void
341 8
     */
342 8
    public function detailAction(Event $event = null)
343
    {
344
        $event = $this->evaluateSingleEventSetting($event);
345 8
        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 8
349 2
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
350 2
            return $this->handleEventNotFoundError($this->settings);
351 2
        }
352 6
        $values = ['event' => $event];
353 6
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
354
        $this->view->assignMultiple($values);
355 8
        if ($event !== null) {
356
            $this->addCacheTagsByEventRecords([$event]);
357
        }
358 8
    }
359 6
360 6
    /**
361 6
     * Error handling if event is not found
362 6
     *
363
     * @param array $settings
364 6
     * @return string
365 6
     */
366 6
    protected function handleEventNotFoundError($settings)
367 6
    {
368 6
        if (empty($settings['event']['errorHandling'])) {
369
            return null;
370 6
        }
371 6
372
        $configuration = GeneralUtility::trimExplode(',', $settings['event']['errorHandling'], true);
373
374 8
        switch ($configuration[0]) {
375 2
            case 'redirectToListView':
376 2
                $listPid = (int)$settings['listPid'] > 0 ? (int)$settings['listPid'] : 1;
377
                $this->redirect('list', null, null, null, $listPid);
378
                break;
379 8
            case 'pageNotFoundHandler':
380 8
                $GLOBALS['TSFE']->pageNotFoundAndExit('Event not found.');
381
                break;
382 22
            case 'showStandaloneTemplate':
383 2
                if (isset($configuration[2])) {
384 2
                    $statusCode = constant(HttpUtility::class . '::HTTP_STATUS_' . $configuration[2]);
385 2
                    HttpUtility::setResponseCode($statusCode);
386 2
                }
387
                $standaloneTemplate = $this->objectManager->get(StandaloneView::class);
388 2
                $standaloneTemplate->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($configuration[1]));
389 2
390 2
                return $standaloneTemplate->render();
391 2
                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 2
            default:
393 20
        }
394 20
    }
395 20
396 20
    /**
397 20
     * Initiates the iCalendar download for the given event
398 20
     *
399
     * @param Event $event The event
400 22
     *
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 18
            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 18
413 2
        return false;
414 2
    }
415 2
416 16
    /**
417
     * Registration view for an event
418
     *
419
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
420 16
     *
421 2
     * @return mixed string|void
422 2
     */
423 2
    public function registrationAction(Event $event = null)
424 14
    {
425 2
        $event = $this->evaluateSingleEventSetting($event);
426 2
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
427 2
            $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 12
        }
429 2
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
430 2
            return $this->handleEventNotFoundError($this->settings);
431 2
        }
432 10
        if ($event->getRestrictPaymentMethods()) {
433 2
            $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 2
        } else {
435 2
            $paymentMethods = $this->paymentService->getPaymentMethods();
436 8
        }
437 2
438 2
        $values = [
439 2
            'event' => $event,
440 6
            'paymentMethods' => $paymentMethods,
441 2
        ];
442 2
443 2
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
444 4
        $this->view->assignMultiple($values);
445 2
    }
446 2
447 2
    /**
448 2
     * Processes incoming registrations fields and adds field values to arguments
449 2
     *
450 2
     * @return void
451 2
     */
452
    protected function setRegistrationFieldValuesToArguments()
453 18
    {
454 18
        $arguments = $this->request->getArguments();
455 18
        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 6
        // allow creation of new objects (for validation)
466
        $propertyMapping->setTypeConverterOptions(
467
            PersistentObjectConverter::class,
468 6
            [
469
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => true,
470 6
                PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED => true
471 4
            ]
472 4
        );
473
474 4
        // Set event to registration (required for validation)
475 4
        $event = $this->eventRepository->findByUid((int)$this->request->getArgument('event'));
476 2
        $propertyMapping->allowProperties('event');
477 2
        $propertyMapping->allowCreationForSubProperty('event');
478
        $propertyMapping->allowModificationForSubProperty('event');
479
        $arguments['registration']['event'] = (int)$this->request->getArgument('event');
480 4
481 4
        $index = 0;
482 4
        foreach ((array)$arguments['registration']['fields'] as $fieldUid => $value) {
483 4
            // Only accept registration fields of the current event
484
            if (!in_array((int)$fieldUid, $event->getRegistrationFieldsUids(), true)) {
485 4
                continue;
486 4
            }
487 4
488 4
            // allow subvalues in new property mapper
489 4
            $propertyMapping->forProperty('fieldValues')->allowProperties($index);
490
            $propertyMapping->forProperty('fieldValues.' . $index)->allowAllProperties();
491 4
            $propertyMapping->allowCreationForSubProperty('fieldValues.' . $index);
492
            $propertyMapping->allowModificationForSubProperty('fieldValues.' . $index);
493
494 4
            if (is_array($value)) {
495 4
                if (empty($value)) {
496 4
                    $value = '';
497 4
                } else {
498
                    $value = json_encode($value);
499
                }
500 6
            }
501 6
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 6
    }
519 6
520 6
    /**
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 4
                DateTimeConverter::class,
531
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
532
                $this->settings['registration']['formatDateOfBirth']
533 4
            );
534
        $this->setRegistrationFieldValuesToArguments();
535 4
    }
536
537 2
    /**
538 2
     * Saves the registration
539 2
     *
540 2
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
541
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
542 2
     * @validate $registration \DERHANSEN\SfEventMgt\Validation\Validator\RegistrationFieldValidator
543 2
     * @validate $registration \DERHANSEN\SfEventMgt\Validation\Validator\RegistrationValidator
544 2
     *
545 2
     * @return mixed string|void
546 2
     */
547
    public function saveRegistrationAction(Registration $registration, Event $event)
548 2
    {
549
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
550
            $event = $this->checkPidOfEventRecord($event);
551 2
        }
552 2
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
553 2
            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 2
        $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 2
        // Save registration if no errors
560 2
        if ($success) {
561 4
            $isWaitlistRegistration = $this->registrationService->isWaitlistRegistration(
562 4
                $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 4
                $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 2
            $confirmationUntil = new \DateTime();
571
            $confirmationUntil->add(new \DateInterval('PT' . $linkValidity . 'S'));
572 2
573 2
            $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 2
            $registration->setPid($event->getPid());
575 2
            $registration->setConfirmationUntil($confirmationUntil);
576 2
            $registration->setLanguage($GLOBALS['TSFE']->config['config']['language']);
577 2
            $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 2
            $registration->setWaitlist($isWaitlistRegistration);
579 2
            $registration->_setProperty('_languageUid', $GLOBALS['TSFE']->sys_language_uid);
580 2
            $this->registrationRepository->add($registration);
581 2
582 2
            // Persist registration, so we have an UID
583 2
            $this->objectManager->get(PersistenceManager::class)->persistAll();
584 2
585 2
            // Add new registration (or waitlist registration) to event
586 2
            if ($isWaitlistRegistration) {
587 2
                $event->addRegistrationWaitlist($registration);
588 2
                $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 12
            if (!$autoConfirmation) {
599
                $this->notificationService->sendUserMessage(
600 12
                    $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 12
                    $registration,
602 12
                    $this->settings,
603 12
                    $messageType
604
                );
605 12
                $this->notificationService->sendAdminMessage(
606 10
                    $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 10
                    $this->settings,
609 2
                    $messageType
610 2
                );
611
            }
612 10
613 2
            // Create given amount of registrations if necessary
614 2
            if ($registration->getAmountOfRegistrations() > 1) {
615 10
                $this->registrationService->createDependingRegistrations($registration);
616
            }
617 12
618 2
            // Clear cache for configured pages
619 2
            $this->utilityService->clearCacheForConfiguredUids($this->settings);
620
        }
621 12
622 12
        if ($autoConfirmation && $success) {
623
            $this->redirect(
624 12
                'confirmRegistration',
625
                null,
626 12
                null,
627 12
                [
628 12
                    'reguid' => $registration->getUid(),
629 12
                    'hmac' => $this->hashService->generateHmac('reg-' . $registration->getUid())
630 12
                ]
631 12
            );
632
        } else {
633
            $this->redirect(
634
                'saveRegistrationResult',
635
                null,
636
                null,
637
                [
638
                    'result' => $result,
639 18
                    'eventuid' => $event->getUid(),
640
                    'hmac' => $this->hashService->generateHmac('event-' . $event->getUid())
641 18
                ]
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