Passed
Push — master ( f1d4b4...ee4364 )
by Greg
05:58
created

Router   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 80
rs 10
c 0
b 0
f 0
wmc 6

2 Methods

Rating   Name   Duplication   Size   Complexity  
A process() 0 51 5
A __construct() 0 7 1
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 Aura\Router\RouterContainer;
22
use Fig\Http\Message\RequestMethodInterface;
23
use Fisharebest\Webtrees\Services\ModuleService;
24
use Fisharebest\Webtrees\Tree;
25
use Fisharebest\Webtrees\View;
26
use Fisharebest\Webtrees\Webtrees;
27
use Middleland\Dispatcher;
28
use Psr\Http\Message\ResponseInterface;
29
use Psr\Http\Message\ServerRequestInterface;
30
use Psr\Http\Server\MiddlewareInterface;
31
use Psr\Http\Server\RequestHandlerInterface;
32
use function app;
33
use function array_map;
34
use const PHP_URL_PATH;
35
36
/**
37
 * Simple class to help migrate to a third-party routing library.
38
 */
39
class Router implements MiddlewareInterface, RequestMethodInterface
40
{
41
    /** @var ModuleService */
42
    private $module_service;
43
44
    /** @var RouterContainer */
45
    private $router_container;
46
47
    /**
48
     * Router constructor.
49
     *
50
     * @param ModuleService   $module_service
51
     * @param RouterContainer $router_container
52
     */
53
    public function __construct(ModuleService $module_service, RouterContainer $router_container)
54
    {
55
        $this->router_container = $router_container;
56
        $this->module_service   = $module_service;
57
58
        // Save the router in the container, as we'll need it to generate URLs.
59
        app()->instance(RouterContainer::class, $this->router_container);
60
    }
61
62
    /**
63
     * @param ServerRequestInterface  $request
64
     * @param RequestHandlerInterface $handler
65
     *
66
     * @return ResponseInterface
67
     */
68
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
69
    {
70
        // Load the routing table.
71
        require __DIR__ . '/../../../routes/web.php';
72
73
        if ($request->getAttribute('rewrite_urls') !== '1') {
74
            // Turn the URL into a pretty one.
75
            $route   = $request->getQueryParams()['route'] ?? '';
76
            $path    = parse_url($request->getAttribute('base_url') . $route, PHP_URL_PATH) ?? '';
77
            $uri     = $request->getUri()->withPath($path);
78
            $request = $request->withUri($uri);
79
        }
80
81
        // Bind the request into the container and the layout
82
        app()->instance(ServerRequestInterface::class, $request);
83
        View::share('request', $request);
84
85
        // Match the request to a route.
86
        $route = $this->router_container->getMatcher()->match($request);
87
88
        // No route matched?
89
        if ($route === false) {
90
            return $handler->handle($request);
91
        }
92
93
        // Firstly, apply the route middleware
94
        $route_middleware = $route->extras['middleware'] ?? [];
95
        $route_middleware = array_map('app', $route_middleware);
96
97
        // Secondly, apply any module middleware
98
        $module_middleware = $this->module_service->findByInterface(MiddlewareInterface::class)->all();
99
100
        // Add the route as attribute of the request
101
        $request = $request->withAttribute('route', $route->name);
102
103
        // Finally, run the handler using middleware
104
        $handler_middleware = [new WrapHandler($route->handler)];
105
106
        $middleware = array_merge($route_middleware, $module_middleware, $handler_middleware);
107
108
        // Add the matched attributes to the request.
109
        foreach ($route->attributes as $key => $value) {
110
            if ($key === 'tree') {
111
                $value = Tree::findByName($value);
112
            }
113
            $request = $request->withAttribute($key, $value);
114
        }
115
116
        $dispatcher = new Dispatcher($middleware, app());
117
118
        return $dispatcher->dispatch($request);
119
    }
120
}
121