Completed
Push — master ( 70dfe1...a97a1c )
by Torben
04:18
created

EventController::detailAction()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 16
cts 16
cp 1
rs 8.9617
c 0
b 0
f 0
cc 6
nc 6
nop 1
crap 6
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 2
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
138
        $demand->setRestrictForeignRecordsToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
139
140 2
        return $demand;
141 2
    }
142 2
143 2
    /**
144 2
     * Creates a category demand object with the given settings
145 2
     *
146 2
     * @param array $settings The settings
147 2
     *
148 2
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand
149 2
     */
150 2
    public function createCategoryDemandObjectFromSettings(array $settings)
151 2
    {
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 2
178
    /**
179
     * Handle known exceptions
180 2
     *
181 2
     * @param \Exception $exception
182 2
     * @throws \Exception
183 2
     */
184 2
    private function handleKnownExceptionsElseThrowAgain(\Exception $exception)
185 2
    {
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 4
197
    /**
198 4
     * Initialize list action and set format
199 4
     */
200 4
    public function initializeListAction()
201
    {
202 4
        if (isset($this->settings['list']['format'])) {
203 4
            $this->request->setFormat($this->settings['list']['format']);
204 2
        }
205
    }
206 4
207 4
    /**
208 4
     * 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 6
                'locations' => $locations,
231
                'organisators' => $organisators,
232 6
                'speakers' => $speakers,
233 6
                'overwriteDemand' => $overwriteDemand,
234 6
                'eventDemand' => $eventDemand
235 6
            ],
236 2
            $this
237 2
        );
238 6
        $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 6
        $variables = $modifyListViewVariablesEvent->getVariables();
240 6
        $this->view->assignMultiple($variables);
241 6
242 6
        $this->eventCacheService->addPageCacheTagsByEventDemandObject($eventDemand);
243 6
    }
244 6
245 6
    /**
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 2
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
255
        if ($this->isOverwriteDemand($overwriteDemand)) {
256 2
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
257 2
        }
258
259
        // Set month/year to demand if not given
260
        if (!$eventDemand->getMonth()) {
261
            $currentMonth = date('n');
262
            $eventDemand->setMonth($currentMonth);
263
        } else {
264
            $currentMonth = $eventDemand->getMonth();
265
        }
266 2
        if (!$eventDemand->getYear()) {
267
            $currentYear = date('Y');
268 2
            $eventDemand->setYear($currentYear);
269 2
        } else {
270
            $currentYear = $eventDemand->getYear();
271
        }
272
273
        // Set demand from calendar date range instead of month / year
274
        if ((bool)$this->settings['calendar']['includeEventsForEveryDayOfAllCalendarWeeks']) {
275
            $eventDemand = $this->changeEventDemandToFullMonthDateRange($eventDemand);
276
        }
277
278
        $events = $this->eventRepository->findDemanded($eventDemand);
279 2
        $weeks = $this->calendarService->getCalendarArray(
280
            $currentMonth,
281 2
            $currentYear,
282
            strtotime('today midnight'),
283
            (int)$this->settings['calendar']['firstDayOfWeek'],
284 2
            $events
285
        );
286 2
287 2
        $modifyCalendarViewVariablesEvent = new ModifyCalendarViewVariablesEvent(
288 2
            [
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 2
                'overwriteDemand' => $overwriteDemand,
296
                'currentPageId' => $GLOBALS['TSFE']->id,
297 2
                'firstDayOfMonth' => \DateTime::createFromFormat(
298 2
                    'd.m.Y',
299 2
                    sprintf('1.%s.%s', $currentMonth, $currentYear)
300 2
                ),
301 2
                'previousMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '-1 month'),
302 2
                'nextMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '+1 month')
303 2
            ],
304 2
            $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 22
     *
316
     * @param EventDemand $eventDemand
317 22
     * @return EventDemand
318 22
     */
319 22
    protected function changeEventDemandToFullMonthDateRange(EventDemand $eventDemand)
320
    {
321
        $calendarDateRange = $this->calendarService->getCalendarDateRange(
322 22
            $eventDemand->getMonth(),
323 8
            $eventDemand->getYear(),
324 8
            $this->settings['calendar']['firstDayOfWeek']
325 8
        );
326 8
327 8
        $eventDemand->setMonth(0);
328 8
        $eventDemand->setYear(0);
329
330 8
        $startDate = new \DateTime();
331 8
        $startDate->setTimestamp($calendarDateRange['firstDayOfCalendar']);
332 8
        $endDate = new \DateTime();
333 8
        $endDate->setTimestamp($calendarDateRange['lastDayOfCalendar']);
334
        $endDate->setTime(23, 59, 59);
335 8
336 8
        $searchDemand = new SearchDemand();
337 8
        $searchDemand->setStartDate($startDate);
338 8
        $searchDemand->setEndDate($endDate);
339 8
        $eventDemand->setSearchDemand($searchDemand);
340 8
341 8
        return $eventDemand;
342 8
    }
343
344
    /**
345 8
     * Detail view for an event
346
     *
347
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
348 8
     * @return mixed string|void
349 2
     */
350 2
    public function detailAction(Event $event = null)
351 2
    {
352 6
        $event = $this->evaluateSingleEventSetting($event);
353 6
        $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 8
            $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 8
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
359 6
            return $this->handleEventNotFoundError($this->settings);
360 6
        }
361 6
362 6
        $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 6
        $variables = $modifyDetailViewVariablesEvent->getVariables();
365 6
366 6
        $this->view->assignMultiple($variables);
367 6
        if ($event !== null) {
368 6
            $this->eventCacheService->addCacheTagsByEventRecords([$event]);
369
        }
370 6
    }
371 6
372
    /**
373
     * Error handling if event is not found
374 8
     *
375 2
     * @param array $settings
376 2
     * @return string
377
     */
378
    protected function handleEventNotFoundError($settings)
379 8
    {
380 8
        if (empty($settings['event']['errorHandling'])) {
381
            return null;
382 22
        }
383 2
384 2
        $configuration = GeneralUtility::trimExplode(',', $settings['event']['errorHandling'], true);
385 2
386 2
        switch ($configuration[0]) {
387
            case 'redirectToListView':
388 2
                $listPid = (int)$settings['listPid'] > 0 ? (int)$settings['listPid'] : 1;
389 2
                $this->redirect('list', null, null, null, $listPid);
390 2
                break;
391 2
            case 'pageNotFoundHandler':
392 2
                $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
393 20
                    $GLOBALS['TYPO3_REQUEST'],
394 20
                    'Event not found.'
395 20
                );
396 20
                throw new ImmediateResponseException($response, 1549896549734);
397 20
                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 20
            case 'showStandaloneTemplate':
399
                if (isset($configuration[2])) {
400 22
                    $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 18
        }
410
    }
411
412 18
    /**
413 2
     * Initiates the iCalendar download for the given event
414 2
     *
415 2
     * @param Event $event The event
416 16
     *
417
     * @return string|false
418
     */
419
    public function icalDownloadAction(Event $event = null)
420 16
    {
421 2
        if (is_a($event, Event::class) && $this->settings['detail']['checkPidOfEventRecord']) {
422 2
            $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 2
        }
424 14
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
425 2
            return $this->handleEventNotFoundError($this->settings);
426 2
        }
427 2
        $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 12
        exit();
429 2
    }
