Completed
Push — master ( 054192...eb3219 )
by Torben
02:56 queued 01:47
created

removePossibleSpamCheckFieldsFromArguments()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4

Importance

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

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
333 8
        if (is_a($event, Event::class) && $this->settings['detail']['checkPidOfEventRecord']) {
334
            $event = $this->checkPidOfEventRecord($event);
0 ignored issues
show
Documentation introduced by
$event is of type null|object, but the function expects a object<DERHANSEN\SfEventMgt\Domain\Model\Event>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

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

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

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

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

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

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

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

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
627 12
                    $registration,
628 12
                    $this->settings,
629 12
                    $messageType
630 12
                );
631 12
            }
632
633
            // Create given amount of registrations if necessary
634
            $createDependingRegistrations = $registration->getAmountOfRegistrations() > 1;
635
            $this->signalDispatch(
636
                __CLASS__,
637
                __FUNCTION__ . 'BeforeCreateDependingRegistrations',
638
                [$registration, &$createDependingRegistrations, $this]
639 18
            );
640
            if ($createDependingRegistrations) {
641 18
                $this->registrationService->createDependingRegistrations($registration);
642
            }
643
644
            // Flush page cache for event, since new registration has been added
645
            $this->eventCacheService->flushEventCache($event->getUid(), $event->getPid());
646
        }
647
648
        if ($autoConfirmation && $success) {
649
            $this->redirect(
650
                'confirmRegistration',
651
                null,
652
                null,
653
                [
654
                    'reguid' => $registration->getUid(),
655
                    'hmac' => $this->hashService->generateHmac('reg-' . $registration->getUid())
656
                ]
657
            );
658
        } else {
659
            $this->redirect(
660
                'saveRegistrationResult',
661
                null,
662
                null,
663
                [
664
                    'result' => $result,
665
                    'eventuid' => $event->getUid(),
666
                    'hmac' => $this->hashService->generateHmac('event-' . $event->getUid())
667
                ]
668
            );
669
        }
670
    }
671
672
    /**
673
     * Shows the result of the saveRegistrationAction
674
     *
675
     * @param int $result Result
676
     * @param int $eventuid
677
     * @param string $hmac
678
     *
679
     * @return void
680
     */
681
    public function saveRegistrationResultAction($result, $eventuid, $hmac)
682
    {
683
        $event = null;
684
685
        switch ($result) {
686
            case RegistrationResult::REGISTRATION_SUCCESSFUL:
687
                $messageKey = 'event.message.registrationsuccessful';
688
                $titleKey = 'registrationResult.title.successful';
689
                break;
690
            case RegistrationResult::REGISTRATION_SUCCESSFUL_WAITLIST:
691
                $messageKey = 'event.message.registrationwaitlistsuccessful';
692
                $titleKey = 'registrationWaitlistResult.title.successful';
693
                break;
694
            case RegistrationResult::REGISTRATION_FAILED_EVENT_EXPIRED:
695
                $messageKey = 'event.message.registrationfailedeventexpired';
696
                $titleKey = 'registrationResult.title.failed';
697
                break;
698
            case RegistrationResult::REGISTRATION_FAILED_MAX_PARTICIPANTS:
699
                $messageKey = 'event.message.registrationfailedmaxparticipants';
700
                $titleKey = 'registrationResult.title.failed';
701
                break;
702
            case RegistrationResult::REGISTRATION_NOT_ENABLED:
703
                $messageKey = 'event.message.registrationfailednotenabled';
704
                $titleKey = 'registrationResult.title.failed';
705
                break;
706
            case RegistrationResult::REGISTRATION_FAILED_DEADLINE_EXPIRED:
707
                $messageKey = 'event.message.registrationfaileddeadlineexpired';
708
                $titleKey = 'registrationResult.title.failed';
709
                break;
710
            case RegistrationResult::REGISTRATION_FAILED_NOT_ENOUGH_FREE_PLACES:
711
                $messageKey = 'event.message.registrationfailednotenoughfreeplaces';
712
                $titleKey = 'registrationResult.title.failed';
713
                break;
714
            case RegistrationResult::REGISTRATION_FAILED_MAX_AMOUNT_REGISTRATIONS_EXCEEDED:
715
                $messageKey = 'event.message.registrationfailedmaxamountregistrationsexceeded';
716
                $titleKey = 'registrationResult.title.failed';
717
                break;
718
            case RegistrationResult::REGISTRATION_FAILED_EMAIL_NOT_UNIQUE:
719
                $messageKey = 'event.message.registrationfailedemailnotunique';
720
                $titleKey = 'registrationResult.title.failed';
721
                break;
722
            default:
723
                $messageKey = '';
724
                $titleKey = '';
725
        }
726
727
        if (!$this->hashService->validateHmac('event-' . $eventuid, $hmac)) {
728
            $messageKey = 'event.message.registrationsuccessfulwrongeventhmac';
729
            $titleKey = 'registrationResult.title.failed';
730
        } else {
731
            $event = $this->eventRepository->findByUid((int)$eventuid);
732
        }
733
734
        $this->view->assignMultiple([
735
            'messageKey' => $messageKey,
736
            'titleKey' => $titleKey,
737
            'event' => $event,
738
        ]);
739
    }
