Completed
Push — feature/additional-notificatio... ( 81f4ff )
by Torben
05:48
created

NotificationService::sendCustomNotification()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 9.424
c 0
b 0
f 0
cc 4
nc 4
nop 3
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\Dto\CustomNotification;
13
use DERHANSEN\SfEventMgt\Domain\Model\Event;
14
use DERHANSEN\SfEventMgt\Event\AfterAdminMessageSentEvent;
15
use DERHANSEN\SfEventMgt\Event\AfterUserMessageSentEvent;
16
use DERHANSEN\SfEventMgt\Event\ModifyUserMessageAttachmentsEvent;
17
use DERHANSEN\SfEventMgt\Event\ModifyUserMessageSenderEvent;
18
use DERHANSEN\SfEventMgt\Utility\MessageRecipient;
19
use DERHANSEN\SfEventMgt\Utility\MessageType;
20
use Psr\EventDispatcher\EventDispatcherInterface;
21
use TYPO3\CMS\Core\Utility\GeneralUtility;
22
23
/**
24
 * NotificationService
25
 *
26
 * @author Torben Hansen <[email protected]>
27
 */
28
class NotificationService
29
{
30
    /**
31
     * The object manager
32
     *
33
     * @var \TYPO3\CMS\Extbase\Object\ObjectManager
34
     */
35
    protected $objectManager;
36
37
    /**
38
     * Registration repository
39
     *
40
     * @var \DERHANSEN\SfEventMgt\Domain\Repository\RegistrationRepository
41
     */
42
    protected $registrationRepository;
43
44
    /**
45
     * Email Service
46
     *
47
     * @var \DERHANSEN\SfEventMgt\Service\EmailService
48
     */
49
    protected $emailService;
50
51
    /**
52
     * Hash Service
53
     *
54
     * @var \TYPO3\CMS\Extbase\Security\Cryptography\HashService
55
     */
56
    protected $hashService;
57
58
    /**
59
     * FluidStandaloneService
60
     *
61
     * @var \DERHANSEN\SfEventMgt\Service\FluidStandaloneService
62
     */
63
    protected $fluidStandaloneService;
64
65
    /**
66
     * CustomNotificationLogRepository
67
     *
68
     * @var \DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository
69
     */
70
    protected $customNotificationLogRepository;
71
72
    /**
73
     * AttachmentService
74
     *
75
     * @var \DERHANSEN\SfEventMgt\Service\Notification\AttachmentService
76
     */
77
    protected $attachmentService;
78
79
    /**
80
     * @var EventDispatcherInterface
81
     */
82
    protected $eventDispatcher;
83
84
    /**
85
     * DI for $attachmentService
86
     *
87
     * @param Notification\AttachmentService $attachmentService
88
     */
89
    public function injectAttachmentService(
90
        \DERHANSEN\SfEventMgt\Service\Notification\AttachmentService $attachmentService
91
    ) {
92
        $this->attachmentService = $attachmentService;
93
    }
94
95
    /**
96
     * DI for $customNotificationLogRepository
97
     *
98
     * @param \DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository $customNotificationLogRepository
99
     */
100
    public function injectCustomNotificationLogRepository(
101
        \DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository $customNotificationLogRepository
102
    ) {
103
        $this->customNotificationLogRepository = $customNotificationLogRepository;
104
    }
105
106
    /**
107
     * DI for $emailService
108
     *
109
     * @param EmailService $emailService
110
     */
111
    public function injectEmailService(\DERHANSEN\SfEventMgt\Service\EmailService $emailService)
112
    {
113
        $this->emailService = $emailService;
114
    }
115
116
    /**
117
     * DI for $fluidStandaloneService
118
     *
119
     * @param FluidStandaloneService $fluidStandaloneService
120
     */
121
    public function injectFluidStandaloneService(
122
        \DERHANSEN\SfEventMgt\Service\FluidStandaloneService $fluidStandaloneService
123
    ) {
124
        $this->fluidStandaloneService = $fluidStandaloneService;
125
    }
126
127
    /**
128
     * DI for $hashService
129
     *
130
     * @param \TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService
131
     */
132
    public function injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)
