getAdminMessageTemplateSubject()   B
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 28
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

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

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