EventController::saveRegistrationAction()   C
last analyzed

Complexity

Conditions 11
Paths 69

Size

Total Lines 122
Code Lines 84

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 84
c 1
b 0
f 0
nc 69
nop 2
dl 0
loc 122
rs 6.2024

How to fix   Long Method    Complexity   

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
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
7
 *
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
namespace DERHANSEN\SfEventMgt\Controller;
13
14
use DateInterval;
15
use DateTime;
16
use DERHANSEN\SfEventMgt\Domain\Model\Dto\CategoryDemand;
17
use DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand;
18
use DERHANSEN\SfEventMgt\Domain\Model\Dto\ForeignRecordDemand;
19
use DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand;
20
use DERHANSEN\SfEventMgt\Domain\Model\Event;
21
use DERHANSEN\SfEventMgt\Domain\Model\Registration;
22
use DERHANSEN\SfEventMgt\Event\AfterRegistrationCancelledEvent;
0 ignored issues
show
Bug introduced by
The type DERHANSEN\SfEventMgt\Eve...istrationCancelledEvent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use DERHANSEN\SfEventMgt\Event\AfterRegistrationConfirmedEvent;
0 ignored issues
show
Bug introduced by
The type DERHANSEN\SfEventMgt\Eve...istrationConfirmedEvent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use DERHANSEN\SfEventMgt\Event\AfterRegistrationSavedEvent;
0 ignored issues
show
Bug introduced by
The type DERHANSEN\SfEventMgt\Eve...rRegistrationSavedEvent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use DERHANSEN\SfEventMgt\Event\ModifyCalendarViewVariablesEvent;
26
use DERHANSEN\SfEventMgt\Event\ModifyCancelRegistrationViewVariablesEvent;
27
use DERHANSEN\SfEventMgt\Event\ModifyConfirmRegistrationViewVariablesEvent;
28
use DERHANSEN\SfEventMgt\Event\ModifyCreateDependingRegistrationsEvent;
29
use DERHANSEN\SfEventMgt\Event\ModifyDetailViewVariablesEvent;
30
use DERHANSEN\SfEventMgt\Event\ModifyListViewVariablesEvent;
31
use DERHANSEN\SfEventMgt\Event\ModifyRegistrationViewVariablesEvent;
32
use DERHANSEN\SfEventMgt\Event\ModifySearchViewVariablesEvent;
33
use DERHANSEN\SfEventMgt\Event\ProcessCancelDependingRegistrationsEvent;
34
use DERHANSEN\SfEventMgt\Event\ProcessRedirectToPaymentEvent;
35
use DERHANSEN\SfEventMgt\Event\WaitlistMoveUpEvent;
36
use DERHANSEN\SfEventMgt\Exception;
37
use DERHANSEN\SfEventMgt\Security\HashScope;
38
use DERHANSEN\SfEventMgt\Service\EventCacheService;
39
use DERHANSEN\SfEventMgt\Service\EventEvaluationService;
40
use DERHANSEN\SfEventMgt\Utility\MessageType;
41
use DERHANSEN\SfEventMgt\Utility\RegistrationResult;
42
use DERHANSEN\SfEventMgt\Validation\Validator\RegistrationFieldValidator;
43
use DERHANSEN\SfEventMgt\Validation\Validator\RegistrationValidator;
44
use Psr\Http\Message\ResponseInterface;
45
use TYPO3\CMS\Core\Cache\CacheTag;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\Cache\CacheTag was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
46
use TYPO3\CMS\Core\Http\PropagateResponseException;
47
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
48
use TYPO3\CMS\Core\Utility\ArrayUtility;
49
use TYPO3\CMS\Core\Utility\GeneralUtility;
50
use TYPO3\CMS\Core\View\ViewFactoryData;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\View\ViewFactoryData was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
51
use TYPO3\CMS\Core\View\ViewFactoryInterface;
52
use TYPO3\CMS\Extbase\Annotation as Extbase;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Annotation was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
53
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Persis...eric\PersistenceManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
54
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Proper...erter\DateTimeConverter was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
55
use TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Proper...rsistentObjectConverter was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
56
use TYPO3\CMS\Frontend\Controller\ErrorController;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Frontend\Controller\ErrorController was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
57
58
class EventController extends AbstractController
59
{
60
    protected EventCacheService $eventCacheService;
61
    protected ViewFactoryInterface $viewFactory;
62
    protected EventEvaluationService $eventEvaluationService;
63
64
    public function injectEventCacheService(EventCacheService $cacheService): void
65
    {
66
        $this->eventCacheService = $cacheService;
67
    }
68
69
    public function injectViewFactoryInterface(ViewFactoryInterface $viewFactory): void
70
    {
71
        $this->viewFactory = $viewFactory;
72
    }
73
74
    public function injectEventEvaluationService(EventEvaluationService $eventEvaluationService): void
75
    {
76
        $this->eventEvaluationService = $eventEvaluationService;
77
    }
78
79
    /**
80
     * Assign contentObjectData and pageData view
81
     */
82
    protected function initializeView(): void
83
    {
84
        $this->view->assign('contentObjectData', $this->request->getAttribute('currentContentObject')->data ?? null);
85
        $this->view->assign('pageData', $this->getFrontendPageInformation()->getPageRecord());
86
    }
87
88
    /**
89
     * Initializes the current action
90
     */
91
    public function initializeAction(): void
92
    {
93
        static $cacheTagsSet = false;
94
95
        if (!$cacheTagsSet) {
96
            $this->request->getAttribute('frontend.cache.collector')->addCacheTags(new CacheTag('tx_sfeventmgt'));
97
            $cacheTagsSet = true;
98
        }
99
    }
100
101
    /**
102
     * Initialize list action and set format
103
     */
104
    public function initializeListAction(): void
105
    {
106
        if (isset($this->settings['list']['format'])) {
107
            $this->request = $this->request->withFormat($this->settings['list']['format']);
0 ignored issues
show
Bug Best Practice introduced by
The property request does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
108
        }
109
    }
110
111
    /**
112
     * List view
113
     */
114
    public function listAction(array $overwriteDemand = []): ResponseInterface
115
    {
116
        $eventDemand = EventDemand::createFromSettings($this->settings);
117
        $foreignRecordDemand = ForeignRecordDemand::createFromSettings($this->settings);
118
        $categoryDemand = CategoryDemand::createFromSettings($this->settings);
119
        if ($this->isOverwriteDemand($overwriteDemand)) {
120
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
121
        }
122
        $events = $this->eventRepository->findDemanded($eventDemand);
123
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
124
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
125
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
126
        $speakers = $this->speakerRepository->findDemanded($foreignRecordDemand);
127
128
        $modifyListViewVariablesEvent = new ModifyListViewVariablesEvent(
129
            [
130
                'events' => $events,
131
                'pagination' => $this->getPagination($events, $this->settings['pagination'] ?? []),
132
                'categories' => $categories,
133
                'locations' => $locations,
134
                'organisators' => $organisators,
135
                'speakers' => $speakers,
136
                'overwriteDemand' => $overwriteDemand,
137
                'eventDemand' => $eventDemand,
138
                'settings' => $this->settings,
139
            ],
140
            $this,
141
            $this->request
142
        );
143
        $this->eventDispatcher->dispatch($modifyListViewVariablesEvent);
144
        $variables = $modifyListViewVariablesEvent->getVariables();
145
        $this->view->assignMultiple($variables);
146
147
        $cacheDataCollector = $this->request->getAttribute('frontend.cache.collector');
148
        $this->eventCacheService->addPageCacheTagsByEventDemandObject($cacheDataCollector, $eventDemand);
149
150
        return $this->htmlResponse();
151
    }
152
153
    /**
154
     * Calendar view
155
     */
156
    public function calendarAction(array $overwriteDemand = []): ResponseInterface
157
    {
158
        $eventDemand = EventDemand::createFromSettings($this->settings);
159
        $foreignRecordDemand = ForeignRecordDemand::createFromSettings($this->settings);
160
        $categoryDemand = CategoryDemand::createFromSettings($this->settings);
161
        if ($this->isOverwriteDemand($overwriteDemand)) {
162
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
163
        }
164
165
        // Set month/year to demand if not given
166
        if (!$eventDemand->getMonth()) {
167
            $currentMonth = (int)date('n');
168
            $eventDemand->setMonth($currentMonth);
169
        } else {
170
            $currentMonth = $eventDemand->getMonth();
171
        }
172
        if (!$eventDemand->getYear()) {
173
            $currentYear = (int)date('Y');
174
            $eventDemand->setYear($currentYear);
175
        } else {
176
            $currentYear = $eventDemand->getYear();
177
        }
178
179
        // If a weeknumber is given in overwriteDemand['week'], we overwrite the current month
180
        if ($overwriteDemand['week'] ?? false) {
181
            $firstDayOfWeek = (new DateTime())->setISODate($currentYear, (int)$overwriteDemand['week']);
182
            $currentMonth = (int)$firstDayOfWeek->format('m');
183
            $eventDemand->setMonth($currentMonth);
184
        } else {
185
            $firstDayOfWeek = (new DateTime())->setISODate($currentYear, (int)date('W'));
186
        }
187
188
        // Set demand from calendar date range instead of month / year
189
        if ((bool)($this->settings['calendar']['includeEventsForEveryDayOfAllCalendarWeeks'] ?? false)) {
190
            $eventDemand = $this->changeEventDemandToFullMonthDateRange($eventDemand);
191
        }
192
193
        $events = $this->eventRepository->findDemanded($eventDemand);
194
        $weeks = $this->calendarService->getCalendarArray(
195
            $currentMonth,
196
            $currentYear,
197
            strtotime('today midnight'),
198
            (int)($this->settings['calendar']['firstDayOfWeek'] ?? 1),
199
            $events
200
        );
201
202
        $modifyCalendarViewVariablesEvent = new ModifyCalendarViewVariablesEvent(
203
            [
204
                'events' => $events,
205
                'weeks' => $weeks,
206
                'categories' => $this->categoryRepository->findDemanded($categoryDemand),
207
                'locations' => $this->locationRepository->findDemanded($foreignRecordDemand),
208
                'organisators' => $this->organisatorRepository->findDemanded($foreignRecordDemand),
209
                'eventDemand' => $eventDemand,
210
                'overwriteDemand' => $overwriteDemand,
211
                'currentPageId' => $this->getFrontendPageInformation()->getId(),
212
                'firstDayOfMonth' => DateTime::createFromFormat(
213
                    'd.m.Y',
214
                    sprintf('1.%s.%s', $currentMonth, $currentYear)
215
                ),
216
                'previousMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '-1 month'),
217
                'nextMonthConfig' => $this->calendarService->getDateConfig($currentMonth, $currentYear, '+1 month'),
218
                'weekConfig' => $this->calendarService->getWeekConfig($firstDayOfWeek),
219
                'settings' => $this->settings,
220
            ],
221
            $this,
222
            $this->request
223
        );
224
        $this->eventDispatcher->dispatch($modifyCalendarViewVariablesEvent);
225
        $variables = $modifyCalendarViewVariablesEvent->getVariables();
226
227
        $this->view->assignMultiple($variables);
228
        return $this->htmlResponse();
229
    }
230
231
    /**
232
     * Changes the given event demand object to select a date range for a calendar month including days of the previous
233
     * month for the first week and they days for the next month for the last week
234
     */
235
    protected function changeEventDemandToFullMonthDateRange(EventDemand $eventDemand): EventDemand
236
    {
237
        $calendarDateRange = $this->calendarService->getCalendarDateRange(
238
            $eventDemand->getMonth(),
239
            $eventDemand->getYear(),
240
            (int)($this->settings['calendar']['firstDayOfWeek'] ?? 0)
241
        );
242
243
        $eventDemand->setMonth(0);
244
        $eventDemand->setYear(0);
245
246
        $startDate = new DateTime();
247
        $startDate->setTimestamp($calendarDateRange['firstDayOfCalendar']);
248
        $endDate = new DateTime();
249
        $endDate->setTimestamp($calendarDateRange['lastDayOfCalendar']);
250
        $endDate->setTime(23, 59, 59);
251
252
        $searchDemand = GeneralUtility::makeInstance(SearchDemand::class);
253
        $searchDemand->setStartDate($startDate);
254
        $searchDemand->setEndDate($endDate);
255
        $eventDemand->setSearchDemand($searchDemand);
256
257
        return $eventDemand;
258
    }
259
260
    /**
261
     * Detail view for an event
262
     */
263
    public function detailAction(?Event $event = null): ResponseInterface
264
    {
265
        $event = $this->eventEvaluationService->evaluateForDetailAction($this->request, $this->settings, $event);
266
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
267
            return $this->handleEventNotFoundError($this->settings);
268
        }
269
270
        $modifyDetailViewVariablesEvent = new ModifyDetailViewVariablesEvent(
271
            [
272
                'event' => $event,
273
                'settings' => $this->settings,
274
            ],
275
            $this,
276
            $this->request
277
        );
278
        $this->eventDispatcher->dispatch($modifyDetailViewVariablesEvent);
279
        $variables = $modifyDetailViewVariablesEvent->getVariables();
280
281
        $this->view->assignMultiple($variables);
282
        if ($event !== null) {
283
            $cacheDataCollector = $this->request->getAttribute('frontend.cache.collector');
284
            $this->eventCacheService->addCacheTagsByEventRecords($cacheDataCollector, [$event]);
285
        }
286
287
        return $this->htmlResponse();
288
    }
289
290
    /**
291
     * Error handling if event is not found
292
     */
293
    protected function handleEventNotFoundError(array $settings): ResponseInterface
294
    {
295
        if (empty($settings['event']['errorHandling'])) {
296
            throw new Exception('Event errorHandling not configured. Please check settings.event.errorHandling', 1671205677);
297
        }
298
299
        $configuration = GeneralUtility::trimExplode(',', $settings['event']['errorHandling'], true);
300
301
        switch ($configuration[0]) {
302
            case 'redirectToListView':
303
                $listPid = (int)($settings['listPid'] ?? 0) > 0 ? (int)$settings['listPid'] : 1;
304
                return $this->redirect('list', null, null, null, $listPid);
305
            case 'pageNotFoundHandler':
306
                $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
307
                    $this->request,
308
                    'Event not found.'
309
                );
310
                throw new PropagateResponseException($response, 1631261423);
311
            case 'showStandaloneTemplate':
312
            default:
313
                $status = (int)($configuration[2] ?? 200);
314
                $viewFactoryData = new ViewFactoryData(
315
                    templatePathAndFilename: GeneralUtility::getFileAbsFileName($configuration[1]),
316
                    request: $this->request,
317
                );
318
                $view = $this->viewFactory->create($viewFactoryData);
319
320
                $response = $this->responseFactory->createResponse()
321
                    ->withStatus($status)
322
                    ->withHeader('Content-Type', 'text/html; charset=utf-8');
323
                $response->getBody()->write($view->render());
324
                return $response;
325
        }
