Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
48 / 48
100.00% covered (success)
100.00%
19 / 19
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractMessage
100.00% covered (success)
100.00%
48 / 48
100.00% covered (success)
100.00%
19 / 19
37
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addHeader
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addHeaders
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 hasHeader
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHeader
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHeaders
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCharSet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setContentType
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setCharSet
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getHeaderAsString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 getHeadersAsString
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
15
 setIdHeader
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getIdHeader
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setId
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 generateId
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getRandomId
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 getBody
n/a
0 / 0
n/a
0 / 0
0
 render
n/a
0 / 0
n/a
0 / 0
0
 renderAsLines
n/a
0 / 0
n/a
0 / 0
0
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Mail\Message;
15
16use Pop\Mail\Message;
17
18/**
19 * Abstract mail message class
20 *
21 * @category   Pop
22 * @package    Pop\Mail
23 * @author     Nick Sagona, III <dev@nolainteractive.com>
24 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
25 * @license    http://www.popphp.org/license     New BSD License
26 * @version    4.0.0
27 */
28abstract class AbstractMessage implements MessageInterface
29{
30
31    /**
32     * Headers
33     * @var array
34     */
35    protected array $headers = [];
36
37    /**
38     * Content type
39     * @var ?string
40     */
41    protected ?string $contentType = null;
42
43    /**
44     * Character set
45     * @var ?string
46     */
47    protected ?string $charSet = null;
48
49    /**
50     * Message or part ID
51     * @var ?string
52     */
53    protected ?string $id = null;
54
55    /**
56     * Message or part ID header name
57     * @var ?string
58     */
59    protected ?string $idHeader = null;
60
61    /**
62     * Constructor
63     *
64     * Instantiate the message object
65     */
66    public function __construct()
67    {
68
69    }
70
71    /**
72     * Add message part header
73     *
74     * @param  string $header
75     * @param  string $value
76     * @return AbstractMessage
77     */
78    public function addHeader(string $header, string $value): AbstractMessage
79    {
80        $this->headers[$header] = $value;
81        return $this;
82    }
83
84    /**
85     * Add message part headers
86     *
87     * @param  array $headers
88     * @return AbstractMessage
89     */
90    public function addHeaders(array $headers): AbstractMessage
91    {
92        foreach ($headers as $header => $value) {
93            $this->addHeader($header, $value);
94        }
95        return $this;
96    }
97
98    /**
99     * Determine if message part has header
100     *
101     * @param  string $header
102     * @return bool
103     */
104    public function hasHeader(string $header): bool
105    {
106        return isset($this->headers[$header]);
107    }
108
109    /**
110     * Get message part header
111     *
112     * @param  string $header
113     * @return ?string
114     */
115    public function getHeader(string $header): ?string
116    {
117        return $this->headers[$header] ?? null;
118    }
119
120    /**
121     * Get all message part headers
122     *
123     * @return array
124     */
125    public function getHeaders(): array
126    {
127        return $this->headers;
128    }
129
130    /**
131     * Get message part content type
132     *
133     * @return ?string
134     */
135    public function getContentType(): ?string
136    {
137        return $this->contentType;
138    }
139
140    /**
141     * Get message part character set
142     *
143     * @return ?string
144     */
145    public function getCharSet(): ?string
146    {
147        return $this->charSet;
148    }
149
150    /**
151     * Set message part content type
152     *
153     * @param  string $contentType
154     * @return AbstractMessage
155     */
156    public function setContentType(string $contentType): AbstractMessage
157    {
158        $this->contentType = $contentType;
159        return $this;
160    }
161
162    /**
163     * Set message part character set
164     *
165     * @param  ?string $charSet
166     * @return AbstractMessage
167     */
168    public function setCharSet(?string $charSet = null): AbstractMessage
169    {
170        $this->charSet = $charSet;
171        return $this;
172    }
173
174    /**
175     * Get header as string
176     *
177     * @param  string $header
178     * @return string|null
179     */
180    public function getHeaderAsString(string $header): string|null
181    {
182        return ($this->hasHeader($header)) ? $header . ': ' . $this->getHeader($header) : null;
183    }
184
185    /**
186     * Get all message headers as string
187     *
188     * @param  array $omitHeaders
189     * @return string
190     */
191    public function getHeadersAsString(array $omitHeaders = []): string
192    {
193        $headers = null;
194
195        foreach ($this->headers as $header => $value) {
196            if (!in_array($header, $omitHeaders) && !empty($value)) {
197                $headers .= $header . ': ' . $value . Message::CRLF;
198            }
199        }
200
201        if ($this->id !== null) {
202            if ($this->idHeader === null) {
203                $this->setIdHeader((($this instanceof Message) ? 'Message-ID' : 'Content-ID'));
204            }
205
206            if (!in_array($this->idHeader, $omitHeaders)) {
207                $headers .= $this->idHeader . ': ' . $this->id . Message::CRLF;
208            }
209        }
210
211        if (($this->contentType !== null) && !in_array('Content-Type', $omitHeaders)) {
212            $headers .= 'Content-Type: ' . $this->contentType;
213            if (!empty($this->charSet) && (stripos($this->contentType, 'charset') === false)) {
214                $headers .= '; charset="' . $this->charSet . '"';
215            }
216            $headers .= Message::CRLF;
217        }
218
219        if ((!str_contains($headers, 'Content-Type')) && (count($this->parts) == 1)) {
220            $contentType = $this->parts[0]->getContentType();
221            if ($contentType !== null) {
222                $headers .= 'Content-Type: ' . $contentType . Message::CRLF;
223            }
224        }
225
226        return $headers;
227    }
228
229    /**
230     * Set the ID header name
231     *
232     * @param  string $header
233     * @return AbstractMessage
234     */
235    public function setIdHeader(string $header): AbstractMessage
236    {
237        $this->idHeader = $header;
238        return $this;
239    }
240
241    /**
242     * Get the ID
243     *
244     * @return ?string
245     */
246    public function getIdHeader(): ?string
247    {
248        return $this->idHeader;
249    }
250
251    /**
252     * Set the ID
253     *
254     * @param  string $id
255     * @return AbstractMessage
256     */
257    public function setId(string $id): AbstractMessage
258    {
259        $this->id = $id;
260        return $this;
261    }
262
263    /**
264     * Get the ID
265     *
266     * @return ?string
267     */
268    public function getId(): ?string
269    {
270        return $this->id;
271    }
272
273    /**
274     * Generate a new ID
275     *
276     * @string ?string $domain
277     * @return string
278     */
279    public function generateId(?string $domain = null): string
280    {
281        $this->setId($this->getRandomId($domain));
282        return $this->id;
283    }
284
285    /**
286     * Returns a random ID
287     *
288     * @string ?string $idRight
289     * @return string
290     */
291    protected function getRandomId(?string $idRight = null): string
292    {
293        $idLeft = md5(getmypid().'.'.time().'.'.uniqid(mt_rand(), true));
294        if ($idRight === null) {
295            $idRight = !empty($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost';
296        }
297        return '<' . $idLeft . '@' . $idRight . '>';
298    }
299
300    /**
301     * Get body
302     *
303     * @return ?string
304     */
305    abstract public function getBody(): ?string;
306
307    /**
308     * Render
309     *
310     * @return string
311     */
312    abstract public function render(): string;
313
314    /**
315     * Render as an array of lines
316     *
317     * @return array
318     */
319    abstract public function renderAsLines(): array;
320
321    /**
322     * Render message to string
323     *
324     * @return string
325     */
326    public function __toString(): string
327    {
328        return $this->render();
329    }
330
331}