xref: /webtrees/app/Http/Middleware/Router.php (revision f1d4b4a2fcc65f3b3bd1d9fb6ff4b678a9e0aea4)
19e5d8e6fSGreg Roach<?php
29e5d8e6fSGreg Roach
39e5d8e6fSGreg Roach/**
49e5d8e6fSGreg Roach * webtrees: online genealogy
59e5d8e6fSGreg Roach * Copyright (C) 2019 webtrees development team
69e5d8e6fSGreg Roach * This program is free software: you can redistribute it and/or modify
79e5d8e6fSGreg Roach * it under the terms of the GNU General Public License as published by
89e5d8e6fSGreg Roach * the Free Software Foundation, either version 3 of the License, or
99e5d8e6fSGreg Roach * (at your option) any later version.
109e5d8e6fSGreg Roach * This program is distributed in the hope that it will be useful,
119e5d8e6fSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
129e5d8e6fSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
139e5d8e6fSGreg Roach * GNU General Public License for more details.
149e5d8e6fSGreg Roach * You should have received a copy of the GNU General Public License
159e5d8e6fSGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
169e5d8e6fSGreg Roach */
179e5d8e6fSGreg Roachdeclare(strict_types=1);
189e5d8e6fSGreg Roach
199e5d8e6fSGreg Roachnamespace Fisharebest\Webtrees\Http\Middleware;
209e5d8e6fSGreg Roach
219e5d8e6fSGreg Roachuse Fig\Http\Message\RequestMethodInterface;
2282e92bfaSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService;
23a992e8c1SGreg Roachuse Fisharebest\Webtrees\View;
24c48210a4SGreg Roachuse Fisharebest\Webtrees\Webtrees;
2582e92bfaSGreg Roachuse Middleland\Dispatcher;
269e5d8e6fSGreg Roachuse Psr\Http\Message\ResponseInterface;
279e5d8e6fSGreg Roachuse Psr\Http\Message\ServerRequestInterface;
289e5d8e6fSGreg Roachuse Psr\Http\Server\MiddlewareInterface;
299e5d8e6fSGreg Roachuse Psr\Http\Server\RequestHandlerInterface;
309e5d8e6fSGreg Roach
319e5d8e6fSGreg Roachuse function app;
3282e92bfaSGreg Roachuse function array_map;
339e5d8e6fSGreg Roach
349e5d8e6fSGreg Roach/**
359e5d8e6fSGreg Roach * Simple class to help migrate to a third-party routing library.
369e5d8e6fSGreg Roach */
379e5d8e6fSGreg Roachclass Router implements MiddlewareInterface, RequestMethodInterface
389e5d8e6fSGreg Roach{
399e5d8e6fSGreg Roach    /** @var string[][] */
409e5d8e6fSGreg Roach    private $routes = [
419e5d8e6fSGreg Roach        self::METHOD_GET  => [],
429e5d8e6fSGreg Roach        self::METHOD_POST => [],
439e5d8e6fSGreg Roach    ];
449e5d8e6fSGreg Roach
4582e92bfaSGreg Roach    /** @var ModuleService */
4682e92bfaSGreg Roach    private $module_service;
4782e92bfaSGreg Roach
4882e92bfaSGreg Roach    /**
4982e92bfaSGreg Roach     * Router constructor.
5082e92bfaSGreg Roach     *
5182e92bfaSGreg Roach     * @param ModuleService $module_service
5282e92bfaSGreg Roach     */
5382e92bfaSGreg Roach    public function __construct(ModuleService $module_service)
5482e92bfaSGreg Roach    {
5582e92bfaSGreg Roach        $this->module_service = $module_service;
5682e92bfaSGreg Roach    }
5782e92bfaSGreg Roach
589e5d8e6fSGreg Roach    /**
59d403609dSGreg Roach     * @param string $route
60d403609dSGreg Roach     * @param string $url
619e5d8e6fSGreg Roach     * @param string $handler
629e5d8e6fSGreg Roach     *
639e5d8e6fSGreg Roach     * @return Router
649e5d8e6fSGreg Roach     */
65d403609dSGreg Roach    public function get(string $route, string $url, string $handler): Router
669e5d8e6fSGreg Roach    {
67d403609dSGreg Roach        return $this->add(self::METHOD_GET, $route, $handler);
689e5d8e6fSGreg Roach    }
699e5d8e6fSGreg Roach
709e5d8e6fSGreg Roach    /**
719e5d8e6fSGreg Roach     * @param string $method
72d403609dSGreg Roach     * @param string $route
739e5d8e6fSGreg Roach     * @param string $handler
749e5d8e6fSGreg Roach     *
759e5d8e6fSGreg Roach     * @return Router
769e5d8e6fSGreg Roach     */
77d403609dSGreg Roach    private function add(string $method, string $route, string $handler): Router
789e5d8e6fSGreg Roach    {
79d403609dSGreg Roach        $this->routes[$method][$route] = $handler;
809e5d8e6fSGreg Roach
819e5d8e6fSGreg Roach        return $this;
829e5d8e6fSGreg Roach    }
839e5d8e6fSGreg Roach
849e5d8e6fSGreg Roach    /**
85d403609dSGreg Roach     * @param string $route
86d403609dSGreg Roach     * @param string $url
879e5d8e6fSGreg Roach     * @param string $handler
889e5d8e6fSGreg Roach     *
899e5d8e6fSGreg Roach     * @return Router
909e5d8e6fSGreg Roach     */
91d403609dSGreg Roach    public function post(string $route, string $url, string $handler): Router
929e5d8e6fSGreg Roach    {
93d403609dSGreg Roach        return $this->add(self::METHOD_POST, $route, $handler);
949e5d8e6fSGreg Roach    }
959e5d8e6fSGreg Roach
969e5d8e6fSGreg Roach    /**
979e5d8e6fSGreg Roach     * @param ServerRequestInterface  $request
989e5d8e6fSGreg Roach     * @param RequestHandlerInterface $handler
999e5d8e6fSGreg Roach     *
1009e5d8e6fSGreg Roach     * @return ResponseInterface
1019e5d8e6fSGreg Roach     */
1029e5d8e6fSGreg Roach    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
1039e5d8e6fSGreg Roach    {
10482e92bfaSGreg Roach        // Save the router in the container, as we'll need it to generate URLs.
1059e5d8e6fSGreg Roach        app()->instance(self::class, $this);
10682e92bfaSGreg Roach
10782e92bfaSGreg Roach        // Load the routing table.
108c48210a4SGreg Roach        require Webtrees::ROOT_DIR . 'routes/web.php';
1099e5d8e6fSGreg Roach
11082e92bfaSGreg Roach        // Match the request to a route.
1119e5d8e6fSGreg Roach        $method  = $request->getMethod();
1129e5d8e6fSGreg Roach        $route   = $request->getQueryParams()['route'] ?? '';
1139e5d8e6fSGreg Roach        $routing = $this->routes[$method][$route] ?? '';
1149e5d8e6fSGreg Roach
115a992e8c1SGreg Roach        // Bind the request into the container and the layout
1169e5d8e6fSGreg Roach        app()->instance(ServerRequestInterface::class, $request);
117a992e8c1SGreg Roach        View::share('request', $request);
1189e5d8e6fSGreg Roach
1199e5d8e6fSGreg Roach        // No route matched?
1209e5d8e6fSGreg Roach        if ($routing === '') {
1219e5d8e6fSGreg Roach            return $handler->handle($request);
1229e5d8e6fSGreg Roach        }
1239e5d8e6fSGreg Roach
12482e92bfaSGreg Roach        // Firstly, apply the route middleware
12582e92bfaSGreg Roach        $route_middleware = [];
12682e92bfaSGreg Roach        $route_middleware = array_map('app', $route_middleware);
1279e5d8e6fSGreg Roach
12882e92bfaSGreg Roach        // Secondly, apply any module middleware
12982e92bfaSGreg Roach        $module_middleware = $this->module_service->findByInterface(MiddlewareInterface::class)->all();
1309e5d8e6fSGreg Roach
131*f1d4b4a2SGreg Roach        // Add the route as attribute of the request
132*f1d4b4a2SGreg Roach        $request = $request->withAttribute('route', $routing);
133*f1d4b4a2SGreg Roach
13482e92bfaSGreg Roach        // Finally, run the handler using middleware
13582e92bfaSGreg Roach        $handler_middleware = [new WrapHandler($routing)];
13682e92bfaSGreg Roach
13782e92bfaSGreg Roach        $middleware = array_merge($route_middleware, $module_middleware, $handler_middleware);
13882e92bfaSGreg Roach
13982e92bfaSGreg Roach        $dispatcher = new Dispatcher($middleware, app());
14082e92bfaSGreg Roach
14182e92bfaSGreg Roach        return $dispatcher->dispatch($request);
1429e5d8e6fSGreg Roach    }
1439e5d8e6fSGreg Roach}
144