326
    }
327
328
    /**
329
     * Initiates the iCalendar download for the given event
330
     *
331
     * @return mixed
332
     */
333
    public function icalDownloadAction(?Event $event = null)
334
    {
335
        $event = $this->eventEvaluationService->evaluateForIcalDownloadAction($this->request, $this->settings, $event);
336
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
337
            return $this->handleEventNotFoundError($this->settings);
338
        }
339
        $this->icalendarService->downloadiCalendarFile($this->request, $event);
0 ignored issues
show
Bug introduced by
It seems like $event can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...downloadiCalendarFile() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

339
        $this->icalendarService->downloadiCalendarFile($this->request, /** @scrutinizer ignore-type */ $event);
Loading history...
340
        exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
341
    }
342
343
    /**
344
     * Registration view for an event
345
     */
346
    public function registrationAction(?Event $event = null): ResponseInterface
347
    {
348
        $event = $this->eventEvaluationService->evaluateForRegistrationAction($this->request, $this->settings, $event);
349
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
350
            return $this->handleEventNotFoundError($this->settings);
351
        }
352
        if ($event->getRestrictPaymentMethods()) {
353
            $paymentMethods = $this->paymentService->getRestrictedPaymentMethods($event);
0 ignored issues
show
Bug introduced by
It seems like $event can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...trictedPaymentMethods() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

353
            $paymentMethods = $this->paymentService->getRestrictedPaymentMethods(/** @scrutinizer ignore-type */ $event);
Loading history...
354
        } else {
355
            $paymentMethods = $this->paymentService->getPaymentMethods();
356
        }
357
358
        $modifyRegistrationViewVariablesEvent = new ModifyRegistrationViewVariablesEvent(
359
            [
360
                'event' => $event,
361
                'paymentMethods' => $paymentMethods,
362
                'settings' => $this->settings,
363
            ],
364
            $this,
365
            $this->request
366
        );
367
        $this->eventDispatcher->dispatch($modifyRegistrationViewVariablesEvent);
368
        $variables = $modifyRegistrationViewVariablesEvent->getVariables();
369
        $this->view->assignMultiple($variables);
370
371
        return $this->htmlResponse();
372
    }
373
374
    /**
375
     * Removes all possible spamcheck fields (which do not belong to the domain model) from arguments.
376
     */
377
    protected function removePossibleSpamCheckFieldsFromArguments(): void
378
    {
379
        $arguments = $this->request->getArguments();
380
        if (!isset($arguments['event'])) {
381
            return;
382
        }
383
384
        // Remove a possible honeypot field
385
        $honeypotField = 'hp' . (int)$arguments['event'];
386
        if (isset($arguments['registration'][$honeypotField])) {
387
            unset($arguments['registration'][$honeypotField]);
388
        }
389
390
        // Remove a possible challenge/response field
391
        if (isset($arguments['registration']['cr-response'])) {
392
            unset($arguments['registration']['cr-response']);
393
        }
394
395
        $this->request = $this->request->withArguments($arguments);
0 ignored issues
show
Bug Best Practice introduced by
The property request does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
396
    }
