ConfirmationEmailSender::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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

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
 * Copyright (C) 2020  Jan Böhmer
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Affero General Public License as published
7
 * by the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU Affero General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Affero General Public License
16
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
 */
18
19
namespace App\Services\EmailConfirmation;
20
21
use App\Entity\PaymentOrder;
22
use DateTime;
23
use Doctrine\ORM\EntityManagerInterface;
24
use InvalidArgumentException;
25
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
26
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
27
use Symfony\Component\Mailer\MailerInterface;
28
use Symfony\Component\Mime\Email;
29
use Symfony\Contracts\Translation\TranslatorInterface;
30
31
/**
32
 * This service is responsible for sending the confirmation emails for a payment_order.
33
 */
34
class ConfirmationEmailSender
35
{
36
    private $mailer;
37
    private $tokenGenerator;
38
    private $entityManager;
39
    private $translator;
40
41
    private $fsb_email;
42
    private $hhv_email;
43
    private $send_notifications;
44
    private $notifications_bcc;
45
46
    public function __construct(MailerInterface $mailer, ConfirmationTokenGenerator $tokenGenerator,
47
        EntityManagerInterface $entityManager, TranslatorInterface $translator,
48
        string $fsb_email, string $hhv_email, bool $send_notifications, array $notifications_bcc)
49
    {
50
        $this->mailer = $mailer;
51
        $this->tokenGenerator = $tokenGenerator;
52
        $this->entityManager = $entityManager;
53
        $this->translator = $translator;
54
55
        $this->fsb_email = $fsb_email;
56
        $this->hhv_email = $hhv_email;
57
        $this->send_notifications = $send_notifications;
58
        $this->notifications_bcc = $notifications_bcc;
59
    }
60
61
    /**
62
     * Send the confirmation email to the first verification person for the given payment_order.
63
     * Email addresses are taken from department (and are added as BCC)
64
     * A token is generated, send via email and saved in hashed form in the payment order.
65
     * Calling this function will flush database.
66
     * If no applicable emails are found (or email notifications are disabled) the payment order will be confirmed and
67
     * no email is sent.
68
     */
69
    public function sendConfirmation1(PaymentOrder $paymentOrder): void
70
    {
71
        $token = $this->tokenGenerator->getToken();
72
        $paymentOrder->setConfirm1Token($this->hash_token($token));
73
        $email = $paymentOrder->getDepartment()
74
            ->getEmailHhv();
75
        //Dont send the confirmation email if no email is set, otherwise just confirm it
76
        if (!empty($email) && $this->send_notifications) {
77
            $this->sendConfirmation($paymentOrder, $email, $token, 1);
78
        } else {
79
            $paymentOrder->setConfirm1Timestamp(new DateTime());
80
        }
81
82
        $this->entityManager->flush();
83
    }
84
85
    /**
86
     * Send the confirmation email to the second verification person for the given payment_order.
87
     * Email addresses are taken from department (and are added as BCC)
88
     * A token is generated, send via email and saved in hashed form in the payment order.
89
     * Calling this function will flush database.
90
     * If no applicable emails are found (or email notifications are disabled) the payment order will be confirmed and
91
     * no email is sent.
92
     */
93
    public function sendConfirmation2(PaymentOrder $paymentOrder): void
94
    {
95
        $token = $this->tokenGenerator->getToken();
96
        $paymentOrder->setConfirm2Token($this->hash_token($token));
97
        $email = $paymentOrder->getDepartment()
98
            ->getEmailTreasurer();
99
        //Dont send the confirmation email if no email is set, otherwise just confirm it
100
        if (!empty($email) && $this->send_notifications) {
101
            $this->sendConfirmation($paymentOrder, $email, $token, 2);
102
        } else {
103
            $paymentOrder->setConfirm2Timestamp(new DateTime());
104
        }
105
        $this->entityManager->flush();
106
    }
107
108
    /**
109
     * Sents a confirmation email for the given payment order for a plaintext token.
110
     *
111
     * @param PaymentOrder $paymentOrder        The paymentOrder for which the email should be generated
112
     * @param string[]     $email_addresses     The mail addresses that should be added as BCC
113
     * @param string       $token               The plaintext token to access confirmation page.
114
     * @param int          $verification_number The verification step (1 or 2)
115
     *
116
     * @throws TransportExceptionInterface
117
     */
118
    private function sendConfirmation(PaymentOrder $paymentOrder, array $email_addresses, string $token, int $verification_number): void
119
    {
120
        //We can not continue if the payment order is not serialized / has an ID (as we cannot generate an URL for it)
121
        if (null === $paymentOrder->getId()) {
0 ignored issues
show
introduced by
The condition null === $paymentOrder->getId() is always false.
Loading history...
122
            throw new InvalidArgumentException('$paymentOrder must be serialized / have an ID so than an confirmation URL can be generated!');
123
        }
124
125
        $email = new TemplatedEmail();
126
127
        $email->priority(Email::PRIORITY_HIGH);
128
        $email->replyTo($paymentOrder->getDepartment()->isFSR() ? $this->fsb_email : $this->hhv_email);
129
130
        $email->subject(
131
            $this->translator->trans(
132
                'payment_order.confirmation_email.subject',
133
                [
134
                    '%project%' => $paymentOrder->getProjectName(),
135
                ]
136
            ));
137
138
        $email->htmlTemplate('mails/confirmation.html.twig');
139
        $email->context([
140
            'payment_order' => $paymentOrder,
141
            'token' => $token,
142
            'verification_number' => $verification_number,
143
        ]);
144
145
        $email->addBcc(...$email_addresses);
146
        $this->mailer->send($email);
147
    }
148
149
    /**
150
     * Resend all confirmation emails for cases where a confirmation is missing.
151
     * If some part is already confirmed this confirmation is not sent again.
152
     * If a confirmation is missing a new token will be generated and sent via email.
153
     */
154
    public function resendConfirmations(PaymentOrder $paymentOrder): void
155
    {
156
        //Resend emails that not already were confirmed
157
        if (null === $paymentOrder->getConfirm1Timestamp()) {
158
            $this->sendConfirmation1($paymentOrder);
159
        }
160
161
        if (null === $paymentOrder->getConfirm2Timestamp()) {
162
            $this->sendConfirmation2($paymentOrder);
163
        }
164
    }
165
166
    private function hash_token(string $token): string
167
    {
168
        return password_hash($token, PASSWORD_DEFAULT);
0 ignored issues
show
Bug Best Practice introduced by
The expression return password_hash($to...ation\PASSWORD_DEFAULT) could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
169
    }
170
}
171