From 39070d225d48a86fce23e05f6c01459c302f4826 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Tue, 15 Aug 2023 18:41:59 +0000 Subject: [PATCH] [1.x] Adds route named to `folio:list` command (#86) * Adds route name to `folio:list` command * Fixes style * Fix code styling * formatting --------- Co-authored-by: nunomaduro Co-authored-by: Taylor Otwell --- src/Console/ListCommand.php | 76 +++++++++++++++-------- src/FolioRoutes.php | 10 +++ tests/Feature/Console/ListCommandTest.php | 62 +++++++++++------- 3 files changed, 102 insertions(+), 46 deletions(-) diff --git a/src/Console/ListCommand.php b/src/Console/ListCommand.php index ec7e654..cfe6b55 100644 --- a/src/Console/ListCommand.php +++ b/src/Console/ListCommand.php @@ -7,7 +7,9 @@ use Illuminate\Support\Str; use Illuminate\Support\Stringable; use Laravel\Folio\FolioManager; +use Laravel\Folio\FolioRoutes; use Laravel\Folio\MountPath; +use Laravel\Folio\Support\Project; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Finder\Finder; @@ -28,7 +30,7 @@ class ListCommand extends RouteListCommand * * @var array */ - protected $headers = ['Domain', 'Method', 'URI', 'View']; + protected $headers = ['Domain', 'Method', 'URI', 'Name', 'View']; /** * Execute the console command. @@ -55,7 +57,13 @@ public function handle(): void */ protected function formatActionForCli($route): string { - return $route['view']; + $action = $route['view']; + + if (is_string($route['name'])) { + $action = $route['name'].' › '.$action; + } + + return $action; } /** @@ -128,7 +136,7 @@ protected function routesFromMountPaths(array $mountPaths): Collection 'method' => 'GET', 'domain' => $domain, 'uri' => $uri === '' ? '/' : $uri, - 'name' => '', + 'name' => $this->routeName($mountPath, $viewPath), 'action' => $action, 'view' => $action, ]; @@ -139,30 +147,16 @@ protected function routesFromMountPaths(array $mountPaths): Collection } /** - * Filter the route by URI and / or name. - * - * @param array $route - * @return array|null + * Get the route name for the given mount path and view path. */ - protected function filterRoute(array $route): ?array + protected function routeName(string $mountPath, string $viewPath): ?string { - if (($this->option('path') && ! Str::contains($route['uri'], $this->option('path')))) { - return null; - } + return collect($this->laravel->make(FolioRoutes::class)->routes())->search(function (array $route) use ($mountPath, $viewPath) { + [$routeRelativeMountPath, $routeRelativeViewPath] = $route; - if (($this->option('domain') && ! Str::contains((string) $route['domain'], $this->option('domain')))) { - return null; - } - - if ($this->option('except-path')) { - foreach (explode(',', $this->option('except-path')) as $path) { - if (str_contains($route['uri'], $path)) { - return null; - } - } - } - - return $route; + return $routeRelativeMountPath === Project::relativePathOf($mountPath) + && $routeRelativeViewPath === Project::relativePathOf($viewPath); + }) ?: null; } /** @@ -211,6 +205,37 @@ protected function toDisplayableFormat(array $routes): array return $this->pluckColumns($routes); } + /** + * Filter the route by URI and / or name. + * + * @param array $route + * @return array|null + */ + protected function filterRoute(array $route): ?array + { + if ($this->option('name') && ! Str::contains((string) $route['name'], $this->option('name'))) { + return null; + } + + if (($this->option('path') && ! Str::contains($route['uri'], $this->option('path')))) { + return null; + } + + if (($this->option('domain') && ! Str::contains((string) $route['domain'], $this->option('domain')))) { + return null; + } + + if ($this->option('except-path')) { + foreach (explode(',', $this->option('except-path')) as $path) { + if (str_contains($route['uri'], $path)) { + return null; + } + } + } + + return $route; + } + /** * Sort the routes by a given element. * @@ -253,11 +278,12 @@ protected function getOptions(): array { return [ ['json', null, InputOption::VALUE_NONE, 'Output the route list as JSON'], + ['name', null, InputOption::VALUE_OPTIONAL, 'Filter the routes by name'], ['domain', null, InputOption::VALUE_OPTIONAL, 'Filter the routes by domain'], ['path', null, InputOption::VALUE_OPTIONAL, 'Only show routes matching the given path pattern'], ['except-path', null, InputOption::VALUE_OPTIONAL, 'Do not display the routes matching the given path pattern'], ['reverse', 'r', InputOption::VALUE_NONE, 'Reverse the ordering of the routes'], - ['sort', null, InputOption::VALUE_OPTIONAL, 'The column (uri, view) to sort by', 'uri'], + ['sort', null, InputOption::VALUE_OPTIONAL, 'The column (domain, name, uri, view) to sort by', 'uri'], ]; } } diff --git a/src/FolioRoutes.php b/src/FolioRoutes.php index e753455..b2c314b 100644 --- a/src/FolioRoutes.php +++ b/src/FolioRoutes.php @@ -184,6 +184,16 @@ protected function formatParameter(string $uri, string $name, mixed $parameter, return $value; } + /** + * Get all of the registered routes. + */ + public function routes(): array + { + $this->ensureLoaded(); + + return $this->routes; + } + /** * Flush the cached routes. */ diff --git a/tests/Feature/Console/ListCommandTest.php b/tests/Feature/Console/ListCommandTest.php index 76d7dd7..dd08667 100644 --- a/tests/Feature/Console/ListCommandTest.php +++ b/tests/Feature/Console/ListCommandTest.php @@ -29,9 +29,9 @@ GET /books ........................................................................................................... books/index.blade.php GET /books/{...book}/detail ........................................................ books/[...Tests.Feature.Fixtures.Book]/detail.blade.php GET /categories/{category} ......................................................... categories/[.Tests.Feature.Fixtures.Category].blade.php - GET /dashboard ......................................................................................................... dashboard.blade.php + GET /dashboard ............................................................................................. dashboard › dashboard.blade.php GET /deleted-podcasts/{podcast} ............................................... deleted-podcasts/[.Tests.Feature.Fixtures.Podcast].blade.php - GET /domain ............................................................................................................... domain.blade.php + GET /domain ................................................................................................... my-domain › domain.blade.php GET /events/{event} ............................................................................................... events/[Event].blade.php GET /flights ....................................................................................................... flights/index.blade.php GET /non-routables/{nonRoutable} ............................................. non-routables/[.Tests.Feature.Fixtures.NonRoutable].blade.php @@ -39,10 +39,10 @@ GET /podcasts/{podcast} ............................................................... podcasts/[.Tests.Feature.Fixtures.Podcast].blade.php GET /podcasts/{podcast}/comments ....................................... podcasts/[.Tests.Feature.Fixtures.Podcast]/comments/index.blade.php GET /podcasts/{podcast}/comments/{comment:id} podcasts/[.Tests.Feature.Fixtures.Podcast]/comments/[.Tests.Feature.Fixtures.Comment-id].blad… - GET /posts/{lowerCase}/{upperCase}/{podcast}/{user:email}/show ......... posts/[lowerCase]/[UpperCase]/[Podcast]/[User-email]/show.blade.php - GET /users/articles/{user:wrongColumn} ........................................................ users/articles/[User-wrong_column].blade.php - GET /users/nuno ....................................................................................................... users/nuno.blade.php - GET /users/{id} ....................................................................................................... users/[id].blade.php + GET /posts/{lowerCase}/{upperCase}/{podcast}/{user:email}/show posts.show › posts/[lowerCase]/[UpperCase]/[Podcast]/[User-email]/show.bla… + GET /users/articles/{user:wrongColumn} ........................................ user.articles › users/articles/[User-wrong_column].blade.php + GET /users/nuno .......................................................................................... users.nuno › users/nuno.blade.php + GET /users/{id} .......................................................................................... users.show › users/[id].blade.php Showing [17] routes @@ -60,7 +60,7 @@ expect($exitCode)->toBe(0) ->and($output->fetch())->toStartWith(<<<'EOF' - [{"method":"GET","domain":null,"uri":"\/books","view":"books\/index.blade.php"},{"method":"GET","domain":null,"uri":"\/books\/{...book}\/detail + [{"method":"GET","domain":null,"uri":"\/books","name":null,"view":"books\/index.blade.php"},{"method":"GET","domain":null,"uri":"\/books\/{...book}\/detail EOF); }); @@ -87,6 +87,26 @@ EOF); }); +it('has the `--name` option', function () { + $output = new BufferedOutput(); + + Folio::route(__DIR__.'/../resources/views/pages'); + $exitCode = Artisan::call('folio:list', [ + '--name' => 'users', + ], $output); + + expect($exitCode)->toBe(0) + ->and($output->fetch())->toOutput(<<<'EOF' + + GET /users/nuno .......................................................................................... users.nuno › users/nuno.blade.php + GET /users/{id} .......................................................................................... users.show › users/[id].blade.php + + Showing [2] routes + + + EOF); +}); + it('has the `--except-path` option', function () { $output = new BufferedOutput(); @@ -101,15 +121,15 @@ GET /books ........................................................................................................... books/index.blade.php GET /books/{...book}/detail ........................................................ books/[...Tests.Feature.Fixtures.Book]/detail.blade.php GET /categories/{category} ......................................................... categories/[.Tests.Feature.Fixtures.Category].blade.php - GET /dashboard ......................................................................................................... dashboard.blade.php - GET /domain ............................................................................................................... domain.blade.php + GET /dashboard ............................................................................................. dashboard › dashboard.blade.php + GET /domain ................................................................................................... my-domain › domain.blade.php GET /events/{event} ............................................................................................... events/[Event].blade.php GET /flights ....................................................................................................... flights/index.blade.php GET /non-routables/{nonRoutable} ............................................. non-routables/[.Tests.Feature.Fixtures.NonRoutable].blade.php - GET /posts/{lowerCase}/{upperCase}/{podcast}/{user:email}/show ......... posts/[lowerCase]/[UpperCase]/[Podcast]/[User-email]/show.blade.php - GET /users/articles/{user:wrongColumn} ........................................................ users/articles/[User-wrong_column].blade.php - GET /users/nuno ....................................................................................................... users/nuno.blade.php - GET /users/{id} ....................................................................................................... users/[id].blade.php + GET /posts/{lowerCase}/{upperCase}/{podcast}/{user:email}/show posts.show › posts/[lowerCase]/[UpperCase]/[Podcast]/[User-email]/show.bla… + GET /users/articles/{user:wrongColumn} ........................................ user.articles › users/articles/[User-wrong_column].blade.php + GET /users/nuno .......................................................................................... users.nuno › users/nuno.blade.php + GET /users/{id} .......................................................................................... users.show › users/[id].blade.php Showing [12] routes @@ -194,13 +214,13 @@ expect($exitCode)->toBe(0) ->and($output->fetch())->toOutput(<<<'EOF' - GET / ............................................................................. tests/Feature/resources/views/more-pages/index.blade.php + GET / .......................................................... more-pages.index › tests/Feature/resources/views/more-pages/index.blade.php GET /books ....................................................................... tests/Feature/resources/views/pages/books/index.blade.php GET /books/{...book}/detail .................... tests/Feature/resources/views/pages/books/[...Tests.Feature.Fixtures.Book]/detail.blade.php GET /categories/{category} ..................... tests/Feature/resources/views/pages/categories/[.Tests.Feature.Fixtures.Category].blade.php - GET /dashboard ..................................................................... tests/Feature/resources/views/pages/dashboard.blade.php + GET /dashboard ......................................................... dashboard › tests/Feature/resources/views/pages/dashboard.blade.php GET /deleted-podcasts/{podcast} ........... tests/Feature/resources/views/pages/deleted-podcasts/[.Tests.Feature.Fixtures.Podcast].blade.php - GET /domain ........................................................................... tests/Feature/resources/views/pages/domain.blade.php + GET /domain ............................................................... my-domain › tests/Feature/resources/views/pages/domain.blade.php GET /events/{event} ........................................................... tests/Feature/resources/views/pages/events/[Event].blade.php GET /flights ................................................................... tests/Feature/resources/views/pages/flights/index.blade.php GET /non-routables/{nonRoutable} ......... tests/Feature/resources/views/pages/non-routables/[.Tests.Feature.Fixtures.NonRoutable].blade.php @@ -208,12 +228,12 @@ GET /podcasts/{podcast} ........................... tests/Feature/resources/views/pages/podcasts/[.Tests.Feature.Fixtures.Podcast].blade.php GET /podcasts/{podcast}/comments ... tests/Feature/resources/views/pages/podcasts/[.Tests.Feature.Fixtures.Podcast]/comments/index.blade.php GET /podcasts/{podcast}/comments/{comment:id} tests/Feature/resources/views/pages/podcasts/[.Tests.Feature.Fixtures.Podcast]/comments/[.Tes… - GET /posts/{lowerCase}/{upperCase}/{podcast}/{user:email}/show tests/Feature/resources/views/pages/posts/[lowerCase]/[UpperCase]/[Podcast]/… - GET /users/articles/{user:wrongColumn} .................... tests/Feature/resources/views/pages/users/articles/[User-wrong_column].blade.php - GET /users/nuno ................................................................... tests/Feature/resources/views/pages/users/nuno.blade.php - GET /users/{id} ................................................................... tests/Feature/resources/views/pages/users/[id].blade.php + GET /posts/{lowerCase}/{upperCase}/{podcast}/{user:email}/show posts.show › tests/Feature/resources/views/pages/posts/[lowerCase]/[UpperC… + GET /users/articles/{user:wrongColumn} .... user.articles › tests/Feature/resources/views/pages/users/articles/[User-wrong_column].blade.php + GET /users/nuno ...................................................... users.nuno › tests/Feature/resources/views/pages/users/nuno.blade.php + GET /users/{id} ...................................................... users.show › tests/Feature/resources/views/pages/users/[id].blade.php GET /{...user} ................................................................ tests/Feature/resources/views/more-pages/[...User].blade.php - GET /{...user}/detail .................................................. tests/Feature/resources/views/more-pages/[...User]/detail.blade.php + GET /{...user}/detail ......................... more-pages.user.detail › tests/Feature/resources/views/more-pages/[...User]/detail.blade.php Showing [20] routes