Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
57 / 57
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
1 / 1
Queue
100.00% covered (success)
100.00%
57 / 57
100.00% covered (success)
100.00%
11 / 11
29
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 setRecipients
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 addRecipients
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 addRecipient
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 setMessages
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 addMessages
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 addMessage
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getMessages
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRecipients
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPreparedMessages
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 prepare
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
8
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Mail;
16
17/**
18 * Mail queue class
19 *
20 * @category   Pop
21 * @package    Pop\Mail
22 * @author     Nick Sagona, III <nick@popphp.org>
23 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
24 * @license    https://www.popphp.org/license     New BSD License
25 * @version    5.0.0
26 */
27class Queue
28{
29
30    /**
31     * Recipients
32     * @var array
33     */
34    protected array $recipients = [];
35
36    /**
37     * Messages
38     * @var array
39     */
40    protected array $messages = [];
41
42    /**
43     * Prepared messages
44     * @var array
45     */
46    protected array $prepared = [];
47
48    /**
49     * Hashes of recipients currently in the queue, for O(1) dedup lookups
50     * @var array
51     */
52    protected array $recipientHashes = [];
53
54    /**
55     * Object IDs of messages currently in the queue, for O(1) dedup lookups
56     * @var array
57     */
58    protected array $messageIds = [];
59
60    /**
61     * Constructor
62     *
63     * Instantiate the mail queue object
64     */
65    public function __construct()
66    {
67        $args = func_get_args();
68
69        foreach ($args as $arg) {
70            if ($arg instanceof Message) {
71                $this->addMessage($arg);
72            } else if (is_array($arg)) {
73                $keys = array_keys($arg);
74                if (is_numeric($keys[0])) {
75                    $this->addRecipients($arg);
76                } else {
77                    $this->addRecipient($arg);
78                }
79            }
80        }
81    }
82
83    /**
84     * Set (and clear) recipients in the queue
85     *
86     * @param  array $recipients
87     * @return Queue
88     */
89    public function setRecipients(array $recipients): Queue
90    {
91        $this->recipients      = [];
92        $this->recipientHashes = [];
93        foreach ($recipients as $recipient) {
94            $this->addRecipient($recipient);
95        }
96        return $this;
97    }
98
99    /**
100     * Add recipients to the queue
101     *
102     * @param  array $recipients
103     * @return Queue
104     */
105    public function addRecipients(array $recipients): Queue
106    {
107        foreach ($recipients as $recipient) {
108            $this->addRecipient($recipient);
109        }
110        return $this;
111    }
112
113    /**
114     * Add a recipient to the queue
115     *
116     * $recipient = [
117     *     'email'   => 'me@domain.com', // Required
118     *     'name'    => 'My Name',       // Everything else is optional for individual message customization
119     *     'company' => 'My Company'
120     * ]
121     *
122     * @param  array $recipient
123     * @throws Exception
124     * @return Queue
125     */
126    public function addRecipient(array $recipient): Queue
127    {
128        if (!isset($recipient['email'])) {
129            throw new Exception("Error: The recipient's array must contain at least an 'email' key.");
130        }
131
132        $hash = md5(serialize($recipient));
133        if (!isset($this->recipientHashes[$hash])) {
134            $this->recipientHashes[$hash] = true;
135            $this->recipients[]           = $recipient;
136        }
137
138        return $this;
139    }
140
141    /**
142     * Set (and clear) messages in the queue
143     *
144     * @param  array $messages
145     * @return Queue
146     */
147    public function setMessages(array $messages): Queue
148    {
149        $this->messages   = [];
150        $this->messageIds = [];
151        foreach ($messages as $message) {
152            $this->addMessage($message);
153        }
154        return $this;
155    }
156
157    /**
158     * Add messages to the queue
159     *
160     * @param  array $messages
161     * @return Queue
162     */
163    public function addMessages(array $messages): Queue
164    {
165        foreach ($messages as $message) {
166            $this->addMessage($message);
167        }
168        return $this;
169    }
170
171    /**
172     * Add a message to the queue
173     *
174     * @param  Message $message
175     * @return Queue
176     */
177    public function addMessage(Message $message): Queue
178    {
179        $id = spl_object_id($message);
180        if (!isset($this->messageIds[$id])) {
181            $this->messageIds[$id] = true;
182            $this->messages[]      = $message;
183        }
184        return $this;
185    }
186
187    /**
188     * Get messages
189     *
190     * @return array
191     */
192    public function getMessages(): array
193    {
194        return $this->messages;
195    }
196
197    /**
198     * Get recipients
199     *
200     * @return array
201     */
202    public function getRecipients(): array
203    {
204        return $this->recipients;
205    }
206
207    /**
208     * Get prepared messages
209     *
210     * @return array
211     */
212    public function getPreparedMessages(): array
213    {
214        return $this->prepared;
215    }
216
217    /**
218     * Prepare queue for sending messages
219     *
220     * @return array
221     */
222    public function prepare(): array
223    {
224        foreach ($this->recipients as $recipient) {
225            foreach ($this->messages as $message) {
226                $to  = (isset($recipient['name'])) ? [$recipient['email'] => $recipient['name']] : $recipient['email'];
227
228                $msg = clone $message;
229                $msg->setTo($to);
230
231                $subject = (string)$msg->getSubject();
232                foreach ($recipient as $key => $value) {
233                    $subject = str_replace('[{' . $key . '}]', $value, $subject);
234                }
235                $msg->setSubject($subject);
236
237                foreach ($msg->getParts() as $i => $part) {
238                    if (!($part instanceof Message\Attachment)) {
239                        $content = $part->getContent();
240                        foreach ($recipient as $key => $value) {
241                            $content = str_replace('[{' . $key . '}]', $value, $content);
242                        }
243                        $msg->getPart($i)->setContent($content);
244                    }
245                }
246                $this->prepared[] = $msg;
247            }
248        }
249
250        return $this->prepared;
251    }
252
253}