740
741
    /**
742
     * Confirms the registration if possible and sends e-mails to admin and user
743
     *
744
     * @param int $reguid UID of registration
745
     * @param string $hmac HMAC for parameters
746
     *
747
     * @return void
748
     */
749
    public function confirmRegistrationAction($reguid, $hmac)
750
    {
751
        $event = null;
752
753
        /* @var $registration Registration */
754
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkConfirmRegistration(
755
            $reguid,
756
            $hmac
757
        );
758
759
        if ($failed === false) {
760
            $registration->setConfirmed(true);
761
            $event = $registration->getEvent();
762
            $this->registrationRepository->update($registration);
763
764
            $this->signalDispatch(__CLASS__, __FUNCTION__ . 'AfterRegistrationConfirmed', [$registration, $this]);
765
766
            $messageType = MessageType::REGISTRATION_CONFIRMED;
767
            if ($registration->getWaitlist()) {
768
                $messageType = MessageType::REGISTRATION_WAITLIST_CONFIRMED;
769
            }
770
771
            // Send notifications to user and admin
772
            $this->notificationService->sendUserMessage(
773
                $registration->getEvent(),
774
                $registration,
775
                $this->settings,
776
                $messageType
777
            );
778
            $this->notificationService->sendAdminMessage(
779
                $registration->getEvent(),
780
                $registration,
781
                $this->settings,
782
                $messageType
783
            );
784
785
            // Confirm registrations depending on main registration if necessary
786
            if ($registration->getAmountOfRegistrations() > 1) {
787
                $this->registrationService->confirmDependingRegistrations($registration);
788
            }
789
        }
790
791
        // Redirect to payment provider if payment/redirect is enabled
792
        $paymentPid = (int)$this->settings['paymentPid'];
793
        if (!$failed && $paymentPid > 0 && $this->registrationService->redirectPaymentEnabled($registration)) {
794
            $this->uriBuilder->reset()
795
                ->setTargetPageUid($paymentPid)
796
                ->setUseCacheHash(false);
797
            $uri = $this->uriBuilder->uriFor(
798
                'redirect',
799
                [
800
                    'registration' => $registration,
801
                    'hmac' => $this->hashService->generateHmac('redirectAction-' . $registration->getUid())
802
                ],
803
                'Payment',
804
                'sfeventmgt',
805
                'Pipayment'
806
            );
807
            $this->redirectToUri($uri);
808
        }
809
810
        $values = [
811
            'failed' => $failed,
812
            'messageKey' => $messageKey,
813
            'titleKey' => $titleKey,
814
            'event' => $event,
815
            'registration' => $registration,
816
        ];
817
818
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
819
        $this->view->assignMultiple($values);
820
    }
