GenericHeader::__toString()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/*
3
 * This file is part of the Borobudur-Http package.
4
 *
5
 * (c) Hexacodelabs <http://hexacodelabs.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Borobudur\Http\Header;
12
13
use Borobudur\Http\Exception\InvalidArgumentException;
14
use Borobudur\Http\Header\Exception\InvalidHeaderValueException;
15
16
/**
17
 * @author      Iqbal Maulana <[email protected]>
18
 * @created     7/19/15
19
 */
20
class GenericHeader implements HeaderInterface
21
{
22
    /**
23
     * @var string
24
     */
25
    private $fieldName;
26
27
    /**
28
     * @var string
29
     */
30
    private $fieldValue;
31
32
    /**
33
     * Constructor.
34
     *
35
     * @param string $fieldName
36
     * @param string $fieldValue
37
     */
38
    public function __construct($fieldName, $fieldValue)
39
    {
40
        $this->fieldName  = $fieldName;
41
        $this->fieldValue = $fieldValue;
42
    }
43
44
    /**
45
     * Factory create GenericHeader from string representation.
46
     *
47
     * @param string $headerLine
48
     *
49
     * @return $this
50
     */
51
    public static function fromString($headerLine)
52
    {
53
        list($fieldName, $fieldValue) = self::splitHeaderLine($headerLine);
54
55
        return new static($fieldName, $fieldValue);
56
    }
57
58
    /**
59
     * Split name and value by header line.
60
     *
61
     * @param string $headerLine
62
     *
63
     * @return array
64
     *
65
     * @throws InvalidArgumentException
66
     */
67
    public static function splitHeaderLine($headerLine)
68
    {
69
        $parts = explode(':', (string) $headerLine, 2);
70
71
        if (2 !== count($parts)) {
72
            throw new InvalidArgumentException(sprintf(
73
                'Header must match with format "name: value", "%s" given.',
74
                $headerLine
75
            ));
76
        }
77
78
        if (!self::isValidHeaderValue($parts[1])) {
79
            throw new InvalidArgumentException('Invalid header value.');
80
        }
81
82
        $parts[1] = ltrim($parts[1]);
83
84
        return $parts;
85
    }
86
87
    /**
88
     * Compute delta seconds.
89
     *
90
     * @param int $deltaSeconds
91
     *
92
     * @return int
93
     */
94
    public static function computeDeltaSeconds($deltaSeconds)
95
    {
96
        if (!is_numeric($deltaSeconds)) {
97
            throw new InvalidHeaderValueException(sprintf(
98
                'Delta seconds should be integer, "%s" given',
99
                $deltaSeconds
100
            ));
101
        }
102
103
        $max = PHP_INT_MAX;
104
105
        return $deltaSeconds > $max ? $max : (int)$deltaSeconds;
106
    }
107
108
    /**
109
     * Check if header value is valid based on RFC 7230.
110
     * Borrowed from Zend-Framework.
111
     *
112
     * @see http://en.wikipedia.org/wiki/HTTP_response_splitting
113
     *
114
     * @param string $value
115
     *
116
     * @return bool
117
     */
118
    public static function isValidHeaderValue($value)
119
    {
120
        $value  = (string) $value;
121
        $length = strlen($value);
122
        for ($i = 0; $i < $length; $i += 1) {
123
            $ascii = ord($value[$i]);
124
125
            if (($ascii < 32 && $ascii !== 9)
126
                || $ascii === 127
127
                || $ascii > 254
128
            ) {
129
                return false;
130
            }
131
        }
132
133
        return true;
134
    }
135
136
    /**
137
     * Assert empty header field name.
138
     *
139
     * @param string $headerName
140
     */
141
    public static function assertEmptyHeaderFieldName($headerName)
142
    {
143
        if (null === $headerName) {
144
            throw new InvalidHeaderValueException(sprintf(
145
                'Header name not defined on class "%s".',
146
                get_called_class()
147
            ));
148
        }
149
    }
150
151
    /**
152
     * Assert match header field name.
153
     *
154
     * @param string $fieldName
155
     * @param string $givenFieldName
156
     *
157
     * @throws InvalidHeaderValueException
158
     */
159
    public static function assertHeaderFieldName($fieldName, $givenFieldName)
160
    {
161
        if (strtolower($fieldName) !== strtolower($givenFieldName)) {
162
            throw InvalidHeaderValueException::invalidHeaderName($givenFieldName, $fieldName);
163
        }
164
    }
165
166
    /**
167
     * Assert header value.
168
     *
169
     * @param string $value
170
     *
171
     * @throws InvalidHeaderValueException
172
     */
173
    public static function assertHeaderValue($value)
174
    {
175
        if (!GenericHeader::isValidHeaderValue($value)) {
176
            throw InvalidHeaderValueException::invalidValue($value);
177
        }
178
    }
179
    
180
    /**
181
     * Get header field name.
182
     *
183
     * @return string
184
     */
185
    public function getFieldName()
186
    {
187
        return $this->fieldName;
188
    }
189
190
    /**
191
     * Get header field value.
192
     *
193
     * @return mixed
194
     */
195
    public function getFieldValue()
196
    {
197
        return $this->fieldValue;
198
    }
199
200
    /**
201
     * Cast header to string.
202
     *
203
     * @return string
204
     */
205
    public function __toString()
206
    {
207
        return sprintf('%s: %s', $this->fieldName, $this->fieldValue);
208
    }
209
}
210