the browser-facing portion of osu!
at master 3.9 kB view raw
1<?php 2 3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4// See the LICENCE file in the repository root for full licence text. 5 6declare(strict_types=1); 7 8namespace App\Libraries; 9 10use App\Http\Middleware\RequireScopes; 11use Closure; 12use Ds\Set; 13use Illuminate\Contracts\Http\Kernel as HttpKernelContract; 14use Route; 15 16class RouteScopesHelper 17{ 18 public $routes; 19 20 private static $requireScopesPrefix = RequireScopes::class.':'; 21 22 public static function keyForMethods(array $methods) 23 { 24 sort($methods); 25 26 return implode('|', $methods); 27 } 28 29 public function fromCsv(string $filename) 30 { 31 $csv = array_map('str_getcsv', file($filename)); 32 33 $routes = array_map(function ($line) use ($csv) { 34 $a = array_combine($csv[0], $line); 35 $a['methods'] = explode('|', $a['methods']); 36 $a['middlewares'] = explode('|', $a['middlewares']); 37 $a['scopes'] = array_filter(explode('|', $a['scopes'])); 38 39 return $a; 40 }, $csv); 41 42 array_shift($routes); // remove column header 43 44 $this->routes = $routes; 45 } 46 47 public function fromJson(string $filename) 48 { 49 $this->routes = json_decode(file_get_contents($filename), true); 50 } 51 52 public function loadRoutes() 53 { 54 // Force the http kernel singleton to boot if it hasn't. 55 // This ensures the router has the middleware groups loaded. 56 app(HttpKernelContract::class); 57 58 $this->routes = []; 59 $apiGroup = new Set(Route::getMiddlewareGroups()['api']); 60 61 /** @var \Illuminate\Routing\Route $route */ 62 foreach (Route::getRoutes() as $route) { 63 if (!starts_with($route->uri, 'api/')) { 64 continue; 65 } 66 67 // uri will still have the placeholders and wrong verbs, but we don't need them. 68 $request = request()->create($route->uri, 'GET'); 69 app()->instance('request', $request); // set current request so is_api_request can work. 70 71 $uri = $route->uri; 72 73 // filter out closures and global middleware. 74 $middlewares = array_values(array_filter( 75 Route::gatherRouteMiddleware($route), 76 fn ($middleware) => !($middleware instanceof Closure) && !$apiGroup->contains($middleware) 77 )); 78 $controller = $route->action['controller'] ?? null; 79 80 // extract scopes 81 $scopes = []; 82 83 foreach ($middlewares as $middleware) { 84 if (is_string($middleware) && starts_with($middleware, static::$requireScopesPrefix)) { 85 $scopes = array_merge($scopes, explode(',', substr($middleware, strlen(static::$requireScopesPrefix)))); 86 } 87 } 88 89 sort($scopes); 90 91 $methods = $route->methods; 92 sort($methods); 93 94 $this->routes[] = compact('uri', 'methods', 'controller', 'middlewares', 'scopes'); 95 } 96 } 97 98 public function toArray() 99 { 100 if (!isset($this->routes)) { 101 $this->loadRoutes(); 102 } 103 104 return $this->routes; 105 } 106 107 public function toCsv(string $filename) 108 { 109 $file = fopen($filename, 'w'); 110 fputcsv($file, ['uri', 'methods', 'controller', 'middlewares', 'scopes']); 111 112 foreach ($this->toArray() as $obj) { 113 $fields = [ 114 $obj['uri'], 115 implode('|', $obj['methods']), 116 $obj['controller'], 117 implode('|', $obj['middlewares']), 118 implode('|', $obj['scopes']), 119 ]; 120 121 fputcsv($file, $fields); 122 } 123 124 fclose($file); 125 } 126 127 public function toJson(string $filename) 128 { 129 file_put_contents($filename, json_encode($this->toArray(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)."\n"); 130 } 131}