*/ private array $commands = []; public function register(Command $command): void { $this->commands[$command->name()] = $command; } /** * @param list $argv Raw CLI arguments (including script name at [0]) */ public function run(array $argv): int { $commandName = $argv[1] ?? ''; if ($commandName === '' || $commandName === 'list' || $commandName === '--help') { $this->printCommandList(); return 0; } if (!isset($this->commands[$commandName])) { fwrite(STDERR, "Unknown command: {$commandName}\n\n"); $this->printCommandList(); return 1; } [$args, $options] = self::parseArgv(array_slice($argv, 2)); return $this->commands[$commandName]->execute($args, $options); } private function printCommandList(): void { fwrite(STDOUT, "Usage: php bin/console [arguments] [options]\n\n"); fwrite(STDOUT, "Available commands:\n"); // Group by namespace prefix $grouped = []; foreach ($this->commands as $name => $command) { $parts = explode(':', $name, 2); $group = count($parts) === 2 ? $parts[0] : ''; $grouped[$group][$name] = $command->description(); } ksort($grouped); foreach ($grouped as $group => $commands) { if ($group !== '') { fwrite(STDOUT, " {$group}\n"); } ksort($commands); foreach ($commands as $name => $description) { fwrite(STDOUT, sprintf(" %-30s %s\n", $name, $description)); } } } /** * @param list $tokens * @return array{list, array} */ private static function parseArgv(array $tokens): array { $args = []; $options = []; foreach ($tokens as $token) { if (str_starts_with($token, '--')) { $option = substr($token, 2); if (str_contains($option, '=')) { [$key, $value] = explode('=', $option, 2); $options[$key] = $value; } else { $options[$option] = true; } } else { $args[] = $token; } } return [$args, $options]; } }