Completed
Push — master ( ebee1b...83e9b5 )
by Samuel
02:50
created

Api::run()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 21
ccs 7
cts 14
cp 0.5
rs 9.0534
cc 4
eloc 14
nc 3
nop 1
crap 6
1
<?php
2
3
namespace Kelemen\ApiNette;
4
5
use Kelemen\ApiNette\Exception\HandlerException;
6
use Kelemen\ApiNette\Route\RouteResolverInterface;
7
use Kelemen\ApiNette\Route\Route;
8
use Kelemen\ApiNette\Route\RouteContainer;
9
use Kelemen\ApiNette\Validator\Input\CustomInput;
10
use Kelemen\ApiNette\Validator\Validator;
11
use Kelemen\ApiNette\Validator\ValidatorInterface;
12
use Nette\DI\Container;
13
use Nette\DI\MissingServiceException;
14
use Nette\Http\IResponse;
15
use Nette\Http\Request;
16
use Nette\Http\Response;
17
use Kelemen\ApiNette\Response\JsonApiResponse;
18
19
class Api
20
{
21
    /** @var RouteResolverInterface */
22
    private $routeResolver;
23
24
    /** @var RouteContainer */
25
    private $routes;
26
27
    /** @var Request */
28
    private $request;
29
30
    /** @var Response */
31
    private $response;
32
33
    /** @var Container */
34
    private $container;
35
36
    /** @var Validator */
37
    private $validator;
38
39
    /**
40
     * @param RouteResolverInterface $routeResolver
41
     * @param Request $request
42
     * @param Response $response
43
     * @param Container $container
44
     * @param ValidatorInterface $validator
45
     */
46 4
    public function __construct(
47
        RouteResolverInterface $routeResolver,
48
        Request $request,
49
        Response $response,
50
        Container $container,
51
        ValidatorInterface $validator = null
52
    ) {
53 4
        $this->routeResolver = $routeResolver;
54 4
        $this->request = $request;
55 4
        $this->response = $response;
56 4
        $this->container = $container;
57 4
        $this->validator = $validator ?: new Validator();
0 ignored issues
show
Documentation Bug introduced by
$validator ?: new \Kelem...e\Validator\Validator() is of type object<Kelemen\ApiNette\...tor\ValidatorInterface>, but the property $validator was declared to be of type object<Kelemen\ApiNette\Validator\Validator>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
58 4
        $this->routes = new RouteContainer();
59 4
    }
60
61
    /**
62
     * Add api call
63
     * @param string $method
64
     * @param string $pattern
65
     * @param string $handler
66
     * @param array $params
67
     */
68 2
    public function add($method, $pattern, $handler, $params = [])
69
    {
70 2
        $this->routes->add(new Route($method, $pattern, $handler, $params));
71 2
    }
72
73
    /**
74
     * Add get api call
75
     * @param string $pattern
76
     * @param string $handler
77
     * @param array $params
78
     */
79
    public function get($pattern, $handler, $params = [])
80
    {
81
        $this->add('get', $pattern, $handler, $params);
82
    }
83
84
    /**
85
     * Add post api call
86
     * @param string $pattern
87
     * @param string $handler
88
     * @param array $params
89
     */
90 2
    public function post($pattern, $handler, $params = [])
91
    {
92 2
        $this->add('post', $pattern, $handler, $params);
93 2
    }
94
95
    /**
96
     * Add put api call
97
     * @param string $pattern
98
     * @param string $handler
99
     * @param array $params
100
     */
101
    public function put($pattern, $handler, $params = [])
102
    {
103
        $this->add('put', $pattern, $handler, $params);
104
    }
105
106
    /**
107
     * Add patch api call
108
     * @param string $pattern
109
     * @param string $handler
110
     * @param array $params
111
     */
112
    public function patch($pattern, $handler, $params = [])
113
    {
114
        $this->add('patch', $pattern, $handler, $params);
115
    }
116
117
    /**
118
     * Add delete api call
119
     * @param string $pattern
120
     * @param string $handler
121
     * @param array $params
122
     */
123
    public function delete($pattern, $handler, $params = [])
124
    {
125
        $this->add('delete', $pattern, $handler, $params);
126
    }
127
128
    /**
129
     * Add options api call
130
     * @param string $pattern
131
     * @param string $handler
132
     * @param array $params
133
     */
134
    public function options($pattern, $handler, $params = [])
135
    {
136
        $this->add('options', $pattern, $handler, $params);
137
    }
138
139
    /**
140
     * Run api
141
     * @param string $url
142
     * @return JsonApiResponse
143
     * @throws Exception\ValidatorException
144
     * @throws HandlerException
145
     */
146 4
    public function run($url)
147
    {
148 4
        $resolvedRoute = $this->routeResolver->resolve($this->routes, $url);
149 4
        if (!$resolvedRoute) {
150 2
            return new JsonApiResponse(IResponse::S400_BAD_REQUEST, ['error' => 'Unresolved api route']);
151
        }
152
153 2
        $handler = $this->getFromContainer($resolvedRoute->getRoute()->getHandler());
154 2
        if (!$handler) {
155 2
            throw new HandlerException('Handler ' . $resolvedRoute->getRoute()->getHandler() . ' not found in container');
156
        }
157
158
        $this->validator->setInput('path', new CustomInput($resolvedRoute->getParams()));
159
        $this->validator->validate($handler->validate());
160
        $handler->setValidatedValues($this->validator->getValues());
161
162
        $middleware = $resolvedRoute->getRoute()->getConfig('middleware');
163
        $runner = new Runner($middleware ?: [], $handler, $this->container);
164
        $response = $runner($this->request, $this->response);
165
        return $response;
166
    }
167
168
    /**
169
     * Get service by type or name from container
170
     * @param string $entry
171
     * @return bool|object
172
     */
173 2 View Code Duplication
    private function getFromContainer($entry)
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...
174
    {
175
        try {
176 2
            if (substr($entry, 0, 1) === '#') {
177 2
                return $this->container->getService(substr($entry, 1));
178
            }
179
180
            return $this->container->getByType($entry);
181 2
        } catch (MissingServiceException $e) {
182 2
            return false;
183
        }
184
    }
185
}
186