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

WithParamsHeaderValue::getParams()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

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