Passed
Push — master ( 58c4da...af9933 )
by Torben
04:48
created

RegistrationService::updateRegistrationEventUid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 9
c 3
b 0
f 0
nc 1
nop 2
dl 0
loc 13
ccs 0
cts 0
cp 0
crap 2
rs 9.9666
1
<?php
2
3
/*
4
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
5
 *
6
 * For the full copyright and license information, please read the
7
 * LICENSE.txt file that was distributed with this source code.
8
 */
9
10
namespace DERHANSEN\SfEventMgt\Service;
11
12
use DERHANSEN\SfEventMgt\Domain\Model\Event;
13
use DERHANSEN\SfEventMgt\Domain\Model\Registration;
14
use DERHANSEN\SfEventMgt\Event\AfterRegistrationMovedFromWaitlist;
15
use DERHANSEN\SfEventMgt\Payment\AbstractPayment;
16
use DERHANSEN\SfEventMgt\Utility\MessageType;
17
use DERHANSEN\SfEventMgt\Utility\RegistrationResult;
18
use Psr\EventDispatcher\EventDispatcherInterface;
19
use TYPO3\CMS\Core\Database\Connection;
20
use TYPO3\CMS\Core\Database\ConnectionPool;
21
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
22
use TYPO3\CMS\Core\Utility\GeneralUtility;
23
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
24
25
/**
26
 * RegistrationService
27
 */
28
class RegistrationService
29
{
30
    /**
31
     * The object manager
32
     *
33
     * @var \TYPO3\CMS\Extbase\Object\ObjectManager
34
     * */
35
    protected $objectManager;
36
37
    /**
38
     * @var EventDispatcherInterface
39
     */
40
    protected $eventDispatcher;
41
42
    /**
43
     * RegistrationRepository
44
     *
45
     * @var \DERHANSEN\SfEventMgt\Domain\Repository\RegistrationRepository
46
     * */
47
    protected $registrationRepository;
48
49
    /**
50
     * FrontendUserRepository
51
     *
52
     * @var \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
53
     * */
54
    protected $frontendUserRepository;
55
56
    /**
57
     * Hash Service
58
     *
59
     * @var \TYPO3\CMS\Extbase\Security\Cryptography\HashService
60
     * */
61
    protected $hashService;
62
63
    /**
64
     * Payment Service
65
     *
66
     * @var \DERHANSEN\SfEventMgt\Service\PaymentService
67
     * */
68
    protected $paymentService;
69
70
    /**
71
     * Notification Service
72
     *
73
     * @var \DERHANSEN\SfEventMgt\Service\NotificationService
74
     */
75
    protected $notificationService;
76
77
    /**
78 4
     * DI for $frontendUserRepository
79
     *
80 4
     * @param \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository $frontendUserRepository
81 4
     */
82 4
    public function injectFrontendUserRepository(
83
        \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository $frontendUserRepository
84 4
    ) {
85 2
        $this->frontendUserRepository = $frontendUserRepository;
86 2
    }
87 2
88 2
    /**
89
     * DI for $hashService
90 4
     *
91 4
     * @param \TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService
92 4
     */
93
    public function injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)
94
    {
95
        $this->hashService = $hashService;
96
    }
97
98
    /**
99
     * @param \DERHANSEN\SfEventMgt\Service\NotificationService $notificationService
100
     */
101
    public function injectNotificationService(\DERHANSEN\SfEventMgt\Service\NotificationService $notificationService)
102 2
    {
103
        $this->notificationService = $notificationService;
104 2
    }
105 2
106
    /**
107 2
     * DI for $objectManager
108 2
     *
109 2
     * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager
110 2
     */
111 2
    public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager)
112 2
    {
113 2
        $this->objectManager = $objectManager;
114 2
    }
115 2
116 2
    /**
117 2
     * @param EventDispatcherInterface $eventDispatcher
118
     */
119
    public function injectEventDispatcher(EventDispatcherInterface $eventDispatcher)
