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

RegistrationService   F

Complexity

Total Complexity 80

Size/Duplication

Total Lines 611
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 14

Importance

Changes 0
Metric Value
wmc 80
lcom 3
cbo 14
dl 0
loc 611
rs 1.989
c 0
b 0
f 0

24 Methods

Rating   Name   Duplication   Size   Complexity  
A injectFrontendUserRepository() 0 5 1
A injectHashService() 0 4 1
A injectNotificationService() 0 4 1
A injectObjectManager() 0 4 1
A injectEventDispatcher() 0 4 1
A injectPaymentService() 0 4 1
A injectRegistrationRepository() 0 5 1
A createDependingRegistrations() 0 17 3
A confirmDependingRegistrations() 0 9 2
B checkConfirmRegistration() 0 46 10
A cancelDependingRegistrations() 0 7 2
B checkCancelRegistration() 0 49 11
A getCurrentFeUserObject() 0 8 2
C checkRegistrationSuccess() 0 38 17
A emailNotUnique() 0 22 1
A redirectPaymentEnabled() 0 14 4
A isWaitlistRegistration() 0 14 6
A fixRegistrationEvent() 0 9 2
A fixRegistationFieldValueLanguage() 0 9 3
A updateRegistrationFieldValueLanguage() 0 14 1
A updateRegistrationEventUid() 0 14 1
A updateEventRegistrationCounters() 0 25 1
A getEventRegistrationCount() 0 21 1
B moveUpWaitlistRegistrations() 0 39 6

How to fix   Complexity   

Complex Class

Complex classes like RegistrationService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RegistrationService, and based on these observations, apply Extract Interface, too.

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\DebugUtility;
23
use TYPO3\CMS\Core\Utility\GeneralUtility;
24
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
25
26
/**
27
 * RegistrationService
28
 *
29
 * @author Torben Hansen <[email protected]>
30
 */
31
class RegistrationService
32
{
33
    /**
34
     * The object manager
35
     *
36
     * @var \TYPO3\CMS\Extbase\Object\ObjectManager
37
     * */
38
    protected $objectManager;
39
40
    /**
41
     * @var EventDispatcherInterface
42
     */
43
    protected $eventDispatcher;
44
45
    /**
46
     * RegistrationRepository
47
     *
48
     * @var \DERHANSEN\SfEventMgt\Domain\Repository\RegistrationRepository
49
     * */
50
    protected $registrationRepository;
51
52
    /**
53
     * FrontendUserRepository
54
     *
55
     * @var \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
56
     * */
57
    protected $frontendUserRepository;
58
59
    /**
60
     * Hash Service
61
     *
62
     * @var \TYPO3\CMS\Extbase\Security\Cryptography\HashService
63
     * */
64
    protected $hashService;
65
66
    /**
67
     * Payment Service
68
     *
69
     * @var \DERHANSEN\SfEventMgt\Service\PaymentService
70
     * */
71
    protected $paymentService;
72
73
    /**
74
     * Notification Service
75
     *
76
     * @var \DERHANSEN\SfEventMgt\Service\NotificationService
77
     */
78
    protected $notificationService;
79
80
    /**
81
     * DI for $frontendUserRepository
82
     *
83
     * @param \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository $frontendUserRepository
84
     */
85
    public function injectFrontendUserRepository(
86
        \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository $frontendUserRepository
87
    ) {
88
        $this->frontendUserRepository = $frontendUserRepository;
89
    }
90
91
    /**
92
     * DI for $hashService
93
     *
94
     * @param \TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService
95
     */
96
    public function injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)
97
    {
98
        $this->hashService = $hashService;
99
    }
100
101
    /**
102
     * @param \DERHANSEN\SfEventMgt\Service\NotificationService $notificationService
103
     */
104
    public function injectNotificationService(\DERHANSEN\SfEventMgt\Service\NotificationService $notificationService)
105
    {
106
        $this->notificationService = $notificationService;
107
    }
108
109
    /**
110
     * DI for $objectManager
111
     *
112
     * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager
113
     */
114
    public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager)
115
    {
116
        $this->objectManager = $objectManager;
117
    }
