xref: /webtrees/app/Http/Middleware/Router.php (revision 82e92bfae343d705cca07385d9e2dc90a3d85621)
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;
22*82e92bfaSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService;
23c48210a4SGreg Roachuse Fisharebest\Webtrees\Webtrees;
24*82e92bfaSGreg Roachuse Middleland\Dispatcher;
259e5d8e6fSGreg Roachuse Psr\Http\Message\ResponseInterface;
269e5d8e6fSGreg Roachuse Psr\Http\Message\ServerRequestInterface;
279e5d8e6fSGreg Roachuse Psr\Http\Server\MiddlewareInterface;
289e5d8e6fSGreg Roachuse Psr\Http\Server\RequestHandlerInterface;
299e5d8e6fSGreg Roach
309e5d8e6fSGreg Roachuse function app;
31*82e92bfaSGreg Roachuse function array_map;
329e5d8e6fSGreg Roach
339e5d8e6fSGreg Roach/**
349e5d8e6fSGreg Roach * Simple class to help migrate to a third-party routing library.
359e5d8e6fSGreg Roach */
369e5d8e6fSGreg Roachclass Router implements MiddlewareInterface, RequestMethodInterface
379e5d8e6fSGreg Roach{
389e5d8e6fSGreg Roach    /** @var string[][] */
399e5d8e6fSGreg Roach    private $routes = [
409e5d8e6fSGreg Roach        self::METHOD_GET  => [],
419e5d8e6fSGreg Roach        self::METHOD_POST => [],
429e5d8e6fSGreg Roach    ];
439e5d8e6fSGreg Roach
44*82e92bfaSGreg Roach    /** @var ModuleService */
45*82e92bfaSGreg Roach    private $module_service;
46*82e92bfaSGreg Roach
47*82e92bfaSGreg Roach    /**
48*82e92bfaSGreg Roach     * Router constructor.
49*82e92bfaSGreg Roach     *
50*82e92bfaSGreg Roach     * @param ModuleService $module_service
51*82e92bfaSGreg Roach     */
52*82e92bfaSGreg Roach    public function __construct(ModuleService $module_service)
53*82e92bfaSGreg Roach    {
54*82e92bfaSGreg Roach        $this->module_service = $module_service;
55*82e92bfaSGreg Roach    }
56*82e92bfaSGreg Roach
57*82e92bfaSGreg Roach
589e5d8e6fSGreg Roach    /**
599e5d8e6fSGreg Roach     * @param string $path
609e5d8e6fSGreg Roach     * @param string $handler
619e5d8e6fSGreg Roach     *
629e5d8e6fSGreg Roach     * @return Router
639e5d8e6fSGreg Roach     */
649e5d8e6fSGreg Roach    public function get(string $path, string $handler): Router
659e5d8e6fSGreg Roach    {
669e5d8e6fSGreg Roach        return $this->add(self::METHOD_GET, $path, $handler);
679e5d8e6fSGreg Roach    }
689e5d8e6fSGreg Roach
699e5d8e6fSGreg Roach    /**
709e5d8e6fSGreg Roach     * @param string $method
719e5d8e6fSGreg Roach     * @param string $path
729e5d8e6fSGreg Roach     * @param string $handler
739e5d8e6fSGreg Roach     *
749e5d8e6fSGreg Roach     * @return Router
759e5d8e6fSGreg Roach     */
769e5d8e6fSGreg Roach    private function add(string $method, string $path, string $handler): Router
779e5d8e6fSGreg Roach    {
789e5d8e6fSGreg Roach        $this->routes[$method][$path] = $handler;
799e5d8e6fSGreg Roach
809e5d8e6fSGreg Roach        return $this;
819e5d8e6fSGreg Roach    }
829e5d8e6fSGreg Roach
839e5d8e6fSGreg Roach    /**
849e5d8e6fSGreg Roach     * @param string $path
859e5d8e6fSGreg Roach     * @param string $handler
869e5d8e6fSGreg Roach     *
879e5d8e6fSGreg Roach     * @return Router
889e5d8e6fSGreg Roach     */
899e5d8e6fSGreg Roach    public function post(string $path, string $handler): Router
909e5d8e6fSGreg Roach    {
919e5d8e6fSGreg Roach        return $this->add(self::METHOD_POST, $path, $handler);
929e5d8e6fSGreg Roach    }
939e5d8e6fSGreg Roach
949e5d8e6fSGreg Roach    /**
959e5d8e6fSGreg Roach     * @param ServerRequestInterface  $request
969e5d8e6fSGreg Roach     * @param RequestHandlerInterface $handler
979e5d8e6fSGreg Roach     *
989e5d8e6fSGreg Roach     * @return ResponseInterface
999e5d8e6fSGreg Roach     */
1009e5d8e6fSGreg Roach    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
1019e5d8e6fSGreg Roach    {
102*82e92bfaSGreg Roach        // Save the router in the container, as we'll need it to generate URLs.
1039e5d8e6fSGreg Roach        app()->instance(self::class, $this);
104*82e92bfaSGreg Roach
105*82e92bfaSGreg Roach        // Load the routing table.
106c48210a4SGreg Roach        require Webtrees::ROOT_DIR . 'routes/web.php';
1079e5d8e6fSGreg Roach
108*82e92bfaSGreg Roach        // Match the request to a route.
1099e5d8e6fSGreg Roach        $method  = $request->getMethod();
1109e5d8e6fSGreg Roach        $route   = $request->getQueryParams()['route'] ?? '';
1119e5d8e6fSGreg Roach        $routing = $this->routes[$method][$route] ?? '';
1129e5d8e6fSGreg Roach
1139e5d8e6fSGreg Roach        // Bind the request into the container
1149e5d8e6fSGreg Roach        app()->instance(ServerRequestInterface::class, $request);
1159e5d8e6fSGreg Roach
1169e5d8e6fSGreg Roach        // No route matched?
1179e5d8e6fSGreg Roach        if ($routing === '') {
1189e5d8e6fSGreg Roach            return $handler->handle($request);
1199e5d8e6fSGreg Roach        }
1209e5d8e6fSGreg Roach
121*82e92bfaSGreg Roach        // Firstly, apply the route middleware
122*82e92bfaSGreg Roach        $route_middleware = [];
123*82e92bfaSGreg Roach        $route_middleware = array_map('app', $route_middleware);
1249e5d8e6fSGreg Roach
125*82e92bfaSGreg Roach        // Secondly, apply any module middleware
126*82e92bfaSGreg Roach        $module_middleware = $this->module_service->findByInterface(MiddlewareInterface::class)->all();
1279e5d8e6fSGreg Roach
128*82e92bfaSGreg Roach        // Finally, run the handler using middleware
129*82e92bfaSGreg Roach        $handler_middleware = [new WrapHandler($routing)];
130*82e92bfaSGreg Roach
131*82e92bfaSGreg Roach        $middleware = array_merge($route_middleware, $module_middleware, $handler_middleware);
132*82e92bfaSGreg Roach
133*82e92bfaSGreg Roach        $dispatcher = new Dispatcher($middleware, app());
134*82e92bfaSGreg Roach
135*82e92bfaSGreg Roach        return $dispatcher->dispatch($request);
1369e5d8e6fSGreg Roach    }
1379e5d8e6fSGreg Roach}
138