• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

valkyrjaio / valkyrja / 21370229157

26 Jan 2026 07:02PM UTC coverage: 83.691% (+1.2%) from 82.5%
21370229157

push

github

web-flow
[Mail] Add tests and update Message class to be immutable (#395)

# Description

Add tests and update Message class to be immutable.

## Types of changes

- [X] Bug fix _(non-breaking change which fixes an issue)_
    <!-- Target the lowest major affected branch -->
- [ ] New feature _(non-breaking change which adds functionality)_
    <!-- Target master -->
- [X] Deprecation _(breaking change which removes functionality)_
    <!-- Target master -->
- [X] Breaking change _(fix or feature that would cause existing
functionality
  to change)_
<!-- Target master, unless this is a bug fix in which case let's chat
-->
- [ ] Documentation improvement
    <!-- Target appropriate branch -->

31 of 44 new or added lines in 2 files covered. (70.45%)

3 existing lines in 1 file now uncovered.

9760 of 11662 relevant lines covered (83.69%)

9.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

1.83
/src/Valkyrja/Notification/Notifier/Notifier.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the Valkyrja Framework package.
7
 *
8
 * (c) Melech Mizrachi <melechmizrachi@gmail.com>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13

14
namespace Valkyrja\Notification\Notifier;
15

16
use Override;
17
use Valkyrja\Broadcast\Broadcaster\Contract\BroadcasterContract;
18
use Valkyrja\Broadcast\Data\Message as BroadcastMessage;
19
use Valkyrja\Mail\Data\Message as MailMessage;
20
use Valkyrja\Mail\Mailer\Contract\MailerContract;
21
use Valkyrja\Notification\Data\Contract\NotifyContract;
22
use Valkyrja\Notification\Entity\Contract\NotifiableUserContract;
23
use Valkyrja\Notification\Factory\Contract\FactoryContract;
24
use Valkyrja\Notification\Notifier\Contract\NotifierContract;
25
use Valkyrja\Sms\Data\Message as SmsMessage;
26
use Valkyrja\Sms\Messenger\Contract\MessengerContract;
27
use Valkyrja\Throwable\Exception\InvalidArgumentException;
28

29
use function is_string;
30

31
class Notifier implements NotifierContract
32
{
33
    /**
34
     * The mail recipients.
35
     *
36
     * @var array<int, array{email: non-empty-string, name: string, body: non-empty-string, subject: non-empty-string, user?: NotifiableUserContract}>
37
     */
38
    protected array $mailRecipients = [];
39

40
    /**
41
     * The SMS recipients.
42
     *
43
     * @var array<int, array{to: non-empty-string, from: non-empty-string, text: non-empty-string, user?: NotifiableUserContract}>
44
     */
45
    protected array $smsRecipients = [];
46

47
    /**
48
     * The broadcast events.
49
     *
50
     * @var array<int, array{event: string, user?: NotifiableUserContract}>
51
     */
52
    protected array $broadcastEvents = [];
53

54
    public function __construct(
1✔
55
        protected FactoryContract $factory,
56
        protected BroadcasterContract $broadcaster,
57
        protected MailerContract $mailer,
58
        protected MessengerContract $sms,
59
    ) {
60
    }
1✔
61

62
    /**
63
     * @inheritDoc
64
     */
65
    #[Override]
×
66
    public function createNotification(string $name, array $data = []): NotifyContract
67
    {
68
        return $this->factory->createNotification($name, $data);
×
69
    }
70

71
    /**
72
     * @inheritDoc
73
     */
74
    #[Override]
×
75
    public function addMailRecipient(string $email, string $name = ''): static
76
    {
77
        $this->mailRecipients[] = [
×
NEW
78
            'email'   => $email,
×
NEW
79
            'name'    => $name,
×
NEW
80
            'subject' => 'Subject',
×
NEW
81
            'body'    => 'Body',
×
UNCOV
82
        ];
×
83

84
        return $this;
×
85
    }
86

87
    /**
88
     * @inheritDoc
89
     */
90
    #[Override]
×
91
    public function addSmsRecipient(string $phoneNumber): static
92
    {
93
        // TODO: Figure this out
94
        $this->smsRecipients[] = [
×
95
            'to'   => $phoneNumber,
×
96
            'from' => 'us',
×
97
            'text' => 'text',
×
98
        ];
×
99

100
        return $this;
×
101
    }
102

103
    /**
104
     * @inheritDoc
105
     */
106
    #[Override]
×
107
    public function addBroadcastEvent(string $event): static
108
    {
109
        $this->broadcastEvents[] = [
×
110
            'event' => $event,
×
111
        ];
×
112

113
        return $this;
×
114
    }
115

116
    /**
117
     * @inheritDoc
118
     */
119
    #[Override]
×
120
    public function addUserRecipient(NotifiableUserContract $user): static
121
    {
122
        $this->addSmsUserRecipient($user);
×
123
        $this->addMailUserRecipient($user);
×
124
        $this->addBroadcastUserRecipient($user);
×
125

126
        return $this;
×
127
    }
128

129
    /**
130
     * @inheritDoc
131
     */
132
    #[Override]
×
133
    public function notify(NotifyContract $notify): void
134
    {
135
        // $notification = $this->getNotification($notificationName, $data);
136

137
        if ($notify->shouldSendBroadcastMessage()) {
×
138
            $this->notifyByBroadcast($notify);
×
139
        }
140

141
        if ($notify->shouldSendMailMessage()) {
×
142
            $this->notifyByMail($notify);
×
143
        }
144

145
        if ($notify->shouldSendSmsMessage()) {
×
146
            $this->notifyBySms($notify);
×
147
        }
148

149
        $this->resetRecipients();
×
150
    }
151

152
    /**
153
     * @inheritDoc
154
     */
155
    #[Override]
×
156
    public function notifyUser(NotifyContract $notify, NotifiableUserContract $user): void
157
    {
158
        $this->addUserRecipient($user);
×
159
        $this->notify($notify);
×
160
    }
161

162
    /**
163
     * @inheritDoc
164
     */
165
    #[Override]
×
166
    public function notifyUsers(NotifyContract $notify, NotifiableUserContract ...$users): void
167
    {
168
        foreach ($users as $user) {
×
169
            $this->addUserRecipient($user);
×
170
        }
171

172
        $this->notify($notify);
×
173
    }
174

175
    /**
176
     * Reset all the recipient arrays.
177
     */
178
    protected function resetRecipients(): void
×
179
    {
180
        $this->broadcastEvents = [];
×
181
        $this->mailRecipients  = [];
×
182
        $this->smsRecipients   = [];
×
183
    }
184

185
    /**
186
     * Add a user as an broadcast recipient.
187
     *
188
     * @param NotifiableUserContract $user The user
189
     */
190
    protected function addBroadcastUserRecipient(NotifiableUserContract $user): void
×
191
    {
192
        /** @var mixed $secretId */
193
        $secretId = $user::hasSecretIdField()
×
194
            ? $user->__get($user::getSecretIdField())
×
195
            : null;
×
196

197
        if (is_string($secretId)) {
×
198
            $this->broadcastEvents[] = [
×
199
                'event' => $secretId,
×
200
                'user'  => $user,
×
201
            ];
×
202
        }
203
    }
204

205
    /**
206
     * Add a user as a mail recipient.
207
     *
208
     * @param NotifiableUserContract $user The user
209
     */
210
    protected function addMailUserRecipient(NotifiableUserContract $user): void
×
211
    {
212
        /** @var mixed $email */
213
        $email = $user->__get($user::getEmailField());
×
214
        /** @var mixed $name */
215
        $name = $user::hasNameField()
×
216
            ? $user->__get($user::getNameField())
×
217
            : '';
×
218

NEW
219
        if (! is_string($email) || $email === '') {
×
220
            throw new InvalidArgumentException('Invalid email provided');
×
221
        }
222

223
        if (! is_string($name)) {
×
224
            throw new InvalidArgumentException('Invalid name provided');
×
225
        }
226

227
        $this->mailRecipients[] = [
×
NEW
228
            'email'   => $email,
×
NEW
229
            'name'    => $name,
×
NEW
230
            'subject' => 'Subject',
×
NEW
231
            'body'    => 'Body',
×
NEW
232
            'user'    => $user,
×
UNCOV
233
        ];
×
234
    }
235

236
    /**
237
     * Add a user as an SMS recipient.
238
     *
239
     * @param NotifiableUserContract $user The user
240
     */
241
    protected function addSmsUserRecipient(NotifiableUserContract $user): void
×
242
    {
243
        /** @var mixed $phoneNumber */
244
        $phoneNumber = $user::hasPhoneNumberField()
×
245
            ? $user->__get($user::getPhoneNumberField())
×
246
            : null;
×
247

248
        if (is_string($phoneNumber) && $phoneNumber !== '') {
×
249
            $this->smsRecipients[] = [
×
250
                'to'   => $phoneNumber,
×
251
                'from' => 'us',
×
252
                'text' => 'test',
×
253
                'user' => $user,
×
254
            ];
×
255
        }
256
    }
257

258
    /**
259
     * Send a notification by broadcast.
260
     *
261
     * @param NotifyContract $notify The notification
262
     */
263
    protected function notifyByBroadcast(NotifyContract $notify): void
×
264
    {
265
        foreach ($this->broadcastEvents as $broadcastEvent) {
×
266
            $message = new BroadcastMessage();
×
267

268
            $message->setEvent($broadcastEvent['event']);
×
269
            $notify->broadcast($message);
×
270

271
            $this->broadcaster->send($message);
×
272
        }
273
    }
274

275
    /**
276
     * Send a notification by mail.
277
     *
278
     * @param NotifyContract $notify The notification
279
     */
280
    protected function notifyByMail(NotifyContract $notify): void
×
281
    {
282
        foreach ($this->mailRecipients as $mailRecipient) {
×
283
            $message = new MailMessage(
×
284
                $mailRecipient['email'],
×
NEW
285
                $mailRecipient['name'],
×
NEW
286
                $mailRecipient['subject'],
×
NEW
287
                $mailRecipient['body'],
×
UNCOV
288
            );
×
289

290
            $notify->mail($message);
×
291

292
            $this->mailer->send($message);
×
293
        }
294
    }
295

296
    /**
297
     * Send a notification by SMS.
298
     *
299
     * @param NotifyContract $notify The notification
300
     */
301
    protected function notifyBySms(NotifyContract $notify): void
×
302
    {
303
        foreach ($this->smsRecipients as $smsRecipient) {
×
304
            $message = new SmsMessage(
×
305
                $smsRecipient['to'],
×
306
                $smsRecipient['from'],
×
307
                $smsRecipient['text']
×
308
            );
×
309

310
            $notify->sms($message);
×
311

312
            $this->sms->send($message);
×
313
        }
314
    }
315
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc