Passed
Push — master ( b6cfd3...c595fc )
by Dominik
01:48
created

RequestManager::negotiate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 9
nc 3
nop 2
crap 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\ApiHttp\Manager;
6
7
use Chubbyphp\Deserialization\DeserializerInterface;
8
use Chubbyphp\Deserialization\Transformer\TransformerException;
9
use Chubbyphp\Deserialization\TransformerInterface;
10
use Negotiation\Accept as ContentAccept;
11
use Negotiation\AcceptLanguage;
12
use Negotiation\LanguageNegotiator;
13
use Negotiation\Negotiator as ContentNegotiator;
14
use Psr\Http\Message\ServerRequestInterface as Request;
15
16
final class RequestManager implements RequestManagerInterface
17
{
18
    /**
19
     * @var ContentNegotiator
20
     */
21
    private $contentNegotiator;
22
23
    /**
24
     * @var DeserializerInterface
25
     */
26
    private $deserializer;
27
28
    /**
29
     * @var LanguageNegotiator
30
     */
31
    private $languageNegotiator;
32
33
    /**
34
     * @var array
35
     */
36
    private $languages;
37
38
    /**
39
     * @var TransformerInterface
40
     */
41
    private $transformer;
42
43
    /**
44
     * @param ContentNegotiator     $contentNegotiator
45
     * @param DeserializerInterface $deserializer
46
     * @param LanguageNegotiator    $languageNegotiator
47
     * @param array                 $languages
48
     * @param TransformerInterface  $transformer
49
     */
50 13
    public function __construct(
51
        ContentNegotiator $contentNegotiator,
52
        DeserializerInterface $deserializer,
53
        LanguageNegotiator $languageNegotiator,
54
        array $languages,
55
        TransformerInterface $transformer
56
    ) {
57 13
        $this->contentNegotiator = $contentNegotiator;
58 13
        $this->deserializer = $deserializer;
59 13
        $this->languageNegotiator = $languageNegotiator;
60 13
        $this->languages = $languages;
61 13
        $this->transformer = $transformer;
62 13
    }
63
64
    /**
65
     * @param Request $request
66
     *
67
     * @return string|null
68
     */
69 3
    public function getAccept(Request $request)
70
    {
71 3
        return $this->negotiateContentType($request, 'Accept');
72
    }
73
74
    /**
75
     * @param Request $request
76
     *
77
     * @return string|null
78
     */
79 3 View Code Duplication
    public function getAcceptLanguage(Request $request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
80
    {
81 3
        if (!$request->hasHeader('Accept-Language')) {
82 1
            return null;
83
        }
84
85
        /** @var AcceptLanguage $best */
86 2
        $best = $this->languageNegotiator->getBest(
87 2
            $request->getHeaderLine('Accept-Language'),
88 2
            $this->languages
89
        );
90
91 2
        if (null === $best) {
92 1
            return null;
93
        }
94
95 1
        return $best->getNormalizedValue();
96
    }
97
98
    /**
99
     * @param Request $request
100
     *
101
     * @return string|null
102
     */
103 6
    public function getContentType(Request $request)
104
    {
105 6
        return $this->negotiateContentType($request, 'Content-Type');
106
    }
107
108
    /**
109
     * @param Request $request
110
     * @param string  $headerName
111
     *
112
     * @return null|string
113
     */
114 9 View Code Duplication
    private function negotiateContentType(Request $request, string $headerName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
115
    {
116 9
        if (!$request->hasHeader($headerName)) {
117 3
            return null;
118
        }
119
120
        /** @var ContentAccept $best */
121 6
        $best = $this->contentNegotiator->getBest(
122 6
            $request->getHeaderLine($headerName),
123 6
            $this->transformer->getContentTypes()
124
        );
125
126 6
        if (null === $best) {
127 2
            return null;
128
        }
129
130 4
        return $best->getNormalizedValue();
131
    }
132
133
    /**
134
     * @param Request       $request
135
     * @param object|string $object
136
     *
137
     * @return object|null
138
     */
139 3
    public function getDataFromRequestBody(Request $request, $object)
140
    {
141 3
        if (null === $contentType = $this->getContentType($request)) {
142 1
            return null;
143
        }
144
145
        try {
146 2
            $data = $this->transformer->transform((string) $request->getBody(), $contentType);
147 1
        } catch (TransformerException $e) {
148 1
            return null;
149
        }
150
151 1
        $method = $this->getSerializerMethod($object);
152
153 1
        return $this->deserializer->$method($data, $object);
154
    }
155
156
    /**
157
     * @param Request       $request
158
     * @param object|string $object
159
     *
160
     * @return object|null
161
     */
162 1
    public function getDataFromRequestQuery(Request $request, $object)
163
    {
164 1
        $method = $this->getSerializerMethod($object);
165
166 1
        return $this->deserializer->$method($request->getQueryParams(), $object);
167
    }
168
169
    /**
170
     * @param object|string $object
171
     *
172
     * @return string
173
     */
174 2
    private function getSerializerMethod($object): string
175
    {
176 2
        return is_string($object) ? 'deserializeByClass' : 'deserializeByObject';
177
    }
178
}
179