397
398
    /**
399
     * Processes incoming registrations fields and adds field values to arguments
400
     */
401
    protected function setRegistrationFieldValuesToArguments(): void
402
    {
403
        $arguments = $this->request->getArguments();
404
        if (!isset($arguments['event'])) {
405
            return;
406
        }
407
408
        /** @var Event|null $event */
409
        $event = $this->eventRepository->findByUid((int)$this->request->getArgument('event'));
410
        if (!is_a($event, Event::class)) {
411
            return;
412
        }
413
414
        $registrationMvcArgument = $this->arguments->getArgument('registration');
415
        $propertyMapping = $registrationMvcArgument->getPropertyMappingConfiguration();
416
        $propertyMapping->allowProperties('fieldValues');
417
        $propertyMapping->allowCreationForSubProperty('fieldValues');
418
        $propertyMapping->allowModificationForSubProperty('fieldValues');
419
420
        // Set event to registration (required for validation)
421
        $propertyMapping->allowProperties('event');
422
        $propertyMapping->allowCreationForSubProperty('event');
423
        $propertyMapping->allowModificationForSubProperty('event');
424
        $arguments['registration']['event'] = (int)$this->request->getArgument('event');
425
426
        if (count($event->getRegistrationFieldsUids()) === 0) {
427
            // Set arguments to request, so event is set for event
428
            $this->request = $this->request->withArguments($arguments);
0 ignored issues
show
Bug Best Practice introduced by
The property request does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
429
            return;
430
        }
431
432
        // allow creation of new objects (for validation)
433
        $propertyMapping->setTypeConverterOptions(
434
            PersistentObjectConverter::class,
435
            [
436
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => true,
437
                PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED => true,
438
            ]
439
        );
440
441
        $index = 0;
442
        foreach ((array)($arguments['registration']['fields'] ?? []) as $fieldUid => $value) {
443
            // Only accept registration fields of the current event
444
            if (!in_array((int)$fieldUid, $event->getRegistrationFieldsUids(), true)) {
445
                continue;
446
            }
447
448
            // allow subvalues in new property mapper
449
            $propertyMapping->forProperty('fieldValues')->allowProperties($index);
450
            $propertyMapping->forProperty('fieldValues.' . $index)->allowAllProperties();
451
            $propertyMapping->allowCreationForSubProperty('fieldValues.' . $index);
452
            $propertyMapping->allowModificationForSubProperty('fieldValues.' . $index);
453
454
            if (is_array($value)) {
455
                if (empty($value)) {
456
                    $value = '';
457
                } else {
458
                    $value = json_encode($value);
459
                }
460
            }
461
462
            /** @var Registration\Field $field */
463
            $field = $this->fieldRepository->findByUid((int)$fieldUid);
464
465
            $arguments['registration']['fieldValues'][$index] = [
466
                'pid' => $field->getPid(),
467
                'value' => $value,
468
                'field' => (string)$fieldUid,
469
                'valueType' => $field->getValueType(),
470
            ];
471
472
            $index++;
473
        }
474
475
        // Remove temporary "fields" field
476
        if (isset($arguments['registration']['fields'])) {
477
            $arguments = ArrayUtility::removeByPath($arguments, 'registration/fields');
478
        }
479
        $this->request = $this->request->withArguments($arguments);
480
    }
481
482
    /**
483
     * Initialize arguments for saveRegistrationAction and ensures, action is only called via POST
484
     */
485
    public function initializeSaveRegistrationAction(): void
486
    {
487
        if ($this->request->getMethod() !== 'POST') {
488
            $response = GeneralUtility::makeInstance(ErrorController::class)->accessDeniedAction(
489
                $this->request,
490
                'HTTP method is not allowed'
491
            );
492
            throw new PropagateResponseException($response, 1726573183);
493
        }
494
495
        $this->arguments->getArgument('registration')
496
            ->getPropertyMappingConfiguration()->forProperty('dateOfBirth')
497
            ->setTypeConverterOption(
498
                DateTimeConverter::class,
499
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
500
                $this->settings['registration']['formatDateOfBirth'] ?? 'd.m.Y'
501
            );
502
        $this->removePossibleSpamCheckFieldsFromArguments();
503
        $this->setRegistrationFieldValuesToArguments();
504
    }
505
506
    /**
507
     * Saves the registration
508
     */
509
    #[Extbase\Validate([
510
        'validator' => RegistrationFieldValidator::class,
511
        'param' => 'registration',
512
    ])]
513
    #[Extbase\Validate([
514
        'validator' => RegistrationValidator::class,
515
        'param' => 'registration',
516
    ])]
517
    public function saveRegistrationAction(Registration $registration, Event $event): ResponseInterface
