123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- <?php
- namespace League\CLImate;
- use Psr\Log\AbstractLogger;
- use Psr\Log\InvalidArgumentException;
- use Psr\Log\LogLevel;
- use function array_key_exists;
- use function is_array;
- use function str_replace;
- use function strpos;
- /**
- * A PSR-3 compatible logger that uses CLImate for output.
- */
- class Logger extends AbstractLogger
- {
- /**
- * @var array $levels Conversion of the level strings to their numeric representations.
- */
- private $levels = [
- LogLevel::EMERGENCY => 1,
- LogLevel::ALERT => 2,
- LogLevel::CRITICAL => 3,
- LogLevel::ERROR => 4,
- LogLevel::WARNING => 5,
- LogLevel::NOTICE => 6,
- LogLevel::INFO => 7,
- LogLevel::DEBUG => 8,
- ];
- /**
- * @var int $level Ignore logging attempts at a level less than this.
- */
- private $level;
- /**
- * @var CLImate $climate The underlying climate instance we are using for output.
- */
- private $climate;
- /**
- * Create a new Logger instance.
- *
- * @param string $level One of the LogLevel constants
- * @param CLImate $climate An existing CLImate instance to use for output
- */
- public function __construct($level = LogLevel::INFO, CLImate $climate = null)
- {
- $this->level = $this->convertLevel($level);
- if ($climate === null) {
- $climate = new CLImate();
- }
- $this->climate = $climate;
- # Define some default styles to use for the output
- $commands = [
- "emergency" => ["white", "bold", "background_red"],
- "alert" => ["white", "background_yellow"],
- "critical" => ["red", "bold"],
- "error" => ["red"],
- "warning" => "yellow",
- "notice" => "light_cyan",
- "info" => "green",
- "debug" => "dark_gray",
- ];
- # If any of the required styles are not defined then define them now
- foreach ($commands as $command => $style) {
- if (!$this->climate->style->get($command)) {
- $this->climate->style->addCommand($command, $style);
- }
- }
- }
- /**
- * Get a numeric log level for the passed parameter.
- *
- * @param string $level One of the LogLevel constants
- *
- * @return int
- */
- private function convertLevel($level)
- {
- # If this is one of the defined string log levels then return it's numeric value
- if (!array_key_exists($level, $this->levels)) {
- throw new InvalidArgumentException("Unknown log level: {$level}");
- }
- return $this->levels[$level];
- }
- /**
- * Get a new instance logging at a different level
- *
- * @param string $level One of the LogLevel constants
- *
- * @return Logger
- */
- public function withLogLevel($level)
- {
- $logger = clone $this;
- $logger->level = $this->convertLevel($level);
- return $logger;
- }
- /**
- * Log messages to a CLImate instance.
- *
- * @param string $level One of the LogLevel constants
- * @param string|object $message If an object is passed it must implement __toString()
- * @param array $context Placeholders to be substituted in the message
- *
- * @return void
- */
- public function log($level, $message, array $context = []): void
- {
- if ($this->convertLevel($level) > $this->level) {
- return;
- }
- # Handle objects implementing __toString
- $message = (string)$message;
- # Handle any placeholders in the $context array
- foreach ($context as $key => $val) {
- $placeholder = "{" . $key . "}";
- # If this context key is used as a placeholder, then replace it, and remove it from the $context array
- if (strpos($message, $placeholder) !== false) {
- $val = (string)$val;
- $message = str_replace($placeholder, $val, $message);
- unset($context[$key]);
- }
- }
- # Send the message to the climate instance
- $this->climate->{$level}($message);
- # Append any context information not used as placeholders
- $this->outputRecursiveContext($level, $context, 1);
- }
- /**
- * Handle recursive arrays in the logging context.
- *
- * @param string $level One of the LogLevel constants
- * @param array $context The array of context to output
- * @param int $indent The current level of indentation to be used
- *
- * @return void
- */
- private function outputRecursiveContext($level, array $context, $indent)
- {
- foreach ($context as $key => $val) {
- $this->climate->tab($indent);
- $this->climate->{$level}()->inline("{$key}: ");
- if (is_array($val)) {
- $this->climate->{$level}("[");
- $this->outputRecursiveContext($level, $val, $indent + 1);
- $this->climate->tab($indent)->{$level}("]");
- } else {
- $this->climate->{$level}((string)$val);
- }
- }
- }
- }
|