xref: /webtrees/app/Http/Middleware/Router.php (revision 9e5d8e6ff95fdd940cd83d30bd75ef06223d0db7)
1*9e5d8e6fSGreg Roach<?php
2*9e5d8e6fSGreg Roach
3*9e5d8e6fSGreg Roach/**
4*9e5d8e6fSGreg Roach * webtrees: online genealogy
5*9e5d8e6fSGreg Roach * Copyright (C) 2019 webtrees development team
6*9e5d8e6fSGreg Roach * This program is free software: you can redistribute it and/or modify
7*9e5d8e6fSGreg Roach * it under the terms of the GNU General Public License as published by
8*9e5d8e6fSGreg Roach * the Free Software Foundation, either version 3 of the License, or
9*9e5d8e6fSGreg Roach * (at your option) any later version.
10*9e5d8e6fSGreg Roach * This program is distributed in the hope that it will be useful,
11*9e5d8e6fSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*9e5d8e6fSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*9e5d8e6fSGreg Roach * GNU General Public License for more details.
14*9e5d8e6fSGreg Roach * You should have received a copy of the GNU General Public License
15*9e5d8e6fSGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
16*9e5d8e6fSGreg Roach */
17*9e5d8e6fSGreg Roachdeclare(strict_types=1);
18*9e5d8e6fSGreg Roach
19*9e5d8e6fSGreg Roachnamespace Fisharebest\Webtrees\Http\Middleware;
20*9e5d8e6fSGreg Roach
21*9e5d8e6fSGreg Roachuse Fig\Http\Message\RequestMethodInterface;
22*9e5d8e6fSGreg Roachuse Illuminate\Support\Str;
23*9e5d8e6fSGreg Roachuse Psr\Http\Message\ResponseInterface;
24*9e5d8e6fSGreg Roachuse Psr\Http\Message\ServerRequestInterface;
25*9e5d8e6fSGreg Roachuse Psr\Http\Server\MiddlewareInterface;
26*9e5d8e6fSGreg Roachuse Psr\Http\Server\RequestHandlerInterface;
27*9e5d8e6fSGreg Roach
28*9e5d8e6fSGreg Roachuse function app;
29*9e5d8e6fSGreg Roachuse function explode;
30*9e5d8e6fSGreg Roach
31*9e5d8e6fSGreg Roach/**
32*9e5d8e6fSGreg Roach * Simple class to help migrate to a third-party routing library.
33*9e5d8e6fSGreg Roach */
34*9e5d8e6fSGreg Roachclass Router implements MiddlewareInterface, RequestMethodInterface
35*9e5d8e6fSGreg Roach{
36*9e5d8e6fSGreg Roach    private const CONTROLLER_NAMESPACE = '\\Fisharebest\\Webtrees\\Http\\Controllers\\';
37*9e5d8e6fSGreg Roach
38*9e5d8e6fSGreg Roach    // To parse Controller::action
39*9e5d8e6fSGreg Roach    private const SCOPE_OPERATOR = '::';
40*9e5d8e6fSGreg Roach
41*9e5d8e6fSGreg Roach    /** @var string[][] */
42*9e5d8e6fSGreg Roach    private $routes = [
43*9e5d8e6fSGreg Roach        self::METHOD_GET  => [],
44*9e5d8e6fSGreg Roach        self::METHOD_POST => [],
45*9e5d8e6fSGreg Roach    ];
46*9e5d8e6fSGreg Roach
47*9e5d8e6fSGreg Roach    /**
48*9e5d8e6fSGreg Roach     * @param string $path
49*9e5d8e6fSGreg Roach     * @param string $handler
50*9e5d8e6fSGreg Roach     *
51*9e5d8e6fSGreg Roach     * @return Router
52*9e5d8e6fSGreg Roach     */
53*9e5d8e6fSGreg Roach    public function get(string $path, string $handler): Router
54*9e5d8e6fSGreg Roach    {
55*9e5d8e6fSGreg Roach        return $this->add(self::METHOD_GET, $path, $handler);
56*9e5d8e6fSGreg Roach    }
57*9e5d8e6fSGreg Roach
58*9e5d8e6fSGreg Roach    /**
59*9e5d8e6fSGreg Roach     * @param string $method
60*9e5d8e6fSGreg Roach     * @param string $path
61*9e5d8e6fSGreg Roach     * @param string $handler
62*9e5d8e6fSGreg Roach     *
63*9e5d8e6fSGreg Roach     * @return Router
64*9e5d8e6fSGreg Roach     */
65*9e5d8e6fSGreg Roach    private function add(string $method, string $path, string $handler): Router
66*9e5d8e6fSGreg Roach    {
67*9e5d8e6fSGreg Roach        $this->routes[$method][$path] = $handler;
68*9e5d8e6fSGreg Roach
69*9e5d8e6fSGreg Roach        return $this;
70*9e5d8e6fSGreg Roach    }
71*9e5d8e6fSGreg Roach
72*9e5d8e6fSGreg Roach    /**
73*9e5d8e6fSGreg Roach     * @param string $path
74*9e5d8e6fSGreg Roach     * @param string $handler
75*9e5d8e6fSGreg Roach     *
76*9e5d8e6fSGreg Roach     * @return Router
77*9e5d8e6fSGreg Roach     */
78*9e5d8e6fSGreg Roach    public function post(string $path, string $handler): Router
79*9e5d8e6fSGreg Roach    {
80*9e5d8e6fSGreg Roach        return $this->add(self::METHOD_POST, $path, $handler);
81*9e5d8e6fSGreg Roach    }
82*9e5d8e6fSGreg Roach
83*9e5d8e6fSGreg Roach    /**
84*9e5d8e6fSGreg Roach     * @param ServerRequestInterface  $request
85*9e5d8e6fSGreg Roach     * @param RequestHandlerInterface $handler
86*9e5d8e6fSGreg Roach     *
87*9e5d8e6fSGreg Roach     * @return ResponseInterface
88*9e5d8e6fSGreg Roach     */
89*9e5d8e6fSGreg Roach    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
90*9e5d8e6fSGreg Roach    {
91*9e5d8e6fSGreg Roach        app()->instance(self::class, $this);
92*9e5d8e6fSGreg Roach        require 'routes/web.php';
93*9e5d8e6fSGreg Roach
94*9e5d8e6fSGreg Roach        $method  = $request->getMethod();
95*9e5d8e6fSGreg Roach        $route   = $request->getQueryParams()['route'] ?? '';
96*9e5d8e6fSGreg Roach        $routing = $this->routes[$method][$route] ?? '';
97*9e5d8e6fSGreg Roach
98*9e5d8e6fSGreg Roach        // Bind the request into the container
99*9e5d8e6fSGreg Roach        app()->instance(ServerRequestInterface::class, $request);
100*9e5d8e6fSGreg Roach
101*9e5d8e6fSGreg Roach        // No route matched?
102*9e5d8e6fSGreg Roach        if ($routing === '') {
103*9e5d8e6fSGreg Roach            return $handler->handle($request);
104*9e5d8e6fSGreg Roach        }
105*9e5d8e6fSGreg Roach
106*9e5d8e6fSGreg Roach        // Routes defined using controller::action
107*9e5d8e6fSGreg Roach        if (Str::contains($routing, self::SCOPE_OPERATOR)) {
108*9e5d8e6fSGreg Roach            [$class, $method] = explode(self::SCOPE_OPERATOR, $routing);
109*9e5d8e6fSGreg Roach
110*9e5d8e6fSGreg Roach            return app(self::CONTROLLER_NAMESPACE . $class)->$method($request);
111*9e5d8e6fSGreg Roach        }
112*9e5d8e6fSGreg Roach
113*9e5d8e6fSGreg Roach        // Routes defined using a request handler
114*9e5d8e6fSGreg Roach        return app($routing)->handle($request);
115*9e5d8e6fSGreg Roach    }
116*9e5d8e6fSGreg Roach}
117