Completed
Push — feature/780-waitlist-move-up ( 496c4e )
by Torben
44:36
created

EventController::initializeView()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
5
 *
6
 * For the full copyright and license information, please read the
7
 * LICENSE.txt file that was distributed with this source code.
8
 */
9
10
namespace DERHANSEN\SfEventMgt\Controller;
11
12
use DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand;
13
use DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand;
14
use DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand;
15
use DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand;
16
use DERHANSEN\SfEventMgt\Domain\Model\Event;
17
use DERHANSEN\SfEventMgt\Domain\Model\Registration;
18
use DERHANSEN\SfEventMgt\Event\AfterRegistrationConfirmedEvent;
19
use DERHANSEN\SfEventMgt\Event\AfterRegistrationSavedEvent;
20
use DERHANSEN\SfEventMgt\Event\EventPidCheckFailedEvent;
21
use DERHANSEN\SfEventMgt\Event\ModifyCalendarViewVariablesEvent;
22
use DERHANSEN\SfEventMgt\Event\ModifyCancelRegistrationViewVariablesEvent;
23
use DERHANSEN\SfEventMgt\Event\ModifyConfirmRegistrationViewVariablesEvent;
24
use DERHANSEN\SfEventMgt\Event\ModifyCreateDependingRegistrationsEvent;
25
use DERHANSEN\SfEventMgt\Event\ModifyDetailViewVariablesEvent;
26
use DERHANSEN\SfEventMgt\Event\ModifyListViewVariablesEvent;
27
use DERHANSEN\SfEventMgt\Event\ModifyRegistrationViewVariablesEvent;
28
use DERHANSEN\SfEventMgt\Event\ModifySearchViewVariablesEvent;
29
use DERHANSEN\SfEventMgt\Event\WaitlistMoveUpEvent;
30
use DERHANSEN\SfEventMgt\Service\EventCacheService;
31
use DERHANSEN\SfEventMgt\Utility\MessageType;
32
use DERHANSEN\SfEventMgt\Utility\Page;
33
use DERHANSEN\SfEventMgt\Utility\RegistrationResult;
34
use TYPO3\CMS\Core\Context\Context;
35
use TYPO3\CMS\Core\Http\ImmediateResponseException;
36
use TYPO3\CMS\Core\Utility\ArrayUtility;
37
use TYPO3\CMS\Core\Utility\GeneralUtility;
38
use TYPO3\CMS\Core\Utility\HttpUtility;
39
use TYPO3\CMS\Extbase\Annotation as Extbase;
40
use TYPO3\CMS\Extbase\Mvc\RequestInterface;
41
use TYPO3\CMS\Extbase\Mvc\ResponseInterface;
42
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
43
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
44
use TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter;
45
use TYPO3\CMS\Fluid\View\StandaloneView;
46
use TYPO3\CMS\Frontend\Controller\ErrorController;
47
48
/**
49
 * EventController
50
 *
51
 * @author Torben Hansen <[email protected]>
52
 */
