Completed
Push — master ( 65fc0c...845fb3 )
by Frederik
02:01
created

HeaderValue   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 2

Test Coverage

Coverage 97.62%

Importance

Changes 0
Metric Value
wmc 17
lcom 2
cbo 2
dl 0
loc 123
ccs 41
cts 42
cp 0.9762
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A assertValid() 0 6 2
A getParameter() 0 8 2
A __construct() 0 6 1
A withParameter() 0 6 1
A getRaw() 0 4 1
A __toString() 0 10 2
C validate() 0 25 7
A fromEncodedString() 0 6 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Header;
5
6
/**
7
 * Class HeaderValue
8
 * @package Genkgo\Mail\Header
9
 */
10
final class HeaderValue
11
{
12
    /**
13
     * @var string
14
     */
15
    private $value;
16
    /**
17
     * @var array
18
     */
19
    private $parameters = [];
20
    /**
21
     * @var bool
22
     */
23
    private $needsEncoding = true;
24
25
    /**
26
     * HeaderValue constructor.
27
     * @param string $value
28
     */
29 80
    public function __construct(string $value)
30
    {
31 80
        $this->assertValid($value);
32
33 77
        $this->value = $value;
34 77
    }
35
36
    /**
37
     * @param HeaderValueParameter $parameter
38
     * @return HeaderValue
39
     */
40 23
    public function withParameter(HeaderValueParameter $parameter): HeaderValue
41
    {
42 23
        $clone = clone $this;
43 23
        $clone->parameters[$parameter->getName()] = $parameter;
44 23
        return $clone;
45
    }
46
47
    /**
48
     * @return string
49
     */
50 9
    public function getRaw(): string
51
    {
52 9
        return $this->value;
53
    }
54
55
    /**
56
     * @return string
57
     */
58 63
    public function __toString(): string
59
    {
60 63
        $value = implode('; ', array_merge([$this->value], $this->parameters));
61
62 63
        if ($this->needsEncoding) {
63 57
            return (string) (new OptimalEncodedHeaderValue($value));
64
        }
65
66 15
        return $value;
67
    }
68
69
    /**
70
     * @param string $value
71
     */
72 80
    private function assertValid(string $value): void
73
    {
74 80
        if ($this->validate($value) === false) {
75 3
            throw new \InvalidArgumentException('Invalid header value ' . $value);
76
        }
77 77
    }
78
79
    /**
80
     * @param $value
81
     * @return bool
82
     */
83 80
    private function validate(string $value): bool
84
    {
85 80
        $total = strlen($value);
86
87 80
        for ($i = 0; $i < $total; $i += 1) {
88 80
            $ord = ord($value[$i]);
89 80
            if ($ord === 10) {
90 1
                return false;
91
            }
92 80
            if ($ord === 13) {
93 3
                if ($i + 2 >= $total) {
94
                    return false;
95
                }
96 3
                $lf = ord($value[$i + 1]);
97 3
                $sp = ord($value[$i + 2]);
98 3
                if ($lf !== 10 || ! in_array($sp, [9, 32], true)) {
99 2
                    return false;
100
                }
101
                // skip over the LF following this
102 1
                $i += 2;
103
            }
104
        }
105
106 77
        return true;
107
    }
108
109
    /**
110
     * @param string $name
111
     * @return HeaderValueParameter
112
     */
113 4
    public function getParameter(string $name): HeaderValueParameter
114
    {
115 4
        if (isset($this->parameters[$name])) {
116 4
            return $this->parameters[$name];
117
        }
118
119 2
        throw new \UnexpectedValueException('No parameter with name ' . $name);
120
    }
121
122
    /**
123
     * @param string $value
124
     * @return HeaderValue
125
     */
126 15
    public static function fromEncodedString(string $value): HeaderValue
127
    {
128 15
        $headerValue = new self($value);
129 15
        $headerValue->needsEncoding = false;
130 15
        return $headerValue;
131
    }
132
}