first commit

This commit is contained in:
2024-07-15 12:33:27 +02:00
commit ce50ae282b
22084 changed files with 2623791 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
<?php
namespace Consolidation\Log;
use Psr\Log\LogLevel;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\OutputStyle;
/**
* Styles log output based on format mappings provided in the constructor.
*
* Override for greater control.
*/
class LogOutputStyler extends UnstyledLogOutputStyler
{
const TASK_STYLE_INFO = 'fg=white;bg=cyan;options=bold';
const TASK_STYLE_WARNING = 'fg=black;bg=yellow;options=bold;';
const TASK_STYLE_ERROR = 'fg=white;bg=red;options=bold';
protected $defaultStyles = [
'*' => LogLevel::INFO,
];
protected $labelStyles = [
LogLevel::EMERGENCY => self::TASK_STYLE_ERROR,
LogLevel::ALERT => self::TASK_STYLE_ERROR,
LogLevel::CRITICAL => self::TASK_STYLE_ERROR,
LogLevel::ERROR => self::TASK_STYLE_ERROR,
LogLevel::WARNING => self::TASK_STYLE_WARNING,
LogLevel::NOTICE => self::TASK_STYLE_INFO,
LogLevel::INFO => self::TASK_STYLE_INFO,
LogLevel::DEBUG => self::TASK_STYLE_INFO,
];
protected $messageStyles = [
LogLevel::EMERGENCY => self::TASK_STYLE_ERROR,
LogLevel::ALERT => self::TASK_STYLE_ERROR,
LogLevel::CRITICAL => self::TASK_STYLE_ERROR,
LogLevel::ERROR => self::TASK_STYLE_ERROR,
LogLevel::WARNING => '',
LogLevel::NOTICE => '',
LogLevel::INFO => '',
LogLevel::DEBUG => '',
];
public function __construct($labelStyles = [], $messageStyles = [])
{
$this->labelStyles = $labelStyles + $this->labelStyles;
$this->messageStyles = $messageStyles + $this->messageStyles;
}
/**
* {@inheritdoc}
*/
public function defaultStyles()
{
return $this->defaultStyles;
}
/**
* {@inheritdoc}
*/
public function style($context)
{
$context += ['_style' => []];
$context['_style'] += $this->defaultStyles();
foreach ($context as $key => $value) {
$styleKey = $key;
if (!isset($context['_style'][$styleKey])) {
$styleKey = '*';
}
if (is_string($value) && isset($context['_style'][$styleKey])) {
$style = $context['_style'][$styleKey];
$context[$key] = $this->wrapFormatString($context[$key], $style);
}
}
return $context;
}
/**
* Wrap a string in a format element.
*/
protected function wrapFormatString($string, $style)
{
if ($style) {
return "<{$style}>$string</>";
}
return $string;
}
/**
* Look up the label and message styles for the specified log level,
* and use the log level as the label for the log message.
*/
protected function formatMessageByLevel($level, $message, $context)
{
$label = $level;
return $this->formatMessage($label, $message, $context, $this->labelStyles[$level], $this->messageStyles[$level]);
}
/**
* Apply styling with the provided label and message styles.
*/
protected function formatMessage($label, $message, $context, $labelStyle, $messageStyle = '')
{
if (!empty($messageStyle)) {
$message = $this->wrapFormatString(" $message ", $messageStyle);
}
if (!empty($label)) {
$message = ' ' . $this->wrapFormatString("[$label]", $labelStyle) . ' ' . $message;
}
return $message;
}
}

View File

@@ -0,0 +1,100 @@
<?php
namespace Consolidation\Log;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Allow a log message to by styled.
*
* Styling happens in two phases:
*
* 1. Prior to message interpolation, context variables are styled
* via the 'style()' method, using styles provided in the context
* under the '_style' key, and also using styles provided by the
* 'defaultStyles()' method.
*
* @see Symfony\Component\Console\Logger\ConsoleLogger::interpolate()
*
* 2. After message interpolation, an appropriate method based on the
* log level will be called. StyledConsoleLogger::$formatFunctionMap
* is used to map the LogLevel to a LogOutputStylerInterface method to call.
*
* It is possible to select the exact class to use as the log styler
* in the constructor of StyledConsoleLogger, and the mapping from
* LogLevel to format function can also be extended. It is possible to
* add new format methods not defined here, if desired, so long as
* any method named in the format function map is implemented by the
* selected log styler class.
*/
interface LogOutputStylerInterface
{
const STYLE_CONTEXT_KEY = '_style';
/**
* Return an array of default styles to use in an application.
* The key of the style is the variable name that the style
* should be applied to (or '*' to match all variables that have
* no specific style set), and the value is the contents of the
* Symfony style tag to wrap around the variable value.
*
* Example:
* message: 'Running {command}'
* context: ['command' => 'pwd']
* default styles: ['*' => 'info']
* result: 'Running <info>pwd</>'
*/
public function defaultStyles();
/**
* Apply styles specified in the STYLE_CONTEXT_KEY context variable to
* the other named variables stored in the context. The styles from
* the context are unioned with the default styles.
*/
public function style($context);
/**
* Create a wrapper object for the output stream. If this styler
* does not require an output wrapper, it should just return
* its $output parameter.
*/
public function createOutputWrapper(OutputInterface $output);
/**
* Print an ordinary log message, usually unstyled.
*/
public function log($output, $level, $message, $context);
/**
* Print an error message. Used when log level is:
* - LogLevel::EMERGENCY
* - LogLevel::ALERT
* - LogLevel::CRITICAL
* - LogLevel::ERROR
*/
public function error($output, $level, $message, $context);
/**
* Print a warning message. Used when log level is:
* - LogLevel::WARNING
*/
public function warning($output, $level, $message, $context);
/**
* Print a note. Similar to 'text', but may contain additional
* styling (e.g. the task name). Used when log level is:
* - LogLevel::NOTICE
* - LogLevel::INFO
* - LogLevel::DEBUG
*
* IMPORTANT: Symfony loggers only display LogLevel::NOTICE when the
* the verbosity level is VERBOSITY_VERBOSE, unless overridden in the
* constructor. Robo\Common\Logger emits LogLevel::NOTICE at
* VERBOSITY_NORMAL so that these messages will always be displayed.
*/
public function note($output, $level, $message, $context);
/**
* Print an error message. Not used by default by StyledConsoleLogger.
*/
public function caution($output, $level, $message, $context);
}

261
vendor/consolidation/log/src/Logger.php vendored Normal file
View File