430 2
431 2
    /**
432 10
     * Registration view for an event
433 2
     *
434 2
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
435 2
     *
436 8
     * @return mixed string|void
437 2
     */
438 2
    public function registrationAction(Event $event = null)
439 2
    {
440 6
        $event = $this->evaluateSingleEventSetting($event);
441 2
        if (is_a($event, Event::class) && $this->settings['registration']['checkPidOfEventRecord']) {
442 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...
443 2
        }
444 4
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
445 2
            return $this->handleEventNotFoundError($this->settings);
446 2
        }
447 2
        if ($event->getRestrictPaymentMethods()) {
448 2
            $paymentMethods = $this->paymentService->getRestrictedPaymentMethods($event);
0 ignored issues
show
Documentation introduced by
$event is of type object|null, but the function expects a object<DERHANSEN\SfEventMgt\Domain\Model\Event>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
449 2
        } else {
450 2
            $paymentMethods = $this->paymentService->getPaymentMethods();
451 2
        }
452
453 18
        $modifyRegistrationViewVariablesEvent = new ModifyRegistrationViewVariablesEvent(
454 18
            [
455 18
                '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 6
    /**
466
     * Removes all possible spamcheck fields (which do not belong to the domain model) from arguments.
467
     */
468 6
    protected function removePossibleSpamCheckFieldsFromArguments()
469
    {
470 6
        $arguments = $this->request->getArguments();
471 4
        if (!isset($arguments['event'])) {
472 4
            return;
473
        }
474 4
475 4
        // Remove a possible honeypot field
476 2
        $honeypotField = 'hp' . (int)$arguments['event'];
477 2
        if (isset($arguments['registration'][$honeypotField])) {
478
            unset($arguments['registration'][$honeypotField]);
479
        }
480 4
481 4
        // Remove a possible challenge/response field
482 4
        if (isset($arguments['registration']['cr-response'])) {
483 4
            unset($arguments['registration']['cr-response']);
484
        }
485 4
486 4
        $this->request->setArguments($arguments);
487 4
    }
488 4
489 4
    /**
490
     * Processes incoming registrations fields and adds field values to arguments
491 4
     */
492
    protected function setRegistrationFieldValuesToArguments()
493
    {
494 4
        $arguments = $this->request->getArguments();
495 4
        if (!isset($arguments['event'])) {
496 4
            return;
497 4
        }
498
499
        /** @var Event $event */
500 6
        $event = $this->eventRepository->findByUid((int)$this->request->getArgument('event'));
501 6
        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 6
        );
519 6
520 6
        // 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 4
                continue;
531
            }
532
533 4
            // allow subvalues in new property mapper
534
            $propertyMapping->forProperty('fieldValues')->allowProperties($index);
535 4
            $propertyMapping->forProperty('fieldValues.' . $index)->allowAllProperties();
536
            $propertyMapping->allowCreationForSubProperty('fieldValues.' . $index);
537 2
            $propertyMapping->allowModificationForSubProperty('fieldValues.' . $index);
538 2
539 2
            if (is_array($value)) {
540 2
                if (empty($value)) {
541
                    $value = '';
542 2
                } else {
543 2
                    $value = json_encode($value);
544 2
                }
545 2
            }
546 2
547
            /** @var Registration\Field $field */
548 2
            $field = $this->fieldRepository->findByUid((int)$fieldUid);
549
550
            $arguments['registration']['fieldValues'][$index] = [
551 2
                'pid' => $field->getPid(),
552 2
                'value' => $value,
553 2
                'field' => (string)$fieldUid,
554
                'valueType' => $field->getValueType()
555
            ];
556 2
557
            $index++;
558
        }
