diff --git a/src/ZM/Command/Command.php b/src/ZM/Command/Command.php
index c685a5fd..77f77191 100644
--- a/src/ZM/Command/Command.php
+++ b/src/ZM/Command/Command.php
@@ -4,11 +4,11 @@ declare(strict_types=1);
namespace ZM\Command;
+use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-abstract class Command extends \Symfony\Component\Console\Command\Command
+abstract class Command extends \Symfony\Component\Console\Command\Command implements LoggerInterface
{
use CommandInteractTrait;
diff --git a/src/ZM/Command/CommandInteractTrait.php b/src/ZM/Command/CommandInteractTrait.php
index 7344a7ba..02ee99a5 100644
--- a/src/ZM/Command/CommandInteractTrait.php
+++ b/src/ZM/Command/CommandInteractTrait.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace ZM\Command;
+use Psr\Log\LogLevel;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface;
@@ -18,6 +19,119 @@ use ZM\Exception\ZMException;
*/
trait CommandInteractTrait
{
+ /**
+ * System is unusable.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ */
+ public function emergency($message, array $context = [])
+ {
+ $this->log(LogLevel::EMERGENCY, $message, $context);
+ }
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ */
+ public function alert($message, array $context = [])
+ {
+ $this->log(LogLevel::ALERT, $message, $context);
+ }
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ */
+ public function critical($message, array $context = [])
+ {
+ $this->log(LogLevel::CRITICAL, $message, $context);
+ }
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ */
+ public function error($message, array $context = [])
+ {
+ $this->log(LogLevel::ERROR, $message, $context);
+ }
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ */
+ public function warning($message, array $context = [])
+ {
+ $this->log(LogLevel::WARNING, $message, $context);
+ }
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ */
+ public function notice($message, array $context = [])
+ {
+ $this->log(LogLevel::NOTICE, $message, $context);
+ }
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ */
+ public function info($message, array $context = [])
+ {
+ $this->log(LogLevel::INFO, $message, $context);
+ }
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ */
+ public function debug($message, array $context = [])
+ {
+ $this->log(LogLevel::DEBUG, $message, $context);
+ }
+
+ public function log($level, $message, array $context = [])
+ {
+ $msg = match ($level) {
+ 'info' => "{$message}",
+ 'debug' => $this->input->getOption('verbose') ? "{$message}>" : '',
+ 'notice' => "{$message}>",
+ 'warning' => "{$message}",
+ 'error', 'critical', 'alert', 'emergency' => "{$message}",
+ default => '',
+ };
+ $msg = $this->interpolate($msg, $context);
+ if ($msg !== '') {
+ $this->output->write($msg, true);
+ }
+ }
+
/**
* 输出一段文本,默认样式
*
@@ -30,28 +144,6 @@ trait CommandInteractTrait
$this->output->write($message, $newline);
}
- /**
- * 输出文本,一般用于提示信息
- *
- * @param string $message 要输出的文本
- * @param bool $newline 是否在文本后换行
- */
- public function info(string $message, bool $newline = true): void
- {
- $this->write("{$message}", $newline);
- }
-
- /**
- * 输出文本,一般用于错误信息
- *
- * @param string $message 要输出的文本
- * @param bool $newline 是否在文本后换行
- */
- public function error(string $message, bool $newline = true): void
- {
- $this->write("{$message}", $newline);
- }
-
/**
* 输出文本,一般用于警告或附注信息
*
@@ -157,4 +249,45 @@ trait CommandInteractTrait
exit(self::SUCCESS);
}
}
+
+ private function interpolate(string $message, array $context = []): string
+ {
+ $replace = [];
+ foreach ($context as $key => $value) {
+ $replace['{' . $key . '}'] = $this->stringify($value);
+ }
+
+ return strtr($message, $replace);
+ }
+
+ private function stringify($item): string
+ {
+ switch (true) {
+ case is_callable($item):
+ if (is_array($item)) {
+ if (is_object($item[0])) {
+ return get_class($item[0]) . '@' . $item[1];
+ }
+ return $item[0] . '::' . $item[1];
+ }
+ return 'closure';
+ case is_string($item):
+ return $item;
+ case is_array($item):
+ return 'array' . (extension_loaded('json') ? json_encode($item, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_LINE_TERMINATORS) : '');
+ case is_object($item):
+ return get_class($item);
+ case is_resource($item):
+ return 'resource(' . get_resource_type($item) . ')';
+ case is_null($item):
+ return 'null';
+ case is_bool($item):
+ return $item ? 'true' : 'false';
+ case is_float($item):
+ case is_int($item):
+ return (string) $item;
+ default:
+ return 'unknown';
+ }
+ }
}
diff --git a/src/ZM/Framework.php b/src/ZM/Framework.php
index c4134b74..f61b63bf 100644
--- a/src/ZM/Framework.php
+++ b/src/ZM/Framework.php
@@ -47,7 +47,7 @@ class Framework
public const VERSION_ID = 697;
/** @var string 版本名称 */
- public const VERSION = '3.0.3';
+ public const VERSION = '3.1.0';
/** @var array 传入的参数 */
protected array $argv;