Completed
Push — development ( 3341c0...7e1828 )
by Torben
02:23
created

EventController::confirmRegistrationAction()   B

Complexity

Conditions 7
Paths 10

Size

Total Lines 65
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
dl 0
loc 65
ccs 0
cts 0
cp 0
rs 7.1439
c 0
b 0
f 0
cc 7
eloc 41
nc 10
nop 2
crap 56

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace DERHANSEN\SfEventMgt\Controller;
3
4
/*
5
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE.txt file that was distributed with this source code.
9
 */
10
11
use DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand;
12
use DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand;
13
use DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand;
14
use DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand;
15
use DERHANSEN\SfEventMgt\Domain\Model\Event;
16
use DERHANSEN\SfEventMgt\Domain\Model\Registration;
17
use DERHANSEN\SfEventMgt\Utility\MessageType;
18
use DERHANSEN\SfEventMgt\Utility\Page;
19
use DERHANSEN\SfEventMgt\Utility\RegistrationResult;
20
use TYPO3\CMS\Core\Utility\ArrayUtility;
21
use TYPO3\CMS\Core\Utility\GeneralUtility;
22
use TYPO3\CMS\Core\Utility\HttpUtility;
23
use TYPO3\CMS\Extbase\Mvc\RequestInterface;
24
use TYPO3\CMS\Extbase\Mvc\ResponseInterface;
25
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
26
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
27
use TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter;
28
use TYPO3\CMS\Fluid\View\StandaloneView;
29
30
/**
31
 * EventController
32
 *
33
 * @author Torben Hansen <[email protected]>
34
 */
35
class EventController extends AbstractController
36
{
37
    /**
38
     * Assign contentObjectData and pageData to earch view
39
     *
40
     * @param \TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view
41
     */
42
    protected function initializeView(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view)
43
    {
44
        $view->assign('contentObjectData', $this->configurationManager->getContentObject()->data);
45
        if (is_object($GLOBALS['TSFE'])) {
46
            $view->assign('pageData', $GLOBALS['TSFE']->page);
47
        }
48
        parent::initializeView($view);
49
    }
50
51
    /**
52
     * Properties in this array will be ignored by overwriteDemandObject()
53
     *
54
     * @var array
55
     */
56
    protected $ignoredSettingsForOverwriteDemand = ['storagepage', 'orderfieldallowed'];
57
58
    /**
59
     * Creates an event demand object with the given settings
60
     *
61
     * @param array $settings The settings
62
     *
63
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand
64
     */
65
    public function createEventDemandObjectFromSettings(array $settings)
66
    {
67
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand */
68
        $demand = $this->objectManager->get(EventDemand::class);
69
        $demand->setDisplayMode($settings['displayMode']);
70
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
71
        $demand->setCategoryConjunction($settings['categoryConjunction']);
72
        $demand->setCategory($settings['category']);
73
        $demand->setIncludeSubcategories($settings['includeSubcategories']);
74
        $demand->setTopEventRestriction((int)$settings['topEventRestriction']);
75
        $demand->setOrderField($settings['orderField']);
76
        $demand->setOrderFieldAllowed($settings['orderFieldAllowed']);
77
        $demand->setOrderDirection($settings['orderDirection']);
78
        $demand->setQueryLimit($settings['queryLimit']);
79
        $demand->setLocation($settings['location']);
80
        $demand->setOrganisator($settings['organisator']);
81
82
        return $demand;
83
    }
84
85
    /**
86
     * Creates a foreign record demand object with the given settings
87
     *
88
     * @param array $settings The settings
89
     *
90
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand
91
     */
92
    public function createForeignRecordDemandObjectFromSettings(array $settings)
93
    {
94
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand $demand */
95
        $demand = $this->objectManager->get(ForeignRecordDemand::class);
96
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
97
        $demand->setRestrictForeignRecordsToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
98
99
        return $demand;
100
    }
101
102
    /**
103
     * Creates a category demand object with the given settings
104
     *
105
     * @param array $settings The settings
106
     *
107
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand
108
     */
109
    public function createCategoryDemandObjectFromSettings(array $settings)
110
    {
111
        /** @var \DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand $demand */
112
        $demand = $this->objectManager->get(CategoryDemand::class);
113
        $demand->setStoragePage(Page::extendPidListByChildren($settings['storagePage'], $settings['recursive']));
114
        $demand->setRestrictToStoragePage((bool)$settings['restrictForeignRecordsToStoragePage']);
115
        $demand->setCategories($settings['categoryMenu']['categories']);
116
        $demand->setIncludeSubcategories($settings['categoryMenu']['includeSubcategories']);
117
118
        return $demand;
119
    }
120
121
    /**
122
     * Overwrites a given demand object by an propertyName =>  $propertyValue array
123
     *
124
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand $demand Demand
125
     * @param array $overwriteDemand OwerwriteDemand
126
     *
127
     * @return \DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand
128
     */
129
    protected function overwriteEventDemandObject(EventDemand $demand, array $overwriteDemand)
130
    {
131
        foreach ($this->ignoredSettingsForOverwriteDemand as $property) {
132
            unset($overwriteDemand[$property]);
133
        }
134
135
        foreach ($overwriteDemand as $propertyName => $propertyValue) {
136
            if (in_array(strtolower($propertyName), $this->ignoredSettingsForOverwriteDemand, true)) {
137 1
                continue;
138
            }
139
            \TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($demand, $propertyName, $propertyValue);
140 1
        }
141 1
142 1
        return $demand;
143 1
    }
144 1
145 1
    /**
146 1
     * Hook into request processing and catch exceptions
147 1
     *
148 1
     * @param RequestInterface $request
149 1
     * @param ResponseInterface $response
150 1
     * @throws \Exception
151
     */
152
    public function processRequest(RequestInterface $request, ResponseInterface $response)
153
    {
154
        try {
155
            parent::processRequest($request, $response);
156
        } catch (\Exception $exception) {
157
            $this->handleKnownExceptionsElseThrowAgain($exception);
158
        }
159
    }
160
161
    /**
162
     * Handle known exceptions
163
     *
164
     * @param \Exception $exception
165
     * @throws \Exception
166
     */
167
    private function handleKnownExceptionsElseThrowAgain(\Exception $exception)
168
    {
169
        $previousException = $exception->getPrevious();
170
        $actions = ['detailAction', 'registrationAction', 'icalDownloadAction'];
171
        if (in_array($this->actionMethodName, $actions, true)
172
            && $previousException instanceof \TYPO3\CMS\Extbase\Property\Exception
173
        ) {
174
            $this->handleEventNotFoundError($this->settings);
175
        } else {
176 1
            throw $exception;
177
        }
178
    }
179 1
180 1
    /**
181 1
     * Initialize list action and set format
182 1
     *
183 1
     * @return void
184 1
     */
185
    public function initializeListAction()
186
    {
187
        if (isset($this->settings['list']['format'])) {
188
            $this->request->setFormat($this->settings['list']['format']);
189
        }
190
    }
191
192
    /**
193
     * List view
194
     *
195 2
     * @param array $overwriteDemand OverwriteDemand
196
     *
197 2
     * @return void
198 2
     */
199 2
    public function listAction(array $overwriteDemand = [])
200
    {
201 2
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
202 2
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
203 2
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
204 2
        if ($this->isOverwriteDemand($overwriteDemand)) {
205
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
206
        }
207
        $events = $this->eventRepository->findDemanded($eventDemand);
208
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
209
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
210
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
211
        $this->view->assignMultiple([
212
            'events' => $events,
213
            'categories' => $categories,
214
            'locations' => $locations,
215
            'organisators' => $organisators,
216
            'overwriteDemand' => $overwriteDemand,
217
            'eventDemand' => $eventDemand
218
        ]);
219
    }
220
221
    /**
222
     * Calendar view
223
     *
224
     * @param array $overwriteDemand OverwriteDemand
225
     *
226 3
     * @return void
227
     */
228 3
    public function calendarAction(array $overwriteDemand = [])
229 3
    {
230 3
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
231 3
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
232 1
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
233 1
        if ($this->isOverwriteDemand($overwriteDemand)) {
234 3
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
235 3
        }
236 3
237 3
        // Set month/year to demand if not given
238 3
        if (!$eventDemand->getMonth()) {
239 3
            $currentMonth = date('n');
240 3
            $eventDemand->setMonth($currentMonth);
241 3
        } else {
242
            $currentMonth = $eventDemand->getMonth();
243
        }
244
        if (!$eventDemand->getYear()) {
245
            $currentYear = date('Y');
246
            $eventDemand->setYear($currentYear);
247
        } else {
248
            $currentYear = $eventDemand->getYear();
249
        }
250 1
251
        // Set demand from calendar date range instead of month / year
252 1
        if ((bool)$this->settings['calendar']['includeEventsForEveryDayOfAllCalendarWeeks']) {
253 1
            $eventDemand = $this->changeEventDemandToFullMonthDateRange($eventDemand);
254
        }
255
256
        $events = $this->eventRepository->findDemanded($eventDemand);
257
        $weeks = $this->calendarService->getCalendarArray(
258
            $currentMonth,
259
            $currentYear,
260
            strtotime('today midnight'),
261
            (int)$this->settings['calendar']['firstDayOfWeek'],
262 1
            $events
263
        );
264 1
265 1
        $values = [
266
            'weeks' => $weeks,
267
            'categories' => $this->categoryRepository->findDemanded($categoryDemand),
268
            'locations' => $this->locationRepository->findDemanded($foreignRecordDemand),
269
            'organisators' => $this->organisatorRepository->findDemanded($foreignRecordDemand),
270
            'eventDemand' => $eventDemand,
271
            'overwriteDemand' => $overwriteDemand,
272
            'currentPageId' => $GLOBALS['TSFE']->id,
273
            'firstDayOfMonth' => \DateTime::createFromFormat('d.m.Y', sprintf('1.%s.%s', $currentMonth, $currentYear)),
274
            'previousMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '-1 month'),
275 1
            'nextMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '+1 month')
276
        ];
277 1
278
        $this->view->assignMultiple($values);
279
    }
280 1
281
    /**
282 1
     * Changes the given event demand object to select a date range for a calendar month including days of the previous
283 1
     * month for the first week and they days for the next month for the last week
284 1
     *
285
     * @param EventDemand $eventDemand
286
     * @return EventDemand
287
     */
288
    protected function changeEventDemandToFullMonthDateRange(EventDemand $eventDemand)
289
    {
290
        $calendarDateRange = $this->calendarService->getCalendarDateRange(
291 1
            $eventDemand->getMonth(),
292
            $eventDemand->getYear(),
293 1
            $this->settings['calendar']['firstDayOfWeek']
294 1
        );
295 1
296 1
        $eventDemand->setMonth(0);
297 1
        $eventDemand->setYear(0);
298 1
299 1
        $startDate = new \DateTime();
300 1
        $startDate->setTimestamp($calendarDateRange['firstDayOfCalendar']);
301
        $endDate = new \DateTime();
302
        $endDate->setTimestamp($calendarDateRange['lastDayOfCalendar']);
303
        $endDate->setTime(23, 59, 59);
304
305
        $searchDemand = new SearchDemand();
306
        $searchDemand->setStartDate($startDate);
307
        $searchDemand->setEndDate($endDate);
308
        $eventDemand->setSearchDemand($searchDemand);
309
310
        return $eventDemand;
311 11
    }
312
313 11
    /**
314 11
     * Detail view for an event
315 11
     *
316
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
317
     * @return mixed string|void
318 11
     */
319 4
    public function detailAction(Event $event = null)
320 4
    {
321 4
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
322 4
            return $this->handleEventNotFoundError($this->settings);
323 4
        }
324 4
        $this->view->assign('event', $event);
325
    }
326 4
327 4
    /**
328 4
     * Error handling if event is not found
329 4
     *
330
     * @param array $settings
331 4
     * @return string
332 4
     */
333 4
    protected function handleEventNotFoundError($settings)
334 4
    {
335 4
        if (empty($settings['event']['errorHandling'])) {
336 4
            return null;
337 4
        }
338 4
339
        $configuration = GeneralUtility::trimExplode(',', $settings['event']['errorHandling'], true);
340
341 4
        switch ($configuration[0]) {
342
            case 'redirectToListView':
343
                $listPid = (int)$settings['listPid'] > 0 ? (int)$settings['listPid'] : 1;
344 4
                $this->redirect('list', null, null, null, $listPid);
345 1
                break;
346 1
            case 'pageNotFoundHandler':
347 1
                $GLOBALS['TSFE']->pageNotFoundAndExit('Event not found.');
348 3
                break;
349 3
            case 'showStandaloneTemplate':
350
                if (isset($configuration[2])) {
351 4
                    $statusCode = constant(HttpUtility::class . '::HTTP_STATUS_' . $configuration[2]);
352
                    HttpUtility::setResponseCode($statusCode);
353
                }
354 4
                $standaloneTemplate = $this->objectManager->get(StandaloneView::class);
355 3
                $standaloneTemplate->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($configuration[1]));
356 3
357 3
                return $standaloneTemplate->render();
358 3
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

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

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

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

Loading history...
359
            default:
360 3
        }
361 3
    }
362 3
363 3
    /**
364 3
     * Initiates the iCalendar download for the given event
365
     *
366 3
     * @param Event $event The event
367 3
     *
368
     * @return string|false
369
     */
370 4
    public function icalDownloadAction(Event $event = null)
371 1
    {
372 1
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
373
            return $this->handleEventNotFoundError($this->settings);
374
        }
375 4
        $this->icalendarService->downloadiCalendarFile($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by parameter $event on line 370 can be null; however, DERHANSEN\SfEventMgt\Ser...downloadiCalendarFile() 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...
376 4
377
        return false;
378 11
    }
379 1
380 1
    /**
381 1
     * Registration view for an event
382 1
     *
383
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
384 1
     *
385 1
     * @return mixed string|void
386 1
     */
387 1
    public function registrationAction(Event $event = null)
388 1
    {
389 10
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
390 10
            return $this->handleEventNotFoundError($this->settings);
391 10
        }
392 10
        if ($event->getRestrictPaymentMethods()) {
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...
393 10
            $paymentMethods = $this->paymentService->getRestrictedPaymentMethods($event);
0 ignored issues
show
Bug introduced by
It seems like $event defined by parameter $event on line 387 can be null; however, DERHANSEN\SfEventMgt\Ser...trictedPaymentMethods() 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...
394 10
        } else {
395
            $paymentMethods = $this->paymentService->getPaymentMethods();
396 11
        }
397
398
        $this->view->assignMultiple([
399
            'event' => $event,
400
            'paymentMethods' => $paymentMethods,
401
        ]);
402
    }
403
404
    /**
405 9
     * Processes incoming registrations fields and adds field values to arguments
406
     *
407
     * @return void
408 9
     */
409 1
    protected function setRegistrationFieldValuesToArguments()
