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.
Completed
Push — master ( 9ee3c2...6cf3d3 )
by Sergey
05:55
created

JsonApiService::initializeEnvironment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.4285
cc 1
eloc 7
nc 1
nop 2
crap 1
1
<?php
2
/*
3
 * This file is part of the reva2/jsonapi.
4
 *
5
 * (c) Sergey Revenko <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Reva2\JsonApi\Services;
12
13
use Doctrine\Common\Proxy\Exception\InvalidArgumentException;
14
use Neomerx\JsonApi\Contracts\Codec\CodecMatcherInterface;
15
use Neomerx\JsonApi\Contracts\Schema\ContainerInterface;
16
use Neomerx\JsonApi\Document\Error;
17
use Neomerx\JsonApi\Exceptions\JsonApiException;
18
use Reva2\JsonApi\Contracts\Decoders\DataParserInterface;
19
use Reva2\JsonApi\Contracts\Decoders\DecoderInterface;
20
use Reva2\JsonApi\Contracts\Factories\FactoryInterface;
21
use Reva2\JsonApi\Contracts\Http\Query\QueryParametersParserInterface;
22
use Reva2\JsonApi\Contracts\Http\RequestInterface;
23
use Reva2\JsonApi\Contracts\Services\EnvironmentInterface;
24
use Reva2\JsonApi\Contracts\Services\JsonApiRegistryInterface;
25
use Reva2\JsonApi\Contracts\Services\JsonApiServiceInterface;
26
use Reva2\JsonApi\Contracts\Services\ValidationServiceInterface;
27
use Reva2\JsonApi\Http\ResponseFactory;
28
use Symfony\Component\HttpFoundation\Request;
29
use Neomerx\JsonApi\Http\Request as Psr7Request;
30
31
/**
32
 * Service for JSON API requests processing
33
 *
34
 * @package Reva2\JsonApi\Services
35
 * @author Sergey Revenko <[email protected]>
36
 */