133
    {
134
        $this->hashService = $hashService;
135
    }
136
137
    /**
138
     * DI for $objectManager
139
     *
140
     * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager
141
     */
142
    public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager)
143
    {
144
        $this->objectManager = $objectManager;
145
    }
146
147
    /**
148
     * DI for $registrationRepository
149
     *
150
     * @param \DERHANSEN\SfEventMgt\Domain\Repository\RegistrationRepository $registrationRepository
151
     */
152
    public function injectRegistrationRepository(
153
        \DERHANSEN\SfEventMgt\Domain\Repository\RegistrationRepository $registrationRepository
154
    ) {
155
        $this->registrationRepository = $registrationRepository;
156
    }
157
158
    /**
159
     * @param EventDispatcherInterface $eventDispatcher
160
     */
161
    public function injectEventDispatcher(EventDispatcherInterface $eventDispatcher)
162
    {
163
        $this->eventDispatcher = $eventDispatcher;
164
    }
165
166
    /**
167
     * Sends a custom notification defined by the given customNotification key
168
     * to all confirmed users of the event
169
     *
170
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
171
     * @param CustomNotification $customNotification
172
     * @param array $settings Settings
173
     *
174
     * @return int Number of notifications sent
175
     */
176
    public function sendCustomNotification(Event $event, CustomNotification $customNotification, array $settings = [])
177
    {
178
        if ($this->cantSendCustomNotification($event, $settings, $customNotification)) {
179
            return 0;
180
        }
181
        $count = 0;
182
183
        $customNotificationSettings = $settings['notification']['customNotifications'];
184
        $constraints = $customNotificationSettings[$customNotification->getTemplate()]['constraints'] ?? [];
185
        $registrations = $this->registrationRepository->findNotificationRegistrations(
186
            $event,
187
            $customNotification,
188
            $constraints
189
        );
190
191
        foreach ($registrations as $registration) {
192
            /** @var \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration */
193
            $result = $this->sendUserMessage(
194
                $event,
195
                $registration,
196
                $settings,
197
                MessageType::CUSTOM_NOTIFICATION,
198
                $customNotification
199
            );
200
            if ($result) {
201
                $count += 1;
202
            }
203
        }
204
205
        return $count;
206
    }
207
208
    /**
209
     * Returns true if conditions are not met to send a custom notification
210
     *
211
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event
212
     * @param array $settings
213
     * @param CustomNotification $customNotification
214
     *
215
     * @return bool
216
     */
217
    protected function cantSendCustomNotification($event, $settings, $customNotification)
218
    {
219
        return is_null($event) || $customNotification === null || $customNotification->getTemplate() === '' ||
220
            empty($settings);
221
    }
222
223
    /**
224
     * Adds a logentry to the custom notification log
225
     *
226
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
227
     * @param string $details Details
228
     * @param int $emailsSent E-Mails sent
229
     */
230
    public function createCustomNotificationLogentry($event, $details, $emailsSent)
231
    {
232
        $notificationlogEntry = new \DERHANSEN\SfEventMgt\Domain\Model\CustomNotificationLog();
233
        $notificationlogEntry->setEvent($event);
234
        $notificationlogEntry->setDetails($details);
235
        $notificationlogEntry->setEmailsSent($emailsSent);
236
        $notificationlogEntry->setCruserId($GLOBALS['BE_USER']->user['uid']);
237
        $this->customNotificationLogRepository->add($notificationlogEntry);
238
    }
239
240
    /**
241
     * Sends a message to the user based on the given type
242
     *
243
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
244
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
245
     * @param array $settings Settings
246
     * @param int $type Type
247
     * @param CustomNotification $customNotification
248
     *
249
     * @return bool TRUE if successful, else FALSE
250
     */
251
    public function sendUserMessage($event, $registration, $settings, $type, $customNotification = null)
252
    {
253
        list($template, $subject) = $this->getUserMessageTemplateSubject(
254
            $settings,
255
            $type,
256
            $customNotification
257
        );
258
259
        if (is_null($event) || is_null($registration) || is_null($type) || !is_array($settings) ||
260
            (substr($template, -5) != '.html') || (bool)$settings['notification']['disabled']
261
        ) {
262
            return false;
263
        }
264
265
        $additionalBodyVariables = [
266
            'customNotification' => $customNotification
267
        ];
268
269
        if (!$registration->isIgnoreNotifications()) {
270
            $body = $this->getNotificationBody($event, $registration, $template, $settings, $additionalBodyVariables);
271
            $subject = $this->fluidStandaloneService->parseStringFluid(
272
                $subject,
273
                [
274
                    'event' => $event,
275
                    'registration' => $registration
276
                ]
277
            );
278
            $attachments = $this->attachmentService->getAttachments(
279
                $settings,
280
                $registration,
281
                $type,
282
                MessageRecipient::USER
283
            );
284
285
            // Get iCal attachment if configured
286
            $iCalAttachment = $this->attachmentService->getICalAttachment(
287
                $settings,
288
                $registration,
289
                $type,
290
                MessageRecipient::USER
291
            );
292
293
            if ($iCalAttachment !== '') {
294
                $attachments[] = $iCalAttachment;
295
            }
296
297
            $modifyUserMessageSenderEvent = new ModifyUserMessageSenderEvent(
298
                $settings['notification']['senderName'] ?? '',
299
                $settings['notification']['senderEmail'] ?? '',
300
                $settings['notification']['replyToEmail'] ?? '',
301
                $registration,
302
                $type,
303
                $this
304
            );
305
            $this->eventDispatcher->dispatch($modifyUserMessageSenderEvent);
0 ignored issues
show
Documentation introduced by
$modifyUserMessageSenderEvent is of type object<DERHANSEN\SfEvent...UserMessageSenderEvent>, 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...
306
            $senderName = $modifyUserMessageSenderEvent->getSenderName();
307
            $senderEmail = $modifyUserMessageSenderEvent->getSenderEmail();
308
            $replyToEmail = $modifyUserMessageSenderEvent->getReplyToEmail();
309
310
            $modifyUserAttachmentsEvent = new ModifyUserMessageAttachmentsEvent(
311
                $attachments,
312
                $registration,
313
                $type,
314
                $this
315
            );
316
            $this->eventDispatcher->dispatch($modifyUserMessageSenderEvent);
0 ignored issues
show
Documentation introduced by
$modifyUserMessageSenderEvent is of type object<DERHANSEN\SfEvent...UserMessageSenderEvent>, 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...
317
            $attachments = $modifyUserAttachmentsEvent->getAttachments();
318
319
            $result = $this->emailService->sendEmailMessage(
320
                $senderEmail,
321
                $registration->getEmail(),
322
                $subject,
323
                $body,
324
                $senderName,
325
                $attachments,
326
                $replyToEmail
327
            );
328
329
            $afterUserMessageSentEvent = new AfterUserMessageSentEvent(
330
                $registration,
331
                $body,
332
                $subject,
333
                $attachments,
334
                $senderName,
335
                $senderEmail,
336
                $replyToEmail,
337
                $this
338
            );
339
            $this->eventDispatcher->dispatch($afterUserMessageSentEvent);
0 ignored issues
show
Documentation introduced by
$afterUserMessageSentEvent is of type object<DERHANSEN\SfEvent...erUserMessageSentEvent>, 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...
340
341
            // Cleanup iCal attachment if available
342
            if ($iCalAttachment !== '') {
343
                \TYPO3\CMS\Core\Utility\GeneralUtility::unlink_tempfile($iCalAttachment);
344
            }
345
346
            return $result;
347
        }
348
349
        return false;
350
    }