118
119
    /**
120
     * @param EventDispatcherInterface $eventDispatcher
121
     */
122
    public function injectEventDispatcher(EventDispatcherInterface $eventDispatcher)
123
    {
124
        $this->eventDispatcher = $eventDispatcher;
125
    }
126
127
    /**
128
     * DI for $paymentService
129
     *
130
     * @param \DERHANSEN\SfEventMgt\Service\PaymentService $paymentService
131
     */
132
    public function injectPaymentService(\DERHANSEN\SfEventMgt\Service\PaymentService $paymentService)
133
    {
134
        $this->paymentService = $paymentService;
135
    }
136
137
    /**
138
     * DI for $registrationRepository
139
     *
140
     * @param \DERHANSEN\SfEventMgt\Domain\Repository\RegistrationRepository $registrationRepository
141
     */
142
    public function injectRegistrationRepository(
143
        \DERHANSEN\SfEventMgt\Domain\Repository\RegistrationRepository $registrationRepository
144
    ) {
145
        $this->registrationRepository = $registrationRepository;
146
    }
147
148
    /**
149
     * Duplicates (all public accessable properties) the given registration the
150
     * amount of times configured in amountOfRegistrations
151
     *
152
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
153
     */
154
    public function createDependingRegistrations($registration)
155
    {
156
        $registrations = $registration->getAmountOfRegistrations();
157
        for ($i = 1; $i <= $registrations - 1; $i++) {
158
            /** @var \DERHANSEN\SfEventMgt\Domain\Model\Registration $newReg */
159
            $newReg = $this->objectManager->get(Registration::class);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Object\ObjectManager::get() has been deprecated with message: since TYPO3 10.4, will be removed in version 12.0

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

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

Loading history...
160
            $properties = ObjectAccess::getGettableProperties($registration);
0 ignored issues
show
Documentation introduced by
$registration is of type object<DERHANSEN\SfEvent...ain\Model\Registration>, but the function expects a object<TYPO3\CMS\Extbase\Reflection\object>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
161
            foreach ($properties as $propertyName => $propertyValue) {
162
                ObjectAccess::setProperty($newReg, $propertyName, $propertyValue);
163
            }
164
            $newReg->setMainRegistration($registration);
165
            $newReg->setAmountOfRegistrations(1);
166
            $newReg->setIgnoreNotifications(true);
167
            $newReg->_setProperty('_languageUid', $registration->_getProperty('_languageUid'));
168
            $this->registrationRepository->add($newReg);
169
        }
170
    }
171
172
    /**
173
     * Confirms all depending registrations based on the given main registration
174
     *
175
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
176
     */
177
    public function confirmDependingRegistrations($registration)
178
    {
179
        $registrations = $this->registrationRepository->findByMainRegistration($registration);
0 ignored issues
show
Documentation Bug introduced by
The method findByMainRegistration does not exist on object<DERHANSEN\SfEvent...RegistrationRepository>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
180
        foreach ($registrations as $foundRegistration) {
181
            /** @var \DERHANSEN\SfEventMgt\Domain\Model\Registration $foundRegistration */
182
            $foundRegistration->setConfirmed(true);
183
            $this->registrationRepository->update($foundRegistration);
184
        }
185
    }
186
187
    /**
188
     * Checks if the registration can be confirmed and returns an array of variables
189
     *
190
     * @param int $reguid UID of registration
191
     * @param string $hmac HMAC for parameters
192
     *
193
     * @return array
194
     */
195
    public function checkConfirmRegistration($reguid, $hmac)
