Completed
Push — master ( 066b45...e036cb )
by
unknown
26s queued 13s
created

Header   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 265
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 28
eloc 136
c 1
b 0
f 1
dl 0
loc 265
rs 10

13 Methods

Rating   Name   Duplication   Size   Complexity  
A normalizeValue() 0 6 2
A normalizeKey() 0 9 2
A fromRawText() 0 3 1
A parseRawText() 0 24 5
A __construct() 0 11 3
A getIterator() 0 7 2
A offsetGet() 0 7 3
A getRawData() 0 3 1
A count() 0 3 1
A offsetExists() 0 4 1
A offsetSet() 0 7 3
A isValidKeyName() 0 8 3
A offsetUnset() 0 4 1
1
<?php
2
3
namespace Qiniu\Http;
4
5
/**
6
 * field name case-insensitive Header
7
 */
8
class Header implements \ArrayAccess, \IteratorAggregate, \Countable
9
{
10
    /** @var array normalized key name map */
11
    private $data;
12
13
    /**
14
     * @param array $obj non-normalized header object
15
     */
16
    public function __construct($obj = array())
17
    {
18
        foreach ($obj as $key => $values) {
19
            $normalizedKey = self::normalizeKey($key);
20
            $normalizedValues = array();
21
            foreach ($values as $value) {
22
                array_push($normalizedValues, self::normalizeValue($value));
23
            }
24
            $this->data[$normalizedKey] = $normalizedValues;
25
        }
26
        return $this;
27
    }
28
29
    /**
30
     * return origin headers, which is field name case-sensitive
31
     *
32
     * @param string $raw
33
     *
34
     * @return array
35
     */
36
    public static function parseRawText($raw)
37
    {
38
        $headers = array();
39
        $headerLines = explode("\r\n", $raw);
40
        foreach ($headerLines as $line) {
41
            $headerLine = trim($line);
42
            $kv = explode(':', $headerLine);
43
            if (count($kv) <= 1) {
44
                continue;
45
            }
46
            // for http2 [Pseudo-Header Fields](https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2.1)
47
            if ($kv[0] == "") {
48
                $fieldName = ":" . $kv[1];
49
            } else {
50
                $fieldName = $kv[0];
51
            }
52
            $fieldValue = trim(substr($headerLine, strlen($fieldName . ":")));
53
            if (isset($headers[$fieldName])) {
54
                array_push($headers[$fieldName], $fieldValue);
55
            } else {
56
                $headers[$fieldName] = array($fieldValue);
57
            }
58
        }
59
        return $headers;
60
    }
61
62
    /**
63
     * @param string $raw
64
     *
65
     * @return Header
66
     */
67
    public static function fromRawText($raw)
68
    {
69
        return new Header(self::parseRawText($raw));
70
    }
71
72
    /**
73
     * @param string $key
74
     *
75
     * @return string
76
     */
77
    public static function normalizeKey($key)
78
    {
79
        $key = trim($key);
80
81
        if (!self::isValidKeyName($key)) {
82
            return $key;
83
        }
84
85
        return ucwords(strtolower($key), '-');
86
    }
87
88
    /**
89
     * @param string|numeric $value
0 ignored issues
show
Bug introduced by
The type Qiniu\Http\numeric was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
90
     *
91
     * @return string|numeric
92
     */
93
    public static function normalizeValue($value)
94
    {
95
        if (is_numeric($value)) {
96
            return $value + 0;
97
        }
98
        return trim($value);
99
    }
100
101
    /**
102
     * @return array
103
     */
104
    public function getRawData()
105
    {
106
        return $this->data;
107
    }
108
109
    /**
110
     * @param $offset string
111
     *
112
     * @return boolean
113
     */
114
    public function offsetExists($offset)
115
    {
116
        $key = self::normalizeKey($offset);
117
        return isset($this->data[$key]);
118
    }
119
120
    /**
121
     * @param $offset string
122
     *
123
     * @return string|null
124
     */
125
    public function offsetGet($offset)
126
    {
127
        $key = self::normalizeKey($offset);
128
        if (isset($this->data[$key]) && count($this->data[$key])) {
129
            return $this->data[$key][0];
130
        } else {
131
            return null;
132
        }
133
    }
134
135
    /**
136
     * @param $offset string
137
     * @param $value string
138
     *
139
     * @return void
140
     */
141
    public function offsetSet($offset, $value)
142
    {
143
        $key = self::normalizeKey($offset);
144
        if (isset($this->data[$key]) && count($this->data[$key] > 0)) {
0 ignored issues
show
Bug introduced by
$this->data[$key] > 0 of type boolean is incompatible with the type Countable|array expected by parameter $value of count(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

144
        if (isset($this->data[$key]) && count(/** @scrutinizer ignore-type */ $this->data[$key] > 0)) {
Loading history...
145
            $this->data[$key][0] = self::normalizeValue($value);
146
        } else {
147
            $this->data[$key] = array(self::normalizeValue($value));
148
        }
149
    }
150
151
    /**
152
     * @return void
153
     */
154
    public function offsetUnset($offset)
155
    {
156
        $key = self::normalizeKey($offset);
157
        unset($this->data[$key]);
158
    }
159
160
    /**
161
     * @return \ArrayIterator
162
     */
163
    public function getIterator()
164
    {
165
        $arr = array();
166
        foreach ($this->data as $k => $v) {
167
            $arr[$k] = $v[0];
168
        }
169
        return new \ArrayIterator($arr);
170
    }
171
172
    /**
173
     * @return int
174
     */
175
    public function count()
176
    {
177
        return count($this->data);
178
    }
179
180
    private static $isTokenTable = array(
181
        '!' => true,
182
        '#' => true,
183
        '$' => true,
184
        '%' => true,
185
        '&' => true,
186
        '\'' => true,
187
        '*' => true,
188
        '+' => true,
189
        '-' => true,
190
        '.' => true,
191
        '0' => true,
192
        '1' => true,
193
        '2' => true,
194
        '3' => true,
195
        '4' => true,
196
        '5' => true,
197
        '6' => true,
198
        '7' => true,
199
        '8' => true,
200
        '9' => true,
201
        'A' => true,
202
        'B' => true,
203
        'C' => true,
204
        'D' => true,
205
        'E' => true,
206
        'F' => true,
207
        'G' => true,
208
        'H' => true,
209
        'I' => true,
210
        'J' => true,
211
        'K' => true,
212
        'L' => true,
213
        'M' => true,
214
        'N' => true,
215
        'O' => true,
216
        'P' => true,
217
        'Q' => true,
218
        'R' => true,
219
        'S' => true,
220
        'T' => true,
221
        'U' => true,
222
        'W' => true,
223
        'V' => true,
224
        'X' => true,
225
        'Y' => true,
226
        'Z' => true,
227
        '^' => true,
228
        '_' => true,
229
        '`' => true,
230
        'a' => true,
231
        'b' => true,
232
        'c' => true,
233
        'd' => true,
234
        'e' => true,
235
        'f' => true,
236
        'g' => true,
237
        'h' => true,
238
        'i' => true,
239
        'j' => true,
240
        'k' => true,
241
        'l' => true,
242
        'm' => true,
243
        'n' => true,
244
        'o' => true,
245
        'p' => true,
246
        'q' => true,
247
        'r' => true,
248
        's' => true,
249
        't' => true,
250
        'u' => true,
251
        'v' => true,
252
        'w' => true,
253
        'x' => true,
254
        'y' => true,
255
        'z' => true,
256
        '|' => true,
257
        '~' => true,
258
    );
259
260
    /**
261
     * @param string $str
262
     *
263
     * @return boolean
264
     */
265
    private static function isValidKeyName($str)
266
    {
267
        for ($i = 0; $i < count($str); $i += 1) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
Bug introduced by
$str of type string is incompatible with the type Countable|array expected by parameter $value of count(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

267
        for ($i = 0; $i < count(/** @scrutinizer ignore-type */ $str); $i += 1) {
Loading history...
268
            if (!isset(self::$isTokenTable[$str[$i]])) {
269
                return false;
270
            }
271
        }
272
        return true;
273
    }
274
}
275