351
352
    /**
353
     * Returns an array with template and subject for the user message
354
     *
355
     * @param array $settings
356
     * @param int $type Type
357
     * @param CustomNotification $customNotification
358
     * @return array
359
     */
360
    protected function getUserMessageTemplateSubject($settings, $type, $customNotification = null)
361
    {
362
        switch ($type) {
363
            case MessageType::REGISTRATION_NEW:
364
                $template = 'Notification/User/RegistrationNew.html';
365
                $subject = $settings['notification']['registrationNew']['userSubject'];
366
                break;
367
            case MessageType::REGISTRATION_WAITLIST_NEW:
368
                $template = 'Notification/User/RegistrationWaitlistNew.html';
369
                $subject = $settings['notification']['registrationWaitlistNew']['userSubject'];
370
                break;
371
            case MessageType::REGISTRATION_CONFIRMED:
372
                $template = 'Notification/User/RegistrationConfirmed.html';
373
                $subject = $settings['notification']['registrationConfirmed']['userSubject'];
374
                break;
375
            case MessageType::REGISTRATION_WAITLIST_CONFIRMED:
376
                $template = 'Notification/User/RegistrationWaitlistConfirmed.html';
377
                $subject = $settings['notification']['registrationWaitlistConfirmed']['userSubject'];
378
                break;
379
            case MessageType::REGISTRATION_CANCELLED:
380
                $template = 'Notification/User/RegistrationCancelled.html';
381
                $subject = $settings['notification']['registrationCancelled']['userSubject'];
382
                break;
383
            case MessageType::CUSTOM_NOTIFICATION && $customNotification:
384
                $customNotificationSettings = $settings['notification']['customNotifications'];
385
                $templateKey = $customNotification->getTemplate();
0 ignored issues
show
Bug introduced by
It seems like $customNotification is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
386
                $template = 'Notification/User/Custom/' . $customNotificationSettings[$templateKey]['template'];
387
                $subject = $customNotificationSettings[$templateKey]['subject'];
388
                if ($customNotification->getOverwriteSubject() !== '') {
389
                    $subject = $customNotification->getOverwriteSubject();
390
                }
391
                break;
392
            default:
393
                $template = '';
394
                $subject = '';
395
        }
396
397
        return [
398
            $template,
399
            $subject
400
        ];
401
    }
402
403
    /**
404
     * Sends a message to the admin based on the given type
405
     *
406
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
407
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
408
     * @param array $settings Settings
409
     * @param int $type Type
410
     *
411
     * @return bool TRUE if successful, else FALSE
412
     */
413
    public function sendAdminMessage($event, $registration, $settings, $type)
414
    {
415
        list($template, $subject) = $this->getAdminMessageTemplateSubject($settings, $type);
416
417
        if (is_null($event) || is_null($registration || !is_array($settings)) ||
418
            ($event->getNotifyAdmin() === false && $event->getNotifyOrganisator() === false) ||
419
            (bool)$settings['notification']['disabled']
420
        ) {
421
            return false;
422
        }
423
424
        $allEmailsSent = true;
425
        $body = $this->getNotificationBody($event, $registration, $template, $settings);
426
        $subject = $this->fluidStandaloneService->parseStringFluid(
427
            $subject,
428
            [
429
                'event' => $event,
430
                'registration' => $registration
431
            ]
432
        );
433
        $attachments = $this->attachmentService->getAttachments(
434
            $settings,
435
            $registration,
436
            $type,
437
            MessageRecipient::ADMIN
438
        );
439
440
        $senderName = $settings['notification']['senderName'];
441
        $senderEmail = $settings['notification']['senderEmail'];
442
        if ((bool)$settings['notification']['registrationDataAsSenderForAdminEmails']) {
443
            $senderName = $registration->getFullname();
444
            $senderEmail = $registration->getEmail();
445
        }
446
447
        if ($event->getNotifyAdmin()) {
448
            $adminEmailArr = GeneralUtility::trimExplode(',', $settings['notification']['adminEmail'], true);
449
            foreach ($adminEmailArr as $adminEmail) {
450
                $allEmailsSent = $allEmailsSent && $this->emailService->sendEmailMessage(
451
                    $senderEmail,
452
                    $adminEmail,
453
                    $subject,
454
                    $body,
455
                    $senderName,
456
                    $attachments
457
                );
458
            }
459
        }
460
461
        if ($event->getNotifyOrganisator() && $event->getOrganisator()) {
462
            $allEmailsSent = $allEmailsSent && $this->emailService->sendEmailMessage(
463
                $senderEmail,
464
                $event->getOrganisator()->getEmail(),
465
                $subject,
466
                $body,
467
                $senderName,
468
                $attachments
469
            );
470
        }
471
472
        $afterAdminMessageSentEvent = new AfterAdminMessageSentEvent(
473
            $registration,
474
            $body,
475
            $subject,
476
            $attachments,
477
            $senderName,
478
            $senderEmail,
479
            $this
480
        );
481
        $this->eventDispatcher->dispatch($afterAdminMessageSentEvent);
0 ignored issues
show
Documentation introduced by
$afterAdminMessageSentEvent is of type object<DERHANSEN\SfEvent...rAdminMessageSentEvent>, 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...
482
483
        return $allEmailsSent;
484
    }