559 2
560 2
        // Remove temporary "fields" field
561 4
        if (isset($arguments['registration']['fields'])) {
562 4
            $arguments = ArrayUtility::removeByPath($arguments, 'registration/fields');
563 4
        }
564
        $this->request->setArguments($arguments);
565
    }
566
567
    /**
568
     * Set date format for field dateOfBirth
569
     */
570 2
    public function initializeSaveRegistrationAction()
571
    {
572 2
        $this->arguments->getArgument('registration')
573 2
            ->getPropertyMappingConfiguration()->forProperty('dateOfBirth')
574 2
            ->setTypeConverterOption(
575 2
                DateTimeConverter::class,
576 2
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
577 2
                $this->settings['registration']['formatDateOfBirth']
578 2
            );
579 2
        $this->removePossibleSpamCheckFieldsFromArguments();
580 2
        $this->setRegistrationFieldValuesToArguments();
581 2
    }
582 2
583 2
    /**
584 2
     * Saves the registration
585 2
     *
586 2
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
587 2
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
588 2
     * @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 12
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
599
            return $this->handleEventNotFoundError($this->settings);
600 12
        }
601 12
        $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 12
        $result = RegistrationResult::REGISTRATION_SUCCESSFUL;
603 12
        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 12
        // Save registration if no errors
606 10
        if ($success) {
607
            $isWaitlistRegistration = $this->registrationService->isWaitlistRegistration(
608 10
                $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 2
                $registration->getAmountOfRegistrations()
610 2
            );
611
            $linkValidity = (int)$this->settings['confirmation']['linkValidity'];
612 10
            if ($linkValidity === 0) {
613 2
                // Use 3600 seconds as default value if not set
614 2
                $linkValidity = 3600;
615 10
            }
616
            $confirmationUntil = new \DateTime();
617 12
            $confirmationUntil->add(new \DateInterval('PT' . $linkValidity . 'S'));
618 2
619 2
            $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 12
            $registration->setConfirmationUntil($confirmationUntil);
622 12
            $registration->setLanguage($GLOBALS['TSFE']->config['config']['language']);
623
            $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...
624 12
            $registration->setWaitlist($isWaitlistRegistration);
625
            $registration->_setProperty('_languageUid', $this->getSysLanguageUid());
626 12
            $this->registrationRepository->add($registration);
627 12
628 12
            // Persist registration, so we have an UID
629 12
            $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...
630 12
631 12
            if ($isWaitlistRegistration) {
632
                $messageType = MessageType::REGISTRATION_WAITLIST_NEW;
633
            } else {
634
                $messageType = MessageType::REGISTRATION_NEW;
635
            }
636
637
            // Fix event in registration for language other than default language
638
            $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...
639 18
640
            // Fix language of registration fields if other than default language
641 18
            $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...
642
643
            $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...
644
645
            // Send notifications to user and admin if confirmation link should be sent
646
            if (!$autoConfirmation) {
647
                $this->notificationService->sendUserMessage(
648
                    $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...
649
                    $registration,
650
                    $this->settings,
651
                    $messageType
652
                );
653
                $this->notificationService->sendAdminMessage(
654
                    $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...
655
                    $registration,
656
                    $this->settings,
657
                    $messageType
658
                );
659
            }
660
661
            // Create given amount of registrations if necessary
662
            $modifyCreateDependingRegistrationsEvent = new ModifyCreateDependingRegistrationsEvent(
663
                $registration,
664
                ($registration->getAmountOfRegistrations() > 1),
665
                $this
666
            );
667
            $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...
668
            $createDependingRegistrations = $modifyCreateDependingRegistrationsEvent->getCreateDependingRegistrations();
669
            if ($createDependingRegistrations) {
670
                $this->registrationService->createDependingRegistrations($registration);
671
            }
672
673
            // Flush page cache for event, since new registration has been added
674
            $this->eventCacheService->flushEventCache($event->getUid(), $event->getPid());
675
        }
676
677
        if ($autoConfirmation && $success) {
678
            $this->redirect(
679
                'confirmRegistration',
680
                null,
681
                null,
682
                [
683
                    'reguid' => $registration->getUid(),
684
                    'hmac' => $this->hashService->generateHmac('reg-' . $registration->getUid())
685
                ]
686
            );
687
        } else {
688
            $this->redirect(
689
                'saveRegistrationResult',
690
                null,
691
                null,
692
                [
693
                    'result' => $result,
694
                    'eventuid' => $event->getUid(),
695
                    'hmac' => $this->hashService->generateHmac('event-' . $event->getUid())
696
                ]
697
            );
698
        }
699
    }
700
701
    /**
702
     * Shows the result of the saveRegistrationAction
703
     *
704
     * @param int $result Result
705
     * @param int $eventuid
706
     * @param string $hmac
707
     */
