MediaType::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 3
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stadly\Http\Header\Value\MediaType;
6
7
use InvalidArgumentException;
8
use OutOfBoundsException;
9
use Stadly\Http\Utilities\Rfc7231;
10
11
/**
12
 * Class for handling Internet media types.
13
 *
14
 * Specification: https://tools.ietf.org/html/rfc7231#section-3.1.1.1
15
 */
16
final class MediaType
17
{
18
    /**
19
     * @var string Type.
20
     */
21
    private $type;
22
23
    /**
24
     * @var string Subtype.
25
     */
26
    private $subtype;
27
28
    /**
29
     * @var array<Parameter> Parameters.
30
     */
31
    private $parameters = [];
32
33
    /**
34
     * Constructor.
35
     *
36
     * @param string $type Type.
37
     * @param string $subtype Subtype.
38
     * @param Parameter ...$parameters Parameters.
39
     */
40 7
    public function __construct(string $type, string $subtype, Parameter ...$parameters)
41
    {
42 7
        $this->setType($type);
43 5
        $this->setSubtype($subtype);
44 3
        $this->setParameter(...$parameters);
45
    }
46
47
    /**
48
     * Construct media type from string.
49
     *
50
     * @param string $mediaType Media type string.
51
     * @return self Media type generated based on the string.
52
     */
53 10
    public static function fromString(string $mediaType): self
54
    {
55 10
        $regEx = '{^' . Rfc7231::MEDIA_TYPE_CAPTURE . '$}';
56 10
        $plainMediaType = mb_convert_encoding($mediaType, 'ISO-8859-1', 'UTF-8');
57 10
        if ($plainMediaType !== $mediaType || preg_match($regEx, $mediaType, $matches) !== 1) {
58 5
            throw new InvalidArgumentException('Invalid media type: ' . $mediaType);
59
        }
60
61 5
        $parameterRexEx = '{' . Rfc7231::PARAMETER_CAPTURE . '}';
62 5
        preg_match_all($parameterRexEx, $matches['PARAMETERS'], $parameterMatches);
63
64 5
        $parameters = [];
65 5
        foreach ($parameterMatches['PARAMETER'] as $parameter) {
66 4
            $parameters[] = Parameter::fromString($parameter);
67
        }
68
69 5
        return new self($matches['TYPE'], $matches['SUBTYPE'], ...$parameters);
70
    }
71
72
    /**
73
     * @return string String representation of the media type.
74
     */
75 3
    public function __toString(): string
76
    {
77 3
        $mediaType = $this->type . '/' . $this->subtype;
78 3
        if ($this->parameters !== []) {
79 2
            $mediaType .= '; ' . implode('; ', $this->parameters);
80
        }
81
82 3
        return $mediaType;
83
    }
84
85
    /**
86
     * @return string Type.
87
     */
88 1
    public function getType(): string
89
    {
90 1
        return $this->type;
91
    }
92
93
    /**
94
     * Set type.
95
     *
96
     * @param string $type Type.
97
     */
98 3
    public function setType(string $type): void
99
    {
100 3
        $plainType = mb_convert_encoding($type, 'ISO-8859-1', 'UTF-8');
101 3
        if ($plainType !== $type || preg_match('{^' . Rfc7231::TYPE . '$}', $type) !== 1) {
102 2
            throw new InvalidArgumentException('Invalid type: ' . $type);
103
        }
104
105 3
        $this->type = $type;
106
    }
107
108
    /**
109
     * @return string Subtype.
110
     */
111 1
    public function getSubtype(): string
112
    {
113 1
        return $this->subtype;
114
    }
115
116
    /**
117
     * Set subtype.
118
     *
119
     * @param string $subtype Subtype.
120
     */
121 3
    public function setSubtype(string $subtype): void
122
    {
123 3
        $plainSubtype = mb_convert_encoding($subtype, 'ISO-8859-1', 'UTF-8');
124 3
        if ($plainSubtype !== $subtype || preg_match('{^' . Rfc7231::SUBTYPE . '$}', $subtype) !== 1) {
125 2
            throw new InvalidArgumentException('Invalid subtype: ' . $subtype);
126
        }
127
128 3
        $this->subtype = $subtype;
129
    }
130
131
    /**
132
     * @param string $name Parameter name.
133
     * @return bool Whether the parameter exists.
134
     */
135 2
    public function hasParameter(string $name): bool
136
    {
137 2
        return array_key_exists(strtolower($name), $this->parameters);
138
    }
139
140
    /**
141
     * @param string $name Parameter name.
142
     * @return Parameter Parameter.
143
     * @throws OutOfBoundsException If the parameter does not exist.
144
     */
145 2
    public function getParameter(string $name): Parameter
146
    {
147 2
        if (!$this->hasParameter($name)) {
148 1
            throw new OutOfBoundsException('Parameter not found: ' . $name);
149
        }
150
151 1
        return $this->parameters[strtolower($name)];
152
    }
153
154
    /**
155
     * Set parameters.
156
     *
157
     * @param Parameter ...$parameters Parameters to set.
158
     */
159 3
    public function setParameter(Parameter ...$parameters): void
160
    {
161 3
        foreach ($parameters as $parameter) {
162 3
            $this->parameters[strtolower($parameter->getName())] = $parameter;
163
        }
164
    }
165
166
    /**
167
     * Unset parameters.
168
     *
169
     * @param string ...$names Parameter names.
170
     */
171 4
    public function unsetParameter(string ...$names): void
172
    {
173 4
        foreach ($names as $name) {
174 4
            unset($this->parameters[strtolower($name)]);
175
        }
176
    }
177
}
178