Completed
Branch master (85eed3)
by
unknown
06:32
created

AcceptMediaType::parse()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 13
ccs 7
cts 7
cp 1
rs 9.4285
cc 2
eloc 7
nc 2
nop 2
crap 2
1
<?php namespace Neomerx\JsonApi\Http\Headers;
2
3
/**
4
 * Copyright 2015 [email protected] (www.neomerx.com)
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use \InvalidArgumentException;
20
use \Neomerx\JsonApi\Contracts\Http\Headers\AcceptMediaTypeInterface;
21
22
/**
23
 * @package Neomerx\JsonApi
24
 */
25
class AcceptMediaType extends MediaType implements AcceptMediaTypeInterface
26
{
27
    /**
28
     * @var float [0..1]
29
     */
30
    private $quality;
31
32
    /**
33
     * @var array<string,string>|null
34
     */
35
    private $extensions;
36
37
    /**
38
     * @var int
39
     */
40
    private $position;
41
42
    /**
43
     * @param int                       $position
44
     * @param string                    $type
45
     * @param string                    $subType
46
     * @param array<string,string>|null $parameters
47
     * @param float                     $quality
48
     * @param array<string,string>|null $extensions
49
     */
50 54
    public function __construct($position, $type, $subType, $parameters = null, $quality = 1.0, $extensions = null)
51
    {
52 54
        parent::__construct($type, $subType, $parameters);
53
54 52
        if (is_int($position) === false || $position < 0) {
55 1
            throw new InvalidArgumentException('position');
56
        }
57
58
        // rfc2616: 3 digits are meaningful (#3.9 Quality Values)
59 51
        $quality = floor((float)$quality * 1000) / 1000;
60 51
        if ($quality < 0 || $quality > 1) {
61 1
            throw new InvalidArgumentException('quality');
62
        }
63
64 50
        if ($extensions !== null && is_array($extensions) === false) {
65 1
            throw new InvalidArgumentException('extensions');
66
        }
67
68 49
        $this->position   = $position;
69 49
        $this->quality    = $quality;
70 49
        $this->extensions = $extensions;
71 49
    }
72
73
    /**
74
     * @inheritdoc
75
     */
76 3
    public function getPosition()
77
    {
78 3
        return $this->position;
79
    }
80
81
    /**
82
     * @inheritdoc
83
     */
84 34
    public function getQuality()
85
    {
86 34
        return $this->quality;
87
    }
88
89
    /**
90
     * @inheritdoc
91
     */
92 2
    public function getExtensions()
93
    {
94 2
        return $this->extensions;
95
    }
96
97
    /**
98
     * @inheritdoc
99
     *
100
     * @return AcceptMediaTypeInterface
1 ignored issue
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use AcceptMediaType.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
101
     */
102 51
    public static function parse($position, $mediaType)
103
    {
104 51
        $fields = explode(';', $mediaType);
105
106 51
        if (strpos($fields[0], '/') === false) {
107 2
            throw new InvalidArgumentException('mediaType');
108
        }
109
110 49
        list($type, $subType) = explode('/', $fields[0], 2);
111 49
        list($parameters, $quality, $extensions) = self::parseQualityAndParameters($fields);
112
113 47
        return new AcceptMediaType($position, $type, $subType, $parameters, $quality, $extensions);
114
    }
115
116
    /**
117
     * @param array $fields
118
     *
119
     * @return array
1 ignored issue
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<null|integer|double>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
120
     */
121 49
    private static function parseQualityAndParameters(array $fields)
122
    {
123 49
        $quality     = 1;
124 49
        $qParamFound = false;
125 49
        $parameters  = null;
126 49
        $extensions  = null;
127
128 49
        $count = count($fields);
129 49
        for ($idx = 1; $idx < $count; ++$idx) {
130 24
            if (empty($fields[$idx]) === true) {
131 1
                continue;
132
            }
133
134 23
            if (strpos($fields[$idx], '=') === false) {
135 2
                throw new InvalidArgumentException('mediaType');
136
            }
137
138 21
            list($key, $value) = explode('=', $fields[$idx], 2);
139
140 21
            $key   = trim($key);
141 21
            $value = trim($value, ' "');
142
143
            // 'q' param separates media parameters from extension parameters
144
145 21
            if ($key === 'q' && $qParamFound === false) {
146 12
                $quality     = (float)$value;
147 12
                $qParamFound = true;
148 12
                continue;
149
            }
150
151 17
            $qParamFound === false ? $parameters[$key] = $value : $extensions[$key] = $value;
152 17
        }
153
154 47
        return [$parameters, $quality, $extensions];
155
    }
156
}
157