@@ -0,0 +1,261 @@
<?php
namespace Consolidation\Log;
use Psr\Log\AbstractLogger;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Input\StringInput;
/**
* Replacement for Symfony\Component\Console\Logger\ConsoleLogger.
* Each of the different log level messages are routed through the
* corresponding SymfonyStyle formatting method. Log messages are
* always sent to stderr if the provided output object implements
* ConsoleOutputInterface.
*
* Note that this class could extend ConsoleLogger if some methods
* of that class were declared 'protected' instead of 'private'.
*
* @author Greg Anderson <greg.1.anderson@greenknowe.org>
*/
class Logger extends AbstractLogger implements StylableLoggerInterface, SettableLogOutputStreamInterface
{
/**
* @var OutputInterface
*/
protected $output;
/**
* @var OutputInterface
*/
protected $error;
/**
* @var LogOutputStylerInterface
*/
protected $outputStyler;
/**
* @var OutputInterface|SymfonyStyle|other
*/
protected $outputStreamWrapper;
protected $errorStreamWrapper;
protected $formatFunctionMap = [
LogLevel::EMERGENCY => 'error',
LogLevel::ALERT => 'error',
LogLevel::CRITICAL => 'error',
LogLevel::ERROR => 'error',
LogLevel::WARNING => 'warning',
LogLevel::NOTICE => 'note',
LogLevel::INFO => 'note',
LogLevel::DEBUG => 'note',
];
/**
* @param OutputInterface $output
* @param array $verbosityLevelMap
* @param array $formatLevelMap
* @param array $formatFunctionMap
*/
public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array(), array $formatFunctionMap = array())
{
$this->output = $output;
$this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
$this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
$this->formatFunctionMap = $formatFunctionMap + $this->formatFunctionMap;
}
public function setLogOutputStyler(LogOutputStylerInterface $outputStyler, array $formatFunctionMap = array())
{
$this->outputStyler = $outputStyler;
$this->formatFunctionMap = $formatFunctionMap + $this->formatFunctionMap;
$this->outputStreamWrapper = null;
$this->errorStreamWrapper = null;
}
public function getLogOutputStyler()
{
if (!isset($this->outputStyler)) {
$this->outputStyler = new SymfonyLogOutputStyler();
}
return $this->outputStyler;
}
protected function getOutputStream()
{
return $this->output;
}
protected function getErrorStream()
{
if (!isset($this->error)) {
$output = $this->getOutputStream();
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
}
$this->error = $output;
}
return $this->error;
}
public function setOutputStream($output)
{
$this->output = $output;
$this->outputStreamWrapper = null;
}
public function setErrorStream($error)
{
$this->error = $error;
$this->errorStreamWrapper = null;
}
protected function getOutputStreamWrapper()
{
if (!isset($this->outputStreamWrapper)) {
$this->outputStreamWrapper = $this->getLogOutputStyler()->createOutputWrapper($this->getOutputStream());
}
return $this->outputStreamWrapper;
}
protected function getErrorStreamWrapper()
{
if (!isset($this->errorStreamWrapper)) {
$this->errorStreamWrapper = $this->getLogOutputStyler()->createOutputWrapper($this->getErrorStream());
}
return $this->errorStreamWrapper;
}
protected function getOutputStreamForLogLevel($level)
{
// Write to the error output if necessary and available.
// Usually, loggers that log to a terminal should send
// all log messages to stderr.
if (array_key_exists($level, $this->formatLevelMap) && ($this->formatLevelMap[$level] !== self::ERROR)) {
return $this->getOutputStreamWrapper();
}
return $this->getErrorStreamWrapper();
}
/**
* {@inheritdoc}
*/
public function log($level, string|\Stringable $message, array $context = []): void
{
// We use the '_level' context variable to allow log messages
// to be logged at one level (e.g. NOTICE) and formatted at another
// level (e.g. SUCCESS). This helps in instances where we want
// to style log messages at a custom log level that might not
// be available in all loggers. If the logger does not recognize
// the log level, then it is treated like the original log level.
// SUCCESS is no longer a supported log level
if (array_key_exists('_level', $context) && array_key_exists($context['_level'], $this->verbosityLevelMap)) {
$level = $context['_level'];
}
// It is a runtime error if someone logs at a log level that
// we do not recognize.
if (!isset($this->verbosityLevelMap[$level])) {
throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
}
// Write to the error output if necessary and available.
// Usually, loggers that log to a terminal should send
// all log messages to stderr.
$outputStreamWrapper = $this->getOutputStreamForLogLevel($level);
// Ignore messages that are not at the right verbosity level
if ($this->getOutputStream()->getVerbosity() >= $this->verbosityLevelMap[$level]) {
$this->doLog($outputStreamWrapper, $level, $message, $context);
}
}
/**
* Interpolate and style the message, and then send it to the log.
*/
protected function doLog($outputStreamWrapper, $level, $message, $context)
{
$formatFunction = 'log';
if (array_key_exists($level, $this->formatFunctionMap)) {
$formatFunction = $this->formatFunctionMap[$level];
}
$interpolated = $this->interpolate(
$message,
$this->getLogOutputStyler()->style($context)
);
$this->getLogOutputStyler()->$formatFunction(
$outputStreamWrapper,
$level,
$interpolated,
$context
);
}
// The functions below could be eliminated if made `protected` intead
// of `private` in ConsoleLogger
const INFO = 'info';
const ERROR = 'error';
/**
* @var OutputInterface
*/
//private $output;
/**
* @var array
*/
private $verbosityLevelMap = [
LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
];
/**
* @var array
*
* Send all log messages to stderr. Symfony should have the same default.
* See: https://en.wikipedia.org/wiki/Standard_streams
* "Standard error was added to Unix after several wasted phototypesetting runs ended with error messages being typeset instead of displayed on the user's terminal."
*/
private $formatLevelMap = [
LogLevel::EMERGENCY => self::ERROR,
LogLevel::ALERT => self::ERROR,
LogLevel::CRITICAL => self::ERROR,
LogLevel::ERROR => self::ERROR,
LogLevel::WARNING => self::ERROR,
LogLevel::NOTICE => self::ERROR,
LogLevel::INFO => self::ERROR,
LogLevel::DEBUG => self::ERROR,
];
/**
* Interpolates context values into the message placeholders.
*
* @author PHP Framework Interoperability Group
*
* @param string $message
* @param array $context
*
* @return string
*/
private function interpolate($message, array $context)
{
// build a replacement array with braces around the context keys
$replace = array();
foreach ($context as $key => $val) {
if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
$replace[sprintf('{%s}', $key)] = $val;
}
}
// interpolate replacement values into the message and return
return strtr($message, $replace);
}
}

