Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
97.73% |
86 / 88 |
|
90.91% |
20 / 22 |
CRAP | |
0.00% |
0 / 1 |
Value | |
97.73% |
86 / 88 |
|
90.91% |
20 / 22 |
54 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
5 | |||
parse | |
96.88% |
31 / 32 |
|
0.00% |
0 / 1 |
17 | |||
parseParameter | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
6 | |||
setScheme | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getScheme | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasScheme | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setValue | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getValue | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
addParameters | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
addParameter | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getParameters | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getParametersAsString | |
87.50% |
7 / 8 |
|
0.00% |
0 / 1 |
6.07 | |||
getParameter | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasParameters | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasParameter | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setDelimiter | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getDelimiter | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasDelimiter | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setForceQuote | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
isForceQuote | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
render | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
__toString | |
100.00% |
1 / 1 |
|
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 | */ |
14 | namespace Pop\Mime\Part\Header; |
15 | |
16 | /** |
17 | * MIME part header value 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 | */ |
26 | class Value |
27 | { |
28 | |
29 | /** |
30 | * Header value scheme |
31 | * @var ?string |
32 | */ |
33 | protected ?string $scheme = null; |
34 | |
35 | /** |
36 | * Header value |
37 | * @var ?string |
38 | */ |
39 | protected ?string $value = null; |
40 | |
41 | /** |
42 | * Header value parameters |
43 | * @var array |
44 | */ |
45 | protected array $parameters = []; |
46 | |
47 | /** |
48 | * Header value delimiter |
49 | * @var string |
50 | */ |
51 | protected string $delimiter = ';'; |
52 | |
53 | /** |
54 | * Force quotes for parameter values |
55 | * @var bool |
56 | */ |
57 | protected bool $forceQuote = false; |
58 | |
59 | /** |
60 | * Constructor |
61 | * |
62 | * Instantiate the header value object |
63 | * |
64 | * @param ?string $value |
65 | * @param ?string $scheme |
66 | * @param array $parameters |
67 | * @param bool $forceQuote |
68 | */ |
69 | public function __construct(?string $value = null, ?string $scheme = null, array $parameters = [], bool $forceQuote = false) |
70 | { |
71 | if ($value !== null) { |
72 | $this->setValue($value); |
73 | } |
74 | if ($scheme !== null) { |
75 | $this->setScheme($scheme); |
76 | } |
77 | if (!empty($parameters)) { |
78 | $this->addParameters($parameters); |
79 | } |
80 | if ($forceQuote) { |
81 | $this->setForceQuote($forceQuote); |
82 | } |
83 | } |
84 | |
85 | /** |
86 | * Parse header value |
87 | * |
88 | * @param string $value |
89 | * @return Value |
90 | */ |
91 | public static function parse(string $value): Value |
92 | { |
93 | $valueObject = new Value(); |
94 | $parameters = []; |
95 | |
96 | if ((str_contains($value, ';')) || (str_contains($value, ','))) { |
97 | $matches = []; |
98 | preg_match_all('/\w+=[\\a-zA-Z0-9_\s\.\"\/]/mi', $value, $matches, PREG_OFFSET_CAPTURE); |
99 | if (isset($matches[0]) && isset($matches[0][0]) && isset($matches[0][0][1])) { |
100 | $val = trim(substr($value, 0, $matches[0][0][1])); |
101 | if (str_ends_with($val, ';') || str_ends_with($val, ',')) { |
102 | $val = substr($val, 0, -1); |
103 | } |
104 | if ((stripos($val, 'Basic') !== false) || (stripos($val, 'Bearer') !== false) || (stripos($val, 'Digest') !== false)) { |
105 | if (str_contains($val, ' ')) { |
106 | $valueObject->setScheme(substr($val, 0, strpos($val, ' ')) . ' '); |
107 | $valueObject->setValue(substr($val, (strpos($val, ' ') + 1))); |
108 | } else { |
109 | $valueObject->setScheme($val . ' '); |
110 | } |
111 | } else { |
112 | $valueObject->setValue($val); |
113 | } |
114 | |
115 | $params = trim(substr($value, $matches[0][0][1])); |
116 | $paramValues = []; |
117 | $paramMatches = []; |
118 | preg_match_all('/\w+=/mi', $params, $paramMatches, PREG_OFFSET_CAPTURE); |
119 | foreach ($paramMatches[0] as $i => $paramMatch) { |
120 | if (isset($paramMatches[0][$i + 1])) { |
121 | $paramValues[] = trim(substr($params, $paramMatch[1], $paramMatches[0][$i + 1][1] - $paramMatch[1])); |
122 | } else { |
123 | $paramValues[] = trim(substr($params, $paramMatch[1])); |
124 | } |
125 | } |
126 | foreach ($paramValues as $pValue) { |
127 | [$paramName, $paramValue, $delimiter] = self::parseParameter($pValue); |
128 | $parameters[$paramName] = $paramValue; |
129 | if ($delimiter !== null) { |
130 | $valueObject->setDelimiter($delimiter); |
131 | } |
132 | } |
133 | } |
134 | } else { |
135 | $valueObject->setValue($value); |
136 | } |
137 | |
138 | if (!empty($parameters)) { |
139 | $valueObject->addParameters($parameters); |
140 | } |
141 | |
142 | return $valueObject; |
143 | } |
144 | |
145 | /** |
146 | * Parse a parameter value |
147 | * |
148 | * @param string $parameter |
149 | * @return array |
150 | */ |
151 | public static function parseParameter(string $parameter): array |
152 | { |
153 | $paramName = substr($parameter, 0, strpos($parameter, '=')); |
154 | $paramValue = substr($parameter, (strpos($parameter, '=') + 1)); |
155 | $delimiter = null; |
156 | if (str_ends_with($paramValue, ';') || str_ends_with($paramValue, ',')) { |
157 | $delimiter = (str_ends_with($paramValue, ';')) ? ';' : ','; |
158 | $paramValue = substr($paramValue, 0, -1); |
159 | } |
160 | if ((str_starts_with($paramValue, '"')) && (str_ends_with($paramValue, '"'))) { |
161 | $paramValue = substr($paramValue, 1); |
162 | $paramValue = substr($paramValue, 0, -1); |
163 | } |
164 | return [$paramName, $paramValue, $delimiter]; |
165 | } |
166 | |
167 | /** |
168 | * Set the header value scheme |
169 | * |
170 | * @param string $scheme |
171 | * @return Value |
172 | */ |
173 | public function setScheme(string $scheme): Value |
174 | { |
175 | $this->scheme = $scheme; |
176 | return $this; |
177 | } |
178 | |
179 | /** |
180 | * Get the header value scheme |
181 | * |
182 | * @return string|null |
183 | */ |
184 | public function getScheme(): string|null |
185 | { |
186 | return $this->scheme; |
187 | } |
188 | |
189 | /** |
190 | * Has a header value scheme |
191 | * |
192 | * @return bool |
193 | */ |
194 | public function hasScheme(): bool |
195 | { |
196 | return ($this->delimiter !== null); |
197 | } |
198 | |
199 | /** |
200 | * Set the header value |
201 | * |
202 | * @param string $value |
203 | * @return Value |
204 | */ |
205 | public function setValue(string $value): Value |
206 | { |
207 | $this->value = $value; |
208 | return $this; |
209 | } |
210 | |
211 | /** |
212 | * Get the header value |
213 | * |
214 | * @return string|null |
215 | */ |
216 | public function getValue(): string|null |
217 | { |
218 | return $this->value; |
219 | } |
220 | |
221 | /** |
222 | * Add the header value parameters |
223 | * |
224 | * @param array $parameters |
225 | * @return Value |
226 | */ |
227 | public function addParameters(array $parameters): Value |
228 | { |
229 | $this->parameters = $parameters; |
230 | return $this; |
231 | } |
232 | |
233 | /** |
234 | * Set a header value parameter |
235 | * |
236 | * @param string $name |
237 | * @param string $value |
238 | * @return Value |
239 | */ |
240 | public function addParameter(string $name, string $value): Value |
241 | { |
242 | $this->parameters[$name] = $value; |
243 | return $this; |
244 | } |
245 | |
246 | /** |
247 | * Get the header value parameters |
248 | * |
249 | * @return array |
250 | */ |
251 | public function getParameters(): array |
252 | { |
253 | return $this->parameters; |
254 | } |
255 | |
256 | /** |
257 | * Get the header value parameters as string |
258 | * |
259 | * @throws Exception |
260 | * @return string |
261 | */ |
262 | public function getParametersAsString(): string |
263 | { |
264 | if (!$this->hasDelimiter()) { |
265 | throw new Exception('Error: No delimiter has been set.'); |
266 | } |
267 | |
268 | $parameters = []; |
269 | |
270 | foreach ($this->parameters as $name => $value) { |
271 | if (!str_contains($value, '"') && (str_contains($value, ' ') || ($this->forceQuote))) { |
272 | $value = '"' . $value . '"'; |
273 | } |
274 | $parameters[] = $name . '=' . $value; |
275 | } |
276 | |
277 | return implode($this->delimiter . ' ', $parameters); |
278 | } |
279 | |
280 | /** |
281 | * Get a header value parameter |
282 | * |
283 | * @param string $name |
284 | * @return string|null |
285 | */ |
286 | public function getParameter(string $name): string|null |
287 | { |
288 | return $this->parameters[$name] ?? null; |
289 | } |
290 | |
291 | /** |
292 | * Has header value parameters |
293 | * |
294 | * @return bool |
295 | */ |
296 | public function hasParameters(): bool |
297 | { |
298 | return (count($this->parameters) > 0); |
299 | } |
300 | |
301 | /** |
302 | * Has a header value parameter |
303 | * |
304 | * @param string $name |
305 | * @return bool |
306 | */ |
307 | public function hasParameter(string $name): bool |
308 | { |
309 | return (isset($this->parameters[$name])); |
310 | } |
311 | |
312 | /** |
313 | * Set the header value delimiter |
314 | * |
315 | * @param string $delimiter |
316 | * @return Value |
317 | */ |
318 | public function setDelimiter(string $delimiter): Value |
319 | { |
320 | $this->delimiter = $delimiter; |
321 | return $this; |
322 | } |
323 | |
324 | /** |
325 | * Get the header value delimiter |
326 | * |
327 | * @return string |
328 | */ |
329 | public function getDelimiter(): string |
330 | { |
331 | return $this->delimiter; |
332 | } |
333 | |
334 | /** |
335 | * Has a header value delimiter |
336 | * |
337 | * @return bool |
338 | */ |
339 | public function hasDelimiter(): bool |
340 | { |
341 | return ($this->delimiter !== null); |
342 | } |
343 | |
344 | /** |
345 | * Set the header value delimiter |
346 | * |
347 | * @param bool $forceQuote |
348 | * @return Value |
349 | */ |
350 | public function setForceQuote(bool $forceQuote = false): Value |
351 | { |
352 | $this->forceQuote = $forceQuote; |
353 | return $this; |
354 | } |
355 | |
356 | /** |
357 | * Is set to force quote |
358 | * |
359 | * @return bool |
360 | */ |
361 | public function isForceQuote(): bool |
362 | { |
363 | return $this->forceQuote; |
364 | } |
365 | |
366 | /** |
367 | * Render the header value string |
368 | * |
369 | * @throws Exception |
370 | * @return string |
371 | */ |
372 | public function render(): string |
373 | { |
374 | $value = $this->scheme . $this->value; |
375 | |
376 | if (count($this->parameters) > 0) { |
377 | $parameters = $this->getParametersAsString(); |
378 | if (!str_ends_with($value, ' ')) { |
379 | $value .= $this->delimiter . ' '; |
380 | } |
381 | $value .= $parameters; |
382 | } |
383 | |
384 | return $value; |
385 | } |
386 | |
387 | /** |
388 | * Render the header value string |
389 | * |
390 | * @return string |
391 | */ |
392 | public function __toString(): string |
393 | { |
394 | return $this->render(); |
395 | } |
396 | |
397 | } |