Passed
Push — master ( 4a0863...f9bf6d )
by Magnar Ovedal
03:47 queued 10s
created

CacheControl::setDirective()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stadly\Http\Header\Response;
6
7
use InvalidArgumentException;
8
use OutOfBoundsException;
9
use RuntimeException;
10
use Stadly\Http\Header\Value\CacheControl\Directive;
11
use Stadly\Http\Utilities\Rfc7230;
12
use Stadly\Http\Utilities\Rfc7234;
13
14
/**
15
 * Class for handling the HTTP header field Cache-Control.
16
 *
17
 * Specification: https://tools.ietf.org/html/rfc7234#section-5.2
18
 */
19
final class CacheControl implements Header
20
{
21
    /**
22
     * @var array<Directive> Directives.
23
     */
24
    private $directives = [];
25
26
    /**
27
     * Constructor.
28
     *
29
     * @param Directive ...$directives Directives.
30
     */
31 3
    public function __construct(Directive ...$directives)
32
    {
33 3
        $this->setDirective(...$directives);
34 3
    }
35
36
    /**
37
     * Construct header from value.
38
     *
39
     * @param string $value Header value.
40
     * @return self Header generated based on the value.
41
     */
42 6
    public static function fromValue(string $value): self
43
    {
44 6
        $regEx = '{^' . Rfc7230::hashRule(Rfc7234::CACHE_DIRECTIVE, 1) . '$}';
45 6
        if (utf8_decode($value) !== $value || preg_match($regEx, $value) !== 1) {
46 2
            throw new InvalidArgumentException('Invalid header value: ' . $value);
47
        }
48
49 4
        $directiveRegEx = '{' . Rfc7234::CACHE_DIRECTIVE_CAPTURE . '}';
50 4
        preg_match_all($directiveRegEx, $value, $matches);
51
52 4
        $directives = [];
53 4
        foreach ($matches['CACHE_DIRECTIVE'] as $directive) {
54 4
            $directives[] = Directive::fromString($directive);
55
        }
56
57 4
        return new self(...$directives);
58
    }
59
60
    /**
61
     * @inheritDoc
62
     */
63 3
    public function __toString(): string
64
    {
65 3
        return $this->getName() . ': ' . $this->getValue();
66
    }
67
68
    /**
69
     * @inheritDoc
70
     */
71 2
    public function isValid(): bool
72
    {
73 2
        return $this->directives !== [];
74
    }
75
76
    /**
77
     * @inheritDoc
78
     */
79 1
    public function getName(): string
80
    {
81 1
        return 'Cache-Control';
82
    }
83
84
    /**
85
     * @inheritDoc
86
     */
87 3
    public function getValue(): string
88
    {
89 3
        if ($this->directives === []) {
90 1
            throw new RuntimeException('Header has no directives.');
91
        }
92
93 2
        return implode(', ', $this->directives);
94
    }
95
96
    /**
97
     * @param string $name Directive name.
98
     * @return bool Whether the directive exists.
99
     */
100 2
    public function hasDirective(string $name): bool
101
    {
102 2
        return array_key_exists(strtolower($name), $this->directives);
103
    }
104
105
    /**
106
     * @param string $name Directive name.
107
     * @return Directive Directive.
108
     * @throws OutOfBoundsException If the directive does not exist.
109
     */
110 2
    public function getDirective(string $name): Directive
111
    {
112 2
        if (!$this->hasDirective($name)) {
113 1
            throw new OutOfBoundsException('Directive not found: ' . $name);
114
        }
115
116 1
        return $this->directives[strtolower($name)];
117
    }
118
119
    /**
120
     * Set directives.
121
     *
122
     * @param Directive ...$directives Directives to set.
123
     */
124 7
    public function setDirective(Directive ...$directives): void
125
    {
126 7
        foreach ($directives as $directive) {
127 7
            $this->directives[strtolower($directive->getName())] = $directive;
128
        }
129 7
    }
130
131
    /**
132
     * Unset directives.
133
     *
134
     * @param string ...$names Directive names.
135
     */
136 4
    public function unsetDirective(string ...$names): void
137
    {
138 4
        foreach ($names as $name) {
139 4
            unset($this->directives[strtolower($name)]);
140
        }
141 4
    }
142
}
143