821
822
    /**
823
     * Cancels the registration if possible and sends e-mails to admin and user
824
     *
825
     * @param int $reguid UID of registration
826
     * @param string $hmac HMAC for parameters
827
     *
828
     * @return void
829
     */
830
    public function cancelRegistrationAction($reguid, $hmac)
831
    {
832
        $event = null;
833
834
        /* @var $registration Registration */
835
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkCancelRegistration($reguid, $hmac);
836
837
        if ($failed === false) {
838
            $event = $registration->getEvent();
839
840
            // Send notifications (must run before cancelling the registration)
841
            $this->notificationService->sendUserMessage(
842
                $registration->getEvent(),
843
                $registration,
844
                $this->settings,
845
                MessageType::REGISTRATION_CANCELLED
846
            );
847
            $this->notificationService->sendAdminMessage(
848
                $registration->getEvent(),
849
                $registration,
850
                $this->settings,
851
                MessageType::REGISTRATION_CANCELLED
852
            );
853
854
            // First cancel depending registrations
855
            if ($registration->getAmountOfRegistrations() > 1) {
856
                $this->registrationService->cancelDependingRegistrations($registration);
857
            }
858
859
            // Finally cancel registration
860
            $this->registrationRepository->remove($registration);
861
862
            // Dispatch signal, so waitlist registrations can be moved up
863
            $this->signalDispatch(__CLASS__, __FUNCTION__ . 'WaitlistMoveUp', [$event, $this]);
864
865
            // Flush page cache for event, since new registration has been added
866
            $this->eventCacheService->flushEventCache($event->getUid(), $event->getPid());
867
        }
868
869
        $values = [
870
            'failed' => $failed,
871
            'messageKey' => $messageKey,
872
            'titleKey' => $titleKey,
873
            'event' => $event,
874
        ];
875
876
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
877
        $this->view->assignMultiple($values);
878
    }
879
880
    /**
881
     * Set date format for field startDate and endDate
882
     *
883
     * @return void
884
     */
885
    public function initializeSearchAction()
886
    {
887
        if ($this->settings !== null && $this->settings['search']['dateFormat']) {
888
            $this->arguments->getArgument('searchDemand')
889
                ->getPropertyMappingConfiguration()->forProperty('startDate')
890
                ->setTypeConverterOption(
891
                    DateTimeConverter::class,
892
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
893
                    $this->settings['search']['dateFormat']
894
                );
895
            $this->arguments->getArgument('searchDemand')
896
                ->getPropertyMappingConfiguration()->forProperty('endDate')
897
                ->setTypeConverterOption(
898
                    DateTimeConverter::class,
899
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
900
                    $this->settings['search']['dateFormat']
901
                );
902
        }
903
        if ($this->arguments->hasArgument('searchDemand')) {
904
            $propertyMappingConfiguration = $this->arguments->getArgument('searchDemand')
905
                ->getPropertyMappingConfiguration();
906
            $propertyMappingConfiguration->allowAllProperties();
907
            $propertyMappingConfiguration->setTypeConverterOption(
908
                PersistentObjectConverter::class,
909
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED,
910
                true
911
            );
912
        }
913
    }
914
915
    /**
916
     * Search view
917
     *
918
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand $searchDemand SearchDemand
919
     * @param array $overwriteDemand OverwriteDemand
920
     *
921
     * @return void
922
     */
923
    public function searchAction(SearchDemand $searchDemand = null, array $overwriteDemand = [])