196
    {
197
        /* @var $registration Registration */
198
        $registration = null;
199
        $failed = false;
200
        $messageKey = 'event.message.confirmation_successful';
201
        $titleKey = 'confirmRegistration.title.successful';
202
203
        if (!$this->hashService->validateHmac('reg-' . $reguid, $hmac)) {
204
            $failed = true;
205
            $messageKey = 'event.message.confirmation_failed_wrong_hmac';
206
            $titleKey = 'confirmRegistration.title.failed';
207
        } else {
208
            $registration = $this->registrationRepository->findByUid($reguid);
209
        }
210
211
        if (!$failed && is_null($registration)) {
212
            $failed = true;
213
            $messageKey = 'event.message.confirmation_failed_registration_not_found';
214
            $titleKey = 'confirmRegistration.title.failed';
215
        }
216
217
        if (!$failed && $registration->getConfirmationUntil() < new \DateTime()) {
218
            $failed = true;
219
            $messageKey = 'event.message.confirmation_failed_confirmation_until_expired';
220
            $titleKey = 'confirmRegistration.title.failed';
221
        }
222
223
        if (!$failed && $registration->getConfirmed() === true) {
224
            $failed = true;
225
            $messageKey = 'event.message.confirmation_failed_already_confirmed';
226
            $titleKey = 'confirmRegistration.title.failed';
227
        }
228
229
        if (!$failed && $registration->getWaitlist()) {
230
            $messageKey = 'event.message.confirmation_waitlist_successful';
231
            $titleKey = 'confirmRegistrationWaitlist.title.successful';
232
        }
233
234
        return [
235
            $failed,
236
            $registration,
237
            $messageKey,
238
            $titleKey
239
        ];
240
    }
241
242
    /**
243
     * Cancels all depending registrations based on the given main registration
244
     *
245
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
246
     */
247
    public function cancelDependingRegistrations($registration)
248
    {
249
        $registrations = $this->registrationRepository->findByMainRegistration($registration);
0 ignored issues
show
Documentation Bug introduced by
The method findByMainRegistration does not exist on object<DERHANSEN\SfEvent...RegistrationRepository>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
250
        foreach ($registrations as $foundRegistration) {
251
            $this->registrationRepository->remove($foundRegistration);
252
        }
253
    }
254
255
    /**
256
     * Checks if the registration can be cancelled and returns an array of variables
257
     *
258
     * @param int $reguid UID of registration
259
     * @param string $hmac HMAC for parameters
260
     *
261
     * @return array
262
     */
263
    public function checkCancelRegistration($reguid, $hmac)
264
    {
265
        /* @var $registration Registration */
266
        $registration = null;
267
        $failed = false;
268
        $messageKey = 'event.message.cancel_successful';
269
        $titleKey = 'cancelRegistration.title.successful';
270
271
        if (!$this->hashService->validateHmac('reg-' . $reguid, $hmac)) {
272
            $failed = true;
273
            $messageKey = 'event.message.cancel_failed_wrong_hmac';
274
            $titleKey = 'cancelRegistration.title.failed';
275
        } else {
276
            $registration = $this->registrationRepository->findByUid($reguid);
277
        }
278
279
        if (!$failed && is_null($registration)) {
280
            $failed = true;
281
            $messageKey = 'event.message.cancel_failed_registration_not_found_or_cancelled';
282
            $titleKey = 'cancelRegistration.title.failed';
283
        }
284
285
        if (!$failed && $registration->getEvent()->getEnableCancel() === false) {
286
            $failed = true;
287
            $messageKey = 'event.message.confirmation_failed_cancel_disabled';
288
            $titleKey = 'cancelRegistration.title.failed';
289
        }
290
291
        if (!$failed && $registration->getEvent()->getCancelDeadline() > 0
292
            && $registration->getEvent()->getCancelDeadline() < new \DateTime()
293
        ) {
294
            $failed = true;
295
            $messageKey = 'event.message.cancel_failed_deadline_expired';
296
            $titleKey = 'cancelRegistration.title.failed';
297
        }
298
299
        if (!$failed && $registration->getEvent()->getStartdate() < new \DateTime()) {
300
            $failed = true;
301
            $messageKey = 'event.message.cancel_failed_event_started';
302
            $titleKey = 'cancelRegistration.title.failed';
303
        }
304
305
        return [
306
            $failed,
307
            $registration,
308
            $messageKey,
309
            $titleKey
310
        ];
311
    }
312
313
    /**
314
     * Returns the current frontend user object if available
315
     *
316
     * @return mixed \TYPO3\CMS\Extbase\Domain\Model\FrontendUser|null
317
     */
318
    public function getCurrentFeUserObject()