120
    {
121
        $this->eventDispatcher = $eventDispatcher;
122
    }
123
124
    /**
125
     * DI for $paymentService
126 2
     *
127
     * @param \DERHANSEN\SfEventMgt\Service\PaymentService $paymentService
128 2
     */
129 2
    public function injectPaymentService(\DERHANSEN\SfEventMgt\Service\PaymentService $paymentService)
130
    {
131 2
        $this->paymentService = $paymentService;
132 2
    }
133 2
134 2
    /**
135
     * DI for $registrationRepository
136
     *
137
     * @param \DERHANSEN\SfEventMgt\Domain\Repository\RegistrationRepository $registrationRepository
138
     */
139
    public function injectRegistrationRepository(
140
        \DERHANSEN\SfEventMgt\Domain\Repository\RegistrationRepository $registrationRepository
141
    ) {
142
        $this->registrationRepository = $registrationRepository;
143
    }
144 8
145
    /**
146
     * Duplicates (all public accessable properties) the given registration the
147 8
     * amount of times configured in amountOfRegistrations
148 8
     *
149 8
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
150 8
     */
151
    public function createDependingRegistrations($registration)
152 8
    {
153 2
        $registrations = $registration->getAmountOfRegistrations();
154 2
        for ($i = 1; $i <= $registrations - 1; $i++) {
155 2
            /** @var \DERHANSEN\SfEventMgt\Domain\Model\Registration $newReg */
156 2
            $newReg = $this->objectManager->get(Registration::class);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Object\ObjectManager::get() has been deprecated: since TYPO3 10.4, will be removed in version 12.0 ( Ignorable by Annotation )

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

156
            $newReg = /** @scrutinizer ignore-deprecated */ $this->objectManager->get(Registration::class);

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

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

Loading history...
157 6
            $properties = ObjectAccess::getGettableProperties($registration);
158
            foreach ($properties as $propertyName => $propertyValue) {
159
                ObjectAccess::setProperty($newReg, $propertyName, $propertyValue);
160 8
            }
161 2
            $newReg->setMainRegistration($registration);
162 2
            $newReg->setAmountOfRegistrations(1);
163 2
            $newReg->setIgnoreNotifications(true);
164 2
            $this->registrationRepository->add($newReg);
165
        }
166 8
    }
167 2
168 2
    /**
169 2
     * Confirms all depending registrations based on the given main registration
170 2
     *
171
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
172 8
     */
173 2
    public function confirmDependingRegistrations($registration)
174 2
    {
175 2
        $registrations = $this->registrationRepository->findByMainRegistration($registration);
0 ignored issues
show
Bug introduced by
The method findByMainRegistration() does not exist on DERHANSEN\SfEventMgt\Dom...\RegistrationRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

175
        /** @scrutinizer ignore-call */ 
176
        $registrations = $this->registrationRepository->findByMainRegistration($registration);
Loading history...
176 2
        foreach ($registrations as $foundRegistration) {
177
            /** @var \DERHANSEN\SfEventMgt\Domain\Model\Registration $foundRegistration */
178 8
            $foundRegistration->setConfirmed(true);
179
            $this->registrationRepository->update($foundRegistration);
180
        }
181
    }
182
183
    /**
184 8
     * Checks if the registration can be confirmed and returns an array of variables
185 8
     *
186 8
     * @param int $reguid UID of registration
187
     * @param string $hmac HMAC for parameters
188 8
     *
189
     * @return array
190
     */
191
    public function checkConfirmRegistration($reguid, $hmac)
