Completed
Push — master ( 78c728...dff1ec )
by John
02:02
created

GenericServer   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 101
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 9
dl 0
loc 101
ccs 29
cts 29
cp 1
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A handleRequest() 0 20 3
A validateKey() 0 6 2
B validateAcceptableMIMETypes() 0 14 5
1
<?php
2
namespace LunixREST\Server;
3
4
use LunixREST\AccessControl\AccessControl;
5
use LunixREST\Endpoint\Exceptions\ElementConflictException;
6
use LunixREST\Endpoint\Exceptions\ElementNotFoundException;
7
use LunixREST\Endpoint\Exceptions\InvalidRequestException;
8
use LunixREST\Endpoint\Exceptions\UnknownEndpointException;
9
use LunixREST\APIRequest\APIRequest;
10
use LunixREST\APIResponse\Exceptions\NotAcceptableResponseTypeException;
11
use LunixREST\APIResponse\APIResponse;
12
use LunixREST\APIResponse\ResponseFactory;
13
use LunixREST\Server\Exceptions\AccessDeniedException;
14
use LunixREST\Server\Exceptions\InvalidAPIKeyException;
15
use LunixREST\Server\Exceptions\MethodNotFoundException;
16
use LunixREST\Server\Exceptions\ThrottleLimitExceededException;
17
use LunixREST\Throttle\Throttle;
18
19
/**
20
 * A Server implementation that derives it's behaviour from an AccessControl, a Throttle, a ResponseFactory, and a Router.
21
 * Class GenericServer
22
 * @package LunixREST\Server
23
 */
24
class GenericServer implements Server
25
{
26
    /**
27
     * @var AccessControl
28
     */
29
    protected $accessControl;
30
    /**
31
     * @var Throttle
32
     */
33
    protected $throttle;
34
    /**
35
     * @var ResponseFactory
36
     */
37
    protected $responseFactory;
38
    /**
39
     * @var Router
40
     */
41
    private $router;
42
43
    /**
44
     * @param AccessControl $accessControl
45
     * @param Throttle $throttle
46
     * @param ResponseFactory $responseFactory
47
     * @param Router $router
48
     */
49 8
    public function __construct(
50
        AccessControl $accessControl,
51
        Throttle $throttle,
52
        ResponseFactory $responseFactory,
53
        Router $router
54
    ) {
55 8
        $this->accessControl = $accessControl;
56 8
        $this->throttle = $throttle;
57 8
        $this->responseFactory = $responseFactory;
58 8
        $this->router = $router;
59 8
    }
60
61
    /**
62
     * @param APIRequest $request
63
     * @return APIResponse
64
     * @throws InvalidAPIKeyException
65
     * @throws AccessDeniedException
66
     * @throws ThrottleLimitExceededException
67
     * @throws UnknownEndpointException
68
     * @throws ElementNotFoundException
69
     * @throws InvalidRequestException
70
     * @throws ElementConflictException
71
     * @throws MethodNotFoundException
72
     * @throws NotAcceptableResponseTypeException
73
     */
74 8
    public function handleRequest(APIRequest $request): APIResponse
75
    {
76 8
        $this->validateKey($request);
77
78 7
        if ($this->throttle->shouldThrottle($request)) {
79 1
            throw new ThrottleLimitExceededException('Request limit exceeded');
80
        }
81
82 6
        $this->validateAcceptableMIMETypes($request);
83
84 4
        if (!$this->accessControl->validateAccess($request)) {
85 3
            throw new AccessDeniedException("API key does not have the required permissions to access requested resource");
86
        }
87
88 1
        $this->throttle->logRequest($request);
89
90 1
        $responseData = $this->router->route($request);
91
92 1
        return $this->responseFactory->getResponse($responseData, $request->getAcceptableMIMETypes());
93
    }
94
95
    /**
96
     * @param APIRequest $request
97
     * @throws InvalidAPIKeyException
98
     */
99 8
    protected function validateKey(APIRequest $request)
100
    {
101 8
        if (!$this->accessControl->validateKey($request->getApiKey())) {
102 1
            throw new InvalidAPIKeyException('Invalid API key');
103
        }
104 7
    }
105
106
    /**
107
     * @param APIRequest $request
108
     * @throws NotAcceptableResponseTypeException
109
     */
110 6
    protected function validateAcceptableMIMETypes(APIRequest $request)
111
    {
112 6
        $supportedFormats = $this->responseFactory->getSupportedMIMETypes();
113 6
        $requestedFormats = $request->getAcceptableMIMETypes();
114
115
        //Cases that our response factory is capable of responding to
116 6
        $requestedFormatSupported = empty($requestedFormats) ||
117 5
            in_array('*/*', $requestedFormats) ||
118 6
            !empty(array_intersect($requestedFormats, $supportedFormats));
119
120 6
        if (empty($supportedFormats) || !$requestedFormatSupported) {
121 2
            throw new NotAcceptableResponseTypeException('None of the requested acceptable response types are supported');
122
        }
123 4
    }
124
}
125