53
class EventController extends AbstractController
54
{
55
    /**
56
     * @var EventCacheService
57
     */
58
    protected $eventCacheService;
59
60
    /**
61
     * @param EventCacheService $cacheService
62
     */
63
    public function injectEventCacheService(EventCacheService $cacheService)
64
    {
65
        $this->eventCacheService = $cacheService;
66
    }
67
68
    /**
69
     * Assign contentObjectData and pageData to earch view
70
     *
71
     * @param \TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view
72
     */
73
    protected function initializeView(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view)
74
    {
75
        $view->assign('contentObjectData', $this->configurationManager->getContentObject()->data);
76
        if (is_object($GLOBALS['TSFE'])) {
77
            $view->assign('pageData', $GLOBALS['TSFE']->page);
78
        }
79
        parent::initializeView($view);
80
    }
81
82
    /**
83
     * Initializes the current action
84
     */
85
    public function initializeAction()
86
    {
87
        $typoScriptFrontendController = $this->getTypoScriptFrontendController();
88
        if ($typoScriptFrontendController !== null) {
89
            static $cacheTagsSet = false;
90
91
            if (!$cacheTagsSet) {
92
                $typoScriptFrontendController->addCacheTags(['tx_sfeventmgt']);
93
                $cacheTagsSet = true;
94
            }
95
        }
96
    }
97
98
    /**
99
     * Creates an event demand object with the given settings
100
     *
101
     * @param array $settings The settings
102
     *
103
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand
104
     */
105
    public function createEventDemandObjectFromSettings(array $settings)
106
    {
107
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand */
108
        $demand = $this->objectManager->get(EventDemand::class);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated with message: since TYPO3 10.4, will be removed in version 12.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
109
        $demand->setDisplayMode($settings['displayMode']);
110
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
111
        $demand->setCategoryConjunction($settings['categoryConjunction']);
112
        $demand->setCategory($settings['category']);
113
        $demand->setIncludeSubcategories($settings['includeSubcategories']);
114
        $demand->setTopEventRestriction((int)$settings['topEventRestriction']);
115
        $demand->setOrderField($settings['orderField']);
116
        $demand->setOrderFieldAllowed($settings['orderFieldAllowed']);
117
        $demand->setOrderDirection($settings['orderDirection']);
118
        $demand->setQueryLimit($settings['queryLimit']);
119
        $demand->setLocation($settings['location']);
120
        $demand->setOrganisator($settings['organisator']);
121
        $demand->setSpeaker($settings['speaker']);
122
123
        return $demand;
124
    }
125
126
    /**
127
     * Creates a foreign record demand object with the given settings
128
     *
129
     * @param array $settings The settings
130
     *
131
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand
132
     */
133
    public function createForeignRecordDemandObjectFromSettings(array $settings)
134
    {
135
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand $demand */
136
        $demand = $this->objectManager->get(ForeignRecordDemand::class);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated with message: since TYPO3 10.4, will be removed in version 12.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
137
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
138
        $demand->setRestrictForeignRecordsToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
139
140
        return $demand;
141
    }
142
143
    /**
144
     * Creates a category demand object with the given settings
145
     *
146
     * @param array $settings The settings
147
     *
148
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand
149
     */
150
    public function createCategoryDemandObjectFromSettings(array $settings)
151
    {
152
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand $demand */
153
        $demand = $this->objectManager->get(CategoryDemand::class);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated with message: since TYPO3 10.4, will be removed in version 12.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
154
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
155
        $demand->setRestrictToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
156
        $demand->setCategories($settings['categoryMenu']['categories']);
157
        $demand->setIncludeSubcategories($settings['categoryMenu']['includeSubcategories']);
158
159
        return $demand;
160
    }
161
162
    /**
163
     * Hook into request processing and catch exceptions
164
     *
165
     * @param RequestInterface $request
166
     * @param ResponseInterface $response
167
     * @throws \Exception
168
     */
169
    public function processRequest(RequestInterface $request, ResponseInterface $response)
170
    {
171
        try {
172
            parent::processRequest($request, $response);
173
        } catch (\Exception $exception) {
174
            $this->handleKnownExceptionsElseThrowAgain($exception);
175
        }
176
    }
177
178
    /**
179
     * Handle known exceptions
180
     *
181
     * @param \Exception $exception
182
     * @throws \Exception
183
     */
184
    private function handleKnownExceptionsElseThrowAgain(\Exception $exception)
185
    {
186
        $previousException = $exception->getPrevious();
187
        $actions = ['detailAction', 'registrationAction', 'icalDownloadAction'];
188
        if (in_array($this->actionMethodName, $actions, true)
189
            && $previousException instanceof \TYPO3\CMS\Extbase\Property\Exception
190
        ) {
191
            $this->handleEventNotFoundError($this->settings);
192
        } else {
193
            throw $exception;
194
        }
195
    }
196
197
    /**
198
     * Initialize list action and set format
199
     */
200
    public function initializeListAction()
201
    {
202
        if (isset($this->settings['list']['format'])) {
203
            $this->request->setFormat($this->settings['list']['format']);
204
        }
205
    }
206
207
    /**
208
     * List view
209
     *
210
     * @param array $overwriteDemand OverwriteDemand
211
     */
212
    public function listAction(array $overwriteDemand = [])
213
    {
214
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
215
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
216
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
217
        if ($this->isOverwriteDemand($overwriteDemand)) {
218
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
219
        }
220
        $events = $this->eventRepository->findDemanded($eventDemand);
221
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
222
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
223
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
224
        $speakers = $this->speakerRepository->findDemanded($foreignRecordDemand);
225
226
        $modifyListViewVariablesEvent = new ModifyListViewVariablesEvent(
227
            [
228
                'events' => $events,
229
                'categories' => $categories,
230
                'locations' => $locations,
231
                'organisators' => $organisators,
232
                'speakers' => $speakers,
233
                'overwriteDemand' => $overwriteDemand,
234
                'eventDemand' => $eventDemand
235
            ],
236
            $this
237
        );
238
        $this->eventDispatcher->dispatch($modifyListViewVariablesEvent);
0 ignored issues
show
Documentation introduced by
$modifyListViewVariablesEvent is of type object<DERHANSEN\SfEvent...ListViewVariablesEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
239
        $variables = $modifyListViewVariablesEvent->getVariables();
240
        $this->view->assignMultiple($variables);
241
242
        $this->eventCacheService->addPageCacheTagsByEventDemandObject($eventDemand);
243
    }
244
245
    /**
246
     * Calendar view
247
     *
248
     * @param array $overwriteDemand OverwriteDemand
249
     */
250
    public function calendarAction(array $overwriteDemand = [])
251
    {
252
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
253
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
254
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
255
        if ($this->isOverwriteDemand($overwriteDemand)) {
256
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
257
        }
258
259
        // Set month/year to demand if not given
260
        if (!$eventDemand->getMonth()) {
261
            $currentMonth = date('n');
262
            $eventDemand->setMonth($currentMonth);
263
        } else {
264
            $currentMonth = $eventDemand->getMonth();
265
        }
266
        if (!$eventDemand->getYear()) {
267
            $currentYear = date('Y');
268
            $eventDemand->setYear($currentYear);
269
        } else {
270
            $currentYear = $eventDemand->getYear();
271
        }
272
273
        // Set demand from calendar date range instead of month / year
274
        if ((bool)$this->settings['calendar']['includeEventsForEveryDayOfAllCalendarWeeks']) {
275
            $eventDemand = $this->changeEventDemandToFullMonthDateRange($eventDemand);
276
        }
277
278
        $events = $this->eventRepository->findDemanded($eventDemand);
279
        $weeks = $this->calendarService->getCalendarArray(
280
            $currentMonth,
281
            $currentYear,
282
            strtotime('today midnight'),
283
            (int)$this->settings['calendar']['firstDayOfWeek'],
284
            $events
285
        );
286
287
        $modifyCalendarViewVariablesEvent = new ModifyCalendarViewVariablesEvent(
288
            [
289
                'events' => $events,
290
                'weeks' => $weeks,
291
                'categories' => $this->categoryRepository->findDemanded($categoryDemand),
292
                'locations' => $this->locationRepository->findDemanded($foreignRecordDemand),
293
                'organisators' => $this->organisatorRepository->findDemanded($foreignRecordDemand),
294
                'eventDemand' => $eventDemand,
295
                'overwriteDemand' => $overwriteDemand,
296
                'currentPageId' => $GLOBALS['TSFE']->id,
297
                'firstDayOfMonth' => \DateTime::createFromFormat(
298
                    'd.m.Y',
299
                    sprintf('1.%s.%s', $currentMonth, $currentYear)
300
                ),
301
                'previousMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '-1 month'),
302
                'nextMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '+1 month')
303
            ],
304
            $this
305
        );
306
        $this->eventDispatcher->dispatch($modifyCalendarViewVariablesEvent);
0 ignored issues
show
Documentation introduced by
$modifyCalendarViewVariablesEvent is of type object<DERHANSEN\SfEvent...ndarViewVariablesEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
307
        $variables = $modifyCalendarViewVariablesEvent->getVariables();
308
309
        $this->view->assignMultiple($variables);
310
    }
311
312
    /**
313
     * Changes the given event demand object to select a date range for a calendar month including days of the previous
314
     * month for the first week and they days for the next month for the last week
315
     *
316
     * @param EventDemand $eventDemand
317
     * @return EventDemand
318
     */
319
    protected function changeEventDemandToFullMonthDateRange(EventDemand $eventDemand)
320
    {
321
        $calendarDateRange = $this->calendarService->getCalendarDateRange(
322
            $eventDemand->getMonth(),
323
            $eventDemand->getYear(),
324
            $this->settings['calendar']['firstDayOfWeek']
325
        );
326
327
        $eventDemand->setMonth(0);
328
        $eventDemand->setYear(0);
329
330
        $startDate = new \DateTime();
331
        $startDate->setTimestamp($calendarDateRange['firstDayOfCalendar']);
332
        $endDate = new \DateTime();
333
        $endDate->setTimestamp($calendarDateRange['lastDayOfCalendar']);
334
        $endDate->setTime(23, 59, 59);
335
336
        $searchDemand = new SearchDemand();
337
        $searchDemand->setStartDate($startDate);
338
        $searchDemand->setEndDate($endDate);
339
        $eventDemand->setSearchDemand($searchDemand);
340
341
        return $eventDemand;
342
    }
343
344
    /**
345
     * Detail view for an event
346
     *
347
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
348
     * @return mixed string|void
349
     */
350
    public function detailAction(Event $event = null)
351
    {
352
        $event = $this->evaluateSingleEventSetting($event);
353
        $event = $this->evaluateIsShortcutSetting($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->evaluateIsShortcutSetting($event) on line 353 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...
354
        if (is_a($event, Event::class) && $this->settings['detail']['checkPidOfEventRecord']) {
355
            $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...
356
        }
357
358
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
359
            return $this->handleEventNotFoundError($this->settings);
360
        }
361
362
        $modifyDetailViewVariablesEvent = new ModifyDetailViewVariablesEvent(['event' => $event], $this);
363
        $this->eventDispatcher->dispatch($modifyDetailViewVariablesEvent);
0 ignored issues
show
Documentation introduced by
$modifyDetailViewVariablesEvent is of type object<DERHANSEN\SfEvent...tailViewVariablesEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
364
        $variables = $modifyDetailViewVariablesEvent->getVariables();
365
366
        $this->view->assignMultiple($variables);
367
        if ($event !== null) {
368
            $this->eventCacheService->addCacheTagsByEventRecords([$event]);
369
        }
370
    }
371
372
    /**
373
     * Error handling if event is not found
374
     *
375
     * @param array $settings
376
     * @return string
377
     */
378
    protected function handleEventNotFoundError($settings)
379
    {
380
        if (empty($settings['event']['errorHandling'])) {
381
            return null;
382
        }
383
384
        $configuration = GeneralUtility::trimExplode(',', $settings['event']['errorHandling'], true);
385
386
        switch ($configuration[0]) {
387
            case 'redirectToListView':
388
                $listPid = (int)$settings['listPid'] > 0 ? (int)$settings['listPid'] : 1;
389
                $this->redirect('list', null, null, null, $listPid);
390
                break;
391
            case 'pageNotFoundHandler':
392
                $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
393
                    $GLOBALS['TYPO3_REQUEST'],
394
                    'Event not found.'
395
                );
396
                throw new ImmediateResponseException($response, 1549896549734);
397
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
398
            case 'showStandaloneTemplate':
399
                if (isset($configuration[2])) {
400
                    $statusCode = constant(HttpUtility::class . '::HTTP_STATUS_' . $configuration[2]);
401
                    HttpUtility::setResponseCode($statusCode);
402
                }
403
                $standaloneTemplate = $this->objectManager->get(StandaloneView::class);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated with message: since TYPO3 10.4, will be removed in version 12.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
404
                $standaloneTemplate->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($configuration[1]));
405
406
                return $standaloneTemplate->render();
407
                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...
408
            default:
409
        }