192
    {
193
        /* @var $registration Registration */
194
        $registration = null;
195
        $failed = false;
196
        $messageKey = 'event.message.confirmation_successful';
197
        $titleKey = 'confirmRegistration.title.successful';
198 2
199
        if (!$this->hashService->validateHmac('reg-' . $reguid, $hmac)) {
200 2
            $failed = true;
201 2
            $messageKey = 'event.message.confirmation_failed_wrong_hmac';
202 2
            $titleKey = 'confirmRegistration.title.failed';
203 2
        } else {
204 2
            $registration = $this->registrationRepository->findByUid($reguid);
205
        }
206
207
        if (!$failed && is_null($registration)) {
208
            $failed = true;
209
            $messageKey = 'event.message.confirmation_failed_registration_not_found';
210
            $titleKey = 'confirmRegistration.title.failed';
211
        }
212
213
        if (!$failed && $registration->getConfirmationUntil() < new \DateTime()) {
214 8
            $failed = true;
215
            $messageKey = 'event.message.confirmation_failed_confirmation_until_expired';
216
            $titleKey = 'confirmRegistration.title.failed';
217 8
        }
218 8
219 8
        if (!$failed && $registration->getConfirmed() === true) {
220 8
            $failed = true;
221
            $messageKey = 'event.message.confirmation_failed_already_confirmed';
222 8
            $titleKey = 'confirmRegistration.title.failed';
223 2
        }
224 2
225 2
        if (!$failed && $registration->getWaitlist()) {
226 2
            $messageKey = 'event.message.confirmation_waitlist_successful';
227 6
            $titleKey = 'confirmRegistrationWaitlist.title.successful';
228
        }
229
230 8
        return [
231 2
            $failed,
232 2
            $registration,
233 2
            $messageKey,
234 2
            $titleKey
235
        ];
236 8
    }
237 2
238 2
    /**
239 2
     * Cancels all depending registrations based on the given main registration
240 2
     *
241
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
242 8
     */
243 8
    public function cancelDependingRegistrations($registration)
244 8
    {
245 2
        $registrations = $this->registrationRepository->findByMainRegistration($registration);
246 2
        foreach ($registrations as $foundRegistration) {
247 2
            $this->registrationRepository->remove($foundRegistration);
248 2
        }
249
    }
250
251 8
    /**
252 8
     * Checks if the registration can be cancelled and returns an array of variables
253 8
     *
254
     * @param int $reguid UID of registration
255 8
     * @param string $hmac HMAC for parameters
256
     *
257
     * @return array
258
     */
259
    public function checkCancelRegistration($reguid, $hmac)
260
    {
261
        /* @var $registration Registration */
262
        $registration = null;
263 10
        $failed = false;
264
        $messageKey = 'event.message.cancel_successful';
265 10
        $titleKey = 'cancelRegistration.title.successful';
266 2
267
        if (!$this->hashService->validateHmac('reg-' . $reguid, $hmac)) {
268 8
            $failed = true;
269
            $messageKey = 'event.message.cancel_failed_wrong_hmac';
270
            $titleKey = 'cancelRegistration.title.failed';
271
        } else {
272
            $registration = $this->registrationRepository->findByUid($reguid);
273
        }
274
275
        if (!$failed && is_null($registration)) {
276
            $failed = true;
277
            $messageKey = 'event.message.cancel_failed_registration_not_found_or_cancelled';
278
            $titleKey = 'cancelRegistration.title.failed';
279
        }
280
281
        if (!$failed && is_null($registration->getEvent())) {
282 38
            $failed = true;
283
            $messageKey = 'event.message.cancel_failed_event_not_found';
284 38
            $titleKey = 'cancelRegistration.title.failed';
285 38
        }
286 4
287 4
        if (!$failed && $registration->getEvent()->getEnableCancel() === false) {
288 38
            $failed = true;
289 4
            $messageKey = 'event.message.confirmation_failed_cancel_disabled';
290 4
            $titleKey = 'cancelRegistration.title.failed';
291 34
        }
292 4
293 4
        if (!$failed && $registration->getEvent()->getCancelDeadline()
294 30
            && $registration->getEvent()->getCancelDeadline() < new \DateTime()
295 26
        ) {
296 26
            $failed = true;
297 4
            $messageKey = 'event.message.cancel_failed_deadline_expired';
298 4
            $titleKey = 'cancelRegistration.title.failed';
299 26
        }
300 22
301 22
        if (!$failed && $registration->getEvent()->getStartdate() < new \DateTime()) {
302 4
            $failed = true;
303 4
            $messageKey = 'event.message.cancel_failed_event_started';
304 22
            $titleKey = 'cancelRegistration.title.failed';
305 4
        }
306 4
307 18
        return [
308 4
            $failed,
309 14
            $registration,
310 4
            $messageKey,
311 4
            $titleKey
312 14
        ];
313 10
    }