518
    {
519
        $event = $this->eventEvaluationService->evaluateForSaveRegistrationAction(
520
            $this->request,
521
            $this->settings,
522
            $event
523
        );
524
        if (is_null($event) && isset($this->settings['event']['errorHandling'])) {
525
            return $this->handleEventNotFoundError($this->settings);
526
        }
527
        $autoConfirmation = (bool)($this->settings['registration']['autoConfirmation'] ?? false) ||
528
            $event->getEnableAutoconfirm();
529
        [$success, $result] = $this->registrationService->checkRegistrationSuccess($event, $registration);
0 ignored issues
show
Bug introduced by
It seems like $event can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...ckRegistrationSuccess() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

529
        [$success, $result] = $this->registrationService->checkRegistrationSuccess(/** @scrutinizer ignore-type */ $event, $registration);
Loading history...
530
531
        // Save registration if no errors
532
        $registrationUid = 0;
533
        if ($success) {
534
            $isWaitlistRegistration = $this->registrationService->isWaitlistRegistration(
535
                $event,
0 ignored issues
show
Bug introduced by
It seems like $event can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...sWaitlistRegistration() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

535
                /** @scrutinizer ignore-type */ $event,
Loading history...
536
                $registration->getAmountOfRegistrations()
537
            );
538
            $linkValidity = (int)($this->settings['confirmation']['linkValidity'] ?? 3600);
539
            if ($linkValidity === 0) {
540
                // Use 3600 seconds as default value if not set or zero
541
                $linkValidity = 3600;
542
            }
543
            $confirmationUntil = new DateTime();
544
            $confirmationUntil->add(new DateInterval('PT' . $linkValidity . 'S'));
545
            $price = $this->registrationService->evaluateRegistrationPrice($event, $registration, $this->request);
0 ignored issues
show
Bug introduced by
It seems like $event can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...uateRegistrationPrice() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

545
            $price = $this->registrationService->evaluateRegistrationPrice(/** @scrutinizer ignore-type */ $event, $registration, $this->request);
Loading history...
546
547
            $registration->setEvent($event);
548
            $registration->setPid($event->getPid());
549
            $registration->setRegistrationDate(new DateTime());
550
            $registration->setConfirmationUntil($confirmationUntil);
551
            $registration->setLanguage($this->getCurrentLanguageCode());
552
            $registration->setFeUser($this->registrationService->getCurrentFeUserObject());
553
            $registration->setWaitlist($isWaitlistRegistration);
554
            $registration->setPrice($price);
555
556
            $this->registrationRepository->add($registration);
557
558
            // Persist registration, so we have an UID
559
            $this->persistAll();
560
            $registrationUid = $registration->getUid();
561
562
            if ($isWaitlistRegistration) {
563
                $messageType = MessageType::REGISTRATION_WAITLIST_NEW;
564
            } else {
565
                $messageType = MessageType::REGISTRATION_NEW;
566
            }
567
568
            $this->eventDispatcher->dispatch(new AfterRegistrationSavedEvent($registration, $this, $this->request));
569
570
            // Send notifications to user and admin if confirmation link should be sent
571
            if (!$autoConfirmation) {
572
                $this->notificationService->sendUserMessage(
573
                    $this->request,
574
                    $event,
0 ignored issues
show
Bug introduced by
It seems like $event can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...vice::sendUserMessage() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

574
                    /** @scrutinizer ignore-type */ $event,
Loading history...
575
                    $registration,
576
                    $this->settings,
577
                    $messageType
578
                );
579
                $this->notificationService->sendAdminMessage(
580
                    $this->request,
581
                    $event,
0 ignored issues
show
Bug introduced by
It seems like $event can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...ice::sendAdminMessage() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

581
                    /** @scrutinizer ignore-type */ $event,
Loading history...
582
                    $registration,
583
                    $this->settings,
584
                    $messageType
585
                );
586
            }
587
588
            // Create given amount of registrations if necessary
589
            $modifyCreateDependingRegistrationsEvent = new ModifyCreateDependingRegistrationsEvent(
590
                $registration,
591
                ($registration->getAmountOfRegistrations() > 1),
592
                $this,
593
                $this->request
594
            );
595
            $this->eventDispatcher->dispatch($modifyCreateDependingRegistrationsEvent);
596
            $createDependingRegistrations = $modifyCreateDependingRegistrationsEvent->getCreateDependingRegistrations();
597
            if ($createDependingRegistrations) {
598
                $this->registrationService->createDependingRegistrations($registration);
599
            }
600
601
            // Flush page cache for event, since new registration has been added
602
            $this->eventCacheService->flushEventCache($event->getUid(), $event->getPid());
603
        }
604
605
        if ($autoConfirmation && $success) {
606
            return $this->redirect(
607
                'confirmRegistration',
608
                null,
609
                null,
610
                [
611
                    'reguid' => $registration->getUid(),
612
                    'hmac' => $this->hashService->hmac(
613
                        'reg-' . $registration->getUid(),
614
                        HashScope::RegistrationUid->value
615
                    ),
616
                ]
617
            );
618
        }
619
620
        return $this->redirect(
621
            'saveRegistrationResult',
622
            null,
623
            null,
624
            [
625
                'result' => $result,
626
                'eventuid' => $event->getUid(),
627
                'reguid' => $registrationUid,
628
                'hmac' => $this->hashService->hmac(
629
                    'event-' . $event->getUid() . '-reg-' . $registrationUid,
630
                    HashScope::SaveRegistrationResult->value
631
                ),
632
            ]
633
        );
634
    }
635
636
    /**
637
     * Shows the result of the saveRegistrationAction
638
     */
639
    public function saveRegistrationResultAction(int $result, int $eventuid, string $hmac): ResponseInterface
640
    {
641
        $reguid = $this->request->hasArgument('reguid') ? (int)$this->request->getArgument('reguid') : 0;
642
643
        $event = null;
644
        $registration = null;
645
        $failed = true;
646
647
        switch ($result) {
648
            case RegistrationResult::REGISTRATION_SUCCESSFUL:
649
                $messageKey = 'event.message.registrationsuccessful';
650
                $titleKey = 'registrationResult.title.successful';
651
                $failed = false;
652
                break;
653
            case RegistrationResult::REGISTRATION_SUCCESSFUL_WAITLIST:
654
                $messageKey = 'event.message.registrationwaitlistsuccessful';
655
                $titleKey = 'registrationWaitlistResult.title.successful';
656
                $failed = false;
657
                break;
658
            case RegistrationResult::REGISTRATION_FAILED_EVENT_EXPIRED:
659
                $messageKey = 'event.message.registrationfailedeventexpired';
660
                $titleKey = 'registrationResult.title.failed';
661
                break;
662
            case RegistrationResult::REGISTRATION_FAILED_EVENT_ENDED:
663
                $messageKey = 'event.message.registrationfailedeventended';
664
                $titleKey = 'registrationResult.title.failed';
665
                break;
666
            case RegistrationResult::REGISTRATION_FAILED_MAX_PARTICIPANTS:
667
                $messageKey = 'event.message.registrationfailedmaxparticipants';
668
                $titleKey = 'registrationResult.title.failed';
669
                break;
670
            case RegistrationResult::REGISTRATION_NOT_ENABLED:
671
                $messageKey = 'event.message.registrationfailednotenabled';
672
                $titleKey = 'registrationResult.title.failed';
673
                break;
674
            case RegistrationResult::REGISTRATION_FAILED_DEADLINE_EXPIRED:
675
                $messageKey = 'event.message.registrationfaileddeadlineexpired';
676
                $titleKey = 'registrationResult.title.failed';
677
                break;
678
            case RegistrationResult::REGISTRATION_FAILED_NOT_ENOUGH_FREE_PLACES:
679
                $messageKey = 'event.message.registrationfailednotenoughfreeplaces';
680
                $titleKey = 'registrationResult.title.failed';
681
                break;
682
            case RegistrationResult::REGISTRATION_FAILED_MAX_AMOUNT_REGISTRATIONS_EXCEEDED:
683
                $messageKey = 'event.message.registrationfailedmaxamountregistrationsexceeded';
684
                $titleKey = 'registrationResult.title.failed';
685
                break;
686
            case RegistrationResult::REGISTRATION_FAILED_EMAIL_NOT_UNIQUE:
687
                $messageKey = 'event.message.registrationfailedemailnotunique';
688
                $titleKey = 'registrationResult.title.failed';
689
                break;
690
            default:
691
                $messageKey = '';
692
                $titleKey = '';
693
        }
694
695
        $isValidHmac = $this->hashService->validateHmac(
696
            'event-' . $eventuid . '-reg-' . $reguid,
697
            HashScope::SaveRegistrationResult->value,
698
            $hmac
699
        );
700
        if (!$isValidHmac) {
701
            $messageKey = 'event.message.registrationsuccessfulwrongeventhmac';
702
            $titleKey = 'registrationResult.title.failed';
703
        } else {
704
            $event = $this->eventRepository->findByUid($eventuid);
705
            $registration = $this->registrationRepository->findByUid($reguid);
706
        }
707
708
        $this->view->assignMultiple([
709
            'messageKey' => $messageKey,
710
            'titleKey' => $titleKey,
711
            'event' => $event,
712
            'registration' => $registration,
713
            'result' => $result,
714
            'failed' => $failed,
715
        ]);
716
717
        return $this->htmlResponse();
718
    }
719
720
    /**
721
     * Shows the verify confirmation registration view, where the user has to submit a form to finally
722
     * confirm the registration
723
     */
724
    public function verifyConfirmRegistrationAction(int $reguid, string $hmac): ResponseInterface
725
    {
726
        /* @var $registration Registration */
727
        [$failed, $registration, $messageKey, $titleKey] = $this->registrationService->checkConfirmRegistration(
728
            $reguid,
729
            $hmac
730
        );
731
732
        $variables = [
733
            'reguid' => $reguid,
734
            'hmac' => $hmac,
735
            'confirmationPossible' => $registration && !$registration->getConfirmed(),
736
            'failed' => $failed,
737
            'messageKey' => $messageKey,
738
            'titleKey' => $titleKey,
739
            'event' => $registration?->getEvent(),
740
            'registration' => $registration,
741
            'settings' => $this->settings,
742
        ];
743
744
        $this->view->assignMultiple($variables);
745
746
        return $this->htmlResponse();
747
    }
748
749
    /**
750
     * Confirms the registration if possible and sends emails to admin and user
751
     */
752
    public function confirmRegistrationAction(int $reguid, string $hmac): ResponseInterface
753
    {
754
        $event = null;
755
756
        /* @var $registration Registration */
757
        [$failed, $registration, $messageKey, $titleKey] = $this->registrationService->checkConfirmRegistration(
758
            $reguid,
759
            $hmac
760
        );
761
762
        if ($failed === false) {
763
            $registration->setConfirmed(true);
764
            $event = $registration->getEvent();
765
            $this->registrationRepository->update($registration);
766
767
            $this->eventDispatcher->dispatch(new AfterRegistrationConfirmedEvent($registration, $this, $this->request));
768
769
            $messageType = MessageType::REGISTRATION_CONFIRMED;
770
            if ($registration->getWaitlist()) {
771
                $messageType = MessageType::REGISTRATION_WAITLIST_CONFIRMED;
772
            }
773
774
            // Send notifications to user and admin
775
            $this->notificationService->sendUserMessage(
776
                $this->request,
777
                $registration->getEvent(),
0 ignored issues
show
Bug introduced by
It seems like $registration->getEvent() can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...vice::sendUserMessage() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

777
                /** @scrutinizer ignore-type */ $registration->getEvent(),
Loading history...
778
                $registration,
779
                $this->settings,
780
                $messageType
781
            );
782
            $this->notificationService->sendAdminMessage(
783
                $this->request,
784
                $registration->getEvent(),
0 ignored issues
show
Bug introduced by
It seems like $registration->getEvent() can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...ice::sendAdminMessage() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

784
                /** @scrutinizer ignore-type */ $registration->getEvent(),
Loading history...
785
                $registration,
786
                $this->settings,
787
                $messageType
788
            );
789
790
            // Confirm registrations depending on main registration if necessary
791
            if ($registration->getAmountOfRegistrations() > 1) {
792
                $this->registrationService->confirmDependingRegistrations($registration);
793
            }
794
        }
795
796
        // Redirect to payment provider if payment/redirect is enabled.
797
        // Skip if the registration is a waitlist registration, since it is not sure, if the user will participate.
798
        $paymentPid = (int)($this->settings['paymentPid'] ?? 0);
799
        $paymentRedirectResponse = null;
800
        $processRedirect = !$failed &&
801
            $paymentPid > 0 &&
802
            $registration &&
803
            !$registration->getWaitlist() &&
804
            $this->registrationService->redirectPaymentEnabled($registration);
805
        if ($processRedirect) {
806
            $paymentRedirectResponse = $this->getRedirectToPaymentResponse($paymentPid, $registration);
807
        }
808
809
        if ($paymentRedirectResponse instanceof ResponseInterface) {
810
            return $paymentRedirectResponse;
811
        }
812
813
        $modifyConfirmRegistrationViewVariablesEvent = new ModifyConfirmRegistrationViewVariablesEvent(
814
            [
815
                'failed' => $failed,
816
                'messageKey' => $messageKey,
817
                'titleKey' => $titleKey,
818
                'event' => $event,
819
                'registration' => $registration,
820
                'settings' => $this->settings,
821
            ],
822
            $this,
823
            $this->request
824
        );
825
        $this->eventDispatcher->dispatch($modifyConfirmRegistrationViewVariablesEvent);
826
        $variables = $modifyConfirmRegistrationViewVariablesEvent->getVariables();
827
        $this->view->assignMultiple($variables);
828
829
        return $this->htmlResponse();
830
    }