410
    }
411
412
    /**
413
     * Initiates the iCalendar download for the given event
414
     *
415
     * @param Event $event The event
416
     *
417
     * @return string|false
418
     */
419
    public function icalDownloadAction(Event $event = null)
420
    {
421
        if (is_a($event, Event::class) && $this->settings['detail']['checkPidOfEventRecord']) {
422
            $event = $this->checkPidOfEventRecord($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 422 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...
423
        }
424
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
425
            return $this->handleEventNotFoundError($this->settings);
426
        }
427
        $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...
428
        exit();
429
    }
430
431
    /**
432
     * Registration view for an event
433
     *
434
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
435
     *
436
     * @return mixed string|void
437
     */
438
    public function registrationAction(Event $event = null)
439
    {
440
        $event = $this->evaluateSingleEventSetting($event);
441
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
442
            $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...
443
        }
444
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
445
            return $this->handleEventNotFoundError($this->settings);
446
        }
447
        if ($event->getRestrictPaymentMethods()) {
448
            $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...
449
        } else {
450
            $paymentMethods = $this->paymentService->getPaymentMethods();
451
        }
452
453
        $modifyRegistrationViewVariablesEvent = new ModifyRegistrationViewVariablesEvent(
454
            [
455
                'event' => $event,
456
                'paymentMethods' => $paymentMethods,
457
            ],
458
            $this
459
        );
