Router::delete()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 3
rs 10
1
<?php
2
3
namespace MiladRahimi\PhpRouter;
4
5
use Closure;
6
use MiladRahimi\PhpContainer\Container;
7
use MiladRahimi\PhpContainer\Exceptions\ContainerException;
8
use MiladRahimi\PhpRouter\Dispatching\Caller;
9
use MiladRahimi\PhpRouter\Dispatching\Matcher;
10
use MiladRahimi\PhpRouter\Exceptions\InvalidCallableException;
11
use MiladRahimi\PhpRouter\Exceptions\RouteNotFoundException;
12
use MiladRahimi\PhpRouter\Routing\Route;
13
use MiladRahimi\PhpRouter\Routing\Storekeeper;
14
use MiladRahimi\PhpRouter\Routing\Repository;
15
use MiladRahimi\PhpRouter\Publisher\HttpPublisher;
16
use MiladRahimi\PhpRouter\View\PhpView;
17
use MiladRahimi\PhpRouter\Publisher\Publisher;
18
use MiladRahimi\PhpRouter\View\View;
19
use Psr\Container\ContainerInterface;
20
use Laminas\Diactoros\ServerRequestFactory;
21
22
/**
23
 * It defines the application routes and dispatches them (runs the application).
24
 */
25
class Router
26
{
27
    private Container $container;
28
29
    private Storekeeper $storekeeper;
30
31
    private Matcher $matcher;
32
33
    private Caller $caller;
34
35
    private Publisher $publisher;
36
37
    /**
38
     * List of defined parameter patterns with `pattern()` method
39
     *
40
     * @var string[]
41
     */
42
    private array $patterns = [];
43
44
    public function __construct(
45
        Container   $container,
46
        Storekeeper $storekeeper,
47
        Matcher     $matcher,
48
        Caller      $caller,
49
        Publisher   $publisher
50
    )
51
    {
52
        $this->container = $container;
53
        $this->storekeeper = $storekeeper;
54
        $this->matcher = $matcher;
55
        $this->caller = $caller;
56
        $this->publisher = $publisher;
57
    }
58
59
    /**
60
     * Create a new Router instance
61
     *
62
     * @return static
63
     */
64
    public static function create(): self
65
    {
66
        $container = new Container();
67
        $container->singleton(Container::class, $container);
68
        $container->singleton(ContainerInterface::class, $container);
69
        $container->singleton(Repository::class, new Repository());
70
        $container->singleton(Publisher::class, HttpPublisher::class);
71
72
        return $container->instantiate(Router::class);
73
    }
74
75
    /**
76
     * Setup (enable) View
77
     * @param string $directory
78
     * @link View
79
     *
80
     */
81
    public function setupView(string $directory): void
82
    {
83
        $this->container->singleton(View::class, function () use ($directory) {
84
            return new PhpView($directory);
85
        });
86
    }
87
88
    /**
89
     * Group routes with the given common attributes
90
     *
91
     * @param array $attributes
92
     * @param Closure $body
93
     */
94
    public function group(array $attributes, Closure $body): void
95
    {
96
        $oldState = clone $this->storekeeper->getState();
97
98
        $this->storekeeper->getState()->append($attributes);
99
100
        call_user_func($body, $this);
101
102
        $this->storekeeper->setState($oldState);
103
    }
104
105
    /**
106
     * Dispatch routes (and run the application)
107
     *
108
     * @throws ContainerException
109
     * @throws InvalidCallableException
110
     * @throws RouteNotFoundException
111
     */
112
    public function dispatch()
113
    {
114
        $request = ServerRequestFactory::fromGlobals();
115
116
        $route = $this->matcher->find($request, $this->patterns);
117
        $this->container->singleton(Route::class, $route);
118
119
        foreach ($route->getParameters() as $key => $value) {
120
            $this->container->singleton('$' . $key, $value);
121
        }
122
123
        $stack = array_merge($route->getMiddleware(), [$route->getController()]);
124
        $this->publisher->publish($this->caller->stack($stack, $request));
125
    }
126
127
    /**
128
     * Define a parameter pattern
129
     *
130
     * @param string $name
131
     * @param string $pattern
132
     */
133
    public function pattern(string $name, string $pattern)
134
    {
135
        $this->patterns[$name] = $pattern;
136
    }
137
138
    /**
139
     * Index all the defined routes
140
     *
141
     * @return Route[]
142
     */
143
    public function all(): array
144
    {
145
        return $this->storekeeper->getRepository()->all();
146
    }
147
148
    /**
149
     * Define a new route
150
     *
151
     * @param string $method
152
     * @param string $path
153
     * @param Closure|string|array $controller
154
     * @param string|null $name
155
     */
156
    public function define(string $method, string $path, $controller, ?string $name = null): void
157
    {
158
        $this->storekeeper->add($method, $path, $controller, $name);
159
    }
160
161
    /**
162
     * Map a controller to given route for all the http methods
163
     *
164
     * @param string $path
165
     * @param Closure|string|array $controller
166
     * @param string|null $name
167
     */
168
    public function any(string $path, $controller, ?string $name = null): void
169
    {
170
        $this->define('*', $path, $controller, $name);
171
    }
172
173
    /**
174
     * Map a controller to given GET route
175
     *
176
     * @param string $path
177
     * @param Closure|string|array $controller
178
     * @param string|null $name
179
     */
180
    public function get(string $path, $controller, ?string $name = null): void
181
    {
182
        $this->define('GET', $path, $controller, $name);
183
    }
184
185
    /**
186
     * Map a controller to given POST route
187
     *
188
     * @param string $path
189
     * @param Closure|string|array $controller
190
     * @param string|null $name
191
     */
192
    public function post(string $path, $controller, ?string $name = null): void
193
    {
194
        $this->define('POST', $path, $controller, $name);
195
    }
196
197
    /**
198
     * Map a controller to given PUT route
199
     *
200
     * @param string $path
201
     * @param Closure|string|array $controller
202
     * @param string|null $name
203
     */
204
    public function put(string $path, $controller, ?string $name = null): void
205
    {
206
        $this->define('PUT', $path, $controller, $name);
207
    }
208
209
    /**
210
     * Map a controller to given PATCH route
211
     *
212
     * @param string $path
213
     * @param Closure|string|array $controller
214
     * @param string|null $name
215
     */
216
    public function patch(string $path, $controller, ?string $name = null): void
217
    {
218
        $this->define('PATCH', $path, $controller, $name);
219
    }
220
221
    /**
222
     * Map a controller to given DELETE route
223
     *
224
     * @param string $path
225
     * @param Closure|string|array $controller
226
     * @param string|null $name
227
     */
228
    public function delete(string $path, $controller, ?string $name = null): void
229
    {
230
        $this->define('DELETE', $path, $controller, $name);
231
    }
232
233
    /**
234
     * @return Container
235
     */
236
    public function getContainer(): Container
237
    {
238
        return $this->container;
239
    }
240
241
    /**
242
     * @param Container $container
243
     */
244
    public function setContainer(Container $container): void
245
    {
246
        $this->container = $container;
247
    }
248
249
    /**
250
     * @return Publisher
251
     */
252
    public function getPublisher(): Publisher
253
    {
254
        return $this->publisher;
255
    }
256
257
    /**
258
     * @param Publisher $publisher
259
     */
260
    public function setPublisher(Publisher $publisher): void
261
    {
262
        $this->publisher = $publisher;
263
    }
264
}
265