314 10
315 2
    /**
316 2
     * Returns the current frontend user object if available
317 38
     *
318
     * @return mixed \TYPO3\CMS\Extbase\Domain\Model\FrontendUser|null
319
     */
320
    public function getCurrentFeUserObject()
321
    {
322
        if (isset($GLOBALS['TSFE']->fe_user->user['uid'])) {
323
            return $this->frontendUserRepository->findByUid($GLOBALS['TSFE']->fe_user->user['uid']);
324
        }
325
326
        return null;
327 4
    }
328
329 4
    /**
330 4
     * Checks, if the registration can successfully be created. Note, that
331
     * $result is passed by reference!
332
     *
333
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
334
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
335
     * @param int $result Result
336
     *
337
     * @return array
338
     */
339 4
    public function checkRegistrationSuccess($event, $registration, $result)
340
    {
341 4
        $success = true;
342 2
        if ($event->getEnableRegistration() === false) {
343
            $success = false;
344
            $result = RegistrationResult::REGISTRATION_NOT_ENABLED;
345
        } elseif ($event->getRegistrationDeadline() != null && $event->getRegistrationDeadline() < new \DateTime()) {
346 2
            $success = false;
347 2
            $result = RegistrationResult::REGISTRATION_FAILED_DEADLINE_EXPIRED;
348 2
        } elseif ($event->getStartdate() < new \DateTime()) {
349
            $success = false;
350
            $result = RegistrationResult::REGISTRATION_FAILED_EVENT_EXPIRED;
351
        } elseif ($event->getRegistrations()->count() >= $event->getMaxParticipants()
352
            && $event->getMaxParticipants() > 0 && !$event->getEnableWaitlist()
353
        ) {
354
            $success = false;
355
            $result = RegistrationResult::REGISTRATION_FAILED_MAX_PARTICIPANTS;
356
        } elseif ($event->getFreePlaces() < $registration->getAmountOfRegistrations()
357
            && $event->getMaxParticipants() > 0 && !$event->getEnableWaitlist()
358
        ) {
359
            $success = false;
360
            $result = RegistrationResult::REGISTRATION_FAILED_NOT_ENOUGH_FREE_PLACES;
361
        } elseif ($event->getMaxRegistrationsPerUser() < $registration->getAmountOfRegistrations()) {
362 14
            $success = false;
363
            $result = RegistrationResult::REGISTRATION_FAILED_MAX_AMOUNT_REGISTRATIONS_EXCEEDED;
364 14
        } elseif ($event->getUniqueEmailCheck() &&
365 6
            $this->emailNotUnique($event, $registration->getEmail())
366
        ) {
367
            $success = false;
368 8
            $result = RegistrationResult::REGISTRATION_FAILED_EMAIL_NOT_UNIQUE;
369 8
        } elseif ($event->getRegistrations()->count() >= $event->getMaxParticipants()
370 2
            && $event->getMaxParticipants() > 0 && $event->getEnableWaitlist()
371 8
        ) {
372 4
            $result = RegistrationResult::REGISTRATION_SUCCESSFUL_WAITLIST;
373 4
        }
374 8
375
        return [$success, $result];
376
    }
377
378
    /**
379
     * Returns if the given email is registered to the given event
380
     *
381
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
382
     * @param string $email
383
     * @return bool
384
     */
385
    protected function emailNotUnique($event, $email)