319
    {
320
        if (isset($GLOBALS['TSFE']->fe_user->user['uid'])) {
321
            return $this->frontendUserRepository->findByUid($GLOBALS['TSFE']->fe_user->user['uid']);
322
        }
323
324
        return null;
325
    }
326
327
    /**
328
     * Checks, if the registration can successfully be created. Note, that
329
     * $result is passed by reference!
330
     *
331
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
332
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
333
     * @param int $result Result
334
     *
335
     * @return array
336
     */
337
    public function checkRegistrationSuccess($event, $registration, $result)
338
    {
339
        $success = true;
340
        if ($event->getEnableRegistration() === false) {
341
            $success = false;
342
            $result = RegistrationResult::REGISTRATION_NOT_ENABLED;
343
        } elseif ($event->getRegistrationDeadline() != null && $event->getRegistrationDeadline() < new \DateTime()) {
344
            $success = false;
345
            $result = RegistrationResult::REGISTRATION_FAILED_DEADLINE_EXPIRED;
346
        } elseif ($event->getStartdate() < new \DateTime()) {
347
            $success = false;
348
            $result = RegistrationResult::REGISTRATION_FAILED_EVENT_EXPIRED;
349
        } elseif ($event->getRegistrations()->count() >= $event->getMaxParticipants()
350
            && $event->getMaxParticipants() > 0 && !$event->getEnableWaitlist()
351
        ) {
352
            $success = false;
353
            $result = RegistrationResult::REGISTRATION_FAILED_MAX_PARTICIPANTS;
354
        } elseif ($event->getFreePlaces() < $registration->getAmountOfRegistrations()
355
            && $event->getMaxParticipants() > 0 && !$event->getEnableWaitlist()
356
        ) {
357
            $success = false;
358
            $result = RegistrationResult::REGISTRATION_FAILED_NOT_ENOUGH_FREE_PLACES;
359
        } elseif ($event->getMaxRegistrationsPerUser() < $registration->getAmountOfRegistrations()) {
360
            $success = false;
361
            $result = RegistrationResult::REGISTRATION_FAILED_MAX_AMOUNT_REGISTRATIONS_EXCEEDED;
362
        } elseif ($event->getUniqueEmailCheck() &&
363
            $this->emailNotUnique($event, $registration->getEmail())
364
        ) {
365
            $success = false;
366
            $result = RegistrationResult::REGISTRATION_FAILED_EMAIL_NOT_UNIQUE;
367
        } elseif ($event->getRegistrations()->count() >= $event->getMaxParticipants()
368
            && $event->getMaxParticipants() > 0 && $event->getEnableWaitlist()
369
        ) {
370
            $result = RegistrationResult::REGISTRATION_SUCCESSFUL_WAITLIST;
371
        }
372
373
        return [$success, $result];
374
    }
375
376
    /**
377
     * Returns if the given email is registered to the given event
378
     *
379
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
380
     * @param string $email
381
     * @return bool
382
     */
383
    protected function emailNotUnique($event, $email)
384
    {
385
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
386
            ->getQueryBuilderForTable('tx_sfeventmgt_domain_model_registration');
387
        $queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
388
        $registrations = $queryBuilder->count('email')
389
            ->from('tx_sfeventmgt_domain_model_registration')
390
            ->where(
391
                $queryBuilder->expr()->eq(
392
                    'event',
393
                    $queryBuilder->createNamedParameter($event->getUid(), Connection::PARAM_INT)
394
                ),
395
                $queryBuilder->expr()->eq(
396
                    'email',
397
                    $queryBuilder->createNamedParameter($email, Connection::PARAM_STR)
398
                )
399
            )
400
            ->execute()
401
            ->fetchColumn();
402
403
        return $registrations >= 1;
404
    }
405
406
    /**
407
     * Returns, if payment redirect for the payment method is enabled
408
     *
409
     * @param Registration $registration
410
     * @return bool
411
     */
412
    public function redirectPaymentEnabled($registration)
413
    {
414
        if ($registration->getEvent()->getEnablePayment() === false) {
415
            return false;
416
        }
417
418
        /** @var AbstractPayment $paymentInstance */
419
        $paymentInstance = $this->paymentService->getPaymentInstance($registration->getPaymentmethod());
420
        if ($paymentInstance !== null && $paymentInstance->isRedirectEnabled()) {
421
            return true;
422
        }
423
424
        return false;
425
    }
