Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
68 / 68
100.00% covered (success)
100.00%
22 / 22
CRAP
100.00% covered (success)
100.00%
1 / 1
Header
100.00% covered (success)
100.00%
68 / 68
100.00% covered (success)
100.00%
22 / 22
41
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 parse
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 setName
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addValues
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 addValue
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getValues
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getValueAsString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getValueIndex
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 hasValueAtIndex
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasValue
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 getValuesAsStrings
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 setWrap
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getWrap
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasWrap
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setIndent
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getIndent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasIndent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isAttachment
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 render
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 __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\Mime\Part;
15
16/**
17 * MIME part header class
18 *
19 * @category   Pop
20 * @package    Pop\Mime
21 * @author     Nick Sagona, III <dev@nolainteractive.com>
22 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
23 * @license    http://www.popphp.org/license     New BSD License
24 * @version    2.0.0
25 */
26class Header
27{
28
29    /**
30     * Header name
31     * @var ?string
32     */
33    protected ?string$name = null;
34
35    /**
36     * Header values
37     * @var array
38     */
39    protected array $values = [];
40
41    /**
42     * Header wrap
43     * @var int
44     */
45    protected int $wrap = 0;
46
47    /**
48     * Header wrap indent
49     * @var string
50     */
51    protected string $indent = "\t";
52
53    /**
54     * Constructor
55     *
56     * Instantiate the header object
57     *
58     * @param string $name
59     * @param mixed  $value
60     */
61    public function __construct(string $name, mixed $value = null)
62    {
63        $this->setName($name);
64
65        if ($value !== null) {
66            if (is_array($value)) {
67                $this->addValues($value);
68            } else {
69                $this->addValue($value);
70            }
71        }
72    }
73
74    /**
75     * Parse header
76     *
77     * @param  string $header
78     * @return Header
79     */
80    public static function parse(string $header): Header
81    {
82        $name = trim(substr($header, 0, strpos($header, ':')));
83
84        // Handle multiple values
85        if (substr_count($header, $name) > 1) {
86            $values = array_map('trim', array_filter(explode($name . ':', $header)));
87        // Else, handle single value
88        } else {
89            $values = [trim(substr($header, (strpos($header, ':') + 1)))];
90        }
91
92        $headerObject = new static($name);
93
94        foreach ($values as $value) {
95            $headerObject->addValue(Header\Value::parse($value));
96        }
97
98        return $headerObject;
99    }
100
101    /**
102     * Set the header name
103     *
104     * @param  string $name
105     * @return Header
106     */
107    public function setName(string $name): Header
108    {
109        $this->name = $name;
110        return $this;
111    }
112
113    /**
114     * Get the header name
115     *
116     * @return string
117     */
118    public function getName(): string
119    {
120        return $this->name;
121    }
122
123    /**
124     * Add header values
125     *
126     * @param  array $values
127     * @return Header
128     */
129    public function addValues(array $values): Header
130    {
131        foreach ($values as $value) {
132            $this->addValue($value);
133        }
134
135        return $this;
136    }
137
138    /**
139     * Add a header value
140     *
141     * @param  Header\Value|string $value
142     * @param  ?string             $scheme
143     * @param  array               $parameters
144     * @return Header
145     */
146    public function addValue(Header\Value|string $value, ?string $scheme = null, array $parameters = []): Header
147    {
148        if (is_string($value)) {
149            $value = new Header\Value($value, $scheme, $parameters);
150        }
151        $this->values[] = $value;
152        return $this;
153    }
154
155    /**
156     * Get the header values
157     *
158     * @return array
159     */
160    public function getValues(): array
161    {
162        return $this->values;
163    }
164
165    /**
166     * Get a header value object
167     *
168     * @param  int $i
169     * @return Header\Value|null
170     */
171    public function getValue(int $i = 0): Header\Value|null
172    {
173        return $this->values[$i] ?? null;
174    }
175
176    /**
177     * Get a header value as a string
178     *
179     * @param  int $i
180     * @return string|null
181     */
182    public function getValueAsString(int $i = 0): string|null
183    {
184        return (string)$this->values[$i] ?? null;
185    }
186
187    /**
188     * Get index of header value
189     *
190     * @param  string $value
191     * @return bool
192     */
193    public function getValueIndex(string $value): bool
194    {
195        $result = null;
196
197        foreach ($this->values as $i => $val) {
198            if ($val->getValue() == $value) {
199                $result = $i;
200                break;
201            }
202        }
203
204        return $result;
205    }
206
207    /**
208     * Determine if the header has a value at index
209     *
210     * @param  int $i
211     * @return bool
212     */
213    public function hasValueAtIndex(int $i): bool
214    {
215        return (isset($this->values[$i]));
216    }
217
218    /**
219     * Determine if the header has a value
220     *
221     * @param  string $value
222     * @return bool
223     */
224    public function hasValue(string $value): bool
225    {
226        $result = false;
227
228        foreach ($this->values as $val) {
229            if ($val->getValue() == $value) {
230                $result = true;
231                break;
232            }
233        }
234
235        return $result;
236    }
237
238    /**
239     * Get the header values as strings
240     *
241     * @param  ?string $delimiter
242     * @return string|array
243     */
244    public function getValuesAsStrings(?string $delimiter = null): string|array
245    {
246        if (count($this->values) == 1) {
247            return (string)$this->values[0];
248        } else {
249            $values = [];
250            foreach ($this->values as $value) {
251                $values[] = (string)$value;
252            }
253
254            return ($delimiter !== null) ? implode($delimiter, $values) : $values;
255        }
256    }
257
258    /**
259     * Set the header wrap
260     *
261     * @param  int $wrap
262     * @return Header
263     */
264    public function setWrap(int $wrap): Header
265    {
266        $this->wrap = (int)$wrap;
267        return $this;
268    }
269
270    /**
271     * Get the header wrap
272     *
273     * @return int
274     */
275    public function getWrap(): int
276    {
277        return $this->wrap;
278    }
279
280    /**
281     * Has header wrap
282     *
283     * @return bool
284     */
285    public function hasWrap(): bool
286    {
287        return ($this->wrap !== null);
288    }
289
290    /**
291     * Set the header wrap indent
292     *
293     * @param  string $indent
294     * @return Header
295     */
296    public function setIndent(string $indent): Header
297    {
298        $this->indent = $indent;
299        return $this;
300    }
301
302    /**
303     * Get the header wrap indent
304     *
305     * @return string
306     */
307    public function getIndent(): string
308    {
309        return $this->indent;
310    }
311
312    /**
313     * Has header wrap indent
314     *
315     * @return bool
316     */
317    public function hasIndent(): bool
318    {
319        return ($this->indent !== null);
320    }
321
322    /**
323     * Is the header for an attachment
324     *
325     * @return bool
326     */
327    public function isAttachment(): bool
328    {
329        $result = false;
330
331        foreach ($this->values as $value) {
332            if (($this->name == 'Content-Disposition') &&
333                ((stripos((string)$value, 'attachment') !== false) || (stripos((string)$value, 'inline') !== false))) {
334                $result = true;
335                break;
336            }
337        }
338
339        return $result;
340    }
341
342    /**
343     * Render the header string
344     *
345     * @return string
346     */
347    public function render(): string
348    {
349        $headers = [];
350
351        foreach ($this->values as $value) {
352            $header = $this->name . ': ' . $value;
353
354            if ((int)$this->wrap != 0) {
355                $header = wordwrap($header, $this->wrap, "\r\n" . $this->indent);
356            }
357            $headers[] = $header;
358        }
359
360        return implode("\r\n", $headers);
361    }
362
363    /**
364     * Render the header string
365     *
366     * @return string
367     */
368    public function __toString(): string
369    {
370        return $this->render();
371    }
372
373}