Mailer   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 163
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 26
c 1
b 0
f 0
dl 0
loc 163
ccs 34
cts 34
cp 1
rs 10
wmc 13

9 Methods

Rating   Name   Duplication   Size   Complexity  
A withLocale() 0 5 1
A sendMultiple() 0 13 3
A createMessage() 0 3 1
A withTemplate() 0 5 1
A beforeSend() 0 5 1
A send() 0 8 2
A __construct() 0 5 1
A compose() 0 9 2
A afterSend() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Mailer;
6
7
use Psr\EventDispatcher\EventDispatcherInterface;
8
use Throwable;
9
use Yiisoft\Mailer\Event\AfterSend;
10
use Yiisoft\Mailer\Event\BeforeSend;
11
12
/**
13
 * `Mailer` serves as a base class that implements the basic functions required by {@see MailerInterface}.
14
 *
15
 * Concrete child classes may focus on implementing the {@see Mailer::sendMessage()} method.
16
 */
17
abstract class Mailer implements MailerInterface
18
{
19
    public function __construct(
20
        private MessageFactoryInterface $messageFactory,
21
        private MessageBodyRenderer $messageBodyRenderer,
22
        private EventDispatcherInterface $eventDispatcher
23 48
    ) {
24
    }
25
26
    /**
27
     * Returns a new instance with the specified message body template.
28 48
     *
29 48
     * @param MessageBodyTemplate $template The message body template instance.
30 48
     *
31
     * @return self The new instance.
32
     */
33
    public function withTemplate(MessageBodyTemplate $template): self
34
    {
35
        $new = clone $this;
36
        $new->messageBodyRenderer = $new->messageBodyRenderer->withTemplate($template);
37
        return $new;
38
    }
39
40 1
    /**
41
     * Returns a new instance with specified locale code.
42 1
     *
43 1
     * @param string $locale The locale code.
44 1
     *
45
     * @return self
46
     */
47
    public function withLocale(string $locale): self
48
    {
49
        $new = clone $this;
50
        $new->messageBodyRenderer = $new->messageBodyRenderer->withLocale($locale);
51
        return $new;
52
    }
53
54 2
    /**
55
     * Creates a new message instance and optionally composes its body content via view rendering.
56 2
     *
57 2
     * @param array<string, string>|string|null $view The view to be used for rendering the message body.
58 2
     * This can be:
59
     * - a string, which represents the view name for rendering the HTML body of the email.
60
     *   In this case, the text body will be generated by applying `strip_tags()` to the HTML body.
61
     * - an array with 'html' and/or 'text' elements. The 'html' element refers to the view name
62
     *   for rendering the HTML body, while 'text' element is for rendering the text body. For example,
63
     *   `['html' => 'contact-html', 'text' => 'contact-text']`.
64
     * - null, meaning the message instance will be returned without body content.
65
     *
66
     * The view to be rendered can be specified in one of the following formats:
67
     * - a relative view name (e.g. "contact") located under {@see MessageBodyRenderer::$viewPath}.
68
     * @param array $viewParameters The parameters (name-value pairs)
69
     * that will be extracted and available in the view file.
70
     * @param array $layoutParameters The parameters (name-value pairs)
71
     * that will be extracted and available in the layout file.
72
     *
73
     * @throws Throwable If an error occurred during rendering.
74
     *
75
     * @return MessageInterface The message instance.
76
     */
77
    public function compose($view = null, array $viewParameters = [], array $layoutParameters = []): MessageInterface
78
    {
79
        $message = $this->createMessage();
80
81
        if ($view === null) {
82
            return $message;
83
        }
84 7
85
        return $this->messageBodyRenderer->addToMessage($message, $view, $viewParameters, $layoutParameters);
86 7
    }
87
88 7
    /**
89 4
     * Sends the given email message.
90
     * This method will log a message about the email being sent.
91
     * Child classes should implement [[sendMessage()]] with the actual email sending logic.
92 3
     *
93
     * @param MessageInterface $message email message instance to be sent
94
     *
95
     * @throws Throwable If sending failed.
96
     */
97
    public function send(MessageInterface $message): void
98
    {
99
        if (!$this->beforeSend($message)) {
100
            return;
101
        }
102
103
        $this->sendMessage($message);
104 13
        $this->afterSend($message);
105
    }
106 13
107 1
    /**
108
     * Sends multiple messages at once.
109
     *
110 12
     * The default implementation simply calls {@see Mailer::send()} multiple times.
111 6
     * Child classes may override this method to implement more efficient way of sending multiple messages.
112
     *
113
     * @param MessageInterface[] $messages List of email messages, which should be sent.
114
     *
115
     * @return MessageInterface[] List of fails messages, the corresponding
116
     * error can be retrieved by {@see MessageInterface::getError()}.
117
     */
118
    public function sendMultiple(array $messages): array
119
    {
120
        $failed = [];
121
122
        foreach ($messages as $message) {
123
            try {
124
                $this->send($message);
125
            } catch (Throwable $e) {
126 4
                $failed[] = $message->withError($e);
127
            }
128 4
        }
129
130 4
        return $failed;
131
    }
132 3
133 1
    /**
134 1
     * Sends the specified message.
135
     *
136
     * This method should be implemented by child classes with the actual email sending logic.
137
     *
138 4
     * @param MessageInterface $message the message to be sent
139
     *
140
     * @throws Throwable If sending failed.
141
     */
142
    abstract protected function sendMessage(MessageInterface $message): void;
143
144
    /**
145
     * Creates a new message instance.
146
     *
147
     * @return MessageInterface The message instance.
148
     */
149
    protected function createMessage(): MessageInterface
150
    {
151
        return $this->messageFactory->create();
152
    }
153
154
    /**
155
     * This method is invoked right before mail send.
156
     *
157 8
     * You may override this method to do last-minute preparation for the message.
158
     * If you override this method, please make sure you call the parent implementation first.
159 8
     *
160
     * @param MessageInterface $message The message instance.
161
     *
162
     * @return bool Whether to continue sending an email.
163
     */
164
    protected function beforeSend(MessageInterface $message): bool
165
    {
166
        /** @var BeforeSend $event */
167
        $event = $this->eventDispatcher->dispatch(new BeforeSend($message));
168
        return !$event->isPropagationStopped();
169
    }
170
171
    /**
172 13
     * This method is invoked right after mail was send.
173
     *
174
     * You may override this method to do some postprocessing or logging based on mail send status.
175 13
     * If you override this method, please make sure you call the parent implementation first.
176 13
     */
177
    protected function afterSend(MessageInterface $message): void
178
    {
179
        $this->eventDispatcher->dispatch(new AfterSend($message));
180
    }
181
}
182