GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

AbstractNegotiator   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 98.51%

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 4
dl 0
loc 158
ccs 66
cts 67
cp 0.9851
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
C getBest() 0 38 8
C getOrderedElements() 0 39 7
acceptFactory() 0 1 ?
A match() 0 15 3
A parseHeader() 0 10 2
A findMatches() 0 13 4
1
<?php
2
3
namespace Negotiation;
4
5
use Negotiation\Exception\InvalidArgument;
6
use Negotiation\Exception\InvalidHeader;
7
8
abstract class AbstractNegotiator
9
{
10
    /**
11
     * @param string $header     A string containing an `Accept|Accept-*` header.
12
     * @param array  $priorities A set of server priorities.
13
     *
14
     * @return AcceptHeader|null best matching type
15
     */
16 74
    public function getBest($header, array $priorities, $strict = false)
17
    {
18 74
        if (empty($priorities)) {
19 1
            throw new InvalidArgument('A set of server priorities should be given.');
20
        }
21
22 73
        if (!$header) {
23 3
            throw new InvalidArgument('The header string should not be empty.');
24
        }
25
26
        // Once upon a time, two `array_map` calls were sitting there, but for
27
        // some reasons, they triggered `E_WARNING` time to time (because of
28
        // PHP bug [55416](https://bugs.php.net/bug.php?id=55416). Now, they
29
        // are gone.
30
        // See: https://github.com/willdurand/Negotiation/issues/81
31 70
        $acceptedHeaders = array();
32 70
        foreach ($this->parseHeader($header) as $h) {
33
            try {
34 70
                $acceptedHeaders[] = $this->acceptFactory($h);
0 ignored issues
show
Documentation introduced by
$h is of type object<Negotiation\AcceptHeader>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
35 70
            } catch (Exception\Exception $e) {
36 3
                if ($strict) {
37 1
                    throw $e;
38
                }
39
            }
40 69
        }
41 69
        $acceptedPriorities = array();
42 69
        foreach ($priorities as $p) {
43 69
            $acceptedPriorities[] = $this->acceptFactory($p);
44 68
        }
45 68
        $matches         = $this->findMatches($acceptedHeaders, $acceptedPriorities);
46 68
        $specificMatches = array_reduce($matches, 'Negotiation\Match::reduce', []);
47
48 68
        usort($specificMatches, 'Negotiation\Match::compare');
49
50 68
        $match = array_shift($specificMatches);
51
52 68
        return null === $match ? null : $acceptedPriorities[$match->index];
53
    }
54
55
    /**
56
     * @param string $header A string containing an `Accept|Accept-*` header.
57
     *
58
     * @return [AcceptHeader] An ordered list of accept header elements
0 ignored issues
show
Documentation introduced by
The doc-type [AcceptHeader] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
59
     */
60 5
    public function getOrderedElements($header)
61
    {
62 5
        if (!$header) {
63 1
            throw new InvalidArgument('The header string should not be empty.');
64
        }
65
66 4
        $elements = array();
67 4
        $orderKeys = array();
68 4
        foreach ($this->parseHeader($header) as $key => $h) {
69
            try {
70 4
                $element = $this->acceptFactory($h);
0 ignored issues
show
Documentation introduced by
$h is of type object<Negotiation\AcceptHeader>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
71 3
                $elements[] = $element;
72 3
                $orderKeys[] = [$element->getQuality(), $key, $element->getValue()];
73 4
            } catch (Exception\Exception $e) {
74
                // silently skip in case of invalid headers coming in from a client
75
            }
76 4
        }
77
78
        // sort based on quality and then original order. This is necessary as
79
        // to ensure that the first in the list for two items with the same
80
        // quality stays in that order in both PHP5 and PHP7.
81 4
        uasort($orderKeys, function ($a, $b) {
82 3
            $qA = $a[0];
83 3
            $qB = $b[0];
84
85 3
            if ($qA == $qB) {
86 1
                return $a[1] > $b[1];
87
            }
88
89 2
            return ($qA > $qB) ? -1 : 1;
90 4
        });
91
92 4
        $orderedElements = [];
93 4
        foreach ($orderKeys as $key) {
94 3
            $orderedElements[] = $elements[$key[1]];
95 4
        }
96
97 4
        return $orderedElements;
98
    }
99
100
    /**
101
     * @param string $header accept header part or server priority
102
     *
103
     * @return AcceptHeader Parsed header object
104
     */
105
    abstract protected function acceptFactory($header);
106
107
    /**
108
     * @param AcceptHeader $header
109
     * @param AcceptHeader $priority
110
     * @param integer      $index
111
     *
112
     * @return Match|null Headers matched
113
     */
114 22
    protected function match(AcceptHeader $header, AcceptHeader $priority, $index)
115
    {
116 22
        $ac = $header->getType();
117 22
        $pc = $priority->getType();
118
119 22
        $equal = !strcasecmp($ac, $pc);
120
121 22
        if ($equal || $ac === '*') {
122 19
            $score = 1 * $equal;
123
124 19
            return new Match($header->getQuality() * $priority->getQuality(), $score, $index);
125
        }
126
127 22
        return null;
128
    }
129
130
    /**
131
     * @param string $header A string that contains an `Accept*` header.
132
     *
133
     * @return AcceptHeader[]
134
     */
135 91
    private function parseHeader($header)
136
    {
137 91
        $res = preg_match_all('/(?:[^,"]*+(?:"[^"]*+")?)+[^,"]*+/', $header, $matches);
138
139 91
        if (!$res) {
140
            throw new InvalidHeader(sprintf('Failed to parse accept header: "%s"', $header));
141
        }
142
143 91
        return array_values(array_filter(array_map('trim', $matches[0])));
144
    }
145
146
    /**
147
     * @param AcceptHeader[] $headerParts
148
     * @param Priority[]     $priorities  Configured priorities
149
     *
150
     * @return Match[] Headers matched
151
     */
152 71
    private function findMatches(array $headerParts, array $priorities)
153
    {
154 71
        $matches = [];
155 71
        foreach ($priorities as $index => $p) {
156 71
            foreach ($headerParts as $h) {
157 70
                if (null !== $match = $this->match($h, $p, $index)) {
158 61
                    $matches[] = $match;
159 61
                }
160 71
            }
161 71
        }
162
163 71
        return $matches;
164
    }
165
}
166