708
    public function saveRegistrationResultAction($result, $eventuid, $hmac)
709
    {
710
        $event = null;
711
712
        switch ($result) {
713
            case RegistrationResult::REGISTRATION_SUCCESSFUL:
714
                $messageKey = 'event.message.registrationsuccessful';
715
                $titleKey = 'registrationResult.title.successful';
716
                break;
717
            case RegistrationResult::REGISTRATION_SUCCESSFUL_WAITLIST:
718
                $messageKey = 'event.message.registrationwaitlistsuccessful';
719
                $titleKey = 'registrationWaitlistResult.title.successful';
720
                break;
721
            case RegistrationResult::REGISTRATION_FAILED_EVENT_EXPIRED:
722
                $messageKey = 'event.message.registrationfailedeventexpired';
723
                $titleKey = 'registrationResult.title.failed';
724
                break;
725
            case RegistrationResult::REGISTRATION_FAILED_MAX_PARTICIPANTS:
726
                $messageKey = 'event.message.registrationfailedmaxparticipants';
727
                $titleKey = 'registrationResult.title.failed';
728
                break;
729
            case RegistrationResult::REGISTRATION_NOT_ENABLED:
730
                $messageKey = 'event.message.registrationfailednotenabled';
731
                $titleKey = 'registrationResult.title.failed';
732
                break;
733
            case RegistrationResult::REGISTRATION_FAILED_DEADLINE_EXPIRED:
734
                $messageKey = 'event.message.registrationfaileddeadlineexpired';
735
                $titleKey = 'registrationResult.title.failed';
736
                break;
737
            case RegistrationResult::REGISTRATION_FAILED_NOT_ENOUGH_FREE_PLACES:
738
                $messageKey = 'event.message.registrationfailednotenoughfreeplaces';
739
                $titleKey = 'registrationResult.title.failed';
740
                break;
741
            case RegistrationResult::REGISTRATION_FAILED_MAX_AMOUNT_REGISTRATIONS_EXCEEDED:
742
                $messageKey = 'event.message.registrationfailedmaxamountregistrationsexceeded';
743
                $titleKey = 'registrationResult.title.failed';
744
                break;
745
            case RegistrationResult::REGISTRATION_FAILED_EMAIL_NOT_UNIQUE:
746
                $messageKey = 'event.message.registrationfailedemailnotunique';
747
                $titleKey = 'registrationResult.title.failed';
748
                break;
749
            default:
750
                $messageKey = '';
751
                $titleKey = '';
752
        }
753
754
        if (!$this->hashService->validateHmac('event-' . $eventuid, $hmac)) {
755
            $messageKey = 'event.message.registrationsuccessfulwrongeventhmac';
756
            $titleKey = 'registrationResult.title.failed';
757
        } else {
758
            $event = $this->eventRepository->findByUid((int)$eventuid);
759
        }
760
761
        $this->view->assignMultiple([
762
            'messageKey' => $messageKey,
763
            'titleKey' => $titleKey,
764
            'event' => $event,
765
        ]);
766
    }