924
    {
925
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
926
        $eventDemand->setSearchDemand($searchDemand);
0 ignored issues
show
Bug introduced by
It seems like $searchDemand defined by parameter $searchDemand on line 923 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...
927
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
928
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
929
930
        if ($searchDemand !== null) {
931
            $searchDemand->setFields($this->settings['search']['fields']);
932
933
            if ($this->settings['search']['adjustTime'] && $searchDemand->getStartDate() !== null) {
934
                $searchDemand->getStartDate()->setTime(0, 0, 0);
935
            }
936
937
            if ($this->settings['search']['adjustTime'] && $searchDemand->getEndDate() !== null) {
938
                $searchDemand->getEndDate()->setTime(23, 59, 59);
939
            }
940
        }
941
942
        if ($this->isOverwriteDemand($overwriteDemand)) {
943
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
944
        }
945
946
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
947
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
948
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
949
        $speakers = $this->speakerRepository->findDemanded($foreignRecordDemand);
950
        $events = $this->eventRepository->findDemanded($eventDemand);
951
952
        $values = [
953
            'events' => $events,
954
            'categories' => $categories,
955
            'locations' => $locations,
956
            'organisators' => $organisators,
957
            'speakers' => $speakers,
958
            'searchDemand' => $searchDemand,
959
            'overwriteDemand' => $overwriteDemand,
960
        ];
961
962
        $this->signalDispatch(__CLASS__, __FUNCTION__ . 'BeforeRenderView', [&$values, $this]);
963
        $this->view->assignMultiple($values);
964
    }
965
966
    /**
967
     * Returns if a demand object can be overwritten with the given overwriteDemand array
968
     *
969
     * @param array $overwriteDemand
970
     * @return bool
971
     */
972
    protected function isOverwriteDemand($overwriteDemand)
973
    {
974
        return $this->settings['disableOverrideDemand'] != 1 && $overwriteDemand !== [];
975
    }
976
977
    /**
978
     * If no event is given and the singleEvent setting is set, the configured single event is returned
979
     *
980
     * @param Event|null $event
981
     * @return Event|null
982
     */
983
    protected function evaluateSingleEventSetting($event)
984
    {
985
        if ($event === null && (int)$this->settings['singleEvent'] > 0) {
986
            $event = $this->eventRepository->findByUid((int)$this->settings['singleEvent']);
987
        }
988
989
        return $event;
990
    }
991
992
    /**
993
     * If no event is given and the isShortcut setting is set, the event is displayed using the "Insert Record"
994
     * content element and should be loaded from contect object data
995
     *
996
     * @param Event|null $event
997
     * @return Event|null
998
     */
999
    protected function evaluateIsShortcutSetting($event)
1000
    {
1001
        if ($event === null && (bool)$this->settings['detail']['isShortcut']) {
1002
            $eventRawData = $this->configurationManager->getContentObject()->data;
1003
            $event = $this->eventRepository->findByUid($eventRawData['uid']);
1004
        }
1005
1006
        return $event;
1007
    }
1008
1009
    /**
1010
     * Checks if the event pid could be found in the storagePage settings of the detail plugin and
1011
     * if the pid could not be found it return null instead of the event object.
1012
     *
1013
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
1014
     * @return null|\DERHANSEN\SfEventMgt\Domain\Model\Event
1015
     */
1016
    protected function checkPidOfEventRecord(Event $event)
1017
    {
1018
        $allowedStoragePages = GeneralUtility::trimExplode(
1019
            ',',
1020
            Page::extendPidListByChildren(
1021
                $this->settings['storagePage'],
1022
                $this->settings['recursive']
1023
            ),
1024
            true
1025
        );
1026
        if (count($allowedStoragePages) > 0 && !in_array($event->getPid(), $allowedStoragePages)) {
1027
            $this->signalSlotDispatcher->dispatch(
1028
                __CLASS__,
1029
                'checkPidOfEventRecordFailedInDetailAction',
1030
                [
1031
                    'event' => $event,
1032
                    'eventController' => $this
1033
                ]
1034
            );
1035
            $event = null;
1036
        }
1037
1038
        return $event;
1039
    }
1040
1041
    /**
1042
     * Returns the current sys_language_uid
1043
     *
1044
     * @return int
1045
     */
1046
    protected function getSysLanguageUid()
1047
    {
1048
        return $GLOBALS['TSFE']->sys_language_uid;
1049
    }
1050
}
1051