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

AcceptHeader   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 118
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 19
c 1
b 0
f 0
lcom 1
cbo 3
dl 0
loc 118
ccs 36
cts 36
cp 1
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 2
A parse() 0 4 1
A parseMediaType() 0 4 1
A newInstance() 0 5 1
B getMediaTypeCompareClosure() 0 26 5
A compareQuality() 0 11 3
A compareStrings() 0 4 3
A compareParameters() 0 4 3
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 \Closure;
20
use \InvalidArgumentException;
21
use \Neomerx\JsonApi\Contracts\Http\Headers\AcceptHeaderInterface;
22
use \Neomerx\JsonApi\Contracts\Http\Headers\AcceptMediaTypeInterface;
23
24
/**
25
 * @package Neomerx\JsonApi
26
 */
27
class AcceptHeader extends Header implements AcceptHeaderInterface
28
{
29
    /**
30
     * @param AcceptMediaTypeInterface[] $unsortedMediaTypes
31
     */
32 50
    public function __construct($unsortedMediaTypes)
33
    {
34
35 50
        if (is_array($unsortedMediaTypes) ===  false) {
36 1
            throw new InvalidArgumentException('unsortedMediaTypes');
37
        }
38
39 49
        usort($unsortedMediaTypes, $this->getMediaTypeCompareClosure());
40
41 49
        parent::__construct(self::HEADER_ACCEPT, $unsortedMediaTypes);
42 49
    }
43
44
    /**
45
     * @inheritdoc
46
     *
47
     * @return AcceptHeaderInterface
1 ignored issue
show
Documentation introduced by
Should the return type not be Header?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
48
     */
49 51
    public static function parse($header, $accept = self::HEADER_ACCEPT)
50
    {
51 51
        return parent::parse($header, self::HEADER_ACCEPT);
52
    }
53
54
    /**
55
     * @inheritdoc
56
     *
57
     * @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...
58
     */
59 51
    protected static function parseMediaType($position, $mediaType)
60
    {
61 51
        return AcceptMediaType::parse($position, $mediaType);
62
    }
63
64
    /**
65
     * @inheritdoc
66
     *
67
     * @return AcceptHeaderInterface
1 ignored issue
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use AcceptHeader.

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...
68
     */
69 47
    protected static function newInstance($name, $mediaTypes)
70
    {
71
        /** @var AcceptMediaTypeInterface[] $mediaTypes */
72 47
        return new static($mediaTypes);
73
    }
74
75
    /**
76
     * @return Closure
77
     */
78
    private function getMediaTypeCompareClosure()
79
    {
80 49
        return function (AcceptMediaTypeInterface $lhs, AcceptMediaTypeInterface $rhs) {
81 12
            $qualityCompare = $this->compareQuality($lhs->getQuality(), $rhs->getQuality());
82 12
            if ($qualityCompare !== 0) {
83 10
                return $qualityCompare;
84
            }
85
86 4
            $typeCompare = $this->compareStrings($lhs->getType(), $rhs->getType());
87 4
            if ($typeCompare !== 0) {
88 2
                return $typeCompare;
89
            }
90
91 3
            $subTypeCompare = $this->compareStrings($lhs->getSubType(), $rhs->getSubType());
92 3
            if ($subTypeCompare !== 0) {
93 1
                return $subTypeCompare;
94
            }
95
96 3
            $parametersCompare = $this->compareParameters($lhs->getParameters(), $rhs->getParameters());
97 3
            if ($parametersCompare !== 0) {
98 1
                return $parametersCompare;
99
            }
100
101 2
            return ($lhs->getPosition() - $rhs->getPosition());
102 49
        };
103
    }
104
105
    /**
106
     * @param float $lhs
107
     * @param float $rhs
108
     *
109
     * @return int
110
     */
111 12
    private function compareQuality($lhs, $rhs)
112
    {
113 12
        $qualityDiff = $lhs - $rhs;
114
115
        // rfc2616: 3 digits are meaningful (#3.9 Quality Values)
116 12
        if (abs($qualityDiff) < 0.001) {
117 4
            return 0;
118
        } else {
119 10
            return $lhs > $rhs ? -1 : 1;
120
        }
121
    }
122
123
    /**
124
     * @param string $lhs
125
     * @param string $rhs
126
     *
127
     * @return int
128
     */
129 4
    private function compareStrings($lhs, $rhs)
130
    {
131 4
        return ($rhs !== '*' ? 1 : 0) - ($lhs !== '*' ? 1 : 0);
132
    }
133
134
    /**
135
     * @param array|null $lhs
136
     * @param array|null $rhs
137
     *
138
     * @return int
139
     */
140 3
    private function compareParameters($lhs, $rhs)
141
    {
142 3
        return (empty($lhs) !== false ? 1 : 0) - (empty($rhs) !== false ? 1 : 0);
143
    }
144
}
145