831
832
    /**
833
     * Returns a response object to the given payment PID. Extension authors can use ProcessRedirectToPaymentEvent
834
     * PSR-14 event to intercept the redirect response.
835
     */
836
    private function getRedirectToPaymentResponse(int $paymentPid, Registration $registration): ?ResponseInterface
837
    {
838
        $processRedirectToPaymentEvent = new ProcessRedirectToPaymentEvent($registration, $this, $this->request);
839
        $this->eventDispatcher->dispatch($processRedirectToPaymentEvent);
840
        if ($processRedirectToPaymentEvent->getProcessRedirect()) {
841
            $this->uriBuilder->reset()
842
                ->setTargetPageUid($paymentPid);
843
            $uri = $this->uriBuilder->uriFor(
844
                'redirect',
845
                [
846
                    'registration' => $registration,
847
                    'hmac' => $this->hashService->hmac(
848
                        'redirectAction-' . $registration->getUid(),
849
                        HashScope::PaymentAction->value
850
                    ),
851
                ],
852
                'Payment',
853
                'sfeventmgt',
854
                'Pipayment'
855
            );
856
            return $this->redirectToUri($uri);
857
        }
858
859
        return null;
860
    }
861
862
    /**
863
     * Shows the verify cancel registration view, where the user has to submit a form to finally cancel the registration
864
     */
865
    public function verifyCancelRegistrationAction(int $reguid, string $hmac): ResponseInterface
866
    {
867
        /* @var $registration Registration */
868
        [$failed, $registration, $messageKey, $titleKey] = $this->registrationService->checkCancelRegistration(
869
            $reguid,
870
            $hmac
871
        );
872
873
        $variables = [
874
            'reguid' => $reguid,
875
            'hmac' => $hmac,
876
            'cancellationPossible' => !$failed,
877
            'failed' => $failed,
878
            'messageKey' => $messageKey,
879
            'titleKey' => $titleKey,
880
            'event' => $registration?->getEvent(),
881
            'registration' => $registration,
882
            'settings' => $this->settings,
883
        ];
884
885
        $this->view->assignMultiple($variables);
886
887
        return $this->htmlResponse();
888
    }
889
890
    /**
891
     * Cancels the registration if possible and sends emails to admin and user
892
     */
893
    public function cancelRegistrationAction(int $reguid, string $hmac): ResponseInterface
894
    {
895
        $event = null;
896
897
        /* @var $registration Registration */
898
        [$failed, $registration, $messageKey, $titleKey] = $this->registrationService->checkCancelRegistration(
899
            $reguid,
900
            $hmac
901
        );
902
903
        if ($failed === false) {
904
            $event = $registration->getEvent();
905
906
            // Send notifications (must run before cancelling the registration)
907
            $this->notificationService->sendUserMessage(
908
                $this->request,
909
                $registration->getEvent(),
0 ignored issues
show
Bug introduced by
It seems like $registration->getEvent() can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...vice::sendUserMessage() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

909
                /** @scrutinizer ignore-type */ $registration->getEvent(),
Loading history...
910
                $registration,
911
                $this->settings,
912
                MessageType::REGISTRATION_CANCELLED
913
            );
914
            $this->notificationService->sendAdminMessage(
915
                $this->request,
916
                $registration->getEvent(),
0 ignored issues
show
Bug introduced by
It seems like $registration->getEvent() can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...ice::sendAdminMessage() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

916
                /** @scrutinizer ignore-type */ $registration->getEvent(),
Loading history...
917
                $registration,
918
                $this->settings,
919
                MessageType::REGISTRATION_CANCELLED
920
            );
921
922
            // First cancel depending registrations
923
            $processCancelDependingRegistrations = new ProcessCancelDependingRegistrationsEvent(
924
                $registration,
925
                $registration->getAmountOfRegistrations() > 1,
926
                $this->request
927
            );
928
            $this->eventDispatcher->dispatch($processCancelDependingRegistrations);
929
            if ($processCancelDependingRegistrations->getProcessCancellation()) {
930
                $this->registrationService->cancelDependingRegistrations($registration);
931
            }
932
933
            // Finally cancel registration
934
            $this->registrationRepository->remove($registration);
935
936
            // Persist changes, so following functions can work with $event properties (e.g. amount of registrations)
937
            $this->persistAll();
938
939
            $afterRegistrationCancelledEvent = new AfterRegistrationCancelledEvent(
940
                $registration,
941
                $this,
942
                $this->request
943
            );
944
            $this->eventDispatcher->dispatch($afterRegistrationCancelledEvent);
945
946
            // Dispatch event, so waitlist registrations can be moved up and default move up process can be stopped
947
            $waitlistMoveUpEvent = new WaitlistMoveUpEvent($event, $this, $this->request, true);
0 ignored issues
show
Bug introduced by
It seems like $event can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Eve...eUpEvent::__construct() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

947
            $waitlistMoveUpEvent = new WaitlistMoveUpEvent(/** @scrutinizer ignore-type */ $event, $this, $this->request, true);
Loading history...
948
            $this->eventDispatcher->dispatch($waitlistMoveUpEvent);
949
950
            // Move up waitlist registrations if configured on event basis and if not disabled by $waitlistMoveUpEvent
951
            if ($waitlistMoveUpEvent->getProcessDefaultMoveUp()) {
952
                $this->registrationService->moveUpWaitlistRegistrations($this->request, $event, $this->settings);
0 ignored issues
show
Bug introduced by
It seems like $event can also be of type null; however, parameter $event of DERHANSEN\SfEventMgt\Ser...WaitlistRegistrations() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\Event, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

952
                $this->registrationService->moveUpWaitlistRegistrations($this->request, /** @scrutinizer ignore-type */ $event, $this->settings);
Loading history...
953
            }
954
955
            // Flush page cache for event, since amount of registrations has changed
956
            $this->eventCacheService->flushEventCache($event->getUid(), $event->getPid());
957
        }
958
959
        $modifyCancelRegistrationViewVariablesEvent = new ModifyCancelRegistrationViewVariablesEvent(
960
            [
961
                'failed' => $failed,
962
                'messageKey' => $messageKey,
963
                'titleKey' => $titleKey,
964
                'event' => $event,
965
                'settings' => $this->settings,
966
            ],
967
            $this,
968
            $this->request
969
        );
970
        $this->eventDispatcher->dispatch($modifyCancelRegistrationViewVariablesEvent);
971
        $variables = $modifyCancelRegistrationViewVariablesEvent->getVariables();
972
        $this->view->assignMultiple($variables);
973
974
        return $this->htmlResponse();
975
    }