410 1
    {
411 1
        $arguments = $this->request->getArguments();
412 8
        if (!isset($arguments['registration']['fields']) || !isset($arguments['event'])) {
413
            return;
414
        }
415
416 8
        $registrationMvcArgument = $this->arguments->getArgument('registration');
417 1
        $propertyMapping = $registrationMvcArgument->getPropertyMappingConfiguration();
418 1
        $propertyMapping->allowProperties('fieldValues');
419 1
        $propertyMapping->allowCreationForSubProperty('fieldValues');
420 7
        $propertyMapping->allowModificationForSubProperty('fieldValues');
421 1
422 1
        // allow creation of new objects (for validation)
423 1
        $propertyMapping->setTypeConverterOptions(
424 6
            PersistentObjectConverter::class,
425 1
            [
426 1
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => true,
427 1
                PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED => true
428 5
            ]
429 1
        );
430 1
431 1
        // Set event to registration (required for validation)
432 4
        $event = $this->eventRepository->findByUid((int)$this->request->getArgument('event'));
433 1
        $propertyMapping->allowProperties('event');
434 1
        $propertyMapping->allowCreationForSubProperty('event');
435 1
        $propertyMapping->allowModificationForSubProperty('event');
436 3
        $arguments['registration']['event'] = (int)$this->request->getArgument('event');
437 1
438 1
        $index = 0;
439 1
        foreach ((array)$arguments['registration']['fields'] as $fieldUid => $value) {
440 2
            // Only accept registration fields of the current event
441 1
            if (!in_array((int)$fieldUid, $event->getRegistrationFieldsUids(), true)) {
442 1
                continue;
443 1
            }
444 1
445 1
            // allow subvalues in new property mapper
446 1
            $propertyMapping->forProperty('fieldValues')->allowProperties($index);
447 1
            $propertyMapping->forProperty('fieldValues.' . $index)->allowAllProperties();
448
            $propertyMapping->allowCreationForSubProperty('fieldValues.' . $index);
449 9
            $propertyMapping->allowModificationForSubProperty('fieldValues.' . $index);
450 9
451 9
            if (is_array($value)) {
452
                if (empty($value)) {
453
                    $value = '';
454
                } else {
455
                    $value = json_encode($value);
456
                }
457
            }
458
459
            /** @var Registration\Field $field */
460
            $field = $this->fieldRepository->findByUid((int)$fieldUid);
461 3
462
            $arguments['registration']['fieldValues'][$index] = [
463
                'value' => $value,
464 3
                'field' => strval($fieldUid),
465
                'valueType' => $field->getValueType()
466 3
            ];
467 2
468 2
            $index++;
469
        }
470 2
471 2
        // Remove temporary "fields" field
472 1
        $arguments = ArrayUtility::removeByPath($arguments, 'registration/fields');
473 1
        $this->request->setArguments($arguments);
474
    }
475
476 2
    /**
477 2
     * Set date format for field dateOfBirth
478 2
     *
479 2
     * @return void
480
     */
481 2
    public function initializeSaveRegistrationAction()
482 2
    {
483 2
        $this->arguments->getArgument('registration')
484 2
            ->getPropertyMappingConfiguration()->forProperty('dateOfBirth')
485 2
            ->setTypeConverterOption(
486
                DateTimeConverter::class,
487 2
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
488
                $this->settings['registration']['formatDateOfBirth']
489
            );
490 2
        $this->setRegistrationFieldValuesToArguments();
491 2
    }
492 2
493 2
    /**
494
     * Saves the registration
495
     *
496 3
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
497 3
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
498
     * @validate $registration \DERHANSEN\SfEventMgt\Validation\Validator\RegistrationFieldValidator
499
     * @validate $registration \DERHANSEN\SfEventMgt\Validation\Validator\RegistrationValidator
500
     *
501
     * @return void
502
     */
503
    public function saveRegistrationAction(Registration $registration, Event $event)