485
486
    /**
487
     * Returns an array with template and subject for the admin message
488
     *
489
     * @param array $settings
490
     * @param int $type Type
491
     * @return array
492
     */
493
    protected function getAdminMessageTemplateSubject($settings, $type)
494
    {
495
        $template = 'Notification/Admin/RegistrationNew.html';
496
        $subject = $settings['notification']['registrationNew']['adminSubject'];
497
        switch ($type) {
498
            case MessageType::REGISTRATION_WAITLIST_NEW:
499
                $template = 'Notification/Admin/RegistrationWaitlistNew.html';
500
                $subject = $settings['notification']['registrationWaitlistNew']['adminSubject'];
501
                break;
502
            case MessageType::REGISTRATION_CONFIRMED:
503
                $template = 'Notification/Admin/RegistrationConfirmed.html';
504
                $subject = $settings['notification']['registrationConfirmed']['adminSubject'];
505
                break;
506
            case MessageType::REGISTRATION_WAITLIST_CONFIRMED:
507
                $template = 'Notification/Admin/RegistrationWaitlistConfirmed.html';
508
                $subject = $settings['notification']['registrationWaitlistConfirmed']['adminSubject'];
509
                break;
510
            case MessageType::REGISTRATION_CANCELLED:
511
                $template = 'Notification/Admin/RegistrationCancelled.html';
512
                $subject = $settings['notification']['registrationCancelled']['adminSubject'];
513
                break;
514
            case MessageType::REGISTRATION_NEW:
515
            default:
516
        }
517
518
        return [
519
            $template,
520
            $subject
521
        ];
522
    }
523
524
    /**
525
     * Returns the rendered HTML for the given template
526
     *
527
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
528
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration Registration
529
     * @param string $template Template
530
     * @param array $settings Settings
531
     * @param array $additionalBodyVariables
532
     * @return string
533
     */
534
    protected function getNotificationBody($event, $registration, $template, $settings, $additionalBodyVariables = [])
535
    {
536
        if (TYPO3_MODE === 'BE' && $registration->getLanguage() !== '') {
537
            // Temporary set Language of current BE user to given language
538
            $GLOBALS['BE_USER']->uc['lang'] = $registration->getLanguage();
539
        }
540
        $defaultVariables = [
541
            'event' => $event,
542
            'registration' => $registration,
543
            'settings' => $settings,
544
            'hmac' => $this->hashService->generateHmac('reg-' . $registration->getUid()),
545
            'reghmac' => $this->hashService->appendHmac((string)$registration->getUid())
546
        ];
547
        $variables = array_merge($additionalBodyVariables, $defaultVariables);
548
549
        return $this->fluidStandaloneService->renderTemplate($template, $variables);
550
    }
551
}
552