37
class JsonApiService implements JsonApiServiceInterface
38
{
39
    /**
40
     * @var FactoryInterface
41
     */
42
    protected $factory;
43
44
    /**
45
     * @var JsonApiRegistryInterface
46
     */
47
    protected $registry;
48
49
    /**
50
     * @var ContainerInterface
51
     */
52
    protected $schemas;
53
54
    /**
55
     * @var ValidationServiceInterface
56
     */
57
    protected $validator;
58
59
    /**
60
     * @var DataParserInterface
61
     */
62
    protected $parser;
63
64
    /**
65
     * Constructor
66
     *
67
     * @param FactoryInterface $factory
68
     * @param JsonApiRegistryInterface $registry
69
     * @param ContainerInterface $schemas
70
     * @param DataParserInterface $parser
71
     * @param ValidationServiceInterface $validator
72
     */
73 6
    public function __construct(
74
        FactoryInterface $factory,
75
        JsonApiRegistryInterface $registry,
76
        ContainerInterface $schemas,
77
        DataParserInterface $parser,
78
        ValidationServiceInterface $validator
79
    ) {
80 6
        $this->factory = $factory;
81 6
        $this->registry = $registry;
82 6
        $this->parser = $parser;
83 6
        $this->schemas = $schemas;
84 6
        $this->validator = $validator;
85 6
    }
86
87
    /**
88
     * @inheritdoc
89
     */
90
    public function getFactory()
91
    {
92
        return $this->factory;
93
    }
94
95
    /**
96
     * @inheritdoc
97
     */
98 6
    public function parseRequest(Request $request, EnvironmentInterface $environment = null)
99
    {
100 6
        if (null === $environment) {
101 6
            $environment = $this->getRequestEnvironment($request);
102 4
        }
103
104 4
        $this->initializeEnvironment($environment, $request);
105
106 3
        $apiRequest = $this->factory->createRequest($environment);
107
        $apiRequest
108 3
            ->setQuery($this->parseQuery($request, $environment))
109 3
            ->setBody($this->parseBody($request, $environment));
110
111 3
        if (null !== $environment->getValidationGroups()) {
112 2
            $this->validateRequest($apiRequest);
113 2
        }
114
115 3
        return $apiRequest;
116
    }
117
118
    /**
119
     * @inheritdoc
120
     */
121 2
    public function validateRequest(RequestInterface $request)
122
    {
123 2
        $validationGroups = $request->getEnvironment()->getValidationGroups();
124 2
        if (is_bool($validationGroups)) {
125
            if (false === $validationGroups) {
126
                return;
127
            } else {
128
                $validationGroups = null;
129
            }
130
        }
131
132 2
        $errors = $this->validateData($request->getQuery(), $validationGroups);
133 2
        $errors = array_merge($errors, $this->validateData($request->getBody(), $validationGroups));
134
135 2
        if (0 === count($errors)) {
136 2
            return;
137
        }
138
139
        $code = null;
140
        foreach ($errors as $error) {
141
            /* @var $error Error */
142
            if (null === $code) {
143
                $code = $error->getStatus();
144
            } elseif ($code !== $error->getStatus()) {
145
                $code = 400;
146
                break;
147
            }
148
        }
149
150
        throw new JsonApiException($errors, $code);
151
    }
152
153
    /**
154
     * @inheritdoc
155
     */
156 1
    public function getResponseFactory(RequestInterface $request)
157
    {
158 1
        return new ResponseFactory($this->schemas, $request->getEnvironment(), $request->getQuery());
159
    }
160
161
    /**
162
     * Returns JSON API environment configured in request
163
     *
164
     * @param Request $request
165
     * @return EnvironmentInterface
166
     */
167 6
    protected function getRequestEnvironment(Request $request)
168
    {
169 6
        if (false === $request->attributes->has('_jsonapi')) {
170 1
            throw new \RuntimeException('JSON API environment is not provided');
171
        }
172
173 5
        $environment = $request->attributes->get('_jsonapi');
174 5
        if (!$environment instanceof EnvironmentInterface) {
175 1
            throw new \InvalidArgumentException(sprintf(
176 1
                "JSON API environment should implement %s interface",
177
                EnvironmentInterface::class
178 1
            ));
179
        }
180
181 4
        return $environment;
182
    }
183
184
    /**
185
     * Initialize JSON API environment for specified request
186
     *
187
     * @param EnvironmentInterface $environment
188
     * @param Request $request
189
     */
190 4
    private function initializeEnvironment(EnvironmentInterface $environment, Request $request)
191
    {
192 4
        $matcher = $this->createMatcher($environment);
193
194 3
        $this->parseRequestHeaders($request, $matcher);
195
196
        $environment
197 3
            ->setDecoder($matcher->getDecoder())
198 3
            ->setEncoder($matcher->getEncoder())
199 3
            ->setEncoderMediaType($matcher->getEncoderRegisteredMatchedType());
200 3
    }
201
202
    /**
203
     * Create codec matcher for specified environment
204
     *
205
     * @param EnvironmentInterface $environment
206
     * @return \Neomerx\JsonApi\Contracts\Codec\CodecMatcherInterface
207
     */
208 4
    private function createMatcher(EnvironmentInterface $environment)
209
    {
210 4
        $matcher = $this->factory->createCodecMatcher();
211
212 4
        $config = $environment->getMatcherConfiguration();
213 4
        if ((array_key_exists('decoders', $config)) && (is_array($config['decoders']))) {
214 4
            $this->registerDecoders($config['decoders'], $matcher);
215 3
        }
216
217 3
        if ((array_key_exists('encoders', $config)) && (is_array($config['encoders']))) {
218 3
            $this->registerEncoders($config['encoders'], $matcher);
219 3
        }
220
221 3
        return $matcher;
222
    }
223
224
    /**
225
     * Convert media type string to media type object
226
     *
227
     * @param string $type
228
     * @return \Neomerx\JsonApi\Contracts\Http\Headers\MediaTypeInterface
229
     */
230 4
    private function parseMediaTypeString($type)
231
    {
232 4
        $parts = explode('/', $type);
233 4
        if (2 !== count($parts)) {
234 1
            throw new InvalidArgumentException(sprintf("Invalid media type '%s' specified", $type));
235
        }
236
237 3
        return $this->factory->createMediaType($parts[0], $parts[1]);
238
    }
239
240
    /**
241
     * Parse request headers and detect appropriate decoder and encoder
242
     *
243
     * @param Request $request
244
     * @param CodecMatcherInterface $matcher
245
     */
246 3
    private function parseRequestHeaders(Request $request, CodecMatcherInterface $matcher)
247
    {
248 3
        $psr7Request = $this->createPsr7Request($request);
249 3
        $headers = $this->factory->createHeaderParametersParser()->parse($psr7Request);
250 3
        $checker = $this->factory->createHeadersChecker($matcher);
251
252 3
        $checker->checkHeaders($headers);
253 3
    }
254
255
    /**
256
     * Create PSR7 request from symfony http foundation request
257
     *
258
     * @param Request $request
259
     * @return Psr7Request
260
     */
261 3
    private function createPsr7Request(Request $request)
262
    {
263 3
        return new Psr7Request(
264
            function () use ($request) {
265 3
                return $request->getMethod();
266 3
            },
267
            function ($name) use ($request) {
268 3
                $header = $request->headers->get($name);
269 3
                if (!is_array($header)) {
270 3
                    $header = array($header);
271 3
                }
272
273 3
                return $header;
274 3
            },
275 2
            function () use ($request) {
276 2
                return $request->query->all();
277
            }
278 3
        );
279
    }
280
281
    /**
282
     * Parse request query parameters
283
     *
284
     * @param Request $request
285
     * @param EnvironmentInterface $environment
286
     * @return \Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface|null
287
     */
288 3
    private function parseQuery(Request $request, EnvironmentInterface $environment)
289
    {
290 3
        if (null === $environment->getQueryType()) {
291 1
            return null;
292
        }
293
294 2
        $queryParser = $this->factory->createQueryParametersParser();
295 2
        if ($queryParser instanceof QueryParametersParserInterface) {
296
            $queryParser
297 2
                ->setDataParser($this->parser)
298 2
                ->setQueryType($environment->getQueryType());
299 2
        }
300
301 2
        return $queryParser->parse($this->createPsr7Request($request));
302
    }
303
304
    /**
305
     * Parse request body
306
     *
307
     * @param Request $request
308
     * @param EnvironmentInterface $environment
309
     * @return mixed|null
310
     */
311 3
    private function parseBody(Request $request, EnvironmentInterface $environment)
312
    {
313 3
        if (null === $environment->getBodyType()) {
314 2
            return null;
315
        }
316
317 1
        $decoder = $environment->getDecoder();
318 1
        if ($decoder instanceof DecoderInterface) {
319 1
            $decoder->setContentType($environment->getBodyType());
320 1
        }
321
322 1
        return $decoder->decode($request->getContent());
323
    }
324
325
    /**
326
     * Validate specified data
327
     *
328
     * @param mixed $data
329
     * @param array|null $validationGroups
330
     * @return Error[]
331
     */
332 2
    private function validateData($data = null, array $validationGroups = null)
333
    {
334 2
        return (null !== $data) ? $this->validator->validate($data, $validationGroups) : [];
335
    }
336
337
    /**
338
     * Register specified decoders
339
     *
340
     * @param array $decoders
341
     * @param CodecMatcherInterface $matcher
342
     */
343 4
    private function registerDecoders(array $decoders, CodecMatcherInterface $matcher)
344
    {
345 4
        foreach ($decoders as $mediaType => $decoderType) {
346 4
            $matcher->registerDecoder(
347 4
                $this->parseMediaTypeString($mediaType),
348 3
                $this->registry->getDecoder($decoderType)
349 3
            );
350 3
        }
351 3
    }
352
353
    /**
354
     * Register specified encoders
355
     *
356
     * @param array $encoders
357
     * @param CodecMatcherInterface $matcher
358
     */
359 3
    private function registerEncoders(array $encoders, CodecMatcherInterface $matcher)
360
    {
361 3
        foreach ($encoders as $mediaType => $encoderType) {
362 3
            $matcher->registerEncoder(
363 3
                $this->parseMediaTypeString($mediaType),
364 3
                $this->registry->getEncoder($encoderType)
365 3
            );
366 3
        }
367 3
    }
368
}
369