ResponseValidator   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 57
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
eloc 25
c 1
b 0
f 0
dl 0
loc 57
ccs 29
cts 29
cp 1
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A findOperation() 0 22 4
A __construct() 0 4 1
A validate() 0 21 5
1
<?php
2
3
namespace CHStudio\Raven\Bridge\LeagueOpenAPIValidation;
4
5
use CHStudio\Raven\Bridge\LeagueOpenAPIValidation\Exception\ValidationExceptionMapper;
6
use CHStudio\Raven\Validator\Exception\OperationNotFoundException;
7
use CHStudio\Raven\Validator\Exception\ResponseNotExpectedException;
8
use CHStudio\Raven\Validator\ResponseValidatorInterface;
9
use League\OpenAPIValidation\PSR7\Exception\NoResponseCode;
10
use League\OpenAPIValidation\PSR7\OperationAddress;
11
use League\OpenAPIValidation\PSR7\PathFinder;
12
use League\OpenAPIValidation\PSR7\ResponseValidator as LeagueResponseValidator;
13
use Psr\Http\Message\RequestInterface;
14
use Psr\Http\Message\ResponseInterface;
15
16
class ResponseValidator implements ResponseValidatorInterface
17
{
18 11
    public function __construct(
19
        private readonly LeagueResponseValidator $adapted,
20
        private readonly ValidationExceptionMapper $mapper
21
    ) {
22 11
    }
23
24 7
    public function validate(ResponseInterface $input, RequestInterface $request): void
25
    {
26
        try {
27 7
            $this->adapted->validate(
28 7
                $this->findOperation($request),
29 7
                $input
30 7
            );
31 5
        } catch (NoResponseCode $e) {
32 1
            throw new ResponseNotExpectedException($request, $input, $e);
33 4
        } catch (\Throwable $e) {
34
            // Capture league/openapi-psr7-validator SpecFinder errors
35
            // it reads properties that might not exists.
36 4
            if (str_contains($e->getFile(), 'SpecFinder.php')) {
37 1
                throw new ResponseNotExpectedException($request, $input, $e);
38
            }
39
40 3
            $error = $this->mapper->map($e);
41 3
            if ($error !== null) {
42 1
                throw $error;
43
            }
44 2
            throw $e;
45
        }
46
    }
47
48
    /**
49
     * Find the best OperationAdress to use to validate the current response
50
     */
51 7
    private function findOperation(RequestInterface $request): OperationAddress
52
    {
53 7
        $pathFinder = new PathFinder(
54 7
            $this->adapted->getSchema(),
55 7
            $request->getUri(),
56 7
            $request->getMethod()
57 7
        );
58
59 7
        $operations = $pathFinder->search();
60 7
        if (\count($operations) === 0) {
61 1
            throw new OperationNotFoundException($request);
62
        }
63
64 6
        foreach ($operations as $operation) {
65
            //If we got an exact path match, we use the current Operation
66 6
            if ($operation->path() === $request->getUri()->getPath()) {
67 1
                return $operation;
68
            }
69
        }
70
71
        //If we haven't an exact match, use the first in the list
72 5
        return $operations[0];
73
    }
74
}
75