426
427
    /**
428
     * Returns if the given amount of registrations for the event will be registrations for the waitlist
429
     * (depending on the total amount of registrations and free places)
430
     *
431
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
432
     * @param int $amountOfRegistrations
433
     * @return bool
434
     */
435
    public function isWaitlistRegistration($event, $amountOfRegistrations)
436
    {
437
        if ($event->getMaxParticipants() === 0 || !$event->getEnableWaitlist()) {
438
            return false;
439
        }
440
441
        $result = false;
442
        if (($event->getFreePlaces() > 0 && $event->getFreePlaces() < $amountOfRegistrations)
443
            || $event->getFreePlaces() <= 0) {
444
            $result = true;
445
        }
446
447
        return $result;
448
    }
449
450
    /**
451
     * Fixes the event uid of a registration if the event has been saved as a child of a translated event.
452
     *
453
     * Since TYPO3 9.5 (#82363), registrations for events are saved to the translated event record
454
     *
455
     * Example:
456
     *
457
     * When a registration is saved for a translated event, the registration $registration->setEvent($event) will
458
     * now save the UID of the translated event instead of the uid of the event in default language.
459
     *
460
     * This behavior breaks limitations on events (e.g. max participants). Therefore, the registration must always
461
     * be related to the default event language (Extbase behavior before TYPO3 9.5)
462
     *
463
     * @param Registration $registration
464
     * @param Event $event
465
     */
466
    public function fixRegistrationEvent(Registration $registration, Event $event)
467
    {
468
        // Early return when event is in default language
469
        if ((int)$event->_getProperty('_languageUid') === 0) {
470
            return;
471
        }
472
        $this->updateRegistrationEventUid($registration, $event);
473
        $this->updateEventRegistrationCounters($event);
474
    }
475
476
    /**
477
     * Ensures, that the field "sys_language_uid" for registration fields values has the same value as the
478
     * language of the registration and event. This is required, so emails include registration field values
479
     * and correct registration field labels in their translated state.
480
     *
481
     * @param Registration $registration
482
     * @param Event $event
483
     */
484
    public function fixRegistationFieldValueLanguage(Registration $registration, Event $event)
485
    {
486
        // Early return when event is in default language or no registration fields
487
        if ((int)$event->_getProperty('_languageUid') === 0 || $event->getRegistrationFields()->count() === 0) {
488
            return;
489
        }
490
491
        $this->updateRegistrationFieldValueLanguage($registration, $event->_getProperty('_languageUid'));
492
    }
493
494
    /**
495
     * Updates the field "sys_language_uid" for all registration field values of the given registration
496
     *
497
     * @param Registration $registration
498
     * @param int $sysLanguageUid
499
     */
500
    protected function updateRegistrationFieldValueLanguage(Registration $registration, int $sysLanguageUid)
501
    {
502
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
503
            ->getQueryBuilderForTable('tx_sfeventmgt_domain_model_registration');
504
        $queryBuilder->update('tx_sfeventmgt_domain_model_registration_fieldvalue')
505
            ->set('sys_language_uid', $sysLanguageUid)
506
            ->where(
507
                $queryBuilder->expr()->eq(
508
                    'registration',
509
                    $queryBuilder->createNamedParameter($registration->getUid(), Connection::PARAM_INT)
510
                )
511
            )
512
            ->execute();
513
    }
514
515
    /**
516
     * Sets the "event" field of the given registration to the uid of the given event
517
     *
518
     * @param Registration $registration
519
     * @param Event $event
520
     */
521
    protected function updateRegistrationEventUid(Registration $registration, Event $event)
522
    {
523
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
524
            ->getQueryBuilderForTable('tx_sfeventmgt_domain_model_registration');
525
        $queryBuilder->update('tx_sfeventmgt_domain_model_registration')
526
            ->set('event', $event->getUid())
527
            ->where(
528
                $queryBuilder->expr()->eq(
529
                    'uid',
530
                    $queryBuilder->createNamedParameter($registration->getUid(), Connection::PARAM_INT)
531
                )
532
            )
533
            ->execute();
534
    }
