NotificationService::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 1
b 0
f 0
nc 1
nop 8
dl 0
loc 10
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\Service;
13
14
use DERHANSEN\SfEventMgt\Domain\Model\CustomNotificationLog;
15
use DERHANSEN\SfEventMgt\Domain\Model\Dto\CustomNotification;
16
use DERHANSEN\SfEventMgt\Domain\Model\Event;
17
use DERHANSEN\SfEventMgt\Domain\Model\Registration;
18
use DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository;
19
use DERHANSEN\SfEventMgt\Domain\Repository\RegistrationRepository;
20
use DERHANSEN\SfEventMgt\Event\AfterAdminMessageSentEvent;
0 ignored issues
show
Bug introduced by
The type DERHANSEN\SfEventMgt\Eve...erAdminMessageSentEvent 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...
21
use DERHANSEN\SfEventMgt\Event\AfterUserMessageSentEvent;
0 ignored issues
show
Bug introduced by
The type DERHANSEN\SfEventMgt\Eve...terUserMessageSentEvent 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...
22
use DERHANSEN\SfEventMgt\Event\ModifyAdminMessageSenderEvent;
23
use DERHANSEN\SfEventMgt\Event\ModifyCustomNotificationLogEvent;
24
use DERHANSEN\SfEventMgt\Event\ModifyUserMessageAttachmentsEvent;
25
use DERHANSEN\SfEventMgt\Event\ModifyUserMessageSenderEvent;
26
use DERHANSEN\SfEventMgt\Security\HashScope;
27
use DERHANSEN\SfEventMgt\Service\Notification\AttachmentService;
28
use DERHANSEN\SfEventMgt\Utility\MessageRecipient;
29
use DERHANSEN\SfEventMgt\Utility\MessageType;
30
use Psr\EventDispatcher\EventDispatcherInterface;
31
use RuntimeException;
32
use TYPO3\CMS\Core\Context\Context;
33
use TYPO3\CMS\Core\Crypto\HashService;
34
use TYPO3\CMS\Core\Http\ApplicationType;
35
use TYPO3\CMS\Core\Utility\GeneralUtility;
36
use TYPO3\CMS\Extbase\Mvc\RequestInterface;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Mvc\RequestInterface 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...
37
38
class NotificationService
39
{
40
    public function __construct(
41
        protected readonly RegistrationRepository $registrationRepository,
42
        protected readonly EmailService $emailService,
43
        protected readonly HashService $hashService,
44
        protected readonly FluidRenderingService $fluidRenderingService,
45
        protected readonly CustomNotificationLogRepository $customNotificationLogRepository,
46
        protected readonly AttachmentService $attachmentService,
47
        protected readonly EventDispatcherInterface $eventDispatcher,
48
        protected readonly Context $context
49
    ) {
50
    }
51
52
    /**
53
     * Sends a custom notification defined by the given customNotification key
54
     * to users of the event. Returns the number of notifications sent.
55
     */
56
    public function sendCustomNotification(
57
        RequestInterface $request,
58
        Event $event,
59
        CustomNotification $customNotification,
60
        array $settings = []
61
    ): int {
62
        if ($this->cantSendCustomNotification($settings, $customNotification)) {
63
            return 0;
64
        }
65
        $count = 0;
66
67
        $customNotificationSettings = $settings['notification']['customNotifications'] ?? [];
68
        $constraints = $customNotificationSettings[$customNotification->getTemplate()]['constraints'] ?? [];
69
        $registrations = $this->registrationRepository->findNotificationRegistrations(
70
            $event,
71
            $customNotification,
72
            $constraints
73
        );
74
75
        foreach ($registrations as $registration) {
76
            /** @var Registration $registration */
77
            $result = $this->sendUserMessage(
78
                $request,
79
                $event,
80
                $registration,
81
                $settings,
82
                MessageType::CUSTOM_NOTIFICATION,
83
                $customNotification
84
            );
85
            if ($result) {
86
                ++$count;
87
            }
88
        }
89
90
        return $count;
91
    }
92
93
    /**
94
     * Returns true if conditions are not met to send a custom notification
95
     */
96
    protected function cantSendCustomNotification(
97
        array $settings,
98
        CustomNotification $customNotification
99
    ): bool {
100
        return $customNotification->getTemplate() === '' || empty($settings);
101
    }
102
103
    /**
104
     * Adds a logentry to the custom notification log
105
     */
106
    public function createCustomNotificationLogentry(
107
        Event $event,
108
        string $details,
109
        int $emailsSent,
110
        CustomNotification $customNotification
111
    ): void {
112
        $notificationlogEntry = new CustomNotificationLog();
113
        $notificationlogEntry->setPid($event->getPid());
114
        $notificationlogEntry->setEvent($event);
115
        $notificationlogEntry->setDetails($details);
116
        $notificationlogEntry->setEmailsSent($emailsSent);
117
        $notificationlogEntry->setCruserId($this->context->getPropertyFromAspect('backend.user', 'id'));
118
119
        $modifyCustomNotificationLogEntry = new ModifyCustomNotificationLogEvent(
120
            $notificationlogEntry,
121
            $event,
122
            $details,
123
            $customNotification
124
        );
125
        $this->eventDispatcher->dispatch($modifyCustomNotificationLogEntry);
126
        $notificationlogEntry = $modifyCustomNotificationLogEntry->getCustomNotificationLog();
127
128
        $this->customNotificationLogRepository->add($notificationlogEntry);
129
    }
130
131
    /**
132
     * Sends a message to the user based on the given type
133
     */
134
    public function sendUserMessage(
135
        RequestInterface $request,
136
        Event $event,
137
        Registration $registration,
138
        array $settings,
139
        int $type,
140
        ?CustomNotification $customNotification = null
141
    ): bool {
142
        [$template, $subject] = $this->getUserMessageTemplateSubject(
143
            $settings,
144
            $type,
145
            $customNotification
146
        );
147
148
        if ((bool)($settings['notification']['disabled'] ?? false) || !str_ends_with($template, '.html')) {
149
            return false;
150
        }
151
152
        $additionalBodyVariables = [
153
            'customNotification' => $customNotification,
154
        ];
155
156
        if (!$registration->isIgnoreNotifications()) {
157
            $body = $this->getNotificationBody($request, $event, $registration, $template, $settings, $additionalBodyVariables);
158
            $subject = $this->fluidRenderingService->parseString(
159
                $request,
160
                $subject,
161
                [
162
                    'event' => $event,
163
                    'registration' => $registration,
164
                ],
165
                $registration->getLanguage()
166
            );
167
            $attachments = $this->attachmentService->getAttachments(
168
                $settings,
169
                $registration,
170
                $type,
171
                MessageRecipient::USER,
172
                $customNotification
173
            );
174
175
            // Get iCal attachment if configured
176
            $iCalAttachment = $this->attachmentService->getICalAttachment(
177
                $request,
178
                $settings,
179
                $registration,
180
                $type,
181
                MessageRecipient::USER,
182
                $customNotification
183
            );
184
185
            if ($iCalAttachment !== '') {
186
                $attachments[] = $iCalAttachment;
187
            }
188
189
            $modifyUserMessageSenderEvent = new ModifyUserMessageSenderEvent(
190
                $settings['notification']['senderName'] ?? '',
191
                $settings['notification']['senderEmail'] ?? '',
192
                $settings['notification']['replyToEmail'] ?? '',
193
                $subject,
194
                $body,
195
                $registration,
196
                $type,
197
                $this,
198
                $request
199
            );
200
            $this->eventDispatcher->dispatch($modifyUserMessageSenderEvent);
201
            $subject = $modifyUserMessageSenderEvent->getSubject();
202
            $body = $modifyUserMessageSenderEvent->getBody();
203
204
            $senderName = $modifyUserMessageSenderEvent->getSenderName();
205
            $senderEmail = $modifyUserMessageSenderEvent->getSenderEmail();
206
            $replyToEmail = $modifyUserMessageSenderEvent->getReplyToEmail();
207
208
            $modifyUserAttachmentsEvent = new ModifyUserMessageAttachmentsEvent(
209
                $attachments,
210
                $registration,
211
                $type,
212
                $settings,
213
                $customNotification,
214
                $this,
215
                $request
216
            );
217
            $this->eventDispatcher->dispatch($modifyUserAttachmentsEvent);
218
            $attachments = $modifyUserAttachmentsEvent->getAttachments();
219
220
            $result = $this->emailService->sendEmailMessage(
221
                $senderEmail,
222
                $registration->getEmail(),
223
                $subject,
224
                $body,
225
                $senderName,
226
                $attachments,
227
                $replyToEmail
228
            );
229
230
            $afterUserMessageSentEvent = new AfterUserMessageSentEvent(
231
                $registration,
232
                $body,
233
                $subject,
234
                $attachments,
235
                $senderName,
236
                $senderEmail,
237
                $replyToEmail,
238
                $this,
239
                $request
240
            );
241
            $this->eventDispatcher->dispatch($afterUserMessageSentEvent);
242
243
            // Cleanup iCal attachment if available
244
            if ($iCalAttachment !== '') {
245
                GeneralUtility::unlink_tempfile($iCalAttachment);
246
            }
247
248
            return $result;
249
        }
250
251
        return false;
252
    }
253
254
    /**
255
     * Returns an array with template and subject for the user message
256
     */
257
    protected function getUserMessageTemplateSubject(
258
        array $settings,
259
        int $type,
260
        ?CustomNotification $customNotification = null
261
    ): array {
262
        if ($type === MessageType::CUSTOM_NOTIFICATION && $customNotification === null) {
263
            return ['', ''];
264
        }
265
266
        switch ($type) {
267
            case MessageType::REGISTRATION_NEW:
268
                $template = 'Notification/User/RegistrationNew.html';
269
                $subject = $settings['notification']['registrationNew']['userSubject'] ?? '';
270
                break;
271
            case MessageType::REGISTRATION_WAITLIST_NEW:
272
                $template = 'Notification/User/RegistrationWaitlistNew.html';
273
                $subject = $settings['notification']['registrationWaitlistNew']['userSubject'] ?? '';
274
                break;
275
            case MessageType::REGISTRATION_CONFIRMED:
276
                $template = 'Notification/User/RegistrationConfirmed.html';
277
                $subject = $settings['notification']['registrationConfirmed']['userSubject'] ?? '';
278
                break;
279
            case MessageType::REGISTRATION_WAITLIST_CONFIRMED:
280
                $template = 'Notification/User/RegistrationWaitlistConfirmed.html';
281
                $subject = $settings['notification']['registrationWaitlistConfirmed']['userSubject'] ?? '';
282
                break;
283
            case MessageType::REGISTRATION_CANCELLED:
284
                $template = 'Notification/User/RegistrationCancelled.html';
285
                $subject = $settings['notification']['registrationCancelled']['userSubject'] ?? '';
286
                break;
287
            case MessageType::REGISTRATION_WAITLIST_MOVE_UP:
288
                $template = 'Notification/User/RegistrationWaitlistMoveUp.html';
289
                $subject = $settings['notification']['registrationWaitlistMoveUp']['userSubject'] ?? '';
290
                break;
291
            case MessageType::CUSTOM_NOTIFICATION:
292
                $customNotificationSettings = $settings['notification']['customNotifications'] ?? [];
293
                $templateKey = $customNotification->getTemplate();
0 ignored issues
show
Bug introduced by
The method getTemplate() does not exist on null. ( Ignorable by Annotation )

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

293
                /** @scrutinizer ignore-call */ 
294
                $templateKey = $customNotification->getTemplate();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
294
                $template = 'Notification/User/Custom/' . ($customNotificationSettings[$templateKey]['template'] ?? '');
295
                $subject = $customNotificationSettings[$templateKey]['subject'] ?? '';
296
                if ($customNotification->getOverwriteSubject() !== '') {
297
                    $subject = $customNotification->getOverwriteSubject();
298
                }
299
                break;
300
            default:
301
                $template = '';
302
                $subject = '';
303
        }
304
305
        return [
306
            $template,
307
            $subject,
308
        ];
309
    }
310
311
    /**
312
     * Sends a message to the admin based on the given type. Returns true, if the message was sent, otherwise false
313
     */
314
    public function sendAdminMessage(
315
        RequestInterface $request,
316
        Event $event,
317
        Registration $registration,
318
        array $settings,
319
        int $type
320
    ): bool {
321
        [$template, $subject] = $this->getAdminMessageTemplateSubject($settings, $type);
322
323
        if ((bool)($settings['notification']['disabled'] ?? false) ||
324
            ($event->getNotifyAdmin() === false && $event->getNotifyOrganisator() === false)
325
        ) {
326
            return false;
327
        }
328
329
        $allEmailsSent = true;
330
        $body = $this->getNotificationBody($request, $event, $registration, $template, $settings);
331
        $subject = $this->fluidRenderingService->parseString(
332
            $request,
333
            $subject,
334
            [
335
                'event' => $event,
336
                'registration' => $registration,
337
            ],
338
            $registration->getLanguage()
339
        );
340
        $attachments = $this->attachmentService->getAttachments(
341
            $settings,
342
            $registration,
343
            $type,
344
            MessageRecipient::ADMIN
345
        );
346
347
        $senderName = $settings['notification']['senderName'] ?? '';
348
        $senderEmail = $settings['notification']['senderEmail'] ?? '';
349
        if ((bool)($settings['notification']['registrationDataAsSenderForAdminEmails'] ?? false)) {
350
            $senderName = $registration->getFullname();
351
            $senderEmail = $registration->getEmail();
352
        }
353
354
        $modifyAdminMessageSenderEvent = new ModifyAdminMessageSenderEvent(
355
            $senderName,
356
            $senderEmail,
357
            $senderEmail,
358
            $subject,
359
            $body,
360
            $registration,
361
            $type,
362
            $this,
363
            $request
364
        );
365
        $this->eventDispatcher->dispatch($modifyAdminMessageSenderEvent);
366
        $subject = $modifyAdminMessageSenderEvent->getSubject();
367
        $body = $modifyAdminMessageSenderEvent->getBody();
368
369
        $senderName = $modifyAdminMessageSenderEvent->getSenderName();
370
        $senderEmail = $modifyAdminMessageSenderEvent->getSenderEmail();
371
        $replyToEmail = $modifyAdminMessageSenderEvent->getReplyToEmail();
372
373
        if ($event->getNotifyAdmin()) {
374
            $adminEmailArr = GeneralUtility::trimExplode(',', $settings['notification']['adminEmail'] ?? '', true);
375
            foreach ($adminEmailArr as $adminEmail) {
376
                $allEmailsSent = $allEmailsSent && $this->emailService->sendEmailMessage(
377
                    $senderEmail,
378
                    $adminEmail,
379
                    $subject,
380
                    $body,
381
                    $senderName,
382
                    $attachments,
383
                    $replyToEmail
384
                );
385
            }
386
        }
387
388
        if ($event->getNotifyOrganisator() && $event->getOrganisator()) {
389
            $allEmailsSent = $allEmailsSent && $this->emailService->sendEmailMessage(
390
                $senderEmail,
391
                $event->getOrganisator()->getEmail(),
392
                $subject,
393
                $body,
394
                $senderName,
395
                $attachments,
396
                $replyToEmail
397
            );
398
        }
399
400
        $afterAdminMessageSentEvent = new AfterAdminMessageSentEvent(
401
            $registration,
402
            $body,
403
            $subject,
404
            $attachments,
405
            $senderName,
406
            $senderEmail,
407
            $type,
408
            $replyToEmail,
409
            $this,
410
            $request
411
        );
412
        $this->eventDispatcher->dispatch($afterAdminMessageSentEvent);
413
414
        return $allEmailsSent;
415
    }
416
417
    /**
418
     * Returns an array with template and subject for the admin message
419
     */
420
    protected function getAdminMessageTemplateSubject(array $settings, int $type): array
421
    {
422
        $template = 'Notification/Admin/RegistrationNew.html';
423
        $subject = $settings['notification']['registrationNew']['adminSubject'] ?? '';
424
        switch ($type) {
425
            case MessageType::REGISTRATION_WAITLIST_NEW:
426
                $template = 'Notification/Admin/RegistrationWaitlistNew.html';
427
                $subject = $settings['notification']['registrationWaitlistNew']['adminSubject'] ?? '';
428
                break;
429
            case MessageType::REGISTRATION_CONFIRMED:
430
                $template = 'Notification/Admin/RegistrationConfirmed.html';
431
                $subject = $settings['notification']['registrationConfirmed']['adminSubject'] ?? '';
432
                break;
433
            case MessageType::REGISTRATION_WAITLIST_CONFIRMED:
434
                $template = 'Notification/Admin/RegistrationWaitlistConfirmed.html';
435
                $subject = $settings['notification']['registrationWaitlistConfirmed']['adminSubject'] ?? '';
436
                break;
437
            case MessageType::REGISTRATION_CANCELLED:
438
                $template = 'Notification/Admin/RegistrationCancelled.html';
439
                $subject = $settings['notification']['registrationCancelled']['adminSubject'] ?? '';
440
                break;
441
            case MessageType::REGISTRATION_WAITLIST_MOVE_UP:
442
                $template = 'Notification/Admin/RegistrationWaitlistMoveUp.html';
443
                $subject = $settings['notification']['registrationWaitlistMoveUp']['adminSubject'] ?? '';
444
                break;
445
        }
446
447
        return [$template, $subject];
448
    }
449
450
    /**
451
     * Returns the rendered HTML for the given template
452
     */
453
    protected function getNotificationBody(
454
        RequestInterface $request,
455
        Event $event,
456
        Registration $registration,
457
        string $template,
458
        array $settings,
459
        array $additionalBodyVariables = []
460
    ): string {
461
        $isBackendRequest = ApplicationType::fromRequest($request)->isBackend();
462
463
        if ($isBackendRequest && $registration->getLanguage() !== '') {
464
            // Temporary set language of current BE user to given language
465
            $GLOBALS['BE_USER']->user['lang'] = $registration->getLanguage();
466
        }
467
        $defaultVariables = [
468
            'event' => $event,
469
            'registration' => $registration,
470
            'settings' => $settings,
471
            'hmac' => $this->hashService->hmac('reg-' . $registration->getUid(), HashScope::RegistrationUid->value),
472
            'reghmac' => $this->hashService->appendHmac((string)$registration->getUid(), HashScope::RegistrationHmac->value),
473
            'confirmAction' => $this->getTargetLinkAction('confirmAction', $settings),
474
            'cancelAction' => $this->getTargetLinkAction('cancelAction', $settings),
475
        ];
476
        $variables = array_merge($additionalBodyVariables, $defaultVariables);
477
478
        return $this->fluidRenderingService->renderTemplate($request, $template, $variables);
479
    }
480
481
    private function getTargetLinkAction(string $action, array $settings): string
482
    {
483
        switch ($action) {
484
            case 'confirmAction':
485
                $additionalStep = (bool)($settings['confirmation']['additionalVerificationStep'] ?? false);
486
                $action = $additionalStep ? 'verifyConfirmRegistration' : 'confirmRegistration';
487
                break;
488
            case 'cancelAction':
489
                $additionalStep = (bool)($settings['cancellation']['additionalVerificationStep'] ?? false);
490
                $action = $additionalStep ? 'verifyCancelRegistration' : 'cancelRegistration';
491
                break;
492
            default:
493
                throw new RuntimeException('Unknown action for getTargetLinkAction()', 1718170550);
494
        }
495
496
        return $action;
497
    }
498
}
499