767
768
    /**
769
     * Confirms the registration if possible and sends emails to admin and user
770
     *
771
     * @param int $reguid UID of registration
772
     * @param string $hmac HMAC for parameters
773
     */
774
    public function confirmRegistrationAction($reguid, $hmac)
775
    {
776
        $event = null;
777
778
        /* @var $registration Registration */
779
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkConfirmRegistration(
780
            $reguid,
781
            $hmac
782
        );
783
784
        if ($failed === false) {
785
            $registration->setConfirmed(true);
786
            $event = $registration->getEvent();
787
            $this->registrationRepository->update($registration);
788
789
            $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...
790
791
            $messageType = MessageType::REGISTRATION_CONFIRMED;
792
            if ($registration->getWaitlist()) {
793
                $messageType = MessageType::REGISTRATION_WAITLIST_CONFIRMED;
794
            }
795
796
            // Send notifications to user and admin
797
            $this->notificationService->sendUserMessage(
798
                $registration->getEvent(),
799
                $registration,
800
                $this->settings,
801
                $messageType
802
            );
803
            $this->notificationService->sendAdminMessage(
804
                $registration->getEvent(),
805
                $registration,
806
                $this->settings,
807
                $messageType
808
            );
809
810
            // Confirm registrations depending on main registration if necessary
811
            if ($registration->getAmountOfRegistrations() > 1) {
812
                $this->registrationService->confirmDependingRegistrations($registration);
813
            }
814
        }
815
816
        // Redirect to payment provider if payment/redirect is enabled
817
        $paymentPid = (int)$this->settings['paymentPid'];
818
        if (!$failed && $paymentPid > 0 && $this->registrationService->redirectPaymentEnabled($registration)) {
819
            $this->uriBuilder->reset()
820
                ->setTargetPageUid($paymentPid);
821
            $uri = $this->uriBuilder->uriFor(
822
                'redirect',
823
                [
824
                    'registration' => $registration,
825
                    'hmac' => $this->hashService->generateHmac('redirectAction-' . $registration->getUid())
826
                ],
827
                'Payment',
828
                'sfeventmgt',
829
                'Pipayment'
830
            );
831
            $this->redirectToUri($uri);
832
        }
833
834
        $modifyConfirmRegistrationViewVariablesEvent = new ModifyConfirmRegistrationViewVariablesEvent(
835
            [
836
                'failed' => $failed,
837
                'messageKey' => $messageKey,
838
                'titleKey' => $titleKey,
839
                'event' => $event,
840
                'registration' => $registration,
841
            ],
842
            $this
843
        );
844
        $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...
845
        $variables = $modifyConfirmRegistrationViewVariablesEvent->getVariables();
846
        $this->view->assignMultiple($variables);
847
    }
