Passed
Push — master ( 2bd34a...07270e )
by Dominik
01:45
created

ContentNegotiator   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 69
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 11
lcom 0
cbo 1
dl 0
loc 69
ccs 28
cts 28
cp 1
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A negotiate() 0 6 1
B aggregatedValues() 0 25 4
B compareAgainstSupportedTypes() 0 16 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\ApiHttp\Negotiation;
6
7
final class ContentNegotiator implements ContentNegotiatorInterface
8
{
9
    /**
10
     * @param string $header
11
     * @param array  $supportedContentTypes
12
     *
13
     * @return Content|null
14
     */
15 6
    public function negotiate(string $header, array $supportedContentTypes)
16
    {
17 6
        $aggregatedValues = $this->aggregatedValues($header);
18
19 6
        return $this->compareAgainstSupportedTypes($aggregatedValues, $supportedContentTypes);
20
    }
21
22
    /**
23
     * @param string $header
24
     *
25
     * @return array
26
     */
27 6
    private function aggregatedValues(string $header): array
28
    {
29 6
        $values = [];
30 6
        foreach (explode(',', $header) as $headerValue) {
31 6
            $headerValueParts = explode(';', $headerValue);
32 6
            $contentType = trim(array_shift($headerValueParts));
33 6
            $attributes = [];
34 6
            foreach ($headerValueParts as $attribute) {
35 5
                list($attributeKey, $attributeValue) = explode('=', $attribute);
36 5
                $attributes[trim($attributeKey)] = trim($attributeValue);
37
            }
38
39 6
            if (!isset($attributes['q'])) {
40 6
                $attributes['q'] = '1.0';
41
            }
42
43 6
            $values[$contentType] = $attributes;
44
        }
45
46 6
        uasort($values, function (array $a, array $b) {
47 6
            return $b['q'] <=> $a['q'];
48 6
        });
49
50 6
        return $values;
51
    }
52
53
    /**
54
     * @param array $aggregatedValues
55
     * @param array $supportedContentTypes
56
     *
57
     * @return Content|null
58
     */
59 6
    private function compareAgainstSupportedTypes(array $aggregatedValues, array $supportedContentTypes)
60
    {
61 6
        foreach ($aggregatedValues as $contentType => $attributes) {
62 6
            list($type, $subType) = explode('/', $contentType);
63 6
            $typePattern = '*' !== $type ? preg_quote($type) : '[^\/]+';
64 6
            $subTypePattern = '*' !== $subType ? preg_quote($subType) : '[^\/]+';
65
66 6
            foreach ($supportedContentTypes as $supportedContentType) {
67 6
                if (1 === preg_match('/^'.$typePattern.'\/'.$subTypePattern.'$/', $supportedContentType)) {
68 6
                    return new Content($supportedContentType, $attributes);
69
                }
70
            }
71
        }
72
73 1
        return null;
74
    }
75
}
76