View File

@@ -0,0 +1,168 @@
<?php
namespace Consolidation\Log;
use Psr\Log\AbstractLogger;
use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel;
use Symfony\Component\Console\Output\OutputInterface;
/**
* LoggerManager is a PSR-3 logger that can delegate
* log messages to other loggers. This is ideal if
* you need to inject a logger into various objects
* in your application, but need to change the way that
* the application logs later.
*
* @author Greg Anderson <greg.1.anderson@greenknowe.org>
*/
class LoggerManager extends AbstractLogger implements StylableLoggerInterface, SettableLogOutputStreamInterface
{
/** @var LoggerInterface[] */
protected $loggers = [];
/** @var LoggerInterface */
protected $fallbackLogger = null;
/** @var LogOutputStylerInterface */
protected $outputStyler;
/** @var array */
protected $formatFunctionMap = [];
/** @var OutputInterface */
protected $outputStream;
/** @var OutputInterface */
protected $errorStream;
/**
* reset removes all loggers from the manager.
*/
public function reset()
{
$this->loggers = [];
return $this;
}
/**
* setLogOutputStyler will remember a style that
* should be applied to every stylable logger
* added to this manager.
*/
public function setLogOutputStyler(LogOutputStylerInterface $outputStyler, array $formatFunctionMap = array())
{
$this->outputStyler = $outputStyler;
$this->formatFunctionMap = $this->formatFunctionMap;
foreach ($this->getLoggers() as $logger) {
if ($logger instanceof StylableLoggerInterface) {
$logger->setLogOutputStyler($this->outputStyler, $this->formatFunctionMap);
}
}
}
/**
* setOutputStream will remember an output stream that should be
* applied to every logger added to this manager.
*/
public function setOutputStream($output)
{
$this->outputStream = $output;
foreach ($this->getLoggers() as $logger) {
if ($logger instanceof SettableLogOutputStreamInterface) {
$logger->setOutputStream($this->outputStream);
}
}
}
/**
* setErrorStream will remember an error stream that should be
* applied to every logger added to this manager.
*/
public function setErrorStream($error)
{
$this->errorStream = $error;
foreach ($this->getLoggers() as $logger) {
if ($logger instanceof SettableLogOutputStreamInterface) {
$logger->setErrorStream($this->errorStream);
}
}
}
/**
* add adds a named logger to the manager,
* replacing any logger of the same name.
*
* @param string $name Name of logger to add
* @param LoggerInterface $logger Logger to send messages to
*/
public function add($name, LoggerInterface $logger)
{
// If this manager has been given a log style,
// and the logger being added accepts a log
// style, then copy our style to the logger
// being added.
if ($this->outputStyler && $logger instanceof StylableLoggerInterface) {
$logger->setLogOutputStyler($this->outputStyler, $this->formatFunctionMap);
}
if ($logger instanceof SettableLogOutputStreamInterface) {
if ($this->outputStream) {
$logger->setOutputStream($this->outputStream);
}
if ($this->errorStream) {
$logger->setErrorStream($this->errorStream);
}
}
$this->loggers[$name] = $logger;
return $this;
}
/**
* remove a named logger from the manager.
*
* @param string $name Name of the logger to remove.
*/
public function remove($name)
{
unset($this->loggers[$name]);
return $this;
}
/**
* fallbackLogger provides a logger that will
* be used only in instances where someone logs
* to the logger manager at a time when there
* are no other loggers registered. If there is
* no fallback logger, then the log messages
* are simply dropped.
*
* @param LoggerInterface $logger Logger to use as the fallback logger
*/
public function fallbackLogger(LoggerInterface $logger)
{
$this->fallbackLogger = $logger;
return $this;
}
/**
* {@inheritdoc}
*/
public function log($level, string|\Stringable $message, array $context = []): void
{
foreach ($this->getLoggers() as $logger) {
$logger->log($level, $message, $context);
}
}
/**
* Return either the list of registered loggers,
* or a single-element list containing only the
* fallback logger.
*/
protected function getLoggers()
{
if (!empty($this->loggers)) {
return $this->loggers;
}
if (isset($this->fallbackLogger)) {
return [ $this->fallbackLogger ];
}
return [];
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Consolidation\Log;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Interface that indicates that a logger's output / error streams
* are settable.
*
* @author Greg Anderson <greg.1.anderson@greenknowe.org>
*/
interface SettableLogOutputStreamInterface
{
/**
* @param OutputInterface $output
*/
public function setOutputStream($output);
/**
* @param OutputInterface $error
*/
public function setErrorStream($error);
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Consolidation\Log;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Input\StringInput;
/**
* StylableLoggerInterface indicates that a logger
* can receive a LogOutputStyler.
*
* @author Greg Anderson <greg.1.anderson@greenknowe.org>
*/
interface StylableLoggerInterface
{
public function setLogOutputStyler(LogOutputStylerInterface $outputStyler, array $formatFunctionMap = array());
}

View File

@@ -0,0 +1,65 @@
<?php
namespace Consolidation\Log;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Style log messages with Symfony\Component\Console\Style\SymfonyStyle.
* No context variable styling is done.
*
* This is the appropriate styler to use if your desire is to replace
* the use of SymfonyStyle with a Psr-3 logger without changing the
* appearance of your application's output.
*/
class SymfonyLogOutputStyler implements LogOutputStylerInterface
{
public function defaultStyles()
{
return [];
}
public function style($context)
{
return $context;
}
public function createOutputWrapper(OutputInterface $output)
{
// SymfonyStyle & c. contain both input and output functions,
// but we only need the output methods here. Create a stand-in
// input object to satisfy the SymfonyStyle constructor.
return new SymfonyStyle(new StringInput(''), $output);
}
public function log($symfonyStyle, $level, $message, $context)
{
$symfonyStyle->text($message);
}
public function success($symfonyStyle, $level, $message, $context)
{
$symfonyStyle->success($message);
}
public function error($symfonyStyle, $level, $message, $context)
{
$symfonyStyle->error($message);
}
public function warning($symfonyStyle, $level, $message, $context)
{
$symfonyStyle->warning($message);
}
public function note($symfonyStyle, $level, $message, $context)
{
$symfonyStyle->note($message);
}
public function caution($symfonyStyle, $level, $message, $context)
{
$symfonyStyle->caution($message);
}
}

View File

@@ -0,0 +1,89 @@
<?php
namespace Consolidation\Log;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\OutputStyle;
/**
* Base class that provides basic unstyled output.
*/
class UnstyledLogOutputStyler implements LogOutputStylerInterface
{
public function createOutputWrapper(OutputInterface $output)
{
return $output;
}
/**
* {@inheritdoc}
*/
public function defaultStyles()
{
return [];
}
/**
* {@inheritdoc}
*/
public function style($context)
{
return $context;
}
/**
* {@inheritdoc}
*/
protected function write($output, $message, $context)
{
$output->writeln($message);
}
/**
* {@inheritdoc}
*/
public function log($output, $level, $message, $context)
{
return $this->write($output, $this->formatMessageByLevel($level, $message, $context), $context);
}
/**
* {@inheritdoc}
*/
public function error($output, $level, $message, $context)
{
return $this->write($output, $this->formatMessageByLevel($level, $message, $context), $context);
}
/**
* {@inheritdoc}
*/
public function warning($output, $level, $message, $context)
{
return $this->write($output, $this->formatMessageByLevel($level, $message, $context), $context);
}
/**
* {@inheritdoc}
*/
public function note($output, $level, $message, $context)
{
return $this->write($output, $this->formatMessageByLevel($level, $message, $context), $context);
}
/**
* {@inheritdoc}
*/
public function caution($output, $level, $message, $context)
{
return $this->write($output, $this->formatMessageByLevel($level, $message, $context), $context);
}
/**
* Look up the label and message styles for the specified log level,
* and use the log level as the label for the log message.
*/
protected function formatMessageByLevel($level, $message, $context)
{
return " [$level] $message";
}
}