504
    {
505
        $autoConfirmation = (bool)$this->settings['registration']['autoConfirmation'] || $event->getEnableAutoconfirm();
506
        $result = RegistrationResult::REGISTRATION_SUCCESSFUL;
507
        $success = $this->registrationService->checkRegistrationSuccess($event, $registration, $result);
508
509
        // Save registration if no errors
510
        if ($success) {
511
            $isWaitlistRegistration = $this->registrationService->isWaitlistRegistration(
512
                $event,
513
                $registration->getAmountOfRegistrations()
514 3
            );
515 3
            $linkValidity = (int)$this->settings['confirmation']['linkValidity'];
516 3
            if ($linkValidity === 0) {
517
                // Use 3600 seconds as default value if not set
518
                $linkValidity = 3600;
519
            }
520
            $confirmationUntil = new \DateTime();
521
            $confirmationUntil->add(new \DateInterval('PT' . $linkValidity . 'S'));
522
523
            $registration->setEvent($event);
524
            $registration->setPid($event->getPid());
525
            $registration->setConfirmationUntil($confirmationUntil);
526 2
            $registration->setLanguage($GLOBALS['TSFE']->config['config']['language']);
527
            $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...
528
            $registration->setWaitlist($isWaitlistRegistration);
529 2
            $registration->_setProperty('_languageUid', $GLOBALS['TSFE']->sys_language_uid);
530
            $this->registrationRepository->add($registration);
531 2
532
            // Persist registration, so we have an UID
533 1
            $this->objectManager->get(PersistenceManager::class)->persistAll();
534 1
535 1
            // Add new registration (or waitlist registration) to event
536 1
            if ($isWaitlistRegistration) {
537
                $event->addRegistrationWaitlist($registration);
538 1
                $messageType = MessageType::REGISTRATION_WAITLIST_NEW;
539 1
            } else {
540 1
                $event->addRegistration($registration);
541 1
                $messageType = MessageType::REGISTRATION_NEW;
542 1
            }
543
            $this->eventRepository->update($event);
544 1
545
            // Send notifications to user and admin if confirmation link should be sent
546
            if (!$autoConfirmation) {
547 1
                $this->notificationService->sendUserMessage(
548 1
                    $event,
549 1
                    $registration,
550
                    $this->settings,
551
                    $messageType
552 1
                );
553
                $this->notificationService->sendAdminMessage(
554
                    $event,
555 1
                    $registration,
556 1
                    $this->settings,
557 2
                    $messageType
558 2
                );
559 2
            }
560
561
            // Create given amount of registrations if necessary
562
            if ($registration->getAmountOfRegistrations() > 1) {
563
                $this->registrationService->createDependingRegistrations($registration);
564
            }
565
566 1
            // Clear cache for configured pages
567
            $this->utilityService->clearCacheForConfiguredUids($this->settings);
568 1
        }
569 1
570 1
        if ($autoConfirmation && $success) {
571 1
            $this->redirect(
572 1
                'confirmRegistration',
573 1
                null,
574 1
                null,
575 1
                [
576 1
                    'reguid' => $registration->getUid(),
577 1
                    'hmac' => $this->hashService->generateHmac('reg-' . $registration->getUid())
578 1
                ]
579 1
            );
580 1
        } else {
581 1
            $this->redirect(
582 1
                'saveRegistrationResult',
583 1
                null,
584 1
                null,
585
                [
586
                    'result' => $result,
587
                    'eventuid' => $event->getUid(),
588
                    'hmac' => $this->hashService->generateHmac('event-' . $event->getUid())
589
                ]
590
            );
591
        }
592
    }
593
594 6
    /**
595
     * Shows the result of the saveRegistrationAction
596 6
     *
597 6
     * @param int $result Result
598 6
     * @param int $eventuid
599 6
     * @param string $hmac
600
     *
601 6
     * @return void
602 5
     */
603
    public function saveRegistrationResultAction($result, $eventuid, $hmac)
604 5
    {
605 1
        $event = null;
606 1
607
        switch ($result) {
608 5
            case RegistrationResult::REGISTRATION_SUCCESSFUL:
609 1
                $messageKey = 'event.message.registrationsuccessful';
610 1
                $titleKey = 'registrationResult.title.successful';
611 5
                break;
612
            case RegistrationResult::REGISTRATION_SUCCESSFUL_WAITLIST:
613 6
                $messageKey = 'event.message.registrationwaitlistsuccessful';
614 1
                $titleKey = 'registrationWaitlistResult.title.successful';
615 1
                break;
616
            case RegistrationResult::REGISTRATION_FAILED_EVENT_EXPIRED:
617 6
                $messageKey = 'event.message.registrationfailedeventexpired';
618 6
                $titleKey = 'registrationResult.title.failed';
619
                break;
620 6
            case RegistrationResult::REGISTRATION_FAILED_MAX_PARTICIPANTS:
621
                $messageKey = 'event.message.registrationfailedmaxparticipants';
622 6
                $titleKey = 'registrationResult.title.failed';
623 6
                break;
624 6
            case RegistrationResult::REGISTRATION_NOT_ENABLED:
625 6
                $messageKey = 'event.message.registrationfailednotenabled';
626 6
                $titleKey = 'registrationResult.title.failed';
627 6
                break;
628
            case RegistrationResult::REGISTRATION_FAILED_DEADLINE_EXPIRED:
629
                $messageKey = 'event.message.registrationfaileddeadlineexpired';
630
                $titleKey = 'registrationResult.title.failed';
631
                break;
632
            case RegistrationResult::REGISTRATION_FAILED_NOT_ENOUGH_FREE_PLACES:
633
                $messageKey = 'event.message.registrationfailednotenoughfreeplaces';
634
                $titleKey = 'registrationResult.title.failed';
635 9
                break;
636
            case RegistrationResult::REGISTRATION_FAILED_MAX_AMOUNT_REGISTRATIONS_EXCEEDED:
637 9
                $messageKey = 'event.message.registrationfailedmaxamountregistrationsexceeded';
638
                $titleKey = 'registrationResult.title.failed';
639
                break;
640
            case RegistrationResult::REGISTRATION_FAILED_EMAIL_NOT_UNIQUE:
641
                $messageKey = 'event.message.registrationfailedemailnotunique';
642
                $titleKey = 'registrationResult.title.failed';
643
                break;
644
            default:
645
                $messageKey = '';
646
                $titleKey = '';
647
        }
648
649
        if (!$this->hashService->validateHmac('event-' . $eventuid, $hmac)) {
650
            $messageKey = 'event.message.registrationsuccessfulwrongeventhmac';
651
            $titleKey = 'registrationResult.title.failed';
652
        } else {
653
            $event = $this->eventRepository->findByUid((int)$eventuid);
654
        }
655
656
        $this->view->assignMultiple([
657
            'messageKey' => $messageKey,
658
            'titleKey' => $titleKey,
659
            'event' => $event,
660
        ]);
661
    }
