diff --git a/src/SPC/ConsoleApplication.php b/src/SPC/ConsoleApplication.php index d9107781..73477b11 100644 --- a/src/SPC/ConsoleApplication.php +++ b/src/SPC/ConsoleApplication.php @@ -16,7 +16,7 @@ use Symfony\Component\Console\Command\ListCommand; */ class ConsoleApplication extends Application { - public const VERSION = '2.0-beta1'; + public const VERSION = '2.0-beta2'; /** * @throws \ReflectionException diff --git a/src/SPC/command/BaseCommand.php b/src/SPC/command/BaseCommand.php index 47671b6a..c045ccca 100644 --- a/src/SPC/command/BaseCommand.php +++ b/src/SPC/command/BaseCommand.php @@ -13,6 +13,18 @@ use ZM\Logger\ConsoleLogger; abstract class BaseCommand extends Command { + /** + * 输入 + */ + protected InputInterface $input; + + /** + * 输出 + * + * 一般来说同样会是 ConsoleOutputInterface + */ + protected OutputInterface $output; + public function __construct(string $name = null) { parent::__construct($name); @@ -56,4 +68,44 @@ abstract class BaseCommand extends Command "; } } + + abstract public function handle(): int; + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $this->input = $input; + $this->output = $output; + if ($this->shouldExecute()) { + try { + return $this->handle(); + } catch (\Throwable $e) { + $msg = explode("\n", $e->getMessage()); + foreach ($msg as $v) { + logger()->error($v); + } + return self::FAILURE; + } + } + return self::SUCCESS; + } + + protected function getOption(string $name): mixed + { + return $this->input->getOption($name); + } + + protected function getArgument(string $name): mixed + { + return $this->input->getArgument($name); + } + + /** + * 是否应该执行 + * + * @return bool 返回 true 以继续执行,返回 false 以中断执行 + */ + protected function shouldExecute(): bool + { + return true; + } } diff --git a/src/SPC/command/BuildCliCommand.php b/src/SPC/command/BuildCliCommand.php index 3bc182d0..34b0ea44 100644 --- a/src/SPC/command/BuildCliCommand.php +++ b/src/SPC/command/BuildCliCommand.php @@ -9,38 +9,34 @@ use SPC\exception\ExceptionHandler; use SPC\exception\WrongUsageException; use SPC\util\DependencyUtil; use SPC\util\LicenseDumper; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -/** @noinspection PhpUnused */ +#[AsCommand('build', 'build CLI binary')] class BuildCliCommand extends BuildCommand { - protected static $defaultName = 'build'; - public function configure() { - $this->setDescription('Build CLI binary'); $this->addArgument('extensions', InputArgument::REQUIRED, 'The extensions will be compiled, comma separated'); $this->addOption('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', ''); $this->addOption('build-micro', null, null, 'build micro only'); $this->addOption('build-all', null, null, 'build both cli and micro'); } - public function execute(InputInterface $input, OutputInterface $output): int + public function handle(): int { // 从参数中获取要编译的 libraries,并转换为数组 - $libraries = array_map('trim', array_filter(explode(',', $input->getOption('with-libs')))); + $libraries = array_map('trim', array_filter(explode(',', $this->getOption('with-libs')))); // 从参数中获取要编译的 extensions,并转换为数组 - $extensions = array_map('trim', array_filter(explode(',', $input->getArgument('extensions')))); + $extensions = array_map('trim', array_filter(explode(',', $this->getArgument('extensions')))); define('BUILD_ALL_STATIC', true); - if ($input->getOption('build-all')) { + if ($this->getOption('build-all')) { $rule = BUILD_MICRO_BOTH; logger()->info('Builder will build php-cli and phpmicro SAPI'); - } elseif ($input->getOption('build-micro')) { + } elseif ($this->getOption('build-micro')) { $rule = BUILD_MICRO_ONLY; logger()->info('Builder will build phpmicro SAPI'); } else { @@ -49,7 +45,7 @@ class BuildCliCommand extends BuildCommand } try { // 构建对象 - $builder = BuilderProvider::makeBuilderByInput($input); + $builder = BuilderProvider::makeBuilderByInput($this->input); // 根据提供的扩展列表获取依赖库列表并编译 [$extensions, $libraries, $not_included] = DependencyUtil::getExtLibsByDeps($extensions, $libraries); @@ -64,7 +60,7 @@ class BuildCliCommand extends BuildCommand // 执行扩展检测 $builder->proveExts($extensions); // 构建 - $builder->buildPHP($rule, $input->getOption('bloat')); + $builder->buildPHP($rule, $this->getOption('bloat')); // 统计时间 $time = round(microtime(true) - START_TIME, 3); logger()->info('Build complete, used ' . $time . ' s !'); @@ -86,7 +82,7 @@ class BuildCliCommand extends BuildCommand logger()->critical($e->getMessage()); return 1; } catch (\Throwable $e) { - if ($input->getOption('debug')) { + if ($this->getOption('debug')) { ExceptionHandler::getInstance()->handle($e); } else { logger()->critical('Build failed with ' . get_class($e) . ': ' . $e->getMessage()); diff --git a/src/SPC/command/BuildLibsCommand.php b/src/SPC/command/BuildLibsCommand.php index 78c1f8a9..d4a23a2a 100644 --- a/src/SPC/command/BuildLibsCommand.php +++ b/src/SPC/command/BuildLibsCommand.php @@ -6,20 +6,17 @@ namespace SPC\command; use SPC\builder\BuilderProvider; use SPC\exception\ExceptionHandler; -use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -/** @noinspection PhpUnused */ +#[AsCommand('build:libs', 'Build dependencies')] class BuildLibsCommand extends BuildCommand { - protected static $defaultName = 'build:libs'; - public function configure() { - $this->setDescription('Build dependencies'); $this->addArgument('libraries', InputArgument::REQUIRED, 'The libraries will be compiled, comma separated'); $this->addOption('clean', null, null, 'Clean old download cache and source before fetch'); $this->addOption('all', 'A', null, 'Build all libs that static-php-cli needed'); @@ -36,15 +33,14 @@ class BuildLibsCommand extends BuildCommand /** * @throws RuntimeException - * @throws FileSystemException */ - public function execute(InputInterface $input, OutputInterface $output): int + public function handle(): int { // 从参数中获取要编译的 libraries,并转换为数组 - $libraries = array_map('trim', array_filter(explode(',', $input->getArgument('libraries')))); + $libraries = array_map('trim', array_filter(explode(',', $this->getArgument('libraries')))); // 删除旧资源 - if ($input->getOption('clean')) { + if ($this->getOption('clean')) { logger()->warning('You are doing some operations that not recoverable: removing directories below'); logger()->warning(BUILD_ROOT_PATH); logger()->warning('I will remove these dir after you press [Enter] !'); @@ -59,7 +55,7 @@ class BuildLibsCommand extends BuildCommand try { // 构建对象 - $builder = BuilderProvider::makeBuilderByInput($input); + $builder = BuilderProvider::makeBuilderByInput($this->input); // 只编译 library 的情况下,标记 $builder->setLibsOnly(); // 编译和检查库完整 @@ -69,7 +65,7 @@ class BuildLibsCommand extends BuildCommand logger()->info('Build libs complete, used ' . $time . ' s !'); return 0; } catch (\Throwable $e) { - if ($input->getOption('debug')) { + if ($this->getOption('debug')) { ExceptionHandler::getInstance()->handle($e); } else { logger()->critical('Build failed with ' . get_class($e) . ': ' . $e->getMessage()); diff --git a/src/SPC/command/DeployCommand.php b/src/SPC/command/DeployCommand.php index 4e580151..dc97b035 100644 --- a/src/SPC/command/DeployCommand.php +++ b/src/SPC/command/DeployCommand.php @@ -7,32 +7,28 @@ namespace SPC\command; use CliHelper\Tools\ArgFixer; use CliHelper\Tools\DataProvider; use CliHelper\Tools\SeekableArrayIterator; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -/** @noinspection PhpUnused */ +#[AsCommand('deploy', 'Deploy static-php-cli self to an .phar application')] class DeployCommand extends BaseCommand { - protected static $defaultName = 'deploy'; - public function configure() { - $this->setDescription('Deploy static-php-cli self to an .phar application'); $this->addArgument('target', InputArgument::OPTIONAL, 'The file or directory to pack.'); $this->addOption('auto-phar-fix', null, InputOption::VALUE_NONE, 'Automatically fix ini option.'); $this->addOption('overwrite', 'W', InputOption::VALUE_NONE, 'Overwrite existing files.'); } - public function execute(InputInterface $input, OutputInterface $output): int + public function handle(): int { // 第一阶段流程:如果没有写path,将会提示输入要打包的path - $prompt = new ArgFixer($input, $output); + $prompt = new ArgFixer($this->input, $this->output); // 首先得确认是不是关闭了readonly模式 if (ini_get('phar.readonly') == 1) { - if ($input->getOption('auto-phar-fix')) { + if ($this->getOption('auto-phar-fix')) { $ask = true; } else { $ask = $prompt->requireBool('pack command needs "phar.readonly" = "Off" !' . PHP_EOL . 'If you want to automatically set it and continue, just Enter', true); @@ -41,12 +37,12 @@ class DeployCommand extends BaseCommand global $argv; $args = array_merge(['-d', 'phar.readonly=0'], $_SERVER['argv']); if (function_exists('pcntl_exec')) { - $output->writeln('Changing to phar.readonly=0 mode ...'); + $this->output->writeln('Changing to phar.readonly=0 mode ...'); if (pcntl_exec(PHP_BINARY, $args) === false) { throw new \PharException('切换到读写模式失败,请检查环境。'); } } else { - $output->writeln('Now running command in child process.'); + $this->output->writeln('Now running command in child process.'); passthru(PHP_BINARY . ' -d phar.readonly=0 ' . implode(' ', $argv), $retcode); exit($retcode); } @@ -61,9 +57,9 @@ class DeployCommand extends BaseCommand $phar_path = '/tmp/' . $phar_path; } if (file_exists($phar_path)) { - $ask = $input->getOption('overwrite') ? true : $prompt->requireBool('The file "' . $phar_path . '" already exists, do you want to overwrite it?' . PHP_EOL . 'If you want to, just Enter'); + $ask = $this->getOption('overwrite') ? true : $prompt->requireBool('The file "' . $phar_path . '" already exists, do you want to overwrite it?' . PHP_EOL . 'If you want to, just Enter'); if (!$ask) { - $output->writeln('User canceled.'); + $this->output->writeln('User canceled.'); return 1; } @unlink($phar_path); @@ -83,9 +79,9 @@ class DeployCommand extends BaseCommand $map[$v] = $path . '/' . $v; } - $output->writeln('Start packing files...'); + $this->output->writeln('Start packing files...'); try { - foreach ($this->progress($output)->iterate($map) as $file => $origin_file) { + foreach ($this->progress()->iterate($map) as $file => $origin_file) { $phar->addFromString($file, php_strip_whitespace($origin_file)); } // $phar->buildFromIterator(new SeekableArrayIterator($map, new ProgressBar($output))); @@ -100,30 +96,30 @@ class DeployCommand extends BaseCommand $stub = '.phar-entry.php'; $phar->setStub($phar->createDefaultStub($stub)); } catch (\Throwable $e) { - $output->writeln($e); + $this->output->writeln($e); return 1; } $phar->addFromString('.prod', 'true'); $phar->stopBuffering(); - $output->writeln(PHP_EOL . 'Done! Phar file is generated at "' . $phar_path . '".'); + $this->output->writeln(PHP_EOL . 'Done! Phar file is generated at "' . $phar_path . '".'); if (file_exists(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx')) { - $output->writeln('Detected you have already compiled micro binary, I will make executable now for you!'); + $this->output->writeln('Detected you have already compiled micro binary, I will make executable now for you!'); file_put_contents( pathinfo($phar_path, PATHINFO_DIRNAME) . '/spc', file_get_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx') . file_get_contents($phar_path) ); chmod(pathinfo($phar_path, PATHINFO_DIRNAME) . '/spc', 0755); - $output->writeln('Binary Executable: ' . pathinfo($phar_path, PATHINFO_DIRNAME) . '/spc'); + $this->output->writeln('Binary Executable: ' . pathinfo($phar_path, PATHINFO_DIRNAME) . '/spc'); } chmod($phar_path, 0755); - $output->writeln('Phar Executable: ' . $phar_path . ''); + $this->output->writeln('Phar Executable: ' . $phar_path . ''); return 0; } - private function progress(OutputInterface $output, int $max = 0): ProgressBar + private function progress(int $max = 0): ProgressBar { - $progress = new ProgressBar($output, $max); + $progress = new ProgressBar($this->output, $max); $progress->setBarCharacter('⚬'); $progress->setEmptyBarCharacter('⚬'); $progress->setProgressCharacter('➤'); diff --git a/src/SPC/command/DoctorCommand.php b/src/SPC/command/DoctorCommand.php new file mode 100644 index 00000000..6a4ea752 --- /dev/null +++ b/src/SPC/command/DoctorCommand.php @@ -0,0 +1,17 @@ +error('Not implemented'); + return 1; + } +} diff --git a/src/SPC/command/DumpLicenseCommand.php b/src/SPC/command/DumpLicenseCommand.php index 93df9a2c..00f6f3fd 100644 --- a/src/SPC/command/DumpLicenseCommand.php +++ b/src/SPC/command/DumpLicenseCommand.php @@ -9,20 +9,17 @@ use SPC\exception\RuntimeException; use SPC\exception\WrongUsageException; use SPC\util\DependencyUtil; use SPC\util\LicenseDumper; -use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; /** * 修改 config 后对其 kv 进行排序的操作 */ +#[AsCommand('dump-license', 'Dump licenses for required libraries')] class DumpLicenseCommand extends BaseCommand { - protected static $defaultName = 'dump-license'; - public function configure() { - $this->setDescription('Dump licenses for required libraries'); $this->addOption('by-extensions', null, InputOption::VALUE_REQUIRED, 'Dump by extensions and related libraries', null); $this->addOption('without-php', null, InputOption::VALUE_NONE, 'Dump without php-src'); $this->addOption('by-libs', null, InputOption::VALUE_REQUIRED, 'Dump by libraries', null); @@ -35,42 +32,42 @@ class DumpLicenseCommand extends BaseCommand * @throws FileSystemException * @throws RuntimeException */ - public function execute(InputInterface $input, OutputInterface $output): int + public function handle(): int { $dumper = new LicenseDumper(); - if ($input->getOption('by-extensions') !== null) { + if ($this->getOption('by-extensions') !== null) { // 从参数中获取要编译的 extensions,并转换为数组 - $extensions = array_map('trim', array_filter(explode(',', $input->getOption('by-extensions')))); + $extensions = array_map('trim', array_filter(explode(',', $this->getOption('by-extensions')))); // 根据提供的扩展列表获取依赖库列表并编译 [$extensions, $libraries, $not_included] = DependencyUtil::getExtLibsByDeps($extensions); $dumper->addExts($extensions); $dumper->addLibs($libraries); - if (!$input->getOption('without-php')) { + if (!$this->getOption('without-php')) { $dumper->addSources(['php-src']); } - $dumper->dump($input->getOption('dump-dir')); - $output->writeln('Dump license with extensions: ' . implode(', ', $extensions)); - $output->writeln('Dump license with libraries: ' . implode(', ', $libraries)); - $output->writeln('Dump license with' . ($input->getOption('without-php') ? 'out' : '') . ' php-src'); - $output->writeln('Dump target dir: ' . $input->getOption('dump-dir')); + $dumper->dump($this->getOption('dump-dir')); + $this->output->writeln('Dump license with extensions: ' . implode(', ', $extensions)); + $this->output->writeln('Dump license with libraries: ' . implode(', ', $libraries)); + $this->output->writeln('Dump license with' . ($this->getOption('without-php') ? 'out' : '') . ' php-src'); + $this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir')); return 0; } - if ($input->getOption('by-libs') !== null) { - $libraries = array_map('trim', array_filter(explode(',', $input->getOption('by-libs')))); + if ($this->getOption('by-libs') !== null) { + $libraries = array_map('trim', array_filter(explode(',', $this->getOption('by-libs')))); $libraries = DependencyUtil::getLibsByDeps($libraries); $dumper->addLibs($libraries); - $dumper->dump($input->getOption('dump-dir')); - $output->writeln('Dump target dir: ' . $input->getOption('dump-dir')); + $dumper->dump($this->getOption('dump-dir')); + $this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir')); return 0; } - if ($input->getOption('by-sources') !== null) { - $sources = array_map('trim', array_filter(explode(',', $input->getOption('by-sources')))); + if ($this->getOption('by-sources') !== null) { + $sources = array_map('trim', array_filter(explode(',', $this->getOption('by-sources')))); $dumper->addSources($sources); - $dumper->dump($input->getOption('dump-dir')); - $output->writeln('Dump target dir: ' . $input->getOption('dump-dir')); + $dumper->dump($this->getOption('dump-dir')); + $this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir')); return 0; } - $output->writeln('You must use one of "--by-extensions=", "--by-libs=", "--by-sources=" to dump'); + $this->output->writeln('You must use one of "--by-extensions=", "--by-libs=", "--by-sources=" to dump'); return 1; } } diff --git a/src/SPC/command/FetchSourceCommand.php b/src/SPC/command/FetchSourceCommand.php index 131efa71..a0f4adad 100644 --- a/src/SPC/command/FetchSourceCommand.php +++ b/src/SPC/command/FetchSourceCommand.php @@ -13,23 +13,20 @@ use SPC\store\Config; use SPC\store\Downloader; use SPC\util\Patcher; use SPC\util\Util; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @noinspection PhpUnused */ +#[AsCommand('fetch', 'Fetch required sources')] class FetchSourceCommand extends BaseCommand { - protected static $defaultName = 'fetch'; - protected string $php_major_ver; - protected InputInterface $input; - public function configure() { - $this->setDescription('Fetch required sources'); $this->addArgument('extensions', InputArgument::REQUIRED, 'The extensions will be compiled, comma separated'); $this->addArgument('libraries', InputArgument::REQUIRED, 'The libraries will be compiled, comma separated'); $this->addOption('hash', null, null, 'Hash only'); @@ -50,12 +47,11 @@ class FetchSourceCommand extends BaseCommand parent::initialize($input, $output); } - public function execute(InputInterface $input, OutputInterface $output): int + public function handle(): int { - $this->input = $input; try { // 匹配版本 - $ver = $this->php_major_ver = $input->getOption('with-php') ?? '8.1'; + $ver = $this->php_major_ver = $this->getOption('with-php') ?? '8.1'; define('SPC_BUILD_PHP_VERSION', $ver); preg_match('/^\d+\.\d+$/', $ver, $matches); if (!$matches) { @@ -64,7 +60,7 @@ class FetchSourceCommand extends BaseCommand } // 删除旧资源 - if ($input->getOption('clean')) { + if ($this->getOption('clean')) { logger()->warning('You are doing some operations that not recoverable: removing directories below'); logger()->warning(SOURCE_PATH); logger()->warning(DOWNLOAD_PATH); @@ -85,7 +81,7 @@ class FetchSourceCommand extends BaseCommand } // 使用浅克隆可以减少调用 git 命令下载资源时的存储空间占用 - if ($input->getOption('shallow-clone')) { + if ($this->getOption('shallow-clone')) { define('GIT_SHALLOW_CLONE', true); } @@ -93,7 +89,7 @@ class FetchSourceCommand extends BaseCommand Config::getSource('openssl'); // 是否启用openssl11 - if ($input->getOption('with-openssl11')) { + if ($this->getOption('with-openssl11')) { logger()->debug('Using openssl 1.1'); // 手动修改配置 Config::$source['openssl']['regex'] = '/href="(?openssl-(?1.[^"]+)\.tar\.gz)\"/'; @@ -103,7 +99,7 @@ class FetchSourceCommand extends BaseCommand $chosen_sources = ['micro']; // 从参数中获取要编译的 libraries,并转换为数组 - $libraries = array_map('trim', array_filter(explode(',', $input->getArgument('libraries')))); + $libraries = array_map('trim', array_filter(explode(',', $this->getArgument('libraries')))); if ($libraries) { foreach ($libraries as $lib) { // 从 lib 的 config 中找到对应 source 资源名称,组成一个 lib 的 source 列表 @@ -115,7 +111,7 @@ class FetchSourceCommand extends BaseCommand } // 从参数中获取要编译的 extensions,并转换为数组 - $extensions = array_map('trim', array_filter(explode(',', $input->getArgument('extensions')))); + $extensions = array_map('trim', array_filter(explode(',', $this->getArgument('extensions')))); if ($extensions) { foreach ($extensions as $lib) { if (Config::getExt($lib, 'type') !== 'builtin') { @@ -133,9 +129,9 @@ class FetchSourceCommand extends BaseCommand $chosen_sources = array_unique($chosen_sources); // 是否只hash,不下载资源 - if ($input->getOption('hash')) { + if ($this->getOption('hash')) { $hash = $this->doHash($chosen_sources); - $output->writeln($hash); + $this->output->writeln($hash); return 0; } @@ -167,7 +163,7 @@ class FetchSourceCommand extends BaseCommand return 0; } catch (\Throwable $e) { // 不开 debug 模式就不要再显示复杂的调试栈信息了 - if ($input->getOption('debug')) { + if ($this->getOption('debug')) { ExceptionHandler::getInstance()->handle($e); } else { logger()->emergency($e->getMessage() . ', previous message: ' . $e->getPrevious()?->getMessage()); diff --git a/src/SPC/command/ListExtCommand.php b/src/SPC/command/ListExtCommand.php index 408c944e..4a5d8741 100644 --- a/src/SPC/command/ListExtCommand.php +++ b/src/SPC/command/ListExtCommand.php @@ -5,22 +5,19 @@ declare(strict_types=1); namespace SPC\command; use SPC\builder\traits\NoMotdTrait; +use SPC\exception\FileSystemException; use SPC\store\Config; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Attribute\AsCommand; +#[AsCommand('list-ext', 'List supported extensions')] class ListExtCommand extends BaseCommand { use NoMotdTrait; - protected static $defaultName = 'list-ext'; - - public function configure() - { - $this->setDescription('List supported extensions'); - } - - public function execute(InputInterface $input, OutputInterface $output) + /** + * @throws FileSystemException + */ + public function handle(): int { foreach (Config::getExts() as $ext => $meta) { echo $ext . PHP_EOL; diff --git a/src/SPC/command/SortConfigCommand.php b/src/SPC/command/SortConfigCommand.php index 153a64c4..8ca09801 100644 --- a/src/SPC/command/SortConfigCommand.php +++ b/src/SPC/command/SortConfigCommand.php @@ -8,20 +8,17 @@ use SPC\exception\FileSystemException; use SPC\exception\ValidationException; use SPC\store\FileSystem; use SPC\util\ConfigValidator; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; /** * 修改 config 后对其 kv 进行排序的操作 */ +#[AsCommand('sort-config', 'After config edited, sort it by alphabet')] class SortConfigCommand extends BaseCommand { - protected static $defaultName = 'sort-config'; - public function configure() { - $this->setDescription('After config edited, sort it by alphabet'); $this->addArgument('config-name', InputArgument::REQUIRED, 'Your config to be sorted, you can sort "lib", "source" and "ext".'); } @@ -29,9 +26,9 @@ class SortConfigCommand extends BaseCommand * @throws ValidationException * @throws FileSystemException */ - public function execute(InputInterface $input, OutputInterface $output): int + public function handle(): int { - switch ($name = $input->getArgument('config-name')) { + switch ($name = $this->getArgument('config-name')) { case 'lib': $file = json_decode(FileSystem::readFile(ROOT_DIR . '/config/lib.json'), true); ConfigValidator::validateLibs($file); @@ -51,10 +48,10 @@ class SortConfigCommand extends BaseCommand file_put_contents(ROOT_DIR . '/config/ext.json', json_encode($file, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); break; default: - $output->writeln("invalid config name: {$name}"); + $this->output->writeln("invalid config name: {$name}"); return 1; } - $output->writeln('sort success'); + $this->output->writeln('sort success'); return 0; } }