static-php-cli/src/SPC/command/BaseCommand.php

133 lines
4.5 KiB
PHP
Raw Normal View History

2023-03-15 20:40:49 +08:00
<?php
declare(strict_types=1);
namespace SPC\command;
use Laravel\Prompts\ConfirmPrompt;
use Laravel\Prompts\Prompt;
2023-03-15 20:40:49 +08:00
use Psr\Log\LogLevel;
use SPC\ConsoleApplication;
2023-04-30 12:42:19 +08:00
use SPC\exception\ExceptionHandler;
use SPC\exception\WrongUsageException;
2023-03-15 20:40:49 +08:00
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\QuestionHelper;
2023-03-15 20:40:49 +08:00
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
2023-03-15 20:40:49 +08:00
use ZM\Logger\ConsoleLogger;
abstract class BaseCommand extends Command
{
2023-04-23 20:54:51 +08:00
protected bool $no_motd = false;
2023-04-22 17:45:43 +08:00
protected InputInterface $input;
protected OutputInterface $output;
2023-03-15 20:40:49 +08:00
public function __construct(string $name = null)
{
parent::__construct($name);
$this->addOption('debug', null, null, 'Enable debug mode');
2023-04-23 20:54:51 +08:00
$this->addOption('no-motd', null, null, 'Disable motd');
2023-03-15 20:40:49 +08:00
}
public function initialize(InputInterface $input, OutputInterface $output): void
2023-03-15 20:40:49 +08:00
{
2023-04-23 20:54:51 +08:00
if ($input->getOption('no-motd')) {
$this->no_motd = true;
}
2023-03-15 20:40:49 +08:00
set_error_handler(static function ($error_no, $error_msg, $error_file, $error_line) {
$tips = [
E_WARNING => ['PHP Warning: ', 'warning'],
E_NOTICE => ['PHP Notice: ', 'notice'],
E_USER_ERROR => ['PHP Error: ', 'error'],
E_USER_WARNING => ['PHP Warning: ', 'warning'],
E_USER_NOTICE => ['PHP Notice: ', 'notice'],
E_STRICT => ['PHP Strict: ', 'notice'],
E_RECOVERABLE_ERROR => ['PHP Recoverable Error: ', 'error'],
E_DEPRECATED => ['PHP Deprecated: ', 'notice'],
E_USER_DEPRECATED => ['PHP User Deprecated: ', 'notice'],
];
$level_tip = $tips[$error_no] ?? ['PHP Unknown: ', 'error'];
$error = $level_tip[0] . $error_msg . ' in ' . $error_file . ' on ' . $error_line;
logger()->{$level_tip[1]}($error);
// 如果 return false 则错误会继续递交给 PHP 标准错误处理
return true;
}, E_ALL | E_STRICT);
if ($input->getOption('debug')) {
global $ob_logger;
$ob_logger = new ConsoleLogger(LogLevel::DEBUG);
define('DEBUG_MODE', true);
}
$version = ConsoleApplication::VERSION;
2023-04-23 20:54:51 +08:00
if (!$this->no_motd) {
2023-03-15 20:40:49 +08:00
echo " _ _ _ _
___| |_ __ _| |_(_) ___ _ __ | |__ _ __
/ __| __/ _` | __| |/ __|____| '_ \\| '_ \\| '_ \\
\\__ \\ || (_| | |_| | (_|_____| |_) | | | | |_) |
|___/\\__\\__,_|\\__|_|\\___| | .__/|_| |_| .__/ v{$version}
|_| |_|
";
}
}
2023-04-22 17:45:43 +08:00
/**
* @throws WrongUsageException
*/
2023-04-22 17:45:43 +08:00
abstract public function handle(): int;
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->input = $input;
$this->output = $output;
// windows fallback
Prompt::fallbackWhen(PHP_OS_FAMILY === 'Windows');
ConfirmPrompt::fallbackUsing(function (ConfirmPrompt $prompt) use ($input, $output) {
$helper = new QuestionHelper();
$case = $prompt->default ? ' [Y/n] ' : ' [y/N] ';
$question = new ConfirmationQuestion($prompt->label . $case, $prompt->default);
return $helper->ask($input, $output, $question);
});
2023-04-22 17:45:43 +08:00
if ($this->shouldExecute()) {
try {
return $this->handle();
2023-04-30 12:42:19 +08:00
} catch (WrongUsageException $e) {
2023-04-22 17:45:43 +08:00
$msg = explode("\n", $e->getMessage());
foreach ($msg as $v) {
logger()->error($v);
}
2023-08-06 10:43:20 +08:00
return static::FAILURE;
2023-04-30 12:42:19 +08:00
} catch (\Throwable $e) {
if ($this->getOption('debug')) {
ExceptionHandler::getInstance()->handle($e);
} else {
$msg = explode("\n", $e->getMessage());
foreach ($msg as $v) {
logger()->error($v);
}
}
2023-08-06 10:43:20 +08:00
return static::FAILURE;
2023-04-22 17:45:43 +08:00
}
}
2023-08-06 10:43:20 +08:00
return static::SUCCESS;
2023-04-22 17:45:43 +08:00
}
protected function getOption(string $name): mixed
{
return $this->input->getOption($name);
}
protected function getArgument(string $name): mixed
{
return $this->input->getArgument($name);
}
protected function shouldExecute(): bool
{
return true;
}
2023-03-15 20:40:49 +08:00
}