386
    {
387
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
388
            ->getQueryBuilderForTable('tx_sfeventmgt_domain_model_registration');
389
        $queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
390
        $registrations = $queryBuilder->count('email')
391
            ->from('tx_sfeventmgt_domain_model_registration')
392
            ->where(
393
                $queryBuilder->expr()->eq(
394
                    'event',
395
                    $queryBuilder->createNamedParameter($event->getUid(), Connection::PARAM_INT)
396
                ),
397
                $queryBuilder->expr()->eq(
398
                    'email',
399
                    $queryBuilder->createNamedParameter($email, Connection::PARAM_STR)
400
                )
401
            )
402
            ->execute()
403
            ->fetchColumn();
404
405
        return $registrations >= 1;
406
    }
407
408
    /**
409
     * Returns, if payment redirect for the payment method is enabled
410
     *
411
     * @param Registration $registration
412
     * @return bool
413
     */
414
    public function redirectPaymentEnabled($registration)
415
    {
416
        if ($registration->getEvent()->getEnablePayment() === false) {
417
            return false;
418
        }
419
420
        /** @var AbstractPayment $paymentInstance */
421
        $paymentInstance = $this->paymentService->getPaymentInstance($registration->getPaymentmethod());
422
        if ($paymentInstance !== null && $paymentInstance->isRedirectEnabled()) {
423
            return true;
424
        }
425
426
        return false;
427
    }
428
429
    /**
430
     * Returns if the given amount of registrations for the event will be registrations for the waitlist
431
     * (depending on the total amount of registrations and free places)
432
     *
433
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
434
     * @param int $amountOfRegistrations
435
     * @return bool
436
     */
437
    public function isWaitlistRegistration($event, $amountOfRegistrations)
438
    {
439
        if ($event->getMaxParticipants() === 0 || !$event->getEnableWaitlist()) {
440
            return false;
441
        }
442
443
        $result = false;
444
        if (($event->getFreePlaces() > 0 && $event->getFreePlaces() < $amountOfRegistrations)
445
            || $event->getFreePlaces() <= 0) {
446
            $result = true;
447
        }
448
449
        return $result;
450
    }
451
452
    /**
453
     * Handles the process of moving registration up from the waitlist.
454
     *
455
     * @param Event $event
456
     * @param array $settings
457
     */
458
    public function moveUpWaitlistRegistrations(Event $event, array $settings)
459
    {
460
        // Early return if move up not enabled, no registrations on waitlist or no free places left
461
        if (!$event->getEnableWaitlistMoveup() || $event->getRegistrationsWaitlist()->count() === 0 ||
462
            $event->getFreePlaces() === 0
463
        ) {
464
            return;
465
        }
466
467
        $keepMainRegistrationDependency = $settings['waitlist']['moveUp']['keepMainRegistrationDependency'] ?? false;
468
        $freePlaces = $event->getFreePlaces();
469
        $moveupRegistrations = $this->registrationRepository->findWaitlistMoveUpRegistrations($event);
470
471
        /** @var Registration $registration */
472
        foreach ($moveupRegistrations as $registration) {
473
            $registration->setWaitlist(false);
474
            $registration->setIgnoreNotifications(false);
475
476
            if (!(bool)$keepMainRegistrationDependency) {
477
                $registration->_setProperty('mainRegistration', 0);
478
            }
479
480
            $this->registrationRepository->update($registration);
481
482
            // Send messages to user and admin
483
            $this->notificationService->sendUserMessage(
484
                $event,
485
                $registration,
486
                $settings,
487
                MessageType::REGISTRATION_WAITLIST_MOVE_UP
488
            );
489
            $this->notificationService->sendAdminMessage(
490
                $registration->getEvent(),
491
                $registration,
492
                $settings,
493
                MessageType::REGISTRATION_WAITLIST_MOVE_UP
494
            );
495
496
            $this->eventDispatcher->dispatch(new AfterRegistrationMovedFromWaitlist($registration, $this));
497
498
            $freePlaces--;
499
            if ($freePlaces === 0) {
500
                break;
501
            }
502
        }
503
    }
504
}
505