460
        $this->eventDispatcher->dispatch($modifyRegistrationViewVariablesEvent);
0 ignored issues
show
Documentation introduced by
$modifyRegistrationViewVariablesEvent is of type object<DERHANSEN\SfEvent...tionViewVariablesEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
461
        $variables = $modifyRegistrationViewVariablesEvent->getVariables();
462
        $this->view->assignMultiple($variables);
463
    }
464
465
    /**
466
     * Removes all possible spamcheck fields (which do not belong to the domain model) from arguments.
467
     */
468
    protected function removePossibleSpamCheckFieldsFromArguments()
469
    {
470
        $arguments = $this->request->getArguments();
471
        if (!isset($arguments['event'])) {
472
            return;
473
        }
474
475
        // Remove a possible honeypot field
476
        $honeypotField = 'hp' . (int)$arguments['event'];
477
        if (isset($arguments['registration'][$honeypotField])) {
478
            unset($arguments['registration'][$honeypotField]);
479
        }
480
481
        // Remove a possible challenge/response field
482
        if (isset($arguments['registration']['cr-response'])) {
483
            unset($arguments['registration']['cr-response']);
484
        }
485
486
        $this->request->setArguments($arguments);
487
    }
488
489
    /**
490
     * Processes incoming registrations fields and adds field values to arguments
491
     */
492
    protected function setRegistrationFieldValuesToArguments()
493
    {
494
        $arguments = $this->request->getArguments();
495
        if (!isset($arguments['event'])) {
496
            return;
497
        }
498
499
        /** @var Event $event */
500
        $event = $this->eventRepository->findByUid((int)$this->request->getArgument('event'));
501
        if (!$event || $event->getRegistrationFields()->count() === 0) {
502
            return;
503
        }
504
505
        $registrationMvcArgument = $this->arguments->getArgument('registration');
506
        $propertyMapping = $registrationMvcArgument->getPropertyMappingConfiguration();
507
        $propertyMapping->allowProperties('fieldValues');
508
        $propertyMapping->allowCreationForSubProperty('fieldValues');
509
        $propertyMapping->allowModificationForSubProperty('fieldValues');
510
511
        // allow creation of new objects (for validation)
512
        $propertyMapping->setTypeConverterOptions(
513
            PersistentObjectConverter::class,
514
            [
515
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => true,
516
                PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED => true
517
            ]
518
        );
519
520
        // Set event to registration (required for validation)
521
        $propertyMapping->allowProperties('event');
522
        $propertyMapping->allowCreationForSubProperty('event');
523
        $propertyMapping->allowModificationForSubProperty('event');
524
        $arguments['registration']['event'] = (int)$this->request->getArgument('event');
525
526
        $index = 0;
527
        foreach ((array)$arguments['registration']['fields'] as $fieldUid => $value) {
528
            // Only accept registration fields of the current event
529
            if (!in_array((int)$fieldUid, $event->getRegistrationFieldsUids(), true)) {
530
                continue;
531
            }
532
533
            // allow subvalues in new property mapper
534
            $propertyMapping->forProperty('fieldValues')->allowProperties($index);
535
            $propertyMapping->forProperty('fieldValues.' . $index)->allowAllProperties();
536
            $propertyMapping->allowCreationForSubProperty('fieldValues.' . $index);
537
            $propertyMapping->allowModificationForSubProperty('fieldValues.' . $index);
538
539
            if (is_array($value)) {
540
                if (empty($value)) {
541
                    $value = '';
542
                } else {
543
                    $value = json_encode($value);
544
                }
545
            }
546
547
            /** @var Registration\Field $field */
548
            $field = $this->fieldRepository->findByUid((int)$fieldUid);
549
550
            $arguments['registration']['fieldValues'][$index] = [
551
                'pid' => $field->getPid(),
552
                'value' => $value,
553
                'field' => (string)$fieldUid,
554
                'valueType' => $field->getValueType()
555
            ];
556
557
            $index++;
558
        }
559
560
        // Remove temporary "fields" field
561
        if (isset($arguments['registration']['fields'])) {
562
            $arguments = ArrayUtility::removeByPath($arguments, 'registration/fields');
563
        }
564
        $this->request->setArguments($arguments);
565
    }