848
849
    /**
850
     * Cancels the registration if possible and sends emails to admin and user
851
     *
852
     * @param int $reguid UID of registration
853
     * @param string $hmac HMAC for parameters
854
     */
855
    public function cancelRegistrationAction($reguid, $hmac)
856
    {
857
        $event = null;
858
859
        /* @var $registration Registration */
860
        list($failed, $registration, $messageKey, $titleKey) =
861
            $this->registrationService->checkCancelRegistration($reguid, $hmac);
862
863
        if ($failed === false) {
864
            $event = $registration->getEvent();
865
866
            // Send notifications (must run before cancelling the registration)
867
            $this->notificationService->sendUserMessage(
868
                $registration->getEvent(),
869
                $registration,
870
                $this->settings,
871
                MessageType::REGISTRATION_CANCELLED
872
            );
873
            $this->notificationService->sendAdminMessage(
874
                $registration->getEvent(),
875
                $registration,
876
                $this->settings,
877
                MessageType::REGISTRATION_CANCELLED
878
            );
879
880
            // First cancel depending registrations
881
            if ($registration->getAmountOfRegistrations() > 1) {
882
                $this->registrationService->cancelDependingRegistrations($registration);
883
            }
884
885
            // Finally cancel registration
886
            $this->registrationRepository->remove($registration);
887
888
            // Dispatch event, so waitlist registrations can be moved up
889
            $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...
890
891
            // Flush page cache for event, since new registration has been added
892
            $this->eventCacheService->flushEventCache($event->getUid(), $event->getPid());
893
        }
894
895
        $modifyCancelRegistrationViewVariablesEvent = new ModifyCancelRegistrationViewVariablesEvent(
896
            [
897
                'failed' => $failed,
898
                'messageKey' => $messageKey,
899
                'titleKey' => $titleKey,
900
                'event' => $event,
901
            ],
902
            $this
903
        );
904
        $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...
905
        $variables = $modifyCancelRegistrationViewVariablesEvent->getVariables();
906
        $this->view->assignMultiple($variables);
907
    }
908
909
    /**
910
     * Set date format for field startDate and endDate
911
     */
912
    public function initializeSearchAction()
913
    {
914
        if ($this->settings !== null && $this->settings['search']['dateFormat']) {
915
            $this->arguments->getArgument('searchDemand')
916
                ->getPropertyMappingConfiguration()->forProperty('startDate')
917
                ->setTypeConverterOption(
918
                    DateTimeConverter::class,
919
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
920
                    $this->settings['search']['dateFormat']
921
                );
922
            $this->arguments->getArgument('searchDemand')
923
                ->getPropertyMappingConfiguration()->forProperty('endDate')
924
                ->setTypeConverterOption(
925
                    DateTimeConverter::class,
926
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
927
                    $this->settings['search']['dateFormat']
928
                );
929
        }
930
        if ($this->arguments->hasArgument('searchDemand')) {
931
            $propertyMappingConfiguration = $this->arguments->getArgument('searchDemand')
932
                ->getPropertyMappingConfiguration();
933
            $propertyMappingConfiguration->allowAllProperties();
934
            $propertyMappingConfiguration->setTypeConverterOption(
935
                PersistentObjectConverter::class,
936
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED,
937
                true
938
            );
939
        }
940
    }
941
942
    /**
943
     * Search view
944
     *
945
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand $searchDemand SearchDemand
946
     * @param array $overwriteDemand OverwriteDemand
947
     */
948
    public function searchAction(SearchDemand $searchDemand = null, array $overwriteDemand = [])
