Test Failed
Pull Request — master (#32)
by Anatoly
04:53
created

Route::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 16
c 3
b 0
f 0
dl 0
loc 21
rs 9.7333
cc 1
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
/**
4
 * It's free open-source software released under the MIT License.
5
 *
6
 * @author Anatoly Fenric <[email protected]>
7
 * @copyright Copyright (c) 2018, Anatoly Fenric
8
 * @license https://github.com/sunrise-php/http-router/blob/master/LICENSE
9
 * @link https://github.com/sunrise-php/http-router
10
 */
11
12
namespace Sunrise\Http\Router\Annotation;
13
14
/**
15
 * Import classes
16
 */
17
use Psr\Http\Server\MiddlewareInterface;
18
use Psr\Http\Server\RequestHandlerInterface;
19
use Sunrise\Http\Router\Exception\InvalidAnnotationParameterException;
20
use Sunrise\Http\Router\Exception\InvalidAnnotationSourceException;
21
22
/**
23
 * Import functions
24
 */
25
use function class_exists;
26
use function is_array;
27
use function is_int;
28
use function is_string;
29
use function is_subclass_of;
30
31
/**
32
 * @Annotation
33
 * @Target({"CLASS"})
34
 */
35
final class Route
36
{
37
38
    /**
39
     * @var string
40
     */
41
    public $source;
42
43
    /**
44
     * @var string
45
     */
46
    public $name;
47
48
    /**
49
     * @var string
50
     */
51
    public $path;
52
53
    /**
54
     * @var array
55
     */
56
    public $methods;
57
58
    /**
59
     * @var array
60
     */
61
    public $middlewares;
62
63
    /**
64
     * @var array
65
     */
66
    public $attributes;
67
68
    /**
69
     * @var int
70
     */
71
    public $priority;
72
73
    /**
74
     * @param array $params
75
     */
76
    public function __construct(array $params)
77
    {
78
        $params += [
79
            'middlewares' => [],
80
            'attributes' => [],
81
            'priority' => 0,
82
        ];
83
84
        $this->assertParamsContainValidName($params);
85
        $this->assertParamsContainValidPath($params);
86
        $this->assertParamsContainValidMethods($params);
87
        $this->assertParamsContainValidMiddlewares($params);
88
        $this->assertParamsContainValidAttributes($params);
89
        $this->assertParamsContainValidPriority($params);
90
91
        $this->name = $params['name'];
92
        $this->path = $params['path'];
93
        $this->methods = $params['methods'];
94
        $this->middlewares = $params['middlewares'];
95
        $this->attributes = $params['attributes'];
96
        $this->priority = $params['priority'];
97
    }
98
99
    /**
100
     * @param string $source
101
     * @return void
102
     * @throws InvalidAnnotationSourceException
103
     */
104
    public static function assertValidSource(string $source) : void
105
    {
106
        if (!is_subclass_of($source, RequestHandlerInterface::class)) {
107
            throw new InvalidAnnotationSourceException(
108
                sprintf('@Route annotation source %s is not a request handler.', $source)
109
            );
110
        }
111
    }
112
113
    /**
114
     * @param array $params
115
     * @return void
116
     * @throws InvalidAnnotationParameterException
117
     */
118
    private function assertParamsContainValidName(array $params) : void
119
    {
120
        if (empty($params['name']) || !is_string($params['name'])) {
121
            throw new InvalidAnnotationParameterException('@Route.name must be not an empty string.');
122
        }
123
    }
124
125
    /**
126
     * @param array $params
127
     * @return void
128
     * @throws InvalidAnnotationParameterException
129
     */
130
    private function assertParamsContainValidPath(array $params) : void
131
    {
132
        if (empty($params['path']) || !is_string($params['path'])) {
133
            throw new InvalidAnnotationParameterException('@Route.path must be not an empty string.');
134
        }
135
    }
136
137
    /**
138
     * @param array $params
139
     * @return void
140
     * @throws InvalidAnnotationParameterException
141
     */
142
    private function assertParamsContainValidMethods(array $params) : void
143
    {
144
        if (empty($params['methods']) || !is_array($params['methods'])) {
145
            throw new InvalidAnnotationParameterException('@Route.methods must be not an empty array.');
146
        }
147
148
        foreach ($params['methods'] as $method) {
149
            $this->assertValidMethod($method);
150
        }
151
    }
152
153
    /**
154
     * @param array $params
155
     * @return void
156
     * @throws InvalidAnnotationParameterException
157
     */
158
    private function assertParamsContainValidMiddlewares(array $params) : void
159
    {
160
        if (!is_array($params['middlewares'])) {
161
            throw new InvalidAnnotationParameterException('@Route.middlewares must be an array.');
162
        }
163
164
        foreach ($params['middlewares'] as $middleware) {
165
            $this->assertValidMiddleware($middleware);
166
        }
167
    }
168
169
    /**
170
     * @param array $params
171
     * @return void
172
     * @throws InvalidAnnotationParameterException
173
     */
174
    private function assertParamsContainValidAttributes(array $params) : void
175
    {
176
        if (!is_array($params['attributes'])) {
177
            throw new InvalidAnnotationParameterException('@Route.attributes must be an array.');
178
        }
179
    }
180
181
    /**
182
     * @param array $params
183
     * @return void
184
     * @throws InvalidAnnotationParameterException
185
     */
186
    private function assertParamsContainValidPriority(array $params) : void
187
    {
188
        if (!is_int($params['priority'])) {
189
            throw new InvalidAnnotationParameterException('@Route.priority must be an integer.');
190
        }
191
    }
192
193
    /**
194
     * @param mixed $method
195
     * @return void
196
     * @throws InvalidAnnotationParameterException
197
     */
198
    private function assertValidMethod($method) : void
199
    {
200
        if (!is_string($method)) {
201
            throw new InvalidAnnotationParameterException('@Route.methods must contain only strings.');
202
        }
203
    }
204
205
    /**
206
     * @param mixed $middleware
207
     * @return void
208
     * @throws InvalidAnnotationParameterException
209
     */
210
    private function assertValidMiddleware($middleware) : void
211
    {
212
        if (!is_string($middleware)) {
213
            throw new InvalidAnnotationParameterException('@Route.middlewares must contain only strings.');
214
        }
215
216
        if (!class_exists($middleware)) {
217
            throw new InvalidAnnotationParameterException('@Route.middlewares contains nonexistent class.');
218
        }
219
220
        if (!is_subclass_of($middleware, MiddlewareInterface::class)) {
221
            throw new InvalidAnnotationParameterException('@Route.middlewares contains non middleware class.');
222
        }
223
    }
224
}
225