976
977
    /**
978
     * Set date format for field startDate and endDate
979
     */
980
    public function initializeSearchAction(): void
981
    {
982
        if ($this->settings !== [] && ($this->settings['search']['dateFormat'] ?? false)) {
983
            $this->arguments->getArgument('searchDemand')
984
                ->getPropertyMappingConfiguration()->forProperty('startDate')
985
                ->setTypeConverterOption(
986
                    DateTimeConverter::class,
987
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
988
                    $this->settings['search']['dateFormat']
989
                );
990
            $this->arguments->getArgument('searchDemand')
991
                ->getPropertyMappingConfiguration()->forProperty('endDate')
992
                ->setTypeConverterOption(
993
                    DateTimeConverter::class,
994
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
995
                    $this->settings['search']['dateFormat']
996
                );
997
        }
998
        if ($this->arguments->hasArgument('searchDemand')) {
999
            $propertyMappingConfiguration = $this->arguments->getArgument('searchDemand')
1000
                ->getPropertyMappingConfiguration();
1001
            $propertyMappingConfiguration->allowAllProperties();
1002
            $propertyMappingConfiguration->setTypeConverterOption(
1003
                PersistentObjectConverter::class,
1004
                PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED,
1005
                true
1006
            );
1007
        }
1008
    }
1009
1010
    /**
1011
     * Search view
1012
     */
1013
    public function searchAction(?SearchDemand $searchDemand = null, array $overwriteDemand = []): ResponseInterface
1014
    {
1015
        $eventDemand = EventDemand::createFromSettings($this->settings);
1016
        $eventDemand->setSearchDemand($searchDemand);
1017
        $foreignRecordDemand = ForeignRecordDemand::createFromSettings($this->settings);
1018
        $categoryDemand = CategoryDemand::createFromSettings($this->settings);
1019
1020
        if ($searchDemand !== null) {
1021
            $searchDemand->setFields($this->settings['search']['fields'] ?? '');
1022
1023
            $adjustTime = (bool)($this->settings['search']['adjustTime'] ?? false);
1024
            if ($adjustTime && $searchDemand->getStartDate() !== null) {
1025
                $searchDemand->getStartDate()->setTime(0, 0);
1026
            }
1027
1028
            if ($adjustTime && $searchDemand->getEndDate() !== null) {
1029
                $searchDemand->getEndDate()->setTime(23, 59, 59);
1030
            }
1031
        }
1032
1033
        if ($this->isOverwriteDemand($overwriteDemand)) {
1034
            $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
1035
        }
1036
1037
        $categories = $this->categoryRepository->findDemanded($categoryDemand);
1038
        $locations = $this->locationRepository->findDemanded($foreignRecordDemand);
1039
        $organisators = $this->organisatorRepository->findDemanded($foreignRecordDemand);
1040
        $speakers = $this->speakerRepository->findDemanded($foreignRecordDemand);
1041
        $events = $this->eventRepository->findDemanded($eventDemand);
1042
1043
        $modifySearchViewVariablesEvent = new ModifySearchViewVariablesEvent(
1044
            [
1045
                'events' => $events,
1046
                'categories' => $categories,
1047
                'locations' => $locations,
1048
                'organisators' => $organisators,
1049
                'speakers' => $speakers,
1050
                'searchDemand' => $searchDemand,
1051
                'overwriteDemand' => $overwriteDemand,
1052
                'settings' => $this->settings,
1053
            ],
1054
            $this,
1055
            $this->request,
1056
        );
1057
        $this->eventDispatcher->dispatch($modifySearchViewVariablesEvent);
1058
        $variables = $modifySearchViewVariablesEvent->getVariables();
1059
        $this->view->assignMultiple($variables);
1060
1061
        return $this->htmlResponse();
1062
    }
1063
1064
    /**
1065
     * Returns if a demand object can be overwritten with the given overwriteDemand array
1066
     */
1067
    protected function isOverwriteDemand(array $overwriteDemand): bool
1068
    {
1069
        return (int)($this->settings['disableOverrideDemand'] ?? 0) !== 1 && $overwriteDemand !== [];
1070
    }
1071
1072
    /**
1073
     * Calls persistAll() of the persistenceManager
1074
     */
1075
    protected function persistAll(): void
1076
    {
1077
        GeneralUtility::makeInstance(PersistenceManager::class)->persistAll();
1078
    }
1079
1080
    /**
1081
     * Returns the language code of the current language
1082
     */
1083
    protected function getCurrentLanguageCode(): string
1084
    {
1085
        if ($this->request->getAttribute('language') instanceof SiteLanguage) {
1086
            /** @var SiteLanguage $siteLanguage */
1087
            $siteLanguage = $this->request->getAttribute('language');
1088
            return $siteLanguage->getLocale()->getLanguageCode();
1089
        }
1090
1091
        return '';
1092
    }
1093
}
1094