blitz-php /
framework
| 1 | <?php |
||||
| 2 | |||||
| 3 | /** |
||||
| 4 | * This file is part of Blitz PHP framework. |
||||
| 5 | * |
||||
| 6 | * (c) 2022 Dimitri Sitchet Tomkeu <[email protected]> |
||||
| 7 | * |
||||
| 8 | * For the full copyright and license information, please view |
||||
| 9 | * the LICENSE file that was distributed with this source code. |
||||
| 10 | */ |
||||
| 11 | |||||
| 12 | namespace BlitzPHP\Cli\Commands\Utilities; |
||||
| 13 | |||||
| 14 | use Ahc\Cli\Output\Color; |
||||
| 15 | use BlitzPHP\Cli\Console\Command; |
||||
| 16 | use BlitzPHP\Debug\Toolbar\Collectors\Config; |
||||
| 17 | use BlitzPHP\Facades\Container; |
||||
| 18 | use BlitzPHP\Utilities\Iterable\Collection; |
||||
| 19 | use BlitzPHP\Utilities\String\Text; |
||||
| 20 | use Closure; |
||||
| 21 | |||||
| 22 | /** |
||||
| 23 | * Affiche les informations de base sur de l'application |
||||
| 24 | */ |
||||
| 25 | class About extends Command |
||||
| 26 | { |
||||
| 27 | /** |
||||
| 28 | * @var string Groupe |
||||
| 29 | */ |
||||
| 30 | protected $group = 'BlitzPHP'; |
||||
| 31 | |||||
| 32 | protected $service = 'Service de configuration'; |
||||
| 33 | |||||
| 34 | /** |
||||
| 35 | * @var string Nom |
||||
| 36 | */ |
||||
| 37 | protected $name = 'about'; |
||||
| 38 | |||||
| 39 | /** |
||||
| 40 | * @var string Description |
||||
| 41 | */ |
||||
| 42 | protected $description = 'Affiche les informations de base sur de l\'application.'; |
||||
| 43 | |||||
| 44 | /** |
||||
| 45 | * Options de la commande |
||||
| 46 | * |
||||
| 47 | * @var array<string, string> |
||||
| 48 | */ |
||||
| 49 | protected $options = [ |
||||
| 50 | '--only' => 'La section à afficher.', |
||||
| 51 | '--json' => 'Afficher les informations au format json.', |
||||
| 52 | ]; |
||||
| 53 | |||||
| 54 | /** |
||||
| 55 | * Donnees a afficher. |
||||
| 56 | */ |
||||
| 57 | protected static array $data = []; |
||||
| 58 | |||||
| 59 | /** |
||||
| 60 | * Les callables enregistrés qui ajoutent des données personnalisées à la sortie de la commande. |
||||
| 61 | */ |
||||
| 62 | protected static array $customDataResolvers = []; |
||||
| 63 | |||||
| 64 | /** |
||||
| 65 | * Elements deja afficher |
||||
| 66 | */ |
||||
| 67 | protected static array $displayed = []; |
||||
| 68 | |||||
| 69 | /** |
||||
| 70 | * {@inheritDoc} |
||||
| 71 | */ |
||||
| 72 | public function execute(array $params) |
||||
| 73 | { |
||||
| 74 | $this->gatherApplicationInformation(); |
||||
| 75 | |||||
| 76 | $this->center('Information générales sur votre application', ['fg' => Color::YELLOW]); |
||||
| 77 | $this->border(); |
||||
| 78 | |||||
| 79 | collect(static::$data) |
||||
| 80 | ->map( |
||||
| 81 | static fn ($items) => collect($items) |
||||
| 82 | ->map(static function ($value) { |
||||
| 83 | if (is_array($value)) { |
||||
| 84 | return [$value]; |
||||
| 85 | } |
||||
| 86 | |||||
| 87 | if (is_string($value)) { |
||||
| 88 | $value = Container::make($value); |
||||
| 89 | } |
||||
| 90 | |||||
| 91 | return collect(Container::call($value)) |
||||
| 92 | ->map(static fn ($value, $key) => [$key, $value]) |
||||
| 93 | ->values() |
||||
| 94 | ->all(); |
||||
| 95 | })->flatten(1) |
||||
| 96 | ) |
||||
| 97 | ->sortBy(static function ($data, $key): int { |
||||
| 98 | $index = array_search($key, ['Environnement', 'Cache', 'Gestionnaires'], true); |
||||
| 99 | |||||
| 100 | return $index === false ? 99 : $index; |
||||
|
0 ignored issues
–
show
Bug
Best Practice
introduced
by
Loading history...
|
|||||
| 101 | }) |
||||
| 102 | ->filter(fn ($data, $key) => ((bool) $this->option('only')) ? in_array($this->toSearchKeyword($key), $this->sections(), true) : true) |
||||
| 103 | ->pipe(fn ($data) => $this->display($data)); |
||||
| 104 | |||||
| 105 | return EXIT_SUCCESS; |
||||
| 106 | } |
||||
| 107 | |||||
| 108 | /** |
||||
| 109 | * Affiche les informations sur l'application. |
||||
| 110 | */ |
||||
| 111 | protected function display(Collection $data): void |
||||
| 112 | { |
||||
| 113 | ((bool) $this->option('json')) ? $this->displayJson($data) : $this->displayDetail($data); |
||||
| 114 | } |
||||
| 115 | |||||
| 116 | /** |
||||
| 117 | * Affiche les informations sur l'application sous forme de vue détaillée. |
||||
| 118 | */ |
||||
| 119 | protected function displayDetail(Collection $data): void |
||||
| 120 | { |
||||
| 121 | $data->each(function ($data, $section): void { |
||||
| 122 | $this->newLine(); |
||||
| 123 | |||||
| 124 | $this->justify($section, '', ['first' => ['fg' => Color::GREEN]]); |
||||
| 125 | |||||
| 126 | $data->pipe(static fn ($data) => $section !== 'Environnement' ? $data->sort() : $data)->each(function ($detail): void { |
||||
| 127 | [$label, $value] = $detail; |
||||
| 128 | if (! in_array($label, static::$displayed, true)) { |
||||
| 129 | $this->justify($label, value($value, false)); |
||||
| 130 | static::$displayed[] = $label; |
||||
| 131 | } |
||||
| 132 | }); |
||||
| 133 | }); |
||||
| 134 | } |
||||
| 135 | |||||
| 136 | /** |
||||
| 137 | * Affiche les informations sur l'application sous forme de json. |
||||
| 138 | */ |
||||
| 139 | protected function displayJson(Collection $data): void |
||||
| 140 | { |
||||
| 141 | $output = $data->flatMap(fn ($data, $section) => [ |
||||
| 142 | (string) Text::of($section)->snake() => $data->mapWithKeys(fn ($item, $key) => [ |
||||
|
0 ignored issues
–
show
The parameter
$key is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. Loading history...
|
|||||
| 143 | $this->toSearchKeyword($item[0]) => value($item[1], true), |
||||
| 144 | ]), |
||||
| 145 | ]); |
||||
| 146 | |||||
| 147 | $this->eol()->json($output); |
||||
| 148 | } |
||||
| 149 | |||||
| 150 | /** |
||||
| 151 | * Rassemble des informations sur l’application. |
||||
| 152 | */ |
||||
| 153 | protected function gatherApplicationInformation(): void |
||||
| 154 | { |
||||
| 155 | self::$data = []; |
||||
| 156 | |||||
| 157 | $formatEnabledStatus = fn ($value) => $value ? $this->color->warn('ACTIVE') : $this->color->warn('DESACTIVE'); |
||||
| 158 | $formatCachedStatus = fn ($value) => $value ? $this->color->ok('MISE EN CACHE') : $this->color->warn('NON MISE EN CACHE'); |
||||
| 159 | |||||
| 160 | $config = (object) Config::display(); |
||||
| 161 | |||||
| 162 | static::addToSection('Environnement', static fn () => [ |
||||
| 163 | 'Nom de l\'application' => $config->appName, |
||||
| 164 | 'Version de BlitzPHP' => $config->blitzVersion, |
||||
| 165 | 'Version de PHP' => PHP_VERSION, |
||||
| 166 | // 'Composer Version' => $this->composer->getVersion() ?? '<fg=yellow;options=bold>-</>', |
||||
| 167 | 'Environnement' => $config->environment, |
||||
| 168 | 'Mode debug' => static::format(config('app.debug'), console: $formatEnabledStatus), |
||||
| 169 | 'URL' => Text::of($config->baseURL)->replace(['http://', 'https://'], ''), |
||||
|
0 ignored issues
–
show
'' of type string is incompatible with the type iterable expected by parameter $replace of BlitzPHP\Utilities\String\Stringable::replace().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 170 | // 'Maintenance Mode' => static::format($this->laravel->isDownForMaintenance(), console: $formatEnabledStatus), |
||||
| 171 | ]); |
||||
| 172 | |||||
| 173 | static::addToSection('Cache', fn () => [ |
||||
| 174 | // 'Config' => static::format($this->laravel->configurationIsCached(), console: $formatCachedStatus), |
||||
| 175 | // 'Events' => static::format($this->laravel->eventsAreCached(), console: $formatCachedStatus), |
||||
| 176 | // 'Routes' => static::format($this->laravel->routesAreCached(), console: $formatCachedStatus), |
||||
| 177 | 'Vues' => static::format($this->hasPhpFiles(storage_path('framework/cache/views')), console: $formatCachedStatus), |
||||
| 178 | ]); |
||||
| 179 | |||||
| 180 | static::addToSection('Gestionnaires', static fn () => array_filter([ |
||||
| 181 | 'Cache' => config('cache.handler'), |
||||
| 182 | 'Logs' => static function ($json): string { |
||||
|
0 ignored issues
–
show
The parameter
$json is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. Loading history...
|
|||||
| 183 | $handlers = []; |
||||
| 184 | |||||
| 185 | foreach (config('log.handlers') as $k => $v) { |
||||
| 186 | $handlers[] = $k; |
||||
| 187 | } |
||||
| 188 | |||||
| 189 | return implode(', ', $handlers); |
||||
| 190 | }, |
||||
| 191 | 'Mail' => config('mail.handler'), |
||||
| 192 | 'Session' => config('session.handler'), |
||||
| 193 | ])); |
||||
| 194 | |||||
| 195 | collect(static::$customDataResolvers)->each->__invoke(); |
||||
| 196 | } |
||||
| 197 | |||||
| 198 | /** |
||||
| 199 | * Détermine si le répertoire donné contient des fichiers PHP. |
||||
| 200 | */ |
||||
| 201 | protected function hasPhpFiles(string $path): bool |
||||
| 202 | { |
||||
| 203 | return count(glob($path . '/*.php')) > 0; |
||||
| 204 | } |
||||
| 205 | |||||
| 206 | /** |
||||
| 207 | * Ajoute des données supplémentaires à la sortie de la commande "about". |
||||
| 208 | * |
||||
| 209 | * @param array|callable|string $data |
||||
| 210 | */ |
||||
| 211 | public static function add(string $section, $data, ?string $value = null): void |
||||
| 212 | { |
||||
| 213 | static::$customDataResolvers[] = static fn () => static::addToSection($section, $data, $value); |
||||
| 214 | } |
||||
| 215 | |||||
| 216 | /** |
||||
| 217 | * Ajoute des données supplémentaires à la sortie de la commande "about". |
||||
| 218 | * |
||||
| 219 | * @param array|callable|string $data |
||||
| 220 | */ |
||||
| 221 | protected static function addToSection(string $section, $data, ?string $value = null): void |
||||
| 222 | { |
||||
| 223 | if (is_array($data)) { |
||||
| 224 | foreach ($data as $key => $value) { |
||||
| 225 | self::$data[$section][] = [$key, $value]; |
||||
| 226 | } |
||||
| 227 | } elseif (is_callable($data) || ($value === null && class_exists($data))) { |
||||
|
0 ignored issues
–
show
It seems like
$data can also be of type callable; however, parameter $class of class_exists() does only seem to accept string, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 228 | self::$data[$section][] = $data; |
||||
| 229 | } else { |
||||
| 230 | self::$data[$section][] = [$data, $value]; |
||||
| 231 | } |
||||
| 232 | } |
||||
| 233 | |||||
| 234 | /** |
||||
| 235 | * Récupère les sections fournies à la commande. |
||||
| 236 | */ |
||||
| 237 | protected function sections(): array |
||||
| 238 | { |
||||
| 239 | return collect(explode(',', $this->option('only') ?? '')) |
||||
| 240 | ->filter() |
||||
| 241 | ->map(fn ($only) => $this->toSearchKeyword($only)) |
||||
| 242 | ->all(); |
||||
| 243 | } |
||||
| 244 | |||||
| 245 | /** |
||||
| 246 | * Matérialise une fonction qui formate une valeur donnée pour la sortie CLI ou JSON. |
||||
| 247 | * |
||||
| 248 | * @param (Closure(mixed):(mixed))|null $console |
||||
|
0 ignored issues
–
show
|
|||||
| 249 | * @param (Closure(mixed):(mixed))|null $json |
||||
| 250 | * |
||||
| 251 | * @return Closure(bool):mixed |
||||
| 252 | */ |
||||
| 253 | public static function format(mixed $value, ?Closure $console = null, ?Closure $json = null) |
||||
| 254 | { |
||||
| 255 | return static function ($isJson) use ($value, $console, $json) { |
||||
| 256 | if ($isJson === true && $json instanceof Closure) { |
||||
| 257 | return value($json, $value); |
||||
| 258 | } |
||||
| 259 | if ($isJson === false && $console instanceof Closure) { |
||||
| 260 | return value($console, $value); |
||||
| 261 | } |
||||
| 262 | |||||
| 263 | return value($value); |
||||
| 264 | }; |
||||
| 265 | } |
||||
| 266 | |||||
| 267 | /** |
||||
| 268 | * Formatez la chaîne donnée pour la recherche. |
||||
| 269 | */ |
||||
| 270 | protected function toSearchKeyword(string $value): string |
||||
| 271 | { |
||||
| 272 | return (string) Text::of($value)->lower()->snake(); |
||||
| 273 | } |
||||
| 274 | |||||
| 275 | /** |
||||
| 276 | * Videz les données enregistrées. |
||||
| 277 | */ |
||||
| 278 | public static function flushState(): void |
||||
| 279 | { |
||||
| 280 | static::$data = []; |
||||
| 281 | |||||
| 282 | static::$customDataResolvers = []; |
||||
| 283 | } |
||||
| 284 | } |
||||
| 285 |