662
663
    /**
664
     * Confirms the registration if possible and sends e-mails to admin and user
665
     *
666
     * @param int $reguid UID of registration
667
     * @param string $hmac HMAC for parameters
668
     *
669
     * @return void
670
     */
671
    public function confirmRegistrationAction($reguid, $hmac)
672
    {
673
        $event = null;
674
675
        /* @var $registration Registration */
676
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkConfirmRegistration(
677
            $reguid,
678
            $hmac
679
        );
680
681
        if ($failed === false) {
682
            $registration->setConfirmed(true);
683
            $event = $registration->getEvent();
684
            $this->registrationRepository->update($registration);
685
686
            $messageType = MessageType::REGISTRATION_CONFIRMED;
687
            if ($registration->getWaitlist()) {
688
                $messageType = MessageType::REGISTRATION_WAITLIST_CONFIRMED;
689
            }
690
691
            // Send notifications to user and admin
692
            $this->notificationService->sendUserMessage(
693
                $registration->getEvent(),
694
                $registration,
695
                $this->settings,
696
                $messageType
697
            );
698
            $this->notificationService->sendAdminMessage(
699
                $registration->getEvent(),
700
                $registration,
701
                $this->settings,
702
                $messageType
703
            );
704
705
            // Confirm registrations depending on main registration if necessary
706
            if ($registration->getAmountOfRegistrations() > 1) {
707
                $this->registrationService->confirmDependingRegistrations($registration);
708
            }
709
        }
710
711
        // Redirect to payment provider if payment/redirect is enabled
712
        $paymentPid = (int)$this->settings['paymentPid'];
713
        if (!$failed && $paymentPid > 0 && $this->registrationService->redirectPaymentEnabled($registration)) {
714
            $this->uriBuilder->reset()
715
                ->setTargetPageUid($paymentPid)
716
                ->setUseCacheHash(false);
717
            $uri = $this->uriBuilder->uriFor(
718
                'redirect',
719
                [
720
                    'registration' => $registration,
721
                    'hmac' => $this->hashService->generateHmac('redirectAction-' . $registration->getUid())
722
                ],
723
                'Payment',
724
                'sfeventmgt',
725
                'Pipayment'
726
            );
727
            $this->redirectToUri($uri);
728
        }
729
730
        $this->view->assignMultiple([
731
            'messageKey' => $messageKey,
732
            'titleKey' => $titleKey,
733
            'event' => $event,
734
        ]);
735
    }
736
737
    /**
738
     * Cancels the registration if possible and sends e-mails to admin and user
739
     *
740
     * @param int $reguid UID of registration
741
     * @param string $hmac HMAC for parameters
742
     *
743
     * @return void
744
     */
745
    public function cancelRegistrationAction($reguid, $hmac)
746
    {
747
        $event = null;
748
749
        /* @var $registration Registration */
750
        list($failed, $registration, $messageKey, $titleKey) = $this->registrationService->checkCancelRegistration($reguid, $hmac);
751
752
        if ($failed === false) {
753
            $event = $registration->getEvent();
754
755
            // Send notifications (must run before cancelling the registration)
756
            $this->notificationService->sendUserMessage(
757
                $registration->getEvent(),
758
                $registration,
759
                $this->settings,
760
                MessageType::REGISTRATION_CANCELLED
761
            );
762
            $this->notificationService->sendAdminMessage(
763
                $registration->getEvent(),
764
                $registration,
765
                $this->settings,
766
                MessageType::REGISTRATION_CANCELLED
767
            );
768
769
            // First cancel depending registrations
770
            if ($registration->getAmountOfRegistrations() > 1) {
771
                $this->registrationService->cancelDependingRegistrations($registration);
772
            }
773
774
            // Finally cancel registration
775
            $this->registrationRepository->remove($registration);
776
777
            // Clear cache for configured pages
778
            $this->utilityService->clearCacheForConfiguredUids($this->settings);
779
        }
780
781
        $this->view->assignMultiple([
782
            'messageKey' => $messageKey,
783
            'titleKey' => $titleKey,
784
            'event' => $event,
785
        ]);
786
    }
787
788
    /**
789
     * Set date format for field startDate and endDate
790
     *
791
     * @return void
792
     */
793
    public function initializeSearchAction()
794
    {
795
        if ($this->settings !== null && $this->settings['search']['dateFormat']) {
796
            $this->arguments->getArgument('searchDemand')
797
                ->getPropertyMappingConfiguration()->forProperty('startDate')
798
                ->setTypeConverterOption(
799
                    DateTimeConverter::class,
800
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
801
                    $this->settings['search']['dateFormat']
802
                );
803
            $this->arguments->getArgument('searchDemand')
804
                ->getPropertyMappingConfiguration()->forProperty('endDate')
805
                ->setTypeConverterOption(
806
                    DateTimeConverter::class,
807
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
808
                    $this->settings['search']['dateFormat']
809
                );
810
        }
811
    }
812
813
    /**
814
     * Search view
815
     *
816
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand $searchDemand SearchDemand
817
     * @param array $overwriteDemand OverwriteDemand
818
     *
819
     * @return void
820
     */
821
    public function searchAction(SearchDemand $searchDemand = null, array $overwriteDemand = [])
822
    {
823
        $eventDemand = $this->createEventDemandObjectFromSettings($this->settings);
824
        $eventDemand->setSearchDemand($searchDemand);
0 ignored issues
show
Bug introduced by
It seems like $searchDemand defined by parameter $searchDemand on line 821 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...
825
        $foreignRecordDemand = $this->createForeignRecordDemandObjectFromSettings($this->settings);
826
        $categoryDemand = $this->createCategoryDemandObjectFromSettings($this->settings);
827
828
        if ($searchDemand !== null) {
829
            $searchDemand->setFields($this->settings['search']['fields']);
830
831
            if ($this->settings['search']['adjustTime'] && $searchDemand->getStartDate() !== null) {
832
                $searchDemand->getStartDate()->setTime(0, 0, 0);
833
            }
834
835
            if ($this->settings['search']['adjustTime'] && $searchDemand->getEndDate() !== null) {
836
                $searchDemand->getEndDate()->setTime(23, 59, 59);
837
            }
838
        }
839
840
        if ($this->isOverwriteDemand($overwriteDemand)) {
841
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
842
        }
843
844
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
845
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
846
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
847
848
        $events = $this->eventRepository->findDemanded($eventDemand);
849
850
        $this->view->assignMultiple([
851
            'events' => $events,
852
            'categories' => $categories,
853
            'locations' => $locations,
854
            'organisators' => $organisators,
855
            'searchDemand' => $searchDemand,
856
            'overwriteDemand' => $overwriteDemand,
857
        ]);
858
    }
859
860
    /**
861
     * Returns if a demand object can be overwritten with the given overwriteDemand array
862
     *
863
     * @param array $overwriteDemand
864
     * @return bool
865
     */
866
    protected function isOverwriteDemand($overwriteDemand)
867
    {
868
        return $this->settings['disableOverrideDemand'] != 1 && $overwriteDemand !== [];
869
    }
870
}
871