Passed
Pull Request — master (#22)
by Aleksei
02:09
created

WithParamsHeaderValue   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 92
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 40
c 1
b 0
f 1
dl 0
loc 92
ccs 42
cts 42
cp 1
rs 10
wmc 23

7 Methods

Rating   Name   Duplication   Size   Complexity  
B __toString() 0 16 9
A createHeader() 0 4 2
A getParams() 0 7 2
A setQuality() 0 7 3
A setParams() 0 16 5
A getQuality() 0 3 1
A withParams() 0 5 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Http\Header\Internal;
6
7
use Yiisoft\Http\Header\Header;
8
use Yiisoft\Http\Header\SortableHeader;
9
10
abstract class WithParamsHeaderValue extends BaseHeaderValue
11
{
12
    /**
13
     * @see WithParams
14
     * @var array<string, string>
15
     */
16
    private array $params = [];
17
    /**
18
     * @link https://tools.ietf.org/html/rfc7231#section-5.3.1
19
     * @var string value between 0.000 and 1.000
20
     */
21
    private string $quality = '1';
22
23
    protected const PARSING_PARAMS = true;
24
25 67
    public function __toString(): string
26
    {
27 67
        $params = [];
28 67
        foreach ($this->getParams() as $key => $value) {
29 51
            if ($key === 'q' && static::PARSING_Q_PARAM) {
30 17
                if ($value === '1') {
31 16
                    continue;
32
                }
33
            }
34 45
            $escaped = $this->encodeQuotedString($value);
35 45
            $quoted = $value === ''
36 44
                || strlen($escaped) !== strlen($value)
37 45
                || preg_match('/[\\s,;()\\/:<=>?@\\[\\\\\\]{}]/', $value) === 1;
38 45
            $params[] = $key . '=' . ($quoted ? "\"{$escaped}\"" : $value);
39
        }
40 67
        return $this->value === '' ? implode(';', $params) : implode(';', [$this->value, ...$params]);
41
    }
42
43 2
    public static function createHeader(): Header
44
    {
45 2
        $class = static::PARSING_Q_PARAM ? SortableHeader::class : Header::class;
46 2
        return new $class(static::class);
47
    }
48
49
    /**
50
     * It makes sense to use only for HeaderValues that implement the WithParams interface
51
     * @param array<string, string> $params
52
     */
53 93
    public function withParams(array $params): self
54
    {
55 93
        $clone = clone $this;
56 93
        $clone->setParams($params);
57 93
        return $clone;
58
    }
59
60
    /**
61
     * @return array<string, string>
62
     */
63 73
    public function getParams(): array
64
    {
65 73
        $result = $this->params;
66 73
        if (static::PARSING_Q_PARAM) {
67 17
            $result['q'] = $this->quality;
68
        }
69 73
        return $result;
70
    }
71
72 32
    public function getQuality(): string
73
    {
74 32
        return $this->quality;
75
    }
76
77 35
    protected function setQuality(string $q): bool
78
    {
79 35
        if (preg_match('/^0(?:\\.\\d{1,3})?$|^1(?:\\.0{1,3})?$/', $q) !== 1) {
80 10
            return false;
81
        }
82 35
        $this->quality = rtrim($q, '0.') ?: '0';
83 35
        return true;
84
    }
85
86 93
    protected function setParams(array $params): void
87
    {
88 93
        $this->params = [];
89 93
        foreach ($params as $key => $value) {
90
            # todo decide: what about numeric keys?
91 68
            $key = strtolower($key);
92 68
            if (!array_key_exists($key, $this->params)) {
93 68
                $this->params[$key] = $value;
94
            }
95
        }
96 93
        if (static::PARSING_Q_PARAM) {
97 35
            if (array_key_exists('q', $this->params)) {
98 27
                $this->setQuality($this->params['q']);
99 27
                unset($this->params['q']);
100
            } else {
101 15
                $this->setQuality('1');
102
            }
103
        }
104 93
    }
105
}
106