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