Вход Регистрация
Файл: vendor/laravel/framework/src/Illuminate/Foundation/Console/RouteListCommand.php
Строк: 544
<?php

namespace IlluminateFoundationConsole;

use 
Closure;
use 
IlluminateConsoleCommand;
use 
IlluminateContractsRoutingUrlGenerator;
use 
IlluminateRoutingRoute;
use 
IlluminateRoutingRouter;
use 
IlluminateRoutingViewController;
use 
IlluminateSupportArr;
use 
IlluminateSupportStr;
use 
ReflectionClass;
use 
ReflectionFunction;
use 
SymfonyComponentConsoleAttributeAsCommand;
use 
SymfonyComponentConsoleInputInputOption;
use 
SymfonyComponentConsoleTerminal;

#[AsCommand(name: 'route:list')]
class RouteListCommand extends Command
{
    
/**
     * The console command name.
     *
     * @var string
     */
    
protected $name 'route:list';

    
/**
     * The console command description.
     *
     * @var string
     */
    
protected $description 'List all registered routes';

    
/**
     * The router instance.
     *
     * @var IlluminateRoutingRouter
     */
    
protected $router;

    
/**
     * The table headers for the command.
     *
     * @var string[]
     */
    
protected $headers = ['Domain''Method''URI''Name''Action''Middleware'];

    
/**
     * The terminal width resolver callback.
     *
     * @var Closure|null
     */
    
protected static $terminalWidthResolver;

    
/**
     * The verb colors for the command.
     *
     * @var array
     */
    
protected $verbColors = [
        
'ANY' => 'red',
        
'GET' => 'blue',
        
'HEAD' => '#6C7280',
        
'OPTIONS' => '#6C7280',
        
'POST' => 'yellow',
        
'PUT' => 'yellow',
        
'PATCH' => 'yellow',
        
'DELETE' => 'red',
    ];

    
/**
     * Create a new route command instance.
     *
     * @param  IlluminateRoutingRouter  $router
     * @return void
     */
    
public function __construct(Router $router)
    {
        
parent::__construct();

        
$this->router $router;
    }

    
/**
     * Execute the console command.
     *
     * @return void
     */
    
public function handle()
    {
        if (! 
$this->output->isVeryVerbose()) {
            
$this->router->flushMiddlewareGroups();
        }

        if (! 
$this->router->getRoutes()->count()) {
            return 
$this->components->error("Your application doesn't have any routes.");
        }

        if (empty(
$routes $this->getRoutes())) {
            return 
$this->components->error("Your application doesn't have any routes matching the given criteria.");
        }

        
$this->displayRoutes($routes);
    }

    
/**
     * Compile the routes into a displayable format.
     *
     * @return array
     */
    
protected function getRoutes()
    {
        
$routes collect($this->router->getRoutes())->map(function ($route) {
            return 
$this->getRouteInformation($route);
        })->
filter()->all();

        if ((
$sort $this->option('sort')) !== null) {
            
$routes $this->sortRoutes($sort$routes);
        } else {
            
$routes $this->sortRoutes('uri'$routes);
        }

        if (
$this->option('reverse')) {
            
$routes array_reverse($routes);
        }

        return 
$this->pluckColumns($routes);
    }

    
/**
     * Get the route information for a given route.
     *
     * @param  IlluminateRoutingRoute  $route
     * @return array
     */
    
protected function getRouteInformation(Route $route)
    {
        return 
$this->filterRoute([
            
'domain' => $route->domain(),
            
'method' => implode('|'$route->methods()),
            
'uri' => $route->uri(),
            
'name' => $route->getName(),
            
'action' => ltrim($route->getActionName(), '\'),
            '
middleware' => $this->getMiddleware($route),
            '
vendor' => $this->isVendorRoute($route),
        ]);
    }

    /**
     * Sort the routes by a given element.
     *
     * @param  string  $sort
     * @param  array  $routes
     * @return array
     */
    protected function sortRoutes($sort, array $routes)
    {
        return Arr::sort($routes, function ($route) use ($sort) {
            return $route[$sort];
        });
    }

    /**
     * Remove unnecessary columns from the routes.
     *
     * @param  array  $routes
     * @return array
     */
    protected function pluckColumns(array $routes)
    {
        return array_map(function ($route) {
            return Arr::only($route, $this->getColumns());
        }, $routes);
    }

    /**
     * Display the route information on the console.
     *
     * @param  array  $routes
     * @return void
     */
    protected function displayRoutes(array $routes)
    {
        $routes = collect($routes);

        $this->output->writeln(
            $this->option('
json') ? $this->asJson($routes) : $this->forCli($routes)
        );
    }

    /**
     * Get the middleware for the route.
     *
     * @param  IlluminateRoutingRoute  $route
     * @return string
     */
    protected function getMiddleware($route)
    {
        return collect($this->router->gatherRouteMiddleware($route))->map(function ($middleware) {
            return $middleware instanceof Closure ? '
Closure' : $middleware;
        })->implode("n");
    }

    /**
     * Determine if the route has been defined outside of the application.
     *
     * @param  IlluminateRoutingRoute  $route
     * @return bool
     */
    protected function isVendorRoute(Route $route)
    {
        if ($route->action['
uses'] instanceof Closure) {
            $path = (new ReflectionFunction($route->action['
uses']))
                                ->getFileName();
        } elseif (is_string($route->action['
uses']) &&
                  str_contains($route->action['
uses'], 'SerializableClosure')) {
            return false;
        } elseif (is_string($route->action['
uses'])) {
            if ($this->isFrameworkController($route)) {
                return false;
            }

            $path = (new ReflectionClass($route->getControllerClass()))
                                ->getFileName();
        } else {
            return false;
        }

        return str_starts_with($path, base_path('
vendor'));
    }

    /**
     * Determine if the route uses a framework controller.
     *
     * @param  IlluminateRoutingRoute  $route
     * @return bool
     */
    protected function isFrameworkController(Route $route)
    {
        return in_array($route->getControllerClass(), [
            '
IlluminateRoutingRedirectController',
            '
IlluminateRoutingViewController',
        ], true);
    }

    /**
     * Filter the route by URI and / or name.
     *
     * @param  array  $route
     * @return array|null
     */
    protected function filterRoute(array $route)
    {
        if (($this->option('
name') && ! Str::contains((string) $route['name'], $this->option('name'))) ||
            ($this->option('
path') && ! Str::contains($route['uri'], $this->option('path'))) ||
            ($this->option('
method') && ! Str::contains($route['method'], strtoupper($this->option('method')))) ||
            ($this->option('
domain') && ! Str::contains((string) $route['domain'], $this->option('domain'))) ||
            ($this->option('
except-vendor') && $route['vendor']) ||
            ($this->option('
only-vendor') && ! $route['vendor'])) {
            return;
        }

        if ($this->option('
except-path')) {
            foreach (explode('
,', $this->option('except-path')) as $path) {
                if (str_contains($route['
uri'], $path)) {
                    return;
                }
            }
        }

        return $route;
    }

    /**
     * Get the table headers for the visible columns.
     *
     * @return array
     */
    protected function getHeaders()
    {
        return Arr::only($this->headers, array_keys($this->getColumns()));
    }

    /**
     * Get the column names to show (lowercase table headers).
     *
     * @return array
     */
    protected function getColumns()
    {
        return array_map('
strtolower', $this->headers);
    }

    /**
     * Parse the column list.
     *
     * @param  array  $columns
     * @return array
     */
    protected function parseColumns(array $columns)
    {
        $results = [];

        foreach ($columns as $column) {
            if (str_contains($column, '
,')) {
                $results = array_merge($results, explode('
,', $column));
            } else {
                $results[] = $column;
            }
        }

        return array_map('
strtolower', $results);
    }

    /**
     * Convert the given routes to JSON.
     *
     * @param  IlluminateSupportCollection  $routes
     * @return string
     */
    protected function asJson($routes)
    {
        return $routes
            ->map(function ($route) {
                $route['
middleware'] = empty($route['middleware']) ? [] : explode("n", $route['middleware']);

                return $route;
            })
            ->values()
            ->toJson();
    }

    /**
     * Convert the given routes to regular CLI output.
     *
     * @param  IlluminateSupportCollection  $routes
     * @return array
     */
    protected function forCli($routes)
    {
        $routes = $routes->map(
            fn ($route) => array_merge($route, [
                '
action' => $this->formatActionForCli($route),
                '
method' => $route['method'] == 'GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS' ? 'ANY' : $route['method'],
                '
uri' => $route['domain'] ? ($route['domain'].'/'.ltrim($route['uri'], '/')) : $route['uri'],
            ]),
        );

        $maxMethod = mb_strlen($routes->max('
method'));

        $terminalWidth = $this->getTerminalWidth();

        $routeCount = $this->determineRouteCountOutput($routes, $terminalWidth);

        return $routes->map(function ($route) use ($maxMethod, $terminalWidth) {
            [
                '
action' => $action,
                '
domain' => $domain,
                '
method' => $method,
                '
middleware' => $middleware,
                '
uri' => $uri,
            ] = $route;

            $middleware = Str::of($middleware)->explode("n")->filter()->whenNotEmpty(
                fn ($collection) => $collection->map(
                    fn ($middleware) => sprintf('         
%s⇂ %s', str_repeat(' ', $maxMethod), $middleware)
                )
            )->implode("n");

            $spaces = str_repeat(' ', max($maxMethod + 6 - mb_strlen($method), 0));

            $dots = str_repeat('
.', max(
                $terminalWidth - mb_strlen($method.$spaces.$uri.$action) - 6 - ($action ? 1 : 0), 0
            ));

            $dots = empty($dots) ? $dots : " $dots";

            if ($action && ! $this->output->isVerbose() && mb_strlen($method.$spaces.$uri.$action.$dots) > ($terminalWidth - 6)) {
                $action = substr($action, 0, $terminalWidth - 7 - mb_strlen($method.$spaces.$uri.$dots)).'
';
            }

            $method = Str::of($method)->explode('
|')->map(
                fn ($method) => sprintf('
<fg=%s>%s</>', $this->verbColors[$method] ?? 'default', $method),
            )->implode('
<fg=#6C7280>|</>');

            
return [sprintf(
                
'  <fg=white;options=bold>%s</> %s<fg=white>%s</><fg=#6C7280>%s %s</>',
                
$method,
                
$spaces,
                
preg_replace('#({[^}]+})#''<fg=yellow>$1</>'$uri),
                
$dots,
                
str_replace('   '' › '$action ?? ''),
            ), 
$this->output->isVerbose() && ! empty($middleware) ? "<fg=#6C7280>$middleware</>" null];
        })
            ->
flatten()
            ->
filter()
            ->
prepend('')
            ->
push('')->push($routeCount)->push('')
            ->
toArray();
    }

    
/**
     * Get the formatted action for display on the CLI.
     *
     * @param  array  $route
     * @return string
     */
    
protected function formatActionForCli($route)
    {
        [
'action' => $action'name' => $name] = $route;

        if (
$action === 'Closure' || $action === ViewController::class) {
            return 
$name;
        }

        
$name $name "$name   " null;

        
$rootControllerNamespace $this->laravel[UrlGenerator::class]->getRootControllerNamespace()
            ?? (
$this->laravel->getNamespace().'Http\Controllers');

        if (
str_starts_with($action$rootControllerNamespace)) {
            return 
$name.substr($actionmb_strlen($rootControllerNamespace) + 1);
        }

        
$actionClass explode('@'$action)[0];

        if (
class_exists($actionClass) && str_starts_with((new ReflectionClass($actionClass))->getFilename(), base_path('vendor'))) {
            
$actionCollection collect(explode('\', $action));

            return $name.$actionCollection->take(2)->implode('
\').'   '.$actionCollection->last();
        }

        return $name.$action;
    }

    /**
     * Determine and return the output for displaying the number of routes in the CLI output.
     *
     * @param  IlluminateSupportCollection  $routes
     * @param  int  $terminalWidth
     * @return string
     */
    protected function determineRouteCountOutput($routes, $terminalWidth)
    {
        $routeCountText = '
Showing ['.$routes->count().'routes';

        $offset = $terminalWidth - mb_strlen($routeCountText) - 2;

        $spaces = str_repeat(' ', $offset);

        return $spaces.'
<fg=blue;options=bold>Showing ['.$routes->count().'routes</>';
    }

    /**
     * Get the terminal width.
     *
     * @return int
     */
    public static function getTerminalWidth()
    {
        return is_null(static::$terminalWidthResolver)
            ? (new Terminal)->getWidth()
            : call_user_func(static::$terminalWidthResolver);
    }

    /**
     * Set a callback that should be used when resolving the terminal width.
     *
     * @param  Closure|null  $resolver
     * @return void
     */
    public static function resolveTerminalWidthUsing($resolver)
    {
        static::$terminalWidthResolver = $resolver;
    }

    /**
     * Get the console command options.
     *
     * @return array
     */
    protected function getOptions()
    {
        return [
            ['
json', null, InputOption::VALUE_NONE, 'Output the route list as JSON'],
            ['
method', null, InputOption::VALUE_OPTIONAL, 'Filter the routes by method'],
            ['
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 (domainmethodurinameactionmiddlewareto sort by', 'uri'],
            ['
except-vendor', null, InputOption::VALUE_NONE, 'Do not display routes defined by vendor packages'],
            ['
only-vendor', null, InputOption::VALUE_NONE, 'Only display routes defined by vendor packages'],
        ];
    }
}
Онлайн: 0
Реклама