Completed
Push — snyk-fix-a7ffc9795c22fef729062... ( 82e92b )
by Greg
08:14
created

Router::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2019 webtrees development team
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17
declare(strict_types=1);
18
19
namespace Fisharebest\Webtrees\Http\Middleware;
20
21
use Fig\Http\Message\RequestMethodInterface;
22
use Fisharebest\Webtrees\Services\ModuleService;
23
use Fisharebest\Webtrees\Webtrees;
24
use Middleland\Dispatcher;
25
use Psr\Http\Message\ResponseInterface;
26
use Psr\Http\Message\ServerRequestInterface;
27
use Psr\Http\Server\MiddlewareInterface;
28
use Psr\Http\Server\RequestHandlerInterface;
29
30
use function app;
31
use function array_map;
32
33
/**
34
 * Simple class to help migrate to a third-party routing library.
35
 */
36
class Router implements MiddlewareInterface, RequestMethodInterface
37
{
38
    /** @var string[][] */
39
    private $routes = [
40
        self::METHOD_GET  => [],
41
        self::METHOD_POST => [],
42
    ];
43
44
    /** @var ModuleService */
45
    private $module_service;
46
47
    /**
48
     * Router constructor.
49
     *
50
     * @param ModuleService $module_service
51
     */
52
    public function __construct(ModuleService $module_service)
53
    {
54
        $this->module_service = $module_service;
55
    }
56
57
58
    /**
59
     * @param string $path
60
     * @param string $handler
61
     *
62
     * @return Router
63
     */
64
    public function get(string $path, string $handler): Router
65
    {
66
        return $this->add(self::METHOD_GET, $path, $handler);
67
    }
68
69
    /**
70
     * @param string $method
71
     * @param string $path
72
     * @param string $handler
73
     *
74
     * @return Router
75
     */
76
    private function add(string $method, string $path, string $handler): Router
77
    {
78
        $this->routes[$method][$path] = $handler;
79
80
        return $this;
81
    }
82
83
    /**
84
     * @param string $path
85
     * @param string $handler
86
     *
87
     * @return Router
88
     */
89
    public function post(string $path, string $handler): Router
90
    {
91
        return $this->add(self::METHOD_POST, $path, $handler);
92
    }
93
94
    /**
95
     * @param ServerRequestInterface  $request
96
     * @param RequestHandlerInterface $handler
97
     *
98
     * @return ResponseInterface
99
     */
100
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
101
    {
102
        // Save the router in the container, as we'll need it to generate URLs.
103
        app()->instance(self::class, $this);
104
105
        // Load the routing table.
106
        require Webtrees::ROOT_DIR . 'routes/web.php';
107
108
        // Match the request to a route.
109
        $method  = $request->getMethod();
110
        $route   = $request->getQueryParams()['route'] ?? '';
111
        $routing = $this->routes[$method][$route] ?? '';
112
113
        // Bind the request into the container
114
        app()->instance(ServerRequestInterface::class, $request);
115
116
        // No route matched?
117
        if ($routing === '') {
118
            return $handler->handle($request);
119
        }
120
121
        // Firstly, apply the route middleware
122
        $route_middleware = [];
123
        $route_middleware = array_map('app', $route_middleware);
124
125
        // Secondly, apply any module middleware
126
        $module_middleware = $this->module_service->findByInterface(MiddlewareInterface::class)->all();
127
128
        // Finally, run the handler using middleware
129
        $handler_middleware = [new WrapHandler($routing)];
130
131
        $middleware = array_merge($route_middleware, $module_middleware, $handler_middleware);
132
133
        $dispatcher = new Dispatcher($middleware, app());
134
135
        return $dispatcher->dispatch($request);
136
    }
137
}
138