949
    {
950
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
951
        $eventDemand->setSearchDemand($searchDemand);
0 ignored issues
show
Bug introduced by
It seems like $searchDemand defined by parameter $searchDemand on line 948 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...
952
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
953
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
954
955
        if ($searchDemand !== null) {
956
            $searchDemand->setFields($this->settings['search']['fields']);
957
958
            if ($this->settings['search']['adjustTime'] && $searchDemand->getStartDate() !== null) {
959
                $searchDemand->getStartDate()->setTime(0, 0, 0);
960
            }
961
962
            if ($this->settings['search']['adjustTime'] && $searchDemand->getEndDate() !== null) {
963
                $searchDemand->getEndDate()->setTime(23, 59, 59);
964
            }
965
        }
966
967
        if ($this->isOverwriteDemand($overwriteDemand)) {
968
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
969
        }
970
971
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
972
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
973
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
974
        $speakers = $this->speakerRepository->findDemanded($foreignRecordDemand);
975
        $events = $this->eventRepository->findDemanded($eventDemand);
976
977
        $modifySearchViewVariablesEvent = new ModifySearchViewVariablesEvent(
978
            [
979
                'events' => $events,
980
                'categories' => $categories,
981
                'locations' => $locations,
982
                'organisators' => $organisators,
983
                'speakers' => $speakers,
984
                'searchDemand' => $searchDemand,
985
                'overwriteDemand' => $overwriteDemand,
986
            ],
987
            $this
988
        );
989
        $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...
990
        $variables = $modifySearchViewVariablesEvent->getVariables();
991
        $this->view->assignMultiple($variables);
992
    }
993
994
    /**
995
     * Returns if a demand object can be overwritten with the given overwriteDemand array
996
     *
997
     * @param array $overwriteDemand
998
     * @return bool
999
     */
1000
    protected function isOverwriteDemand($overwriteDemand)
1001
    {
1002
        return $this->settings['disableOverrideDemand'] != 1 && $overwriteDemand !== [];
1003
    }
1004
1005
    /**
1006
     * If no event is given and the singleEvent setting is set, the configured single event is returned
1007
     *
1008
     * @param Event|null $event
1009
     * @return Event|null
1010
     */
1011
    protected function evaluateSingleEventSetting($event)
1012
    {
1013
        if ($event === null && (int)$this->settings['singleEvent'] > 0) {
1014
            $event = $this->eventRepository->findByUid((int)$this->settings['singleEvent']);
1015
        }
1016
1017
        return $event;
1018
    }
1019
1020
    /**
1021
     * If no event is given and the isShortcut setting is set, the event is displayed using the "Insert Record"
1022
     * content element and should be loaded from contect object data
1023
     *
1024
     * @param Event|null $event
1025
     * @return Event|null
1026
     */
1027
    protected function evaluateIsShortcutSetting($event)
1028
    {
1029
        if ($event === null && (bool)$this->settings['detail']['isShortcut']) {
1030
            $eventRawData = $this->configurationManager->getContentObject()->data;
1031
            $event = $this->eventRepository->findByUid($eventRawData['uid']);
1032
        }
1033
1034
        return $event;
1035
    }
1036
1037
    /**
1038
     * Checks if the event pid could be found in the storagePage settings of the detail plugin and
1039
     * if the pid could not be found it return null instead of the event object.
1040
     *
1041
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
1042
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Event|null
1043
     */
1044
    protected function checkPidOfEventRecord(Event $event)
1045
    {
1046
        $allowedStoragePages = GeneralUtility::trimExplode(
1047
            ',',
1048
            Page::extendPidListByChildren(
1049
                $this->settings['storagePage'],
1050
                $this->settings['recursive']
1051
            ),
1052
            true
1053
        );
1054
        if (count($allowedStoragePages) > 0 && !in_array($event->getPid(), $allowedStoragePages)) {
1055
            $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...
1056
            $event = null;
1057
        }
1058
1059
        return $event;
1060
    }
1061
1062
    /**
1063
     * Returns the current sys_language_uid
1064
     *
1065
     * @return int
1066
     */
1067
    protected function getSysLanguageUid()
1068
    {
1069
        $languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
1070
1071
        return $languageAspect->getId();
1072
    }
1073
}
1074