535
536
    /**
537
     * Updates registration/waitlist registration counters for the given event
538
     *
539
     * @param Event $event
540
     */
541
    protected function updateEventRegistrationCounters(Event $event)
542
    {
543
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
544
            ->getQueryBuilderForTable('tx_sfeventmgt_domain_model_event');
545
546
        $countRegistrations = $this->getEventRegistrationCount($event, 0);
547
        $countRegistrationsWaitlist = $this->getEventRegistrationCount($event, 1);
548
549
        $queryBuilder->update('tx_sfeventmgt_domain_model_event')
550
            ->set('registration', $countRegistrations)
551
            ->set('registration_waitlist', $countRegistrationsWaitlist)
552
            ->where(
553
                $queryBuilder->expr()->eq(
554
                    'uid',
555
                    $queryBuilder->createNamedParameter($event->getUid(), Connection::PARAM_INT)
556
                )
557
            )
558
            ->orWhere(
559
                $queryBuilder->expr()->eq(
560
                    'l10n_parent',
561
                    $queryBuilder->createNamedParameter($event->getUid(), Connection::PARAM_INT)
562
                )
563
            )
564
            ->execute();
565
    }
566
567
    /**
568
     * Returns the total amount of registrations/waitlist registrations for an event
569
     *
570
     * @param Event $event
571
     * @param int $waitlist
572
     * @return mixed
573
     */
574
    protected function getEventRegistrationCount(Event $event, int $waitlist = 0)
575
    {
576
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
577
            ->getQueryBuilderForTable('tx_sfeventmgt_domain_model_registration');
578
        $queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
579
580
        return $queryBuilder->count('uid')
581
            ->from('tx_sfeventmgt_domain_model_registration')
582
            ->where(
583
                $queryBuilder->expr()->eq(
584
                    'event',
585
                    $queryBuilder->createNamedParameter($event->getUid(), Connection::PARAM_INT)
586
                ),
587
                $queryBuilder->expr()->eq(
588
                    'waitlist',
589
                    $queryBuilder->createNamedParameter($waitlist, Connection::PARAM_INT)
590
                )
591
            )
592
            ->execute()
593
            ->fetchColumn();
594
    }
595
596
    /**
597
     * Handles the process of moving registration up from the waitlist.
598
     *
599
     * @param Event $event
600
     * @param array $settings
601
     */
602
    public function moveUpWaitlistRegistrations(Event $event, array $settings)
603
    {
604
        // Early return if move up not enabled, no registrations on waitlist or no free places left
605
        if (!$event->getEnableWaitlistMoveup() || $event->getRegistrationsWaitlist()->count() === 0 ||
606
            $event->getFreePlaces() === 0
607
        ) {
608
            return;
609
        }
610
611
        $freePlaces = $event->getFreePlaces();
612
        $moveupRegistrations = $this->registrationRepository->findWaitlistMoveUpRegistrations($event);
613
614
        /** @var Registration $registration */
615
        foreach ($moveupRegistrations as $registration) {
616
            $registration->setWaitlist(false);
617
            $this->registrationRepository->update($registration);
618
619
            // Send messages to user and admin
620
            $this->notificationService->sendUserMessage(
621
                $event,
622
                $registration,
623
                $settings,
624
                MessageType::REGISTRATION_WAITLIST_MOVE_UP
625
            );
626
            $this->notificationService->sendAdminMessage(
627
                $registration->getEvent(),
628
                $registration,
629
                $settings,
630
                MessageType::REGISTRATION_WAITLIST_MOVE_UP
631
            );
632
633
            $this->eventDispatcher->dispatch(new AfterRegistrationMovedFromWaitlist($registration, $this));
0 ignored issues
show
Documentation introduced by
new \DERHANSEN\SfEventMg...t($registration, $this) is of type object<DERHANSEN\SfEvent...ationMovedFromWaitlist>, but the function expects a object<Psr\EventDispatcher\object>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
634
635
            $freePlaces--;
636
            if ($freePlaces === 0) {
637
                break;
638
            }
639
        }
640
    }
641
}
642