566
567
    /**
568
     * Set date format for field dateOfBirth
569
     */
570
    public function initializeSaveRegistrationAction()
571
    {
572
        $this->arguments->getArgument('registration')
573
            ->getPropertyMappingConfiguration()->forProperty('dateOfBirth')
574
            ->setTypeConverterOption(
575
                DateTimeConverter::class,
576
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
577
                $this->settings['registration']['formatDateOfBirth']
578
            );
579
        $this->removePossibleSpamCheckFieldsFromArguments();
580
        $this->setRegistrationFieldValuesToArguments();
581
    }
582
583
    /**
584
     * Saves the registration
585
     *
586
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
587
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
588
     * @Extbase\Validate("DERHANSEN\SfEventMgt\Validation\Validator\RegistrationFieldValidator", param="registration")
589
     * @Extbase\Validate("DERHANSEN\SfEventMgt\Validation\Validator\RegistrationValidator", param="registration")
590
     *
591
     * @return mixed string|void
592
     */
593
    public function saveRegistrationAction(Registration $registration, Event $event)
594
    {
595
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
596
            $event = $this->checkPidOfEventRecord($event);
597
        }
598
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
599
            return $this->handleEventNotFoundError($this->settings);
600
        }
601
        $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...
602
        $result = RegistrationResult::REGISTRATION_SUCCESSFUL;
603
        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...
604
605
        // Save registration if no errors
606
        if ($success) {
607
            $isWaitlistRegistration = $this->registrationService->isWaitlistRegistration(
608
                $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 596 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...
609
                $registration->getAmountOfRegistrations()
610
            );
611
            $linkValidity = (int)$this->settings['confirmation']['linkValidity'];
612
            if ($linkValidity === 0) {
613
                // Use 3600 seconds as default value if not set
614
                $linkValidity = 3600;
615
            }
616
            $confirmationUntil = new \DateTime();
617
            $confirmationUntil->add(new \DateInterval('PT' . $linkValidity . 'S'));
618
619
            $registration->setEvent($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 596 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...
620
            $registration->setPid($event->getPid());
621
            $registration->setRegistrationDate(new \DateTime());
622
            $registration->setConfirmationUntil($confirmationUntil);
623
            $registration->setLanguage($GLOBALS['TSFE']->config['config']['language']);
624
            $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...
625
            $registration->setWaitlist($isWaitlistRegistration);
626
            $registration->_setProperty('_languageUid', $this->getSysLanguageUid());
627
            $this->registrationRepository->add($registration);
628
629
            // Persist registration, so we have an UID
630
            $this->persistAll();
631
632
            if ($isWaitlistRegistration) {
633
                $messageType = MessageType::REGISTRATION_WAITLIST_NEW;
634
            } else {
635
                $messageType = MessageType::REGISTRATION_NEW;
636
            }
637
638
            // Fix event in registration for language other than default language
639
            $this->registrationService->fixRegistrationEvent($registration, $event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 596 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...
640
641
            // Fix language of registration fields if other than default language
642
            $this->registrationService->fixRegistationFieldValueLanguage($registration, $event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 596 can be null; however, DERHANSEN\SfEventMgt\Ser...ionFieldValueLanguage() 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...
643
644
            $this->eventDispatcher->dispatch(new AfterRegistrationSavedEvent($registration, $this));
0 ignored issues
show
Documentation introduced by
new \DERHANSEN\SfEventMg...t($registration, $this) is of type object<DERHANSEN\SfEvent...RegistrationSavedEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
645
646
            // Send notifications to user and admin if confirmation link should be sent
647
            if (!$autoConfirmation) {
648
                $this->notificationService->sendUserMessage(
649
                    $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 596 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...
650
                    $registration,
651
                    $this->settings,
652
                    $messageType
653
                );
654
                $this->notificationService->sendAdminMessage(
655
                    $event,
0 ignored issues
show
Bug introduced by
It seems like $event defined by $this->checkPidOfEventRecord($event) on line 596 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...
656
                    $registration,
657
                    $this->settings,
658
                    $messageType
659
                );
660
            }
661
662
            // Create given amount of registrations if necessary
663
            $modifyCreateDependingRegistrationsEvent = new ModifyCreateDependingRegistrationsEvent(
664
                $registration,
665
                ($registration->getAmountOfRegistrations() > 1),
666
                $this
667
            );
668
            $this->eventDispatcher->dispatch($modifyCreateDependingRegistrationsEvent);
0 ignored issues
show
Documentation introduced by
$modifyCreateDependingRegistrationsEvent is of type object<DERHANSEN\SfEvent...dingRegistrationsEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
669
            $createDependingRegistrations = $modifyCreateDependingRegistrationsEvent->getCreateDependingRegistrations();
670
            if ($createDependingRegistrations) {
671
                $this->registrationService->createDependingRegistrations($registration);
672
            }
673
674
            // Flush page cache for event, since new registration has been added
675
            $this->eventCacheService->flushEventCache($event->getUid(), $event->getPid());
676
        }
677
678
        if ($autoConfirmation && $success) {
679
            $this->redirect(
680
                'confirmRegistration',
681
                null,
682
                null,
683
                [
684
                    'reguid' => $registration->getUid(),
685
                    'hmac' => $this->hashService->generateHmac('reg-' . $registration->getUid())
686
                ]
687
            );
688
        } else {
689
            $this->redirect(
690
                'saveRegistrationResult',
691
                null,
692
                null,
693
                [
694
                    'result' => $result,
695
                    'eventuid' => $event->getUid(),
696
                    'hmac' => $this->hashService->generateHmac('event-' . $event->getUid())
697
                ]
698
            );
699
        }
700
    }
701
702
    /**
703
     * Shows the result of the saveRegistrationAction
704
     *
705
     * @param int $result Result
706
     * @param int $eventuid
707
     * @param string $hmac
708
     */
709
    public function saveRegistrationResultAction($result, $eventuid, $hmac)
710
    {
711
        $event = null;
712
713
        switch ($result) {
714
            case RegistrationResult::REGISTRATION_SUCCESSFUL:
715
                $messageKey = 'event.message.registrationsuccessful';
716
                $titleKey = 'registrationResult.title.successful';
717
                break;
718
            case RegistrationResult::REGISTRATION_SUCCESSFUL_WAITLIST:
719
                $messageKey = 'event.message.registrationwaitlistsuccessful';
720
                $titleKey = 'registrationWaitlistResult.title.successful';
721
                break;
722
            case RegistrationResult::REGISTRATION_FAILED_EVENT_EXPIRED:
723
                $messageKey = 'event.message.registrationfailedeventexpired';
724
                $titleKey = 'registrationResult.title.failed';
725
                break;
726
            case RegistrationResult::REGISTRATION_FAILED_MAX_PARTICIPANTS:
727
                $messageKey = 'event.message.registrationfailedmaxparticipants';
728
                $titleKey = 'registrationResult.title.failed';
729
                break;
730
            case RegistrationResult::REGISTRATION_NOT_ENABLED:
731
                $messageKey = 'event.message.registrationfailednotenabled';
732
                $titleKey = 'registrationResult.title.failed';
733
                break;
734
            case RegistrationResult::REGISTRATION_FAILED_DEADLINE_EXPIRED:
735
                $messageKey = 'event.message.registrationfaileddeadlineexpired';
736
                $titleKey = 'registrationResult.title.failed';
737
                break;
738
            case RegistrationResult::REGISTRATION_FAILED_NOT_ENOUGH_FREE_PLACES:
739
                $messageKey = 'event.message.registrationfailednotenoughfreeplaces';
740
                $titleKey = 'registrationResult.title.failed';
741
                break;
742
            case RegistrationResult::REGISTRATION_FAILED_MAX_AMOUNT_REGISTRATIONS_EXCEEDED:
743
                $messageKey = 'event.message.registrationfailedmaxamountregistrationsexceeded';
744
                $titleKey = 'registrationResult.title.failed';
745
                break;
746
            case RegistrationResult::REGISTRATION_FAILED_EMAIL_NOT_UNIQUE:
747
                $messageKey = 'event.message.registrationfailedemailnotunique';
748
                $titleKey = 'registrationResult.title.failed';
749
                break;
750
            default:
751
                $messageKey = '';
752
                $titleKey = '';
753
        }
754
755
        if (!$this->hashService->validateHmac('event-' . $eventuid, $hmac)) {
756
            $messageKey = 'event.message.registrationsuccessfulwrongeventhmac';
757
            $titleKey = 'registrationResult.title.failed';
758
        } else {
759
            $event = $this->eventRepository->findByUid((int)$eventuid);
760
        }
761
762
        $this->view->assignMultiple([
763
            'messageKey' => $messageKey,
764
            'titleKey' => $titleKey,
765
            'event' => $event,
766
        ]);
767
    }
768
769
    /**
770
     * Confirms the registration if possible and sends emails to admin and user
771
     *
772
     * @param int $reguid UID of registration
773
     * @param string $hmac HMAC for parameters
774
     */
775
    public function confirmRegistrationAction($reguid, $hmac)
776
    {
777
        $event = null;
778
779
        /* @var $registration Registration */
780
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkConfirmRegistration(
781
            $reguid,
782
            $hmac
783
        );
784
785
        if ($failed === false) {
786
            $registration->setConfirmed(true);
787
            $event = $registration->getEvent();
788
            $this->registrationRepository->update($registration);
789
790
            $this->eventDispatcher->dispatch(new AfterRegistrationConfirmedEvent($registration, $this));
0 ignored issues
show
Documentation introduced by
new \DERHANSEN\SfEventMg...t($registration, $this) is of type object<DERHANSEN\SfEvent...strationConfirmedEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
791
792
            $messageType = MessageType::REGISTRATION_CONFIRMED;
793
            if ($registration->getWaitlist()) {
794
                $messageType = MessageType::REGISTRATION_WAITLIST_CONFIRMED;
795
            }
796
797
            // Send notifications to user and admin
798
            $this->notificationService->sendUserMessage(
799
                $registration->getEvent(),
800
                $registration,
801
                $this->settings,
802
                $messageType
803
            );
804
            $this->notificationService->sendAdminMessage(
805
                $registration->getEvent(),
806
                $registration,
807
                $this->settings,
808
                $messageType
809
            );
810
811
            // Confirm registrations depending on main registration if necessary
812
            if ($registration->getAmountOfRegistrations() > 1) {
813
                $this->registrationService->confirmDependingRegistrations($registration);
814
            }
815
        }
816
817
        // Redirect to payment provider if payment/redirect is enabled
818
        $paymentPid = (int)$this->settings['paymentPid'];
819
        if (!$failed && $paymentPid > 0 && $this->registrationService->redirectPaymentEnabled($registration)) {
820
            $this->uriBuilder->reset()
821
                ->setTargetPageUid($paymentPid);
822
            $uri = $this->uriBuilder->uriFor(
823
                'redirect',
824
                [
825
                    'registration' => $registration,
826
                    'hmac' => $this->hashService->generateHmac('redirectAction-' . $registration->getUid())
827
                ],
828
                'Payment',
829
                'sfeventmgt',
830
                'Pipayment'
831
            );
832
            $this->redirectToUri($uri);
833
        }
834
835
        $modifyConfirmRegistrationViewVariablesEvent = new ModifyConfirmRegistrationViewVariablesEvent(
836
            [
837
                'failed' => $failed,
838
                'messageKey' => $messageKey,
839
                'titleKey' => $titleKey,
840
                'event' => $event,
841
                'registration' => $registration,
842
            ],
843
            $this
844
        );
845
        $this->eventDispatcher->dispatch($modifyConfirmRegistrationViewVariablesEvent);
0 ignored issues
show
Documentation introduced by
$modifyConfirmRegistrationViewVariablesEvent is of type object<DERHANSEN\SfEvent...tionViewVariablesEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
846
        $variables = $modifyConfirmRegistrationViewVariablesEvent->getVariables();
847
        $this->view->assignMultiple($variables);
848
    }
849
850
    /**
851
     * Cancels the registration if possible and sends emails to admin and user
852
     *
853
     * @param int $reguid UID of registration
854
     * @param string $hmac HMAC for parameters
855
     */
856
    public function cancelRegistrationAction($reguid, $hmac)
857
    {
858
        $event = null;
859
860
        /* @var $registration Registration */
861
        list($failed, $registration, $messageKey, $titleKey) =
862
            $this->registrationService->checkCancelRegistration($reguid, $hmac);
863
864
        if ($failed === false) {
865
            $event = $registration->getEvent();
866
867
            // Send notifications (must run before cancelling the registration)
868
            $this->notificationService->sendUserMessage(
869
                $registration->getEvent(),
870
                $registration,
871
                $this->settings,
872
                MessageType::REGISTRATION_CANCELLED
873
            );
874
            $this->notificationService->sendAdminMessage(
875
                $registration->getEvent(),
876
                $registration,
877
                $this->settings,
878
                MessageType::REGISTRATION_CANCELLED
879
            );
880
881
            // First cancel depending registrations
882
            if ($registration->getAmountOfRegistrations() > 1) {
883
                $this->registrationService->cancelDependingRegistrations($registration);
884
            }
885
886
            // Finally cancel registration
887
            $this->registrationRepository->remove($registration);
888
889
            // Persist changes, so following functions can work with $event properties (e.g. amount of registrations)
890
            $this->persistAll();
891
892
            // Dispatch event, so waitlist registrations can be moved up
893
            $this->eventDispatcher->dispatch(new WaitlistMoveUpEvent($event, $this));
0 ignored issues
show
Documentation introduced by
new \DERHANSEN\SfEventMg...eUpEvent($event, $this) is of type object<DERHANSEN\SfEvent...nt\WaitlistMoveUpEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
894
895
            // Move up waitlist registrations if configured on event basis
896
            $this->registrationService->moveUpWaitlistRegistrations($event, $this->settings);
897
898
            // Flush page cache for event, since amount of registrations has changed
899
            $this->eventCacheService->flushEventCache($event->getUid(), $event->getPid());
900
        }
901
902
        $modifyCancelRegistrationViewVariablesEvent = new ModifyCancelRegistrationViewVariablesEvent(
903
            [
904
                'failed' => $failed,
905
                'messageKey' => $messageKey,
906
                'titleKey' => $titleKey,
907
                'event' => $event,
908
            ],
909
            $this
910
        );
911
        $this->eventDispatcher->dispatch($modifyCancelRegistrationViewVariablesEvent);
0 ignored issues
show
Documentation introduced by
$modifyCancelRegistrationViewVariablesEvent is of type object<DERHANSEN\SfEvent...tionViewVariablesEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
912
        $variables = $modifyCancelRegistrationViewVariablesEvent->getVariables();
913
        $this->view->assignMultiple($variables);
914
    }
915
916
    /**
917
     * Set date format for field startDate and endDate
918
     */
919
    public function initializeSearchAction()
920
    {
921
        if ($this->settings !== null && $this->settings['search']['dateFormat']) {
922
            $this->arguments->getArgument('searchDemand')
923
                ->getPropertyMappingConfiguration()->forProperty('startDate')
924
                ->setTypeConverterOption(
925
                    DateTimeConverter::class,
926
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
927
                    $this->settings['search']['dateFormat']
928
                );
929
            $this->arguments->getArgument('searchDemand')
930
                ->getPropertyMappingConfiguration()->forProperty('endDate')
931
                ->setTypeConverterOption(
932
                    DateTimeConverter::class,
933
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
934
                    $this->settings['search']['dateFormat']
935
                );
936
        }
937
        if ($this->arguments->hasArgument('searchDemand')) {
938
            $propertyMappingConfiguration = $this->arguments->getArgument('searchDemand')
939
                ->getPropertyMappingConfiguration();
940
            $propertyMappingConfiguration->allowAllProperties();
941
            $propertyMappingConfiguration->setTypeConverterOption(
942
                PersistentObjectConverter::class,
943
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED,
944
                true
945
            );
946
        }
947
    }
948
949
    /**
950
     * Search view
951
     *
952
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand $searchDemand SearchDemand
953
     * @param array $overwriteDemand OverwriteDemand
954
     */
955
    public function searchAction(SearchDemand $searchDemand = null, array $overwriteDemand = [])
956
    {
957
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
958
        $eventDemand->setSearchDemand($searchDemand);
0 ignored issues
show
Bug introduced by
It seems like $searchDemand defined by parameter $searchDemand on line 955 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...
959
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
960
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
961
962
        if ($searchDemand !== null) {
963
            $searchDemand->setFields($this->settings['search']['fields']);
964
965
            if ($this->settings['search']['adjustTime'] && $searchDemand->getStartDate() !== null) {
966
                $searchDemand->getStartDate()->setTime(0, 0, 0);
967
            }
968
969
            if ($this->settings['search']['adjustTime'] && $searchDemand->getEndDate() !== null) {
970
                $searchDemand->getEndDate()->setTime(23, 59, 59);
971
            }
972
        }
973
974
        if ($this->isOverwriteDemand($overwriteDemand)) {
975
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
976
        }
977
978
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
979
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
980
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
981
        $speakers = $this->speakerRepository->findDemanded($foreignRecordDemand);
982
        $events = $this->eventRepository->findDemanded($eventDemand);
983
984
        $modifySearchViewVariablesEvent = new ModifySearchViewVariablesEvent(
985
            [
986
                'events' => $events,
987
                'categories' => $categories,
988
                'locations' => $locations,
989
                'organisators' => $organisators,
990
                'speakers' => $speakers,
991
                'searchDemand' => $searchDemand,
992
                'overwriteDemand' => $overwriteDemand,
993
            ],
994
            $this
995
        );
996
        $this->eventDispatcher->dispatch($modifySearchViewVariablesEvent);
0 ignored issues
show
Documentation introduced by
$modifySearchViewVariablesEvent is of type object<DERHANSEN\SfEvent...archViewVariablesEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
997
        $variables = $modifySearchViewVariablesEvent->getVariables();
998
        $this->view->assignMultiple($variables);
999
    }
1000
1001
    /**
1002
     * Returns if a demand object can be overwritten with the given overwriteDemand array
1003
     *
1004
     * @param array $overwriteDemand
1005
     * @return bool
1006
     */
1007
    protected function isOverwriteDemand($overwriteDemand)
1008
    {
1009
        return $this->settings['disableOverrideDemand'] != 1 && $overwriteDemand !== [];
1010
    }
1011
1012
    /**
1013
     * If no event is given and the singleEvent setting is set, the configured single event is returned
1014
     *
1015
     * @param Event|null $event
1016
     * @return Event|null
1017
     */
1018
    protected function evaluateSingleEventSetting($event)
1019
    {
1020
        if ($event === null && (int)$this->settings['singleEvent'] > 0) {
1021
            $event = $this->eventRepository->findByUid((int)$this->settings['singleEvent']);
1022
        }
1023
1024
        return $event;
1025
    }
1026
1027
    /**
1028
     * If no event is given and the isShortcut setting is set, the event is displayed using the "Insert Record"
1029
     * content element and should be loaded from contect object data
1030
     *
1031
     * @param Event|null $event
1032
     * @return Event|null
1033
     */
1034
    protected function evaluateIsShortcutSetting($event)
1035
    {
1036
        if ($event === null && (bool)$this->settings['detail']['isShortcut']) {
1037
            $eventRawData = $this->configurationManager->getContentObject()->data;
1038
            $event = $this->eventRepository->findByUid($eventRawData['uid']);
1039
        }
1040
1041
        return $event;
1042
    }
1043
1044
    /**
1045
     * Checks if the event pid could be found in the storagePage settings of the detail plugin and
1046
     * if the pid could not be found it return null instead of the event object.
1047
     *
1048
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
1049
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Event|null
1050
     */
1051
    protected function checkPidOfEventRecord(Event $event)
1052
    {
1053
        $allowedStoragePages = GeneralUtility::trimExplode(
1054
            ',',
1055
            Page::extendPidListByChildren(
1056
                $this->settings['storagePage'],
1057
                $this->settings['recursive']
1058
            ),
1059
            true
1060
        );
1061
        if (count($allowedStoragePages) > 0 && !in_array($event->getPid(), $allowedStoragePages)) {
1062
            $this->eventDispatcher->dispatch(new EventPidCheckFailedEvent($event, $this));
0 ignored issues
show
Documentation introduced by
new \DERHANSEN\SfEventMg...ledEvent($event, $this) is of type object<DERHANSEN\SfEvent...entPidCheckFailedEvent>, but the function expects a object<Psr\EventDispatcher\object>.

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...
1063
            $event = null;
1064
        }
1065
1066
        return $event;
1067
    }
1068
1069
    /**
1070
     * Calls persistAll() of the persistenceManager
1071
     */
1072
    protected function persistAll()
1073
    {
1074
        $this->objectManager->get(PersistenceManager::class)->persistAll();
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated with message: since TYPO3 10.4, will be removed in version 12.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1075
    }
1076
1077
    /**
1078
     * Returns the current sys_language_uid
1079
     *
1080
     * @return int
1081
     */
1082
    protected function getSysLanguageUid()
1083
    {
1084
        $languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
1085
1086
        return $languageAspect->getId();
1087
    }
1088
}
1089