plugin updates

This commit is contained in:
Tony Volpe
2024-07-18 20:40:50 +00:00
parent 1cbeccbe26
commit f13cad0e36
314 changed files with 45107 additions and 30963 deletions

View File

@@ -1,4 +1,4 @@
Copyright (c) 2011-2016 Jordi Boggiano
Copyright (c) 2011-2020 Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -0,0 +1,42 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Attribute;
/**
* A reusable attribute to help configure a class or a method as a processor.
*
* Using it offers no guarantee: it needs to be leveraged by a Monolog third-party consumer.
*
* Using it with the Monolog library only has no effect at all: processors should still be turned into a callable if
* needed and manually pushed to the loggers and to the processable handlers.
*/
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class AsMonologProcessor
{
/** @var string|null */
public $channel = null;
/** @var string|null */
public $handler = null;
/** @var string|null */
public $method = null;
/**
* @param string|null $channel The logging channel the processor should be pushed to.
* @param string|null $handler The handler the processor should be pushed to.
* @param string|null $method The method that processes the records (if the attribute is used at the class level).
*/
public function __construct(?string $channel = null, ?string $handler = null, ?string $method = null)
{
$this->channel = $channel;
$this->handler = $handler;
$this->method = $method;
}
}

View File

@@ -0,0 +1,45 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog;
use DateTimeZone;
/**
* Overrides default json encoding of date time objects
*
* @author Menno Holtkamp
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable
{
/**
* @var bool
*/
private $useMicroseconds;
public function __construct(bool $useMicroseconds, ?\DateTimeZone $timezone = null)
{
$this->useMicroseconds = $useMicroseconds;
// if you like to use a custom time to pass to Logger::addRecord directly,
// call modify() or setTimestamp() on this instance to change the date after creating it
parent::__construct('now', $timezone);
}
public function jsonSerialize() : string
{
if ($this->useMicroseconds) {
return $this->format('Y-m-d\\TH:i:s.uP');
}
return $this->format('Y-m-d\\TH:i:sP');
}
public function __toString() : string
{
return $this->jsonSerialize();
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -12,7 +13,6 @@ namespace WPMailSMTP\Vendor\Monolog;
use WPMailSMTP\Vendor\Psr\Log\LoggerInterface;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
use WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler;
/**
* Monolog error handler
*
@@ -24,17 +24,28 @@ use WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler;
*/
class ErrorHandler
{
/** @var LoggerInterface */
private $logger;
private $previousExceptionHandler;
private $uncaughtExceptionLevel;
private $previousErrorHandler;
private $errorLevelMap;
private $handleOnlyReportedErrors;
private $hasFatalErrorHandler;
private $fatalLevel;
private $reservedMemory;
private $lastFatalTrace;
private static $fatalErrors = array(\E_ERROR, \E_PARSE, \E_CORE_ERROR, \E_COMPILE_ERROR, \E_USER_ERROR);
/** @var ?callable */
private $previousExceptionHandler = null;
/** @var array<class-string, LogLevel::*> an array of class name to LogLevel::* constant mapping */
private $uncaughtExceptionLevelMap = [];
/** @var callable|true|null */
private $previousErrorHandler = null;
/** @var array<int, LogLevel::*> an array of E_* constant to LogLevel::* constant mapping */
private $errorLevelMap = [];
/** @var bool */
private $handleOnlyReportedErrors = \true;
/** @var bool */
private $hasFatalErrorHandler = \false;
/** @var LogLevel::* */
private $fatalLevel = \WPMailSMTP\Vendor\Psr\Log\LogLevel::ALERT;
/** @var ?string */
private $reservedMemory = null;
/** @var ?array{type: int, message: string, file: string, line: int, trace: mixed} */
private $lastFatalData = null;
/** @var int[] */
private static $fatalErrors = [\E_ERROR, \E_PARSE, \E_CORE_ERROR, \E_COMPILE_ERROR, \E_USER_ERROR];
public function __construct(\WPMailSMTP\Vendor\Psr\Log\LoggerInterface $logger)
{
$this->logger = $logger;
@@ -44,114 +55,162 @@ class ErrorHandler
*
* By default it will handle errors, exceptions and fatal errors
*
* @param LoggerInterface $logger
* @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
* @param int|false $exceptionLevel a LogLevel::* constant, or false to disable exception handling
* @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling
* @param LoggerInterface $logger
* @param array<int, LogLevel::*>|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
* @param array<class-string, LogLevel::*>|false $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling
* @param LogLevel::*|null|false $fatalLevel a LogLevel::* constant, null to use the default LogLevel::ALERT or false to disable fatal error handling
* @return ErrorHandler
*/
public static function register(\WPMailSMTP\Vendor\Psr\Log\LoggerInterface $logger, $errorLevelMap = array(), $exceptionLevel = null, $fatalLevel = null)
public static function register(\WPMailSMTP\Vendor\Psr\Log\LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null) : self
{
//Forces the autoloader to run for LogLevel. Fixes an autoload issue at compile-time on PHP5.3. See https://github.com/Seldaek/monolog/pull/929
\class_exists('WPMailSMTP\\Vendor\\Psr\\Log\\LogLevel', \true);
/** @phpstan-ignore-next-line */
$handler = new static($logger);
if ($errorLevelMap !== \false) {
$handler->registerErrorHandler($errorLevelMap);
}
if ($exceptionLevel !== \false) {
$handler->registerExceptionHandler($exceptionLevel);
if ($exceptionLevelMap !== \false) {
$handler->registerExceptionHandler($exceptionLevelMap);
}
if ($fatalLevel !== \false) {
$handler->registerFatalHandler($fatalLevel);
}
return $handler;
}
public function registerExceptionHandler($level = null, $callPrevious = \true)
/**
* @param array<class-string, LogLevel::*> $levelMap an array of class name to LogLevel::* constant mapping
* @return $this
*/
public function registerExceptionHandler(array $levelMap = [], bool $callPrevious = \true) : self
{
$prev = \set_exception_handler(array($this, 'handleException'));
$this->uncaughtExceptionLevel = $level;
$prev = \set_exception_handler(function (\Throwable $e) : void {
$this->handleException($e);
});
$this->uncaughtExceptionLevelMap = $levelMap;
foreach ($this->defaultExceptionLevelMap() as $class => $level) {
if (!isset($this->uncaughtExceptionLevelMap[$class])) {
$this->uncaughtExceptionLevelMap[$class] = $level;
}
}
if ($callPrevious && $prev) {
$this->previousExceptionHandler = $prev;
}
return $this;
}
public function registerErrorHandler(array $levelMap = array(), $callPrevious = \true, $errorTypes = -1, $handleOnlyReportedErrors = \true)
/**
* @param array<int, LogLevel::*> $levelMap an array of E_* constant to LogLevel::* constant mapping
* @return $this
*/
public function registerErrorHandler(array $levelMap = [], bool $callPrevious = \true, int $errorTypes = -1, bool $handleOnlyReportedErrors = \true) : self
{
$prev = \set_error_handler(array($this, 'handleError'), $errorTypes);
$prev = \set_error_handler([$this, 'handleError'], $errorTypes);
$this->errorLevelMap = \array_replace($this->defaultErrorLevelMap(), $levelMap);
if ($callPrevious) {
$this->previousErrorHandler = $prev ?: \true;
} else {
$this->previousErrorHandler = null;
}
$this->handleOnlyReportedErrors = $handleOnlyReportedErrors;
}
public function registerFatalHandler($level = null, $reservedMemorySize = 20)
{
\register_shutdown_function(array($this, 'handleFatalError'));
$this->reservedMemory = \str_repeat(' ', 1024 * $reservedMemorySize);
$this->fatalLevel = $level;
$this->hasFatalErrorHandler = \true;
}
protected function defaultErrorLevelMap()
{
return array(\E_ERROR => \WPMailSMTP\Vendor\Psr\Log\LogLevel::CRITICAL, \E_WARNING => \WPMailSMTP\Vendor\Psr\Log\LogLevel::WARNING, \E_PARSE => \WPMailSMTP\Vendor\Psr\Log\LogLevel::ALERT, \E_NOTICE => \WPMailSMTP\Vendor\Psr\Log\LogLevel::NOTICE, \E_CORE_ERROR => \WPMailSMTP\Vendor\Psr\Log\LogLevel::CRITICAL, \E_CORE_WARNING => \WPMailSMTP\Vendor\Psr\Log\LogLevel::WARNING, \E_COMPILE_ERROR => \WPMailSMTP\Vendor\Psr\Log\LogLevel::ALERT, \E_COMPILE_WARNING => \WPMailSMTP\Vendor\Psr\Log\LogLevel::WARNING, \E_USER_ERROR => \WPMailSMTP\Vendor\Psr\Log\LogLevel::ERROR, \E_USER_WARNING => \WPMailSMTP\Vendor\Psr\Log\LogLevel::WARNING, \E_USER_NOTICE => \WPMailSMTP\Vendor\Psr\Log\LogLevel::NOTICE, \E_STRICT => \WPMailSMTP\Vendor\Psr\Log\LogLevel::NOTICE, \E_RECOVERABLE_ERROR => \WPMailSMTP\Vendor\Psr\Log\LogLevel::ERROR, \E_DEPRECATED => \WPMailSMTP\Vendor\Psr\Log\LogLevel::NOTICE, \E_USER_DEPRECATED => \WPMailSMTP\Vendor\Psr\Log\LogLevel::NOTICE);
return $this;
}
/**
* @private
* @param LogLevel::*|null $level a LogLevel::* constant, null to use the default LogLevel::ALERT
* @param int $reservedMemorySize Amount of KBs to reserve in memory so that it can be freed when handling fatal errors giving Monolog some room in memory to get its job done
*/
public function handleException($e)
public function registerFatalHandler($level = null, int $reservedMemorySize = 20) : self
{
$this->logger->log($this->uncaughtExceptionLevel === null ? \WPMailSMTP\Vendor\Psr\Log\LogLevel::ERROR : $this->uncaughtExceptionLevel, \sprintf('Uncaught Exception %s: "%s" at %s line %s', \WPMailSMTP\Vendor\Monolog\Utils::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()), array('exception' => $e));
\register_shutdown_function([$this, 'handleFatalError']);
$this->reservedMemory = \str_repeat(' ', 1024 * $reservedMemorySize);
$this->fatalLevel = null === $level ? \WPMailSMTP\Vendor\Psr\Log\LogLevel::ALERT : $level;
$this->hasFatalErrorHandler = \true;
return $this;
}
/**
* @return array<class-string, LogLevel::*>
*/
protected function defaultExceptionLevelMap() : array
{
return ['ParseError' => \WPMailSMTP\Vendor\Psr\Log\LogLevel::CRITICAL, 'Throwable' => \WPMailSMTP\Vendor\Psr\Log\LogLevel::ERROR];
}
/**
* @return array<int, LogLevel::*>
*/
protected function defaultErrorLevelMap() : array
{
return [\E_ERROR => \WPMailSMTP\Vendor\Psr\Log\LogLevel::CRITICAL, \E_WARNING => \WPMailSMTP\Vendor\Psr\Log\LogLevel::WARNING, \E_PARSE => \WPMailSMTP\Vendor\Psr\Log\LogLevel::ALERT, \E_NOTICE => \WPMailSMTP\Vendor\Psr\Log\LogLevel::NOTICE, \E_CORE_ERROR => \WPMailSMTP\Vendor\Psr\Log\LogLevel::CRITICAL, \E_CORE_WARNING => \WPMailSMTP\Vendor\Psr\Log\LogLevel::WARNING, \E_COMPILE_ERROR => \WPMailSMTP\Vendor\Psr\Log\LogLevel::ALERT, \E_COMPILE_WARNING => \WPMailSMTP\Vendor\Psr\Log\LogLevel::WARNING, \E_USER_ERROR => \WPMailSMTP\Vendor\Psr\Log\LogLevel::ERROR, \E_USER_WARNING => \WPMailSMTP\Vendor\Psr\Log\LogLevel::WARNING, \E_USER_NOTICE => \WPMailSMTP\Vendor\Psr\Log\LogLevel::NOTICE, \E_STRICT => \WPMailSMTP\Vendor\Psr\Log\LogLevel::NOTICE, \E_RECOVERABLE_ERROR => \WPMailSMTP\Vendor\Psr\Log\LogLevel::ERROR, \E_DEPRECATED => \WPMailSMTP\Vendor\Psr\Log\LogLevel::NOTICE, \E_USER_DEPRECATED => \WPMailSMTP\Vendor\Psr\Log\LogLevel::NOTICE];
}
/**
* @phpstan-return never
*/
private function handleException(\Throwable $e) : void
{
$level = \WPMailSMTP\Vendor\Psr\Log\LogLevel::ERROR;
foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) {
if ($e instanceof $class) {
$level = $candidate;
break;
}
}
$this->logger->log($level, \sprintf('Uncaught Exception %s: "%s" at %s line %s', \WPMailSMTP\Vendor\Monolog\Utils::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()), ['exception' => $e]);
if ($this->previousExceptionHandler) {
\call_user_func($this->previousExceptionHandler, $e);
($this->previousExceptionHandler)($e);
}
if (!\headers_sent() && \in_array(\strtolower((string) \ini_get('display_errors')), ['0', '', 'false', 'off', 'none', 'no'], \true)) {
\http_response_code(500);
}
exit(255);
}
/**
* @private
*
* @param mixed[] $context
*/
public function handleError($code, $message, $file = '', $line = 0, $context = array())
public function handleError(int $code, string $message, string $file = '', int $line = 0, ?array $context = []) : bool
{
if ($this->handleOnlyReportedErrors && !(\error_reporting() & $code)) {
return;
return \false;
}
// fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries
if (!$this->hasFatalErrorHandler || !\in_array($code, self::$fatalErrors, \true)) {
$level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : \WPMailSMTP\Vendor\Psr\Log\LogLevel::CRITICAL;
$this->logger->log($level, self::codeToString($code) . ': ' . $message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line));
$level = $this->errorLevelMap[$code] ?? \WPMailSMTP\Vendor\Psr\Log\LogLevel::CRITICAL;
$this->logger->log($level, self::codeToString($code) . ': ' . $message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]);
} else {
// http://php.net/manual/en/function.debug-backtrace.php
// As of 5.3.6, DEBUG_BACKTRACE_IGNORE_ARGS option was added.
// Any version less than 5.3.6 must use the DEBUG_BACKTRACE_IGNORE_ARGS constant value '2'.
$trace = \debug_backtrace(\PHP_VERSION_ID < 50306 ? 2 : \DEBUG_BACKTRACE_IGNORE_ARGS);
$trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
\array_shift($trace);
// Exclude handleError from trace
$this->lastFatalTrace = $trace;
$this->lastFatalData = ['type' => $code, 'message' => $message, 'file' => $file, 'line' => $line, 'trace' => $trace];
}
if ($this->previousErrorHandler === \true) {
return \false;
} elseif ($this->previousErrorHandler) {
return \call_user_func($this->previousErrorHandler, $code, $message, $file, $line, $context);
return (bool) ($this->previousErrorHandler)($code, $message, $file, $line, $context);
}
return \true;
}
/**
* @private
*/
public function handleFatalError()
public function handleFatalError() : void
{
$this->reservedMemory = null;
$lastError = \error_get_last();
$this->reservedMemory = '';
if (\is_array($this->lastFatalData)) {
$lastError = $this->lastFatalData;
} else {
$lastError = \error_get_last();
}
if ($lastError && \in_array($lastError['type'], self::$fatalErrors, \true)) {
$this->logger->log($this->fatalLevel === null ? \WPMailSMTP\Vendor\Psr\Log\LogLevel::ALERT : $this->fatalLevel, 'Fatal Error (' . self::codeToString($lastError['type']) . '): ' . $lastError['message'], array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace));
$trace = $lastError['trace'] ?? null;
$this->logger->log($this->fatalLevel, 'Fatal Error (' . self::codeToString($lastError['type']) . '): ' . $lastError['message'], ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $trace]);
if ($this->logger instanceof \WPMailSMTP\Vendor\Monolog\Logger) {
foreach ($this->logger->getHandlers() as $handler) {
if ($handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler) {
$handler->close();
}
$handler->close();
}
}
}
}
private static function codeToString($code)
/**
* @param int $code
*/
private static function codeToString($code) : string
{
switch ($code) {
case \E_ERROR:

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -20,10 +21,12 @@ class ChromePHPFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\Formatt
{
/**
* Translates Monolog log levels to Wildfire levels.
*
* @var array<int, 'log'|'info'|'warn'|'error'>
*/
private $logLevels = array(\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => 'log', \WPMailSMTP\Vendor\Monolog\Logger::INFO => 'info', \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => 'info', \WPMailSMTP\Vendor\Monolog\Logger::WARNING => 'warn', \WPMailSMTP\Vendor\Monolog\Logger::ERROR => 'error', \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => 'error', \WPMailSMTP\Vendor\Monolog\Logger::ALERT => 'error', \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => 'error');
private $logLevels = [\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => 'log', \WPMailSMTP\Vendor\Monolog\Logger::INFO => 'info', \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => 'info', \WPMailSMTP\Vendor\Monolog\Logger::WARNING => 'warn', \WPMailSMTP\Vendor\Monolog\Logger::ERROR => 'error', \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => 'error', \WPMailSMTP\Vendor\Monolog\Logger::ALERT => 'error', \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => 'error'];
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function format(array $record)
{
@@ -33,7 +36,7 @@ class ChromePHPFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\Formatt
$backtrace = $record['extra']['file'] . ' : ' . $record['extra']['line'];
unset($record['extra']['file'], $record['extra']['line']);
}
$message = array('message' => $record['message']);
$message = ['message' => $record['message']];
if ($record['context']) {
$message['context'] = $record['context'];
}
@@ -43,11 +46,14 @@ class ChromePHPFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\Formatt
if (\count($message) === 1) {
$message = \reset($message);
}
return array($record['channel'], $message, $backtrace, $this->logLevels[$record['level']]);
return [$record['channel'], $message, $backtrace, $this->logLevels[$record['level']]];
}
/**
* {@inheritDoc}
*/
public function formatBatch(array $records)
{
$formatted = array();
$formatted = [];
foreach ($records as $record) {
$formatted[] = $this->format($record);
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -15,6 +16,8 @@ use WPMailSMTP\Vendor\Elastica\Document;
* Format a log message into an Elastica Document
*
* @author Jelle Vink <jelle.vink@gmail.com>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
class ElasticaFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter
{
@@ -23,14 +26,14 @@ class ElasticaFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerF
*/
protected $index;
/**
* @var string Elastic search document type
* @var ?string Elastic search document type
*/
protected $type;
/**
* @param string $index Elastic Search index name
* @param string $type Elastic Search document type
* @param string $index Elastic Search index name
* @param ?string $type Elastic Search document type, deprecated as of Elastica 7
*/
public function __construct($index, $type)
public function __construct(string $index, ?string $type)
{
// elasticsearch requires a ISO 8601 format date with optional millisecond precision.
parent::__construct('Y-m-d\\TH:i:s.uP');
@@ -38,40 +41,38 @@ class ElasticaFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerF
$this->type = $type;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function format(array $record)
{
$record = parent::format($record);
return $this->getDocument($record);
}
/**
* Getter index
* @return string
*/
public function getIndex()
public function getIndex() : string
{
return $this->index;
}
/**
* Getter type
* @return string
* @deprecated since Elastica 7 type has no effect
*/
public function getType()
public function getType() : string
{
/** @phpstan-ignore-next-line */
return $this->type;
}
/**
* Convert a log message into an Elastica Document
*
* @param array $record Log message
* @return Document
* @phpstan-param Record $record
*/
protected function getDocument($record)
protected function getDocument(array $record) : \WPMailSMTP\Vendor\Elastica\Document
{
$document = new \WPMailSMTP\Vendor\Elastica\Document();
$document->setData($record);
$document->setType($this->type);
if (\method_exists($document, 'setType')) {
/** @phpstan-ignore-next-line */
$document->setType($this->type);
}
$document->setIndex($this->index);
return $document;
}

View File

@@ -0,0 +1,79 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Formatter;
use DateTimeInterface;
/**
* Format a log message into an Elasticsearch record
*
* @author Avtandil Kikabidze <akalongman@gmail.com>
*/
class ElasticsearchFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter
{
/**
* @var string Elasticsearch index name
*/
protected $index;
/**
* @var string Elasticsearch record type
*/
protected $type;
/**
* @param string $index Elasticsearch index name
* @param string $type Elasticsearch record type
*/
public function __construct(string $index, string $type)
{
// Elasticsearch requires an ISO 8601 format date with optional millisecond precision.
parent::__construct(\DateTimeInterface::ISO8601);
$this->index = $index;
$this->type = $type;
}
/**
* {@inheritDoc}
*/
public function format(array $record)
{
$record = parent::format($record);
return $this->getDocument($record);
}
/**
* Getter index
*
* @return string
*/
public function getIndex() : string
{
return $this->index;
}
/**
* Getter type
*
* @return string
*/
public function getType() : string
{
return $this->type;
}
/**
* Convert a log message into an Elasticsearch record
*
* @param mixed[] $record Log message
* @return mixed[]
*/
protected function getDocument(array $record) : array
{
$record['_index'] = $this->index;
$record['_type'] = $this->type;
return $record;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -14,6 +15,7 @@ namespace WPMailSMTP\Vendor\Monolog\Formatter;
* formats the record to be used in the FlowdockHandler
*
* @author Dominik Liebler <liebler.dominik@gmail.com>
* @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4
*/
class FlowdockFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
@@ -25,45 +27,40 @@ class FlowdockFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\Formatte
* @var string
*/
private $sourceEmail;
/**
* @param string $source
* @param string $sourceEmail
*/
public function __construct($source, $sourceEmail)
public function __construct(string $source, string $sourceEmail)
{
$this->source = $source;
$this->sourceEmail = $sourceEmail;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @return mixed[]
*/
public function format(array $record)
public function format(array $record) : array
{
$tags = array('#logs', '#' . \strtolower($record['level_name']), '#' . $record['channel']);
$tags = ['#logs', '#' . \strtolower($record['level_name']), '#' . $record['channel']];
foreach ($record['extra'] as $value) {
$tags[] = '#' . $value;
}
$subject = \sprintf('in %s: %s - %s', $this->source, $record['level_name'], $this->getShortMessage($record['message']));
$record['flowdock'] = array('source' => $this->source, 'from_address' => $this->sourceEmail, 'subject' => $subject, 'content' => $record['message'], 'tags' => $tags, 'project' => $this->source);
$record['flowdock'] = ['source' => $this->source, 'from_address' => $this->sourceEmail, 'subject' => $subject, 'content' => $record['message'], 'tags' => $tags, 'project' => $this->source];
return $record;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @return mixed[][]
*/
public function formatBatch(array $records)
public function formatBatch(array $records) : array
{
$formatted = array();
$formatted = [];
foreach ($records as $record) {
$formatted[] = $this->format($record);
}
return $formatted;
}
/**
* @param string $message
*
* @return string
*/
public function getShortMessage($message)
public function getShortMessage(string $message) : string
{
static $hasMbString;
if (null === $hasMbString) {

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -38,31 +39,31 @@ class FluentdFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\Formatter
* @var bool $levelTag should message level be a part of the fluentd tag
*/
protected $levelTag = \false;
public function __construct($levelTag = \false)
public function __construct(bool $levelTag = \false)
{
if (!\function_exists('json_encode')) {
throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s FluentdUnixFormatter');
}
$this->levelTag = (bool) $levelTag;
$this->levelTag = $levelTag;
}
public function isUsingLevelsInTag()
public function isUsingLevelsInTag() : bool
{
return $this->levelTag;
}
public function format(array $record)
public function format(array $record) : string
{
$tag = $record['channel'];
if ($this->levelTag) {
$tag .= '.' . \strtolower($record['level_name']);
}
$message = array('message' => $record['message'], 'context' => $record['context'], 'extra' => $record['extra']);
$message = ['message' => $record['message'], 'context' => $record['context'], 'extra' => $record['extra']];
if (!$this->levelTag) {
$message['level'] = $record['level'];
$message['level_name'] = $record['level_name'];
}
return \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode(array($tag, $record['datetime']->getTimestamp(), $message));
return \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode([$tag, $record['datetime']->getTimestamp(), $message]);
}
public function formatBatch(array $records)
public function formatBatch(array $records) : string
{
$message = '';
foreach ($records as $record) {

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -14,6 +15,8 @@ namespace WPMailSMTP\Vendor\Monolog\Formatter;
* Interface for formatters
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
interface FormatterInterface
{
@@ -22,6 +25,8 @@ interface FormatterInterface
*
* @param array $record A record to format
* @return mixed The formatted record
*
* @phpstan-param Record $record
*/
public function format(array $record);
/**
@@ -29,6 +34,8 @@ interface FormatterInterface
*
* @param array $records A set of records to format
* @return mixed The formatted set of records
*
* @phpstan-param Record[] $records
*/
public function formatBatch(array $records);
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -12,15 +13,18 @@ namespace WPMailSMTP\Vendor\Monolog\Formatter;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Gelf\Message;
use WPMailSMTP\Vendor\Monolog\Utils;
/**
* Serializes a log message to GELF
* @see http://www.graylog2.org/about/gelf
* @see http://docs.graylog.org/en/latest/pages/gelf.html
*
* @author Matt Lehner <mlehner@gmail.com>
*
* @phpstan-import-type Level from \Monolog\Logger
*/
class GelfMessageFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter
{
const DEFAULT_MAX_LENGTH = 32766;
protected const DEFAULT_MAX_LENGTH = 32766;
/**
* @var string the name of the system for the Gelf log message
*/
@@ -38,23 +42,45 @@ class GelfMessageFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\Normaliz
*/
protected $maxLength;
/**
* Translates Monolog log levels to Graylog2 log priorities.
* @var int
*/
private $logLevels = array(\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => 7, \WPMailSMTP\Vendor\Monolog\Logger::INFO => 6, \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => 5, \WPMailSMTP\Vendor\Monolog\Logger::WARNING => 4, \WPMailSMTP\Vendor\Monolog\Logger::ERROR => 3, \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => 2, \WPMailSMTP\Vendor\Monolog\Logger::ALERT => 1, \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => 0);
public function __construct($systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_', $maxLength = null)
private $gelfVersion = 2;
/**
* Translates Monolog log levels to Graylog2 log priorities.
*
* @var array<int, int>
*
* @phpstan-var array<Level, int>
*/
private $logLevels = [\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => 7, \WPMailSMTP\Vendor\Monolog\Logger::INFO => 6, \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => 5, \WPMailSMTP\Vendor\Monolog\Logger::WARNING => 4, \WPMailSMTP\Vendor\Monolog\Logger::ERROR => 3, \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => 2, \WPMailSMTP\Vendor\Monolog\Logger::ALERT => 1, \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => 0];
public function __construct(?string $systemName = null, ?string $extraPrefix = null, string $contextPrefix = 'ctxt_', ?int $maxLength = null)
{
if (!\class_exists(\WPMailSMTP\Vendor\Gelf\Message::class)) {
throw new \RuntimeException('Composer package graylog2/gelf-php is required to use Monolog\'s GelfMessageFormatter');
}
parent::__construct('U.u');
$this->systemName = $systemName ?: \gethostname();
$this->extraPrefix = $extraPrefix;
$this->systemName = \is_null($systemName) || $systemName === '' ? (string) \gethostname() : $systemName;
$this->extraPrefix = \is_null($extraPrefix) ? '' : $extraPrefix;
$this->contextPrefix = $contextPrefix;
$this->maxLength = \is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength;
if (\method_exists(\WPMailSMTP\Vendor\Gelf\Message::class, 'setFacility')) {
$this->gelfVersion = 1;
}
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function format(array $record)
public function format(array $record) : \WPMailSMTP\Vendor\Gelf\Message
{
$record = parent::format($record);
$context = $extra = [];
if (isset($record['context'])) {
/** @var mixed[] $context */
$context = parent::normalize($record['context']);
}
if (isset($record['extra'])) {
/** @var mixed[] $extra */
$extra = parent::normalize($record['extra']);
}
if (!isset($record['datetime'], $record['message'], $record['level'])) {
throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, ' . \var_export($record, \true) . ' given');
}
@@ -63,41 +89,48 @@ class GelfMessageFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\Normaliz
// message length + system name length + 200 for padding / metadata
$len = 200 + \strlen((string) $record['message']) + \strlen($this->systemName);
if ($len > $this->maxLength) {
$message->setShortMessage(\substr($record['message'], 0, $this->maxLength));
$message->setShortMessage(\WPMailSMTP\Vendor\Monolog\Utils::substr($record['message'], 0, $this->maxLength));
}
if (isset($record['channel'])) {
$message->setFacility($record['channel']);
if ($this->gelfVersion === 1) {
if (isset($record['channel'])) {
$message->setFacility($record['channel']);
}
if (isset($extra['line'])) {
$message->setLine($extra['line']);
unset($extra['line']);
}
if (isset($extra['file'])) {
$message->setFile($extra['file']);
unset($extra['file']);
}
} else {
$message->setAdditional('facility', $record['channel']);
}
if (isset($record['extra']['line'])) {
$message->setLine($record['extra']['line']);
unset($record['extra']['line']);
}
if (isset($record['extra']['file'])) {
$message->setFile($record['extra']['file']);
unset($record['extra']['file']);
}
foreach ($record['extra'] as $key => $val) {
foreach ($extra as $key => $val) {
$val = \is_scalar($val) || null === $val ? $val : $this->toJson($val);
$len = \strlen($this->extraPrefix . $key . $val);
if ($len > $this->maxLength) {
$message->setAdditional($this->extraPrefix . $key, \substr($val, 0, $this->maxLength));
break;
$message->setAdditional($this->extraPrefix . $key, \WPMailSMTP\Vendor\Monolog\Utils::substr((string) $val, 0, $this->maxLength));
continue;
}
$message->setAdditional($this->extraPrefix . $key, $val);
}
foreach ($record['context'] as $key => $val) {
foreach ($context as $key => $val) {
$val = \is_scalar($val) || null === $val ? $val : $this->toJson($val);
$len = \strlen($this->contextPrefix . $key . $val);
if ($len > $this->maxLength) {
$message->setAdditional($this->contextPrefix . $key, \substr($val, 0, $this->maxLength));
break;
$message->setAdditional($this->contextPrefix . $key, \WPMailSMTP\Vendor\Monolog\Utils::substr((string) $val, 0, $this->maxLength));
continue;
}
$message->setAdditional($this->contextPrefix . $key, $val);
}
if (null === $message->getFile() && isset($record['context']['exception']['file'])) {
if (\preg_match("/^(.+):([0-9]+)\$/", $record['context']['exception']['file'], $matches)) {
$message->setFile($matches[1]);
$message->setLine($matches[2]);
if ($this->gelfVersion === 1) {
/** @phpstan-ignore-next-line */
if (null === $message->getFile() && isset($context['exception']['file'])) {
if (\preg_match("/^(.+):([0-9]+)\$/", $context['exception']['file'], $matches)) {
$message->setFile($matches[1]);
$message->setLine($matches[2]);
}
}
}
return $message;

View File

@@ -0,0 +1,36 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Formatter;
use DateTimeInterface;
use WPMailSMTP\Vendor\Monolog\LogRecord;
/**
* Encodes message information into JSON in a format compatible with Cloud logging.
*
* @see https://cloud.google.com/logging/docs/structured-logging
* @see https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry
*
* @author Luís Cobucci <lcobucci@gmail.com>
*/
final class GoogleCloudLoggingFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\JsonFormatter
{
/** {@inheritdoc} **/
public function format(array $record) : string
{
// Re-key level for GCP logging
$record['severity'] = $record['level_name'];
$record['time'] = $record['datetime']->format(\DateTimeInterface::RFC3339_EXTENDED);
// Remove keys that are not used by GCP
unset($record['level'], $record['level_name'], $record['datetime']);
return parent::format($record);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -23,24 +24,25 @@ class HtmlFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
{
/**
* Translates Monolog log levels to html color priorities.
*
* @var array<int, string>
*/
protected $logLevels = array(\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => '#cccccc', \WPMailSMTP\Vendor\Monolog\Logger::INFO => '#468847', \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => '#3a87ad', \WPMailSMTP\Vendor\Monolog\Logger::WARNING => '#c09853', \WPMailSMTP\Vendor\Monolog\Logger::ERROR => '#f0ad4e', \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => '#FF7708', \WPMailSMTP\Vendor\Monolog\Logger::ALERT => '#C12A19', \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => '#000000');
protected $logLevels = [\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => '#CCCCCC', \WPMailSMTP\Vendor\Monolog\Logger::INFO => '#28A745', \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => '#17A2B8', \WPMailSMTP\Vendor\Monolog\Logger::WARNING => '#FFC107', \WPMailSMTP\Vendor\Monolog\Logger::ERROR => '#FD7E14', \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => '#DC3545', \WPMailSMTP\Vendor\Monolog\Logger::ALERT => '#821722', \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => '#000000'];
/**
* @param string $dateFormat The format of the timestamp: one supported by DateTime::format
* @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
*/
public function __construct($dateFormat = null)
public function __construct(?string $dateFormat = null)
{
parent::__construct($dateFormat);
}
/**
* Creates an HTML table row
*
* @param string $th Row header content
* @param string $td Row standard cell content
* @param bool $escapeTd false if td content must not be html escaped
* @return string
* @param string $th Row header content
* @param string $td Row standard cell content
* @param bool $escapeTd false if td content must not be html escaped
*/
protected function addRow($th, $td = ' ', $escapeTd = \true)
protected function addRow(string $th, string $td = ' ', bool $escapeTd = \true) : string
{
$th = \htmlspecialchars($th, \ENT_NOQUOTES, 'UTF-8');
if ($escapeTd) {
@@ -55,7 +57,7 @@ class HtmlFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
* @param int $level Error level
* @return string
*/
protected function addTitle($title, $level)
protected function addTitle(string $title, int $level) : string
{
$title = \htmlspecialchars($title, \ENT_NOQUOTES, 'UTF-8');
return '<h1 style="background: ' . $this->logLevels[$level] . ';color: #ffffff;padding: 5px;" class="monolog-output">' . $title . '</h1>';
@@ -63,20 +65,19 @@ class HtmlFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
/**
* Formats a log record.
*
* @param array $record A record to format
* @return mixed The formatted record
* @return string The formatted record
*/
public function format(array $record)
public function format(array $record) : string
{
$output = $this->addTitle($record['level_name'], $record['level']);
$output .= '<table cellspacing="1" width="100%" class="monolog-output">';
$output .= $this->addRow('Message', (string) $record['message']);
$output .= $this->addRow('Time', $record['datetime']->format($this->dateFormat));
$output .= $this->addRow('Time', $this->formatDate($record['datetime']));
$output .= $this->addRow('Channel', $record['channel']);
if ($record['context']) {
$embeddedTable = '<table cellspacing="1" width="100%">';
foreach ($record['context'] as $key => $value) {
$embeddedTable .= $this->addRow($key, $this->convertToString($value));
$embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
}
$embeddedTable .= '</table>';
$output .= $this->addRow('Context', $embeddedTable, \false);
@@ -84,7 +85,7 @@ class HtmlFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
if ($record['extra']) {
$embeddedTable = '<table cellspacing="1" width="100%">';
foreach ($record['extra'] as $key => $value) {
$embeddedTable .= $this->addRow($key, $this->convertToString($value));
$embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
}
$embeddedTable .= '</table>';
$output .= $this->addRow('Extra', $embeddedTable, \false);
@@ -94,10 +95,9 @@ class HtmlFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
/**
* Formats a set of log records.
*
* @param array $records A set of records to format
* @return mixed The formatted set of records
* @return string The formatted set of records
*/
public function formatBatch(array $records)
public function formatBatch(array $records) : string
{
$message = '';
foreach ($records as $record) {
@@ -105,15 +105,15 @@ class HtmlFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
}
return $message;
}
protected function convertToString($data)
/**
* @param mixed $data
*/
protected function convertToString($data) : string
{
if (null === $data || \is_scalar($data)) {
return (string) $data;
}
$data = $this->normalize($data);
if (\version_compare(\PHP_VERSION, '5.4.0', '>=')) {
return \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($data, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE, \true);
}
return \str_replace('\\/', '/', \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($data, null, \true));
return \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($data, \JSON_PRETTY_PRINT | \WPMailSMTP\Vendor\Monolog\Utils::DEFAULT_JSON_FLAGS, \true);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,8 +11,6 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Formatter;
use Exception;
use WPMailSMTP\Vendor\Monolog\Utils;
use Throwable;
/**
* Encodes whatever record data is passed to it as json
@@ -19,27 +18,31 @@ use Throwable;
* This can be useful to log to databases or remote APIs
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
class JsonFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter
{
const BATCH_MODE_JSON = 1;
const BATCH_MODE_NEWLINES = 2;
public const BATCH_MODE_JSON = 1;
public const BATCH_MODE_NEWLINES = 2;
/** @var self::BATCH_MODE_* */
protected $batchMode;
/** @var bool */
protected $appendNewline;
/**
* @var bool
*/
/** @var bool */
protected $ignoreEmptyContextAndExtra;
/** @var bool */
protected $includeStacktraces = \false;
/**
* @param int $batchMode
* @param bool $appendNewline
* @param int $maxDepth
* @param self::BATCH_MODE_* $batchMode
*/
public function __construct($batchMode = self::BATCH_MODE_JSON, $appendNewline = \true, $maxDepth = 9)
public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = \true, bool $ignoreEmptyContextAndExtra = \false, bool $includeStacktraces = \false)
{
parent::__construct(null, $maxDepth);
$this->batchMode = $batchMode;
$this->appendNewline = $appendNewline;
$this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
$this->includeStacktraces = $includeStacktraces;
parent::__construct();
}
/**
* The batch mode option configures the formatting style for
@@ -47,33 +50,44 @@ class JsonFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
* formatted as a JSON-encoded array. However, for
* compatibility with some API endpoints, alternative styles
* are available.
*
* @return int
*/
public function getBatchMode()
public function getBatchMode() : int
{
return $this->batchMode;
}
/**
* True if newlines are appended to every formatted record
*
* @return bool
*/
public function isAppendingNewlines()
public function isAppendingNewlines() : bool
{
return $this->appendNewline;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function format(array $record)
public function format(array $record) : string
{
return $this->toJson($this->normalize($record), \true) . ($this->appendNewline ? "\n" : '');
$normalized = $this->normalize($record);
if (isset($normalized['context']) && $normalized['context'] === []) {
if ($this->ignoreEmptyContextAndExtra) {
unset($normalized['context']);
} else {
$normalized['context'] = new \stdClass();
}
}
if (isset($normalized['extra']) && $normalized['extra'] === []) {
if ($this->ignoreEmptyContextAndExtra) {
unset($normalized['extra']);
} else {
$normalized['extra'] = new \stdClass();
}
}
return $this->toJson($normalized, \true) . ($this->appendNewline ? "\n" : '');
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function formatBatch(array $records)
public function formatBatch(array $records) : string
{
switch ($this->batchMode) {
case static::BATCH_MODE_NEWLINES:
@@ -84,19 +98,19 @@ class JsonFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
}
}
/**
* @param bool $include
* @return self
*/
public function includeStacktraces($include = \true)
public function includeStacktraces(bool $include = \true) : self
{
$this->includeStacktraces = $include;
return $this;
}
/**
* Return a JSON-encoded array of records.
*
* @param array $records
* @return string
* @phpstan-param Record[] $records
*/
protected function formatBatchJson(array $records)
protected function formatBatchJson(array $records) : string
{
return $this->toJson($this->normalize($records), \true);
}
@@ -104,10 +118,9 @@ class JsonFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
* Use new lines to separate records instead of a
* JSON-encoded array.
*
* @param array $records
* @return string
* @phpstan-param Record[] $records
*/
protected function formatBatchNewlines(array $records)
protected function formatBatchNewlines(array $records) : string
{
$instance = $this;
$oldNewline = $this->appendNewline;
@@ -125,25 +138,38 @@ class JsonFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
*
* @return mixed
*/
protected function normalize($data, $depth = 0)
protected function normalize($data, int $depth = 0)
{
if ($depth > $this->maxDepth) {
return 'Over ' . $this->maxDepth . ' levels deep, aborting normalization';
if ($depth > $this->maxNormalizeDepth) {
return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
}
if (\is_array($data)) {
$normalized = array();
$normalized = [];
$count = 1;
foreach ($data as $key => $value) {
if ($count++ > 1000) {
$normalized['...'] = 'Over 1000 items (' . \count($data) . ' total), aborting normalization';
if ($count++ > $this->maxNormalizeItemCount) {
$normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items (' . \count($data) . ' total), aborting normalization';
break;
}
$normalized[$key] = $this->normalize($value, $depth + 1);
}
return $normalized;
}
if ($data instanceof \Exception || $data instanceof \Throwable) {
return $this->normalizeException($data);
if (\is_object($data)) {
if ($data instanceof \DateTimeInterface) {
return $this->formatDate($data);
}
if ($data instanceof \Throwable) {
return $this->normalizeException($data, $depth);
}
// if the object has specific json serializability we want to make sure we skip the __toString treatment below
if ($data instanceof \JsonSerializable) {
return $data;
}
if (\method_exists($data, '__toString')) {
return $data->__toString();
}
return $data;
}
if (\is_resource($data)) {
return parent::normalize($data);
@@ -154,27 +180,13 @@ class JsonFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
* Normalizes given exception with or without its own stack trace based on
* `includeStacktraces` property.
*
* @param Exception|Throwable $e
*
* @return array
* {@inheritDoc}
*/
protected function normalizeException($e)
protected function normalizeException(\Throwable $e, int $depth = 0) : array
{
// TODO 2.0 only check for Throwable
if (!$e instanceof \Exception && !$e instanceof \Throwable) {
throw new \InvalidArgumentException('Exception/Throwable expected, got ' . \gettype($e) . ' / ' . \WPMailSMTP\Vendor\Monolog\Utils::getClass($e));
}
$data = array('class' => \WPMailSMTP\Vendor\Monolog\Utils::getClass($e), 'message' => $e->getMessage(), 'code' => (int) $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine());
if ($this->includeStacktraces) {
$trace = $e->getTrace();
foreach ($trace as $frame) {
if (isset($frame['file'])) {
$data['trace'][] = $frame['file'] . ':' . $frame['line'];
}
}
}
if ($previous = $e->getPrevious()) {
$data['previous'] = $this->normalizeException($previous);
$data = parent::normalizeException($e, $depth);
if (!$this->includeStacktraces) {
unset($data['trace']);
}
return $data;
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -21,43 +22,54 @@ use WPMailSMTP\Vendor\Monolog\Utils;
*/
class LineFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter
{
const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
public const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
/** @var string */
protected $format;
/** @var bool */
protected $allowInlineLineBreaks;
/** @var bool */
protected $ignoreEmptyContextAndExtra;
/** @var bool */
protected $includeStacktraces;
/** @var ?callable */
protected $stacktracesParser;
/**
* @param string $format The format of the message
* @param string $dateFormat The format of the timestamp: one supported by DateTime::format
* @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries
* @param bool $ignoreEmptyContextAndExtra
* @param string|null $format The format of the message
* @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
* @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries
* @param bool $ignoreEmptyContextAndExtra
*/
public function __construct($format = null, $dateFormat = null, $allowInlineLineBreaks = \false, $ignoreEmptyContextAndExtra = \false)
public function __construct(?string $format = null, ?string $dateFormat = null, bool $allowInlineLineBreaks = \false, bool $ignoreEmptyContextAndExtra = \false, bool $includeStacktraces = \false)
{
$this->format = $format ?: static::SIMPLE_FORMAT;
$this->format = $format === null ? static::SIMPLE_FORMAT : $format;
$this->allowInlineLineBreaks = $allowInlineLineBreaks;
$this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
$this->includeStacktraces($includeStacktraces);
parent::__construct($dateFormat);
}
public function includeStacktraces($include = \true)
public function includeStacktraces(bool $include = \true, ?callable $parser = null) : self
{
$this->includeStacktraces = $include;
if ($this->includeStacktraces) {
$this->allowInlineLineBreaks = \true;
$this->stacktracesParser = $parser;
}
return $this;
}
public function allowInlineLineBreaks($allow = \true)
public function allowInlineLineBreaks(bool $allow = \true) : self
{
$this->allowInlineLineBreaks = $allow;
return $this;
}
public function ignoreEmptyContextAndExtra($ignore = \true)
public function ignoreEmptyContextAndExtra(bool $ignore = \true) : self
{
$this->ignoreEmptyContextAndExtra = $ignore;
return $this;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function format(array $record)
public function format(array $record) : string
{
$vars = parent::format($record);
$output = $this->format;
@@ -91,10 +103,14 @@ class LineFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
// remove leftover %extra.xxx% and %context.xxx% if any
if (\false !== \strpos($output, '%')) {
$output = \preg_replace('/%(?:extra|context)\\..+?%/', '', $output);
if (null === $output) {
$pcreErrorCode = \preg_last_error();
throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . \WPMailSMTP\Vendor\Monolog\Utils::pcreLastErrorMessage($pcreErrorCode));
}
}
return $output;
}
public function formatBatch(array $records)
public function formatBatch(array $records) : string
{
$message = '';
foreach ($records as $record) {
@@ -102,29 +118,32 @@ class LineFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
}
return $message;
}
public function stringify($value)
/**
* @param mixed $value
*/
public function stringify($value) : string
{
return $this->replaceNewlines($this->convertToString($value));
}
protected function normalizeException($e)
protected function normalizeException(\Throwable $e, int $depth = 0) : string
{
// TODO 2.0 only check for Throwable
if (!$e instanceof \Exception && !$e instanceof \Throwable) {
throw new \InvalidArgumentException('Exception/Throwable expected, got ' . \gettype($e) . ' / ' . \WPMailSMTP\Vendor\Monolog\Utils::getClass($e));
}
$previousText = '';
$str = $this->formatException($e);
if ($previous = $e->getPrevious()) {
do {
$previousText .= ', ' . \WPMailSMTP\Vendor\Monolog\Utils::getClass($previous) . '(code: ' . $previous->getCode() . '): ' . $previous->getMessage() . ' at ' . $previous->getFile() . ':' . $previous->getLine();
$depth++;
if ($depth > $this->maxNormalizeDepth) {
$str .= "\n[previous exception] Over " . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
break;
}
$str .= "\n[previous exception] " . $this->formatException($previous);
} while ($previous = $previous->getPrevious());
}
$str = '[object] (' . \WPMailSMTP\Vendor\Monolog\Utils::getClass($e) . '(code: ' . $e->getCode() . '): ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine() . $previousText . ')';
if ($this->includeStacktraces) {
$str .= "\n[stacktrace]\n" . $e->getTraceAsString() . "\n";
}
return $str;
}
protected function convertToString($data)
/**
* @param mixed $data
*/
protected function convertToString($data) : string
{
if (null === $data || \is_bool($data)) {
return \var_export($data, \true);
@@ -132,19 +151,56 @@ class LineFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerForma
if (\is_scalar($data)) {
return (string) $data;
}
if (\version_compare(\PHP_VERSION, '5.4.0', '>=')) {
return $this->toJson($data, \true);
}
return \str_replace('\\/', '/', $this->toJson($data, \true));
return $this->toJson($data, \true);
}
protected function replaceNewlines($str)
protected function replaceNewlines(string $str) : string
{
if ($this->allowInlineLineBreaks) {
if (0 === \strpos($str, '{')) {
return \str_replace(array('\\r', '\\n'), array("\r", "\n"), $str);
$str = \preg_replace('/(?<!\\\\)\\\\[rn]/', "\n", $str);
if (null === $str) {
$pcreErrorCode = \preg_last_error();
throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . \WPMailSMTP\Vendor\Monolog\Utils::pcreLastErrorMessage($pcreErrorCode));
}
}
return $str;
}
return \str_replace(array("\r\n", "\r", "\n"), ' ', $str);
return \str_replace(["\r\n", "\r", "\n"], ' ', $str);
}
private function formatException(\Throwable $e) : string
{
$str = '[object] (' . \WPMailSMTP\Vendor\Monolog\Utils::getClass($e) . '(code: ' . $e->getCode();
if ($e instanceof \SoapFault) {
if (isset($e->faultcode)) {
$str .= ' faultcode: ' . $e->faultcode;
}
if (isset($e->faultactor)) {
$str .= ' faultactor: ' . $e->faultactor;
}
if (isset($e->detail)) {
if (\is_string($e->detail)) {
$str .= ' detail: ' . $e->detail;
} elseif (\is_object($e->detail) || \is_array($e->detail)) {
$str .= ' detail: ' . $this->toJson($e->detail, \true);
}
}
}
$str .= '): ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine() . ')';
if ($this->includeStacktraces) {
$str .= $this->stacktracesParser($e);
}
return $str;
}
private function stacktracesParser(\Throwable $e) : string
{
$trace = $e->getTraceAsString();
if ($this->stacktracesParser) {
$trace = $this->stacktracesParserCustom($trace);
}
return "\n[stacktrace]\n" . $trace . "\n";
}
private function stacktracesParserCustom(string $trace) : string
{
return \implode("\n", \array_filter(\array_map($this->stacktracesParser, \explode("\n", $trace))));
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -20,10 +21,8 @@ class LogglyFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\JsonFormatter
/**
* Overrides the default batch mode to new lines for compatibility with the
* Loggly bulk API.
*
* @param int $batchMode
*/
public function __construct($batchMode = self::BATCH_MODE_NEWLINES, $appendNewline = \false)
public function __construct(int $batchMode = self::BATCH_MODE_NEWLINES, bool $appendNewline = \false)
{
parent::__construct($batchMode, $appendNewline);
}
@@ -33,11 +32,11 @@ class LogglyFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\JsonFormatter
* @see https://www.loggly.com/docs/automated-parsing/#json
* @see \Monolog\Formatter\JsonFormatter::format()
*/
public function format(array $record)
public function format(array $record) : string
{
if (isset($record["datetime"]) && $record["datetime"] instanceof \DateTime) {
if (isset($record["datetime"]) && $record["datetime"] instanceof \DateTimeInterface) {
$record["timestamp"] = $record["datetime"]->format("Y-m-d\\TH:i:s.uO");
// TODO 2.0 unset the 'datetime' parameter, retained for BC
unset($record["datetime"]);
}
return parent::format($record);
}

View File

@@ -0,0 +1,57 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Formatter;
/**
* Encodes message information into JSON in a format compatible with Logmatic.
*
* @author Julien Breux <julien.breux@gmail.com>
*/
class LogmaticFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\JsonFormatter
{
protected const MARKERS = ["sourcecode", "php"];
/**
* @var string
*/
protected $hostname = '';
/**
* @var string
*/
protected $appname = '';
public function setHostname(string $hostname) : self
{
$this->hostname = $hostname;
return $this;
}
public function setAppname(string $appname) : self
{
$this->appname = $appname;
return $this;
}
/**
* Appends the 'hostname' and 'appname' parameter for indexing by Logmatic.
*
* @see http://doc.logmatic.io/docs/basics-to-send-data
* @see \Monolog\Formatter\JsonFormatter::format()
*/
public function format(array $record) : string
{
if (!empty($this->hostname)) {
$record["hostname"] = $this->hostname;
}
if (!empty($this->appname)) {
$record["appname"] = $this->appname;
}
$record["@marker"] = static::MARKERS;
return parent::format($record);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -13,15 +14,13 @@ namespace WPMailSMTP\Vendor\Monolog\Formatter;
/**
* Serializes a log message to Logstash Event Format
*
* @see http://logstash.net/
* @see https://github.com/logstash/logstash/blob/master/lib/logstash/event.rb
* @see https://www.elastic.co/products/logstash
* @see https://github.com/elastic/logstash/blob/master/logstash-core/src/main/java/org/logstash/Event.java
*
* @author Tim Mower <timothy.mower@gmail.com>
*/
class LogstashFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter
{
const V0 = 0;
const V1 = 1;
/**
* @var string the name of the system for the Logstash log message, used to fill the @source field
*/
@@ -31,90 +30,38 @@ class LogstashFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerF
*/
protected $applicationName;
/**
* @var string a prefix for 'extra' fields from the Monolog record (optional)
* @var string the key for 'extra' fields from the Monolog record
*/
protected $extraPrefix;
protected $extraKey;
/**
* @var string a prefix for 'context' fields from the Monolog record (optional)
* @var string the key for 'context' fields from the Monolog record
*/
protected $contextPrefix;
protected $contextKey;
/**
* @var int logstash format version to use
* @param string $applicationName The application that sends the data, used as the "type" field of logstash
* @param string|null $systemName The system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine
* @param string $extraKey The key for extra keys inside logstash "fields", defaults to extra
* @param string $contextKey The key for context keys inside logstash "fields", defaults to context
*/
protected $version;
/**
* @param string $applicationName the application that sends the data, used as the "type" field of logstash
* @param string $systemName the system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine
* @param string $extraPrefix prefix for extra keys inside logstash "fields"
* @param string $contextPrefix prefix for context keys inside logstash "fields", defaults to ctxt_
* @param int $version the logstash format version to use, defaults to 0
*/
public function __construct($applicationName, $systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_', $version = self::V0)
public function __construct(string $applicationName, ?string $systemName = null, string $extraKey = 'extra', string $contextKey = 'context')
{
// logstash requires a ISO 8601 format date with optional millisecond precision.
parent::__construct('Y-m-d\\TH:i:s.uP');
$this->systemName = $systemName ?: \gethostname();
$this->systemName = $systemName === null ? (string) \gethostname() : $systemName;
$this->applicationName = $applicationName;
$this->extraPrefix = $extraPrefix;
$this->contextPrefix = $contextPrefix;
$this->version = $version;
$this->extraKey = $extraKey;
$this->contextKey = $contextKey;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function format(array $record)
public function format(array $record) : string
{
$record = parent::format($record);
if ($this->version === self::V1) {
$message = $this->formatV1($record);
} else {
$message = $this->formatV0($record);
}
return $this->toJson($message) . "\n";
}
protected function formatV0(array $record)
{
if (empty($record['datetime'])) {
$record['datetime'] = \gmdate('c');
}
$message = array('@timestamp' => $record['datetime'], '@source' => $this->systemName, '@fields' => array());
if (isset($record['message'])) {
$message['@message'] = $record['message'];
}
if (isset($record['channel'])) {
$message['@tags'] = array($record['channel']);
$message['@fields']['channel'] = $record['channel'];
}
if (isset($record['level'])) {
$message['@fields']['level'] = $record['level'];
}
if ($this->applicationName) {
$message['@type'] = $this->applicationName;
}
if (isset($record['extra']['server'])) {
$message['@source_host'] = $record['extra']['server'];
}
if (isset($record['extra']['url'])) {
$message['@source_path'] = $record['extra']['url'];
}
if (!empty($record['extra'])) {
foreach ($record['extra'] as $key => $val) {
$message['@fields'][$this->extraPrefix . $key] = $val;
}
}
if (!empty($record['context'])) {
foreach ($record['context'] as $key => $val) {
$message['@fields'][$this->contextPrefix . $key] = $val;
}
}
return $message;
}
protected function formatV1(array $record)
{
if (empty($record['datetime'])) {
$record['datetime'] = \gmdate('c');
}
$message = array('@timestamp' => $record['datetime'], '@version' => 1, 'host' => $this->systemName);
$message = ['@timestamp' => $record['datetime'], '@version' => 1, 'host' => $this->systemName];
if (isset($record['message'])) {
$message['message'] = $record['message'];
}
@@ -125,19 +72,18 @@ class LogstashFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerF
if (isset($record['level_name'])) {
$message['level'] = $record['level_name'];
}
if (isset($record['level'])) {
$message['monolog_level'] = $record['level'];
}
if ($this->applicationName) {
$message['type'] = $this->applicationName;
}
if (!empty($record['extra'])) {
foreach ($record['extra'] as $key => $val) {
$message[$this->extraPrefix . $key] = $val;
}
$message[$this->extraKey] = $record['extra'];
}
if (!empty($record['context'])) {
foreach ($record['context'] as $key => $val) {
$message[$this->contextPrefix . $key] = $val;
}
$message[$this->contextKey] = $record['context'];
}
return $message;
return $this->toJson($message) . "\n";
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,6 +11,8 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Formatter;
use MongoDB\BSON\Type;
use MongoDB\BSON\UTCDateTime;
use WPMailSMTP\Vendor\Monolog\Utils;
/**
* Formats a record for use with the MongoDBHandler.
@@ -18,62 +21,84 @@ use WPMailSMTP\Vendor\Monolog\Utils;
*/
class MongoDBFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
/** @var bool */
private $exceptionTraceAsString;
/** @var int */
private $maxNestingLevel;
/** @var bool */
private $isLegacyMongoExt;
/**
* @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2
* @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings
*/
public function __construct($maxNestingLevel = 3, $exceptionTraceAsString = \true)
public function __construct(int $maxNestingLevel = 3, bool $exceptionTraceAsString = \true)
{
$this->maxNestingLevel = \max($maxNestingLevel, 0);
$this->exceptionTraceAsString = (bool) $exceptionTraceAsString;
$this->exceptionTraceAsString = $exceptionTraceAsString;
$this->isLegacyMongoExt = \extension_loaded('mongodb') && \version_compare((string) \phpversion('mongodb'), '1.1.9', '<=');
}
/**
* {@inheritDoc}
*
* @return mixed[]
*/
public function format(array $record)
public function format(array $record) : array
{
return $this->formatArray($record);
/** @var mixed[] $res */
$res = $this->formatArray($record);
return $res;
}
/**
* {@inheritDoc}
*
* @return array<mixed[]>
*/
public function formatBatch(array $records)
public function formatBatch(array $records) : array
{
$formatted = [];
foreach ($records as $key => $record) {
$records[$key] = $this->format($record);
$formatted[$key] = $this->format($record);
}
return $records;
return $formatted;
}
protected function formatArray(array $record, $nestingLevel = 0)
/**
* @param mixed[] $array
* @return mixed[]|string Array except when max nesting level is reached then a string "[...]"
*/
protected function formatArray(array $array, int $nestingLevel = 0)
{
if ($this->maxNestingLevel == 0 || $nestingLevel <= $this->maxNestingLevel) {
foreach ($record as $name => $value) {
if ($value instanceof \DateTime) {
$record[$name] = $this->formatDate($value, $nestingLevel + 1);
} elseif ($value instanceof \Exception) {
$record[$name] = $this->formatException($value, $nestingLevel + 1);
} elseif (\is_array($value)) {
$record[$name] = $this->formatArray($value, $nestingLevel + 1);
} elseif (\is_object($value)) {
$record[$name] = $this->formatObject($value, $nestingLevel + 1);
}
}
} else {
$record = '[...]';
if ($this->maxNestingLevel > 0 && $nestingLevel > $this->maxNestingLevel) {
return '[...]';
}
return $record;
foreach ($array as $name => $value) {
if ($value instanceof \DateTimeInterface) {
$array[$name] = $this->formatDate($value, $nestingLevel + 1);
} elseif ($value instanceof \Throwable) {
$array[$name] = $this->formatException($value, $nestingLevel + 1);
} elseif (\is_array($value)) {
$array[$name] = $this->formatArray($value, $nestingLevel + 1);
} elseif (\is_object($value) && !$value instanceof \MongoDB\BSON\Type) {
$array[$name] = $this->formatObject($value, $nestingLevel + 1);
}
}
return $array;
}
protected function formatObject($value, $nestingLevel)
/**
* @param mixed $value
* @return mixed[]|string
*/
protected function formatObject($value, int $nestingLevel)
{
$objectVars = \get_object_vars($value);
$objectVars['class'] = \WPMailSMTP\Vendor\Monolog\Utils::getClass($value);
return $this->formatArray($objectVars, $nestingLevel);
}
protected function formatException(\Exception $exception, $nestingLevel)
/**
* @return mixed[]|string
*/
protected function formatException(\Throwable $exception, int $nestingLevel)
{
$formattedException = array('class' => \WPMailSMTP\Vendor\Monolog\Utils::getClass($exception), 'message' => $exception->getMessage(), 'code' => (int) $exception->getCode(), 'file' => $exception->getFile() . ':' . $exception->getLine());
$formattedException = ['class' => \WPMailSMTP\Vendor\Monolog\Utils::getClass($exception), 'message' => $exception->getMessage(), 'code' => (int) $exception->getCode(), 'file' => $exception->getFile() . ':' . $exception->getLine()];
if ($this->exceptionTraceAsString === \true) {
$formattedException['trace'] = $exception->getTraceAsString();
} else {
@@ -81,8 +106,29 @@ class MongoDBFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\Formatter
}
return $this->formatArray($formattedException, $nestingLevel);
}
protected function formatDate(\DateTime $value, $nestingLevel)
protected function formatDate(\DateTimeInterface $value, int $nestingLevel) : \MongoDB\BSON\UTCDateTime
{
return new \MongoDate($value->getTimestamp());
if ($this->isLegacyMongoExt) {
return $this->legacyGetMongoDbDateTime($value);
}
return $this->getMongoDbDateTime($value);
}
private function getMongoDbDateTime(\DateTimeInterface $value) : \MongoDB\BSON\UTCDateTime
{
return new \MongoDB\BSON\UTCDateTime((int) \floor((float) $value->format('U.u') * 1000));
}
/**
* This is needed to support MongoDB Driver v1.19 and below
*
* See https://github.com/mongodb/mongo-php-driver/issues/426
*
* It can probably be removed in 2.1 or later once MongoDB's 1.2 is released and widely adopted
*/
private function legacyGetMongoDbDateTime(\DateTimeInterface $value) : \MongoDB\BSON\UTCDateTime
{
$milliseconds = \floor((float) $value->format('U.u') * 1000);
$milliseconds = \PHP_INT_SIZE == 8 ? (int) $milliseconds : (string) $milliseconds;
// @phpstan-ignore-next-line
return new \MongoDB\BSON\UTCDateTime($milliseconds);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,8 +11,9 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Formatter;
use Exception;
use WPMailSMTP\Vendor\Monolog\DateTimeImmutable;
use WPMailSMTP\Vendor\Monolog\Utils;
use Throwable;
/**
* Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
*
@@ -19,30 +21,36 @@ use WPMailSMTP\Vendor\Monolog\Utils;
*/
class NormalizerFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
const SIMPLE_DATE = "Y-m-d H:i:s";
public const SIMPLE_DATE = "Y-m-d\\TH:i:sP";
/** @var string */
protected $dateFormat;
protected $maxDepth;
/** @var int */
protected $maxNormalizeDepth = 9;
/** @var int */
protected $maxNormalizeItemCount = 1000;
/** @var int */
private $jsonEncodeOptions = \WPMailSMTP\Vendor\Monolog\Utils::DEFAULT_JSON_FLAGS;
/**
* @param string $dateFormat The format of the timestamp: one supported by DateTime::format
* @param int $maxDepth
* @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
*/
public function __construct($dateFormat = null, $maxDepth = 9)
public function __construct(?string $dateFormat = null)
{
$this->dateFormat = $dateFormat ?: static::SIMPLE_DATE;
$this->maxDepth = $maxDepth;
$this->dateFormat = null === $dateFormat ? static::SIMPLE_DATE : $dateFormat;
if (!\function_exists('json_encode')) {
throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter');
}
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @param mixed[] $record
*/
public function format(array $record)
{
return $this->normalize($record);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function formatBatch(array $records)
{
@@ -51,24 +59,59 @@ class NormalizerFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\Format
}
return $records;
}
/**
* @return int
*/
public function getMaxDepth()
public function getDateFormat() : string
{
return $this->maxDepth;
return $this->dateFormat;
}
public function setDateFormat(string $dateFormat) : self
{
$this->dateFormat = $dateFormat;
return $this;
}
/**
* @param int $maxDepth
* The maximum number of normalization levels to go through
*/
public function setMaxDepth($maxDepth)
public function getMaxNormalizeDepth() : int
{
$this->maxDepth = $maxDepth;
return $this->maxNormalizeDepth;
}
protected function normalize($data, $depth = 0)
public function setMaxNormalizeDepth(int $maxNormalizeDepth) : self
{
if ($depth > $this->maxDepth) {
return 'Over ' . $this->maxDepth . ' levels deep, aborting normalization';
$this->maxNormalizeDepth = $maxNormalizeDepth;
return $this;
}
/**
* The maximum number of items to normalize per level
*/
public function getMaxNormalizeItemCount() : int
{
return $this->maxNormalizeItemCount;
}
public function setMaxNormalizeItemCount(int $maxNormalizeItemCount) : self
{
$this->maxNormalizeItemCount = $maxNormalizeItemCount;
return $this;
}
/**
* Enables `json_encode` pretty print.
*/
public function setJsonPrettyPrint(bool $enable) : self
{
if ($enable) {
$this->jsonEncodeOptions |= \JSON_PRETTY_PRINT;
} else {
$this->jsonEncodeOptions &= ~\JSON_PRETTY_PRINT;
}
return $this;
}
/**
* @param mixed $data
* @return null|scalar|array<array|scalar|null>
*/
protected function normalize($data, int $depth = 0)
{
if ($depth > $this->maxNormalizeDepth) {
return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
}
if (null === $data || \is_scalar($data)) {
if (\is_float($data)) {
@@ -82,46 +125,57 @@ class NormalizerFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\Format
return $data;
}
if (\is_array($data)) {
$normalized = array();
$normalized = [];
$count = 1;
foreach ($data as $key => $value) {
if ($count++ > 1000) {
$normalized['...'] = 'Over 1000 items (' . \count($data) . ' total), aborting normalization';
if ($count++ > $this->maxNormalizeItemCount) {
$normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items (' . \count($data) . ' total), aborting normalization';
break;
}
$normalized[$key] = $this->normalize($value, $depth + 1);
}
return $normalized;
}
if ($data instanceof \DateTime) {
return $data->format($this->dateFormat);
if ($data instanceof \DateTimeInterface) {
return $this->formatDate($data);
}
if (\is_object($data)) {
// TODO 2.0 only check for Throwable
if ($data instanceof \Exception || \PHP_VERSION_ID > 70000 && $data instanceof \Throwable) {
return $this->normalizeException($data);
if ($data instanceof \Throwable) {
return $this->normalizeException($data, $depth);
}
// non-serializable objects that implement __toString stringified
if (\method_exists($data, '__toString') && !$data instanceof \JsonSerializable) {
if ($data instanceof \JsonSerializable) {
/** @var null|scalar|array<array|scalar|null> $value */
$value = $data->jsonSerialize();
} elseif (\get_class($data) === '__PHP_Incomplete_Class') {
$accessor = new \ArrayObject($data);
$value = (string) $accessor['__PHP_Incomplete_Class_Name'];
} elseif (\method_exists($data, '__toString')) {
/** @var string $value */
$value = $data->__toString();
} else {
// the rest is json-serialized in some way
$value = $this->toJson($data, \true);
// the rest is normalized by json encoding and decoding it
/** @var null|scalar|array<array|scalar|null> $value */
$value = \json_decode($this->toJson($data, \true), \true);
}
return \sprintf("[object] (%s: %s)", \WPMailSMTP\Vendor\Monolog\Utils::getClass($data), $value);
return [\WPMailSMTP\Vendor\Monolog\Utils::getClass($data) => $value];
}
if (\is_resource($data)) {
return \sprintf('[resource] (%s)', \get_resource_type($data));
return \sprintf('[resource(%s)]', \get_resource_type($data));
}
return '[unknown(' . \gettype($data) . ')]';
}
protected function normalizeException($e)
/**
* @return mixed[]
*/
protected function normalizeException(\Throwable $e, int $depth = 0)
{
// TODO 2.0 only check for Throwable
if (!$e instanceof \Exception && !$e instanceof \Throwable) {
throw new \InvalidArgumentException('Exception/Throwable expected, got ' . \gettype($e) . ' / ' . \WPMailSMTP\Vendor\Monolog\Utils::getClass($e));
if ($depth > $this->maxNormalizeDepth) {
return ['Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization'];
}
$data = array('class' => \WPMailSMTP\Vendor\Monolog\Utils::getClass($e), 'message' => $e->getMessage(), 'code' => (int) $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine());
if ($e instanceof \JsonSerializable) {
return (array) $e->jsonSerialize();
}
$data = ['class' => \WPMailSMTP\Vendor\Monolog\Utils::getClass($e), 'message' => $e->getMessage(), 'code' => (int) $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine()];
if ($e instanceof \SoapFault) {
if (isset($e->faultcode)) {
$data['faultcode'] = $e->faultcode;
@@ -144,7 +198,7 @@ class NormalizerFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\Format
}
}
if ($previous = $e->getPrevious()) {
$data['previous'] = $this->normalizeException($previous);
$data['previous'] = $this->normalizeException($previous, $depth + 1);
}
return $data;
}
@@ -152,12 +206,33 @@ class NormalizerFormatter implements \WPMailSMTP\Vendor\Monolog\Formatter\Format
* Return the JSON representation of a value
*
* @param mixed $data
* @param bool $ignoreErrors
* @throws \RuntimeException if encoding fails and errors are not ignored
* @return string if encoding fails and ignoreErrors is true 'null' is returned
*/
protected function toJson($data, bool $ignoreErrors = \false) : string
{
return \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($data, $this->jsonEncodeOptions, $ignoreErrors);
}
/**
* @return string
*/
protected function toJson($data, $ignoreErrors = \false)
protected function formatDate(\DateTimeInterface $date)
{
return \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($data, null, $ignoreErrors);
// in case the date format isn't custom then we defer to the custom DateTimeImmutable
// formatting logic, which will pick the right format based on whether useMicroseconds is on
if ($this->dateFormat === self::SIMPLE_DATE && $date instanceof \WPMailSMTP\Vendor\Monolog\DateTimeImmutable) {
return (string) $date;
}
return $date->format($this->dateFormat);
}
public function addJsonEncodeOption(int $option) : self
{
$this->jsonEncodeOptions |= $option;
return $this;
}
public function removeJsonEncodeOption(int $option) : self
{
$this->jsonEncodeOptions &= ~$option;
return $this;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -19,23 +20,26 @@ namespace WPMailSMTP\Vendor\Monolog\Formatter;
class ScalarFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter
{
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @phpstan-return array<string, scalar|null> $record
*/
public function format(array $record)
public function format(array $record) : array
{
$result = [];
foreach ($record as $key => $value) {
$record[$key] = $this->normalizeValue($value);
$result[$key] = $this->normalizeValue($value);
}
return $record;
return $result;
}
/**
* @param mixed $value
* @return mixed
* @param mixed $value
* @return scalar|null
*/
protected function normalizeValue($value)
{
$normalized = $this->normalize($value);
if (\is_array($normalized) || \is_object($normalized)) {
if (\is_array($normalized)) {
return $this->toJson($normalized, \true);
}
return $normalized;

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -17,18 +18,32 @@ use WPMailSMTP\Vendor\Monolog\Logger;
* @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
* @author Christophe Coevoet <stof@notk.org>
* @author Kirill chEbba Chebunin <iam@chebba.org>
*
* @phpstan-import-type Level from \Monolog\Logger
*/
class WildfireFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter
{
const TABLE = 'table';
/**
* Translates Monolog log levels to Wildfire levels.
*
* @var array<Level, string>
*/
private $logLevels = array(\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => 'LOG', \WPMailSMTP\Vendor\Monolog\Logger::INFO => 'INFO', \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => 'INFO', \WPMailSMTP\Vendor\Monolog\Logger::WARNING => 'WARN', \WPMailSMTP\Vendor\Monolog\Logger::ERROR => 'ERROR', \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => 'ERROR', \WPMailSMTP\Vendor\Monolog\Logger::ALERT => 'ERROR', \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => 'ERROR');
private $logLevels = [\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => 'LOG', \WPMailSMTP\Vendor\Monolog\Logger::INFO => 'INFO', \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => 'INFO', \WPMailSMTP\Vendor\Monolog\Logger::WARNING => 'WARN', \WPMailSMTP\Vendor\Monolog\Logger::ERROR => 'ERROR', \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => 'ERROR', \WPMailSMTP\Vendor\Monolog\Logger::ALERT => 'ERROR', \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => 'ERROR'];
/**
* {@inheritdoc}
* @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
*/
public function format(array $record)
public function __construct(?string $dateFormat = null)
{
parent::__construct($dateFormat);
// http headers do not like non-ISO-8559-1 characters
$this->removeJsonEncodeOption(\JSON_UNESCAPED_UNICODE);
}
/**
* {@inheritDoc}
*
* @return string
*/
public function format(array $record) : string
{
// Retrieve the line and file if set and remove them from the formatted extra
$file = $line = '';
@@ -40,8 +55,9 @@ class WildfireFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerF
$line = $record['extra']['line'];
unset($record['extra']['line']);
}
/** @var mixed[] $record */
$record = $this->normalize($record);
$message = array('message' => $record['message']);
$message = ['message' => $record['message']];
$handleError = \false;
if ($record['context']) {
$message['context'] = $record['context'];
@@ -54,26 +70,36 @@ class WildfireFormatter extends \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerF
if (\count($message) === 1) {
$message = \reset($message);
}
if (isset($record['context'][self::TABLE])) {
if (isset($record['context']['table'])) {
$type = 'TABLE';
$label = $record['channel'] . ': ' . $record['message'];
$message = $record['context'][self::TABLE];
$message = $record['context']['table'];
} else {
$type = $this->logLevels[$record['level']];
$label = $record['channel'];
}
// Create JSON object describing the appearance of the message in the console
$json = $this->toJson(array(array('Type' => $type, 'File' => $file, 'Line' => $line, 'Label' => $label), $message), $handleError);
$json = $this->toJson([['Type' => $type, 'File' => $file, 'Line' => $line, 'Label' => $label], $message], $handleError);
// The message itself is a serialization of the above JSON object + it's length
return \sprintf('%s|%s|', \strlen($json), $json);
return \sprintf('%d|%s|', \strlen($json), $json);
}
/**
* {@inheritDoc}
*
* @phpstan-return never
*/
public function formatBatch(array $records)
{
throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
}
protected function normalize($data, $depth = 0)
/**
* {@inheritDoc}
*
* @return null|scalar|array<array|scalar|null>|object
*/
protected function normalize($data, int $depth = 0)
{
if (\is_object($data) && !$data instanceof \DateTime) {
if (\is_object($data) && !$data instanceof \DateTimeInterface) {
return $data;
}
return parent::normalize($data, $depth);

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,103 +11,51 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\ResettableInterface;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
/**
* Base Handler class providing the Handler structure
* Base Handler class providing basic level/bubble support
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Level from \Monolog\Logger
* @phpstan-import-type LevelName from \Monolog\Logger
*/
abstract class AbstractHandler implements \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface, \WPMailSMTP\Vendor\Monolog\ResettableInterface
abstract class AbstractHandler extends \WPMailSMTP\Vendor\Monolog\Handler\Handler implements \WPMailSMTP\Vendor\Monolog\ResettableInterface
{
protected $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG;
protected $bubble = \true;
/**
* @var FormatterInterface
* @var int
* @phpstan-var Level
*/
protected $formatter;
protected $processors = array();
protected $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG;
/** @var bool */
protected $bubble = \true;
/**
* @param int|string $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*
* @phpstan-param Level|LevelName|LogLevel::* $level
*/
public function __construct($level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct($level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
$this->setLevel($level);
$this->bubble = $bubble;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function isHandling(array $record)
public function isHandling(array $record) : bool
{
return $record['level'] >= $this->level;
}
/**
* {@inheritdoc}
*/
public function handleBatch(array $records)
{
foreach ($records as $record) {
$this->handle($record);
}
}
/**
* Closes the handler.
*
* This will be called automatically when the object is destroyed
*/
public function close()
{
}
/**
* {@inheritdoc}
*/
public function pushProcessor($callback)
{
if (!\is_callable($callback)) {
throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), ' . \var_export($callback, \true) . ' given');
}
\array_unshift($this->processors, $callback);
return $this;
}
/**
* {@inheritdoc}
*/
public function popProcessor()
{
if (!$this->processors) {
throw new \LogicException('You tried to pop from an empty processor stack.');
}
return \array_shift($this->processors);
}
/**
* {@inheritdoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
{
$this->formatter = $formatter;
return $this;
}
/**
* {@inheritdoc}
*/
public function getFormatter()
{
if (!$this->formatter) {
$this->formatter = $this->getDefaultFormatter();
}
return $this->formatter;
}
/**
* Sets minimum logging level at which this handler will be triggered.
*
* @param int|string $level Level or level name
* @param Level|LevelName|LogLevel::* $level Level or level name
* @return self
*/
public function setLevel($level)
public function setLevel($level) : self
{
$this->level = \WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($level);
return $this;
@@ -115,8 +64,10 @@ abstract class AbstractHandler implements \WPMailSMTP\Vendor\Monolog\Handler\Han
* Gets minimum logging level at which this handler will be triggered.
*
* @return int
*
* @phpstan-return Level
*/
public function getLevel()
public function getLevel() : int
{
return $this->level;
}
@@ -127,7 +78,7 @@ abstract class AbstractHandler implements \WPMailSMTP\Vendor\Monolog\Handler\Han
* false means that bubbling is not permitted.
* @return self
*/
public function setBubble($bubble)
public function setBubble(bool $bubble) : self
{
$this->bubble = $bubble;
return $this;
@@ -138,35 +89,14 @@ abstract class AbstractHandler implements \WPMailSMTP\Vendor\Monolog\Handler\Han
* @return bool true means that this handler allows bubbling.
* false means that bubbling is not permitted.
*/
public function getBubble()
public function getBubble() : bool
{
return $this->bubble;
}
public function __destruct()
{
try {
$this->close();
} catch (\Exception $e) {
// do nothing
} catch (\Throwable $e) {
// do nothing
}
}
/**
* {@inheritDoc}
*/
public function reset()
{
foreach ($this->processors as $processor) {
if ($processor instanceof \WPMailSMTP\Vendor\Monolog\ResettableInterface) {
$processor->reset();
}
}
}
/**
* Gets the default formatter.
*
* @return FormatterInterface
*/
protected function getDefaultFormatter()
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter();
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,26 +11,35 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\ResettableInterface;
/**
* Base Handler class providing the Handler structure
* Base Handler class providing the Handler structure, including processors and formatters
*
* Classes extending it should (in most cases) only implement write($record)
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Christophe Coevoet <stof@notk.org>
*
* @phpstan-import-type LevelName from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-type FormattedRecord array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[], formatted: mixed}
*/
abstract class AbstractProcessingHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
abstract class AbstractProcessingHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler implements \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface, \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface
{
use ProcessableHandlerTrait;
use FormattableHandlerTrait;
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handle(array $record)
public function handle(array $record) : bool
{
if (!$this->isHandling($record)) {
return \false;
}
$record = $this->processRecord($record);
if ($this->processors) {
/** @var Record $record */
$record = $this->processRecord($record);
}
$record['formatted'] = $this->getFormatter()->format($record);
$this->write($record);
return \false === $this->bubble;
@@ -37,23 +47,15 @@ abstract class AbstractProcessingHandler extends \WPMailSMTP\Vendor\Monolog\Hand
/**
* Writes the record down to the log of the implementing handler
*
* @param array $record
* @phpstan-param FormattedRecord $record
*/
protected abstract function write(array $record) : void;
/**
* @return void
*/
protected abstract function write(array $record);
/**
* Processes a record.
*
* @param array $record
* @return array
*/
protected function processRecord(array $record)
public function reset()
{
if ($this->processors) {
foreach ($this->processors as $processor) {
$record = \call_user_func($processor, $record);
}
}
return $record;
parent::reset();
$this->resetProcessors();
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,27 +12,32 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
/**
* Common syslog functionality
*
* @phpstan-import-type Level from \Monolog\Logger
*/
abstract class AbstractSyslogHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/** @var int */
protected $facility;
/**
* Translates Monolog log levels to syslog log priorities.
* @var array
* @phpstan-var array<Level, int>
*/
protected $logLevels = array(\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => \LOG_DEBUG, \WPMailSMTP\Vendor\Monolog\Logger::INFO => \LOG_INFO, \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => \LOG_NOTICE, \WPMailSMTP\Vendor\Monolog\Logger::WARNING => \LOG_WARNING, \WPMailSMTP\Vendor\Monolog\Logger::ERROR => \LOG_ERR, \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => \LOG_CRIT, \WPMailSMTP\Vendor\Monolog\Logger::ALERT => \LOG_ALERT, \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => \LOG_EMERG);
protected $logLevels = [\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => \LOG_DEBUG, \WPMailSMTP\Vendor\Monolog\Logger::INFO => \LOG_INFO, \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => \LOG_NOTICE, \WPMailSMTP\Vendor\Monolog\Logger::WARNING => \LOG_WARNING, \WPMailSMTP\Vendor\Monolog\Logger::ERROR => \LOG_ERR, \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => \LOG_CRIT, \WPMailSMTP\Vendor\Monolog\Logger::ALERT => \LOG_ALERT, \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => \LOG_EMERG];
/**
* List of valid log facility names.
* @var array<string, int>
*/
protected $facilities = array('auth' => \LOG_AUTH, 'authpriv' => \LOG_AUTHPRIV, 'cron' => \LOG_CRON, 'daemon' => \LOG_DAEMON, 'kern' => \LOG_KERN, 'lpr' => \LOG_LPR, 'mail' => \LOG_MAIL, 'news' => \LOG_NEWS, 'syslog' => \LOG_SYSLOG, 'user' => \LOG_USER, 'uucp' => \LOG_UUCP);
protected $facilities = ['auth' => \LOG_AUTH, 'authpriv' => \LOG_AUTHPRIV, 'cron' => \LOG_CRON, 'daemon' => \LOG_DAEMON, 'kern' => \LOG_KERN, 'lpr' => \LOG_LPR, 'mail' => \LOG_MAIL, 'news' => \LOG_NEWS, 'syslog' => \LOG_SYSLOG, 'user' => \LOG_USER, 'uucp' => \LOG_UUCP];
/**
* @param mixed $facility
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
*/
public function __construct($facility = \LOG_USER, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct($facility = \LOG_USER, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
parent::__construct($level, $bubble);
if (!\defined('PHP_WINDOWS_VERSION_BUILD')) {
@@ -62,7 +68,7 @@ abstract class AbstractSyslogHandler extends \WPMailSMTP\Vendor\Monolog\Handler\
// LOG_LOCAL7
}
// convert textual description of facility to syslog constant
if (\array_key_exists(\strtolower($facility), $this->facilities)) {
if (\is_string($facility) && \array_key_exists(\strtolower($facility), $this->facilities)) {
$facility = $this->facilities[\strtolower($facility)];
} elseif (!\in_array($facility, \array_values($this->facilities), \true)) {
throw new \UnexpectedValueException('Unknown facility value "' . $facility . '" given');
@@ -70,9 +76,9 @@ abstract class AbstractSyslogHandler extends \WPMailSMTP\Vendor\Monolog\Handler\
$this->facility = $facility;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter('%channel%.%level_name%: %message% %context% %extra%');
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,34 +12,59 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\JsonFormatter;
use WPMailSMTP\Vendor\PhpAmqpLib\Message\AMQPMessage;
use WPMailSMTP\Vendor\PhpAmqpLib\Channel\AMQPChannel;
use AMQPExchange;
/**
* @phpstan-import-type Record from \Monolog\Logger
*/
class AmqpHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/**
* @var AMQPExchange|AMQPChannel $exchange
*/
protected $exchange;
/** @var array<string, mixed> */
private $extraAttributes = [];
/**
* @return array<string, mixed>
*/
public function getExtraAttributes() : array
{
return $this->extraAttributes;
}
/**
* Configure extra attributes to pass to the AMQPExchange (if you are using the amqp extension)
*
* @param array<string, mixed> $extraAttributes One of content_type, content_encoding,
* message_id, user_id, app_id, delivery_mode,
* priority, timestamp, expiration, type
* or reply_to, headers.
* @return AmqpHandler
*/
public function setExtraAttributes(array $extraAttributes) : self
{
$this->extraAttributes = $extraAttributes;
return $this;
}
/**
* @var string
*/
protected $exchangeName;
/**
* @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use
* @param string $exchangeName
* @param int $level
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param string|null $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only
*/
public function __construct($exchange, $exchangeName = 'log', $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct($exchange, ?string $exchangeName = null, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
if ($exchange instanceof \AMQPExchange) {
$exchange->setName($exchangeName);
} elseif ($exchange instanceof \WPMailSMTP\Vendor\PhpAmqpLib\Channel\AMQPChannel) {
$this->exchangeName = $exchangeName;
} else {
if ($exchange instanceof \WPMailSMTP\Vendor\PhpAmqpLib\Channel\AMQPChannel) {
$this->exchangeName = (string) $exchangeName;
} elseif (!$exchange instanceof \AMQPExchange) {
throw new \InvalidArgumentException('PhpAmqpLib\\Channel\\AMQPChannel or AMQPExchange instance required');
} elseif ($exchangeName) {
@\trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', \E_USER_DEPRECATED);
}
$this->exchange = $exchange;
parent::__construct($level, $bubble);
@@ -46,12 +72,16 @@ class AmqpHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingH
/**
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$data = $record["formatted"];
$routingKey = $this->getRoutingKey($record);
if ($this->exchange instanceof \AMQPExchange) {
$this->exchange->publish($data, $routingKey, 0, array('delivery_mode' => 2, 'content_type' => 'application/json'));
$attributes = ['delivery_mode' => 2, 'content_type' => 'application/json'];
if ($this->extraAttributes) {
$attributes = \array_merge($attributes, $this->extraAttributes);
}
$this->exchange->publish($data, $routingKey, 0, $attributes);
} else {
$this->exchange->basic_publish($this->createAmqpMessage($data), $this->exchangeName, $routingKey);
}
@@ -59,7 +89,7 @@ class AmqpHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingH
/**
* {@inheritDoc}
*/
public function handleBatch(array $records)
public function handleBatch(array $records) : void
{
if ($this->exchange instanceof \AMQPExchange) {
parent::handleBatch($records);
@@ -69,6 +99,7 @@ class AmqpHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingH
if (!$this->isHandling($record)) {
continue;
}
/** @var Record $record */
$record = $this->processRecord($record);
$data = $this->getFormatter()->format($record);
$this->exchange->batch_basic_publish($this->createAmqpMessage($data), $this->exchangeName, $this->getRoutingKey($record));
@@ -78,31 +109,25 @@ class AmqpHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingH
/**
* Gets the routing key for the AMQP exchange
*
* @param array $record
* @return string
* @phpstan-param Record $record
*/
protected function getRoutingKey(array $record)
protected function getRoutingKey(array $record) : string
{
$routingKey = \sprintf(
'%s.%s',
// TODO 2.0 remove substr call
\substr($record['level_name'], 0, 4),
$record['channel']
);
$routingKey = \sprintf('%s.%s', $record['level_name'], $record['channel']);
return \strtolower($routingKey);
}
/**
* @param string $data
* @return AMQPMessage
*/
private function createAmqpMessage($data)
private function createAmqpMessage(string $data) : \WPMailSMTP\Vendor\PhpAmqpLib\Message\AMQPMessage
{
return new \WPMailSMTP\Vendor\PhpAmqpLib\Message\AMQPMessage((string) $data, array('delivery_mode' => 2, 'content_type' => 'application/json'));
$attributes = ['delivery_mode' => 2, 'content_type' => 'application/json'];
if ($this->extraAttributes) {
$attributes = \array_merge($attributes, $this->extraAttributes);
}
return new \WPMailSMTP\Vendor\PhpAmqpLib\Message\AMQPMessage($data, $attributes);
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\JsonFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\JsonFormatter::BATCH_MODE_JSON, \false);
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,16 +11,31 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
use WPMailSMTP\Vendor\Monolog\Utils;
use WPMailSMTP\Vendor\Monolog\Logger;
use function count;
use function headers_list;
use function stripos;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
* Handler sending logs to browser's javascript console with no browser extension required
*
* @author Olivier Poitrey <rs@dailymotion.com>
*
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class BrowserConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/** @var bool */
protected static $initialized = \false;
protected static $records = array();
/** @var FormattedRecord[] */
protected static $records = [];
protected const FORMAT_HTML = 'html';
protected const FORMAT_JS = 'js';
protected const FORMAT_UNKNOWN = 'unknown';
/**
* {@inheritDoc}
*
@@ -29,14 +45,14 @@ class BrowserConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractP
*
* You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%');
}
/**
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
// Accumulate records
static::$records[] = $record;
@@ -50,51 +66,50 @@ class BrowserConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractP
* Convert records to javascript console commands and send it to the browser.
* This method is automatically called on PHP shutdown if output is HTML or Javascript.
*/
public static function send()
public static function send() : void
{
$format = static::getResponseFormat();
if ($format === 'unknown') {
if ($format === self::FORMAT_UNKNOWN) {
return;
}
if (\count(static::$records)) {
if ($format === 'html') {
if ($format === self::FORMAT_HTML) {
static::writeOutput('<script>' . static::generateScript() . '</script>');
} elseif ($format === 'js') {
} elseif ($format === self::FORMAT_JS) {
static::writeOutput(static::generateScript());
}
static::resetStatic();
}
}
public function close()
public function close() : void
{
self::resetStatic();
}
public function reset()
{
parent::reset();
self::resetStatic();
}
/**
* Forget all logged records
*/
public static function resetStatic()
public static function resetStatic() : void
{
static::$records = array();
static::$records = [];
}
/**
* Wrapper for register_shutdown_function to allow overriding
*/
protected function registerShutdownFunction()
protected function registerShutdownFunction() : void
{
if (\PHP_SAPI !== 'cli') {
\register_shutdown_function(array('WPMailSMTP\\Vendor\\Monolog\\Handler\\BrowserConsoleHandler', 'send'));
\register_shutdown_function(['WPMailSMTP\\Vendor\\Monolog\\Handler\\BrowserConsoleHandler', 'send']);
}
}
/**
* Wrapper for echo to allow overriding
*
* @param string $str
*/
protected static function writeOutput($str)
protected static function writeOutput(string $str) : void
{
echo $str;
}
@@ -106,59 +121,75 @@ class BrowserConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractP
* If Content-Type is anything else -> unknown
*
* @return string One of 'js', 'html' or 'unknown'
* @phpstan-return self::FORMAT_*
*/
protected static function getResponseFormat()
protected static function getResponseFormat() : string
{
// Check content type
foreach (\headers_list() as $header) {
if (\stripos($header, 'content-type:') === 0) {
// This handler only works with HTML and javascript outputs
// text/javascript is obsolete in favour of application/javascript, but still used
if (\stripos($header, 'application/javascript') !== \false || \stripos($header, 'text/javascript') !== \false) {
return 'js';
}
if (\stripos($header, 'text/html') === \false) {
return 'unknown';
}
break;
return static::getResponseFormatFromContentType($header);
}
}
return 'html';
return self::FORMAT_HTML;
}
private static function generateScript()
/**
* @return string One of 'js', 'html' or 'unknown'
* @phpstan-return self::FORMAT_*
*/
protected static function getResponseFormatFromContentType(string $contentType) : string
{
$script = array();
// This handler only works with HTML and javascript outputs
// text/javascript is obsolete in favour of application/javascript, but still used
if (\stripos($contentType, 'application/javascript') !== \false || \stripos($contentType, 'text/javascript') !== \false) {
return self::FORMAT_JS;
}
if (\stripos($contentType, 'text/html') !== \false) {
return self::FORMAT_HTML;
}
return self::FORMAT_UNKNOWN;
}
private static function generateScript() : string
{
$script = [];
foreach (static::$records as $record) {
$context = static::dump('Context', $record['context']);
$extra = static::dump('Extra', $record['extra']);
if (empty($context) && empty($extra)) {
$script[] = static::call_array('log', static::handleStyles($record['formatted']));
$script[] = static::call_array(static::getConsoleMethodForLevel($record['level']), static::handleStyles($record['formatted']));
} else {
$script = \array_merge($script, array(static::call_array('groupCollapsed', static::handleStyles($record['formatted']))), $context, $extra, array(static::call('groupEnd')));
$script = \array_merge($script, [static::call_array('groupCollapsed', static::handleStyles($record['formatted']))], $context, $extra, [static::call('groupEnd')]);
}
}
return "(function (c) {if (c && c.groupCollapsed) {\n" . \implode("\n", $script) . "\n}})(console);";
}
private static function handleStyles($formatted)
private static function getConsoleMethodForLevel(int $level) : string
{
$args = array();
return [\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => 'debug', \WPMailSMTP\Vendor\Monolog\Logger::INFO => 'info', \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => 'info', \WPMailSMTP\Vendor\Monolog\Logger::WARNING => 'warn', \WPMailSMTP\Vendor\Monolog\Logger::ERROR => 'error', \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => 'error', \WPMailSMTP\Vendor\Monolog\Logger::ALERT => 'error', \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => 'error'][$level] ?? 'log';
}
/**
* @return string[]
*/
private static function handleStyles(string $formatted) : array
{
$args = [];
$format = '%c' . $formatted;
\preg_match_all('/\\[\\[(.*?)\\]\\]\\{([^}]*)\\}/s', $format, $matches, \PREG_OFFSET_CAPTURE | \PREG_SET_ORDER);
foreach (\array_reverse($matches) as $match) {
$args[] = '"font-weight: normal"';
$args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0]));
$pos = $match[0][1];
$format = \substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . \substr($format, $pos + \strlen($match[0][0]));
$format = \WPMailSMTP\Vendor\Monolog\Utils::substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . \WPMailSMTP\Vendor\Monolog\Utils::substr($format, $pos + \strlen($match[0][0]));
}
$args[] = static::quote('font-weight: normal');
$args[] = static::quote($format);
return \array_reverse($args);
}
private static function handleCustomStyles($style, $string)
private static function handleCustomStyles(string $style, string $string) : string
{
static $colors = array('blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey');
static $labels = array();
return \preg_replace_callback('/macro\\s*:(.*?)(?:;|$)/', function ($m) use($string, &$colors, &$labels) {
static $colors = ['blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'];
static $labels = [];
$style = \preg_replace_callback('/macro\\s*:(.*?)(?:;|$)/', function (array $m) use($string, &$colors, &$labels) {
if (\trim($m[1]) === 'autolabel') {
// Format the string as a label with consistent auto assigned background color
if (!isset($labels[$string])) {
@@ -169,10 +200,19 @@ class BrowserConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractP
}
return $m[1];
}, $style);
if (null === $style) {
$pcreErrorCode = \preg_last_error();
throw new \RuntimeException('Failed to run preg_replace_callback: ' . $pcreErrorCode . ' / ' . \WPMailSMTP\Vendor\Monolog\Utils::pcreLastErrorMessage($pcreErrorCode));
}
return $style;
}
private static function dump($title, array $dict)
/**
* @param mixed[] $dict
* @return mixed[]
*/
private static function dump(string $title, array $dict) : array
{
$script = array();
$script = [];
$dict = \array_filter($dict);
if (empty($dict)) {
return $script;
@@ -183,21 +223,29 @@ class BrowserConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractP
if (empty($value)) {
$value = static::quote('');
}
$script[] = static::call('log', static::quote('%s: %o'), static::quote($key), $value);
$script[] = static::call('log', static::quote('%s: %o'), static::quote((string) $key), $value);
}
return $script;
}
private static function quote($arg)
private static function quote(string $arg) : string
{
return '"' . \addcslashes($arg, "\"\n\\") . '"';
}
private static function call()
/**
* @param mixed $args
*/
private static function call(...$args) : string
{
$args = \func_get_args();
$method = \array_shift($args);
if (!\is_string($method)) {
throw new \UnexpectedValueException('Expected the first arg to be a string, got: ' . \var_export($method, \true));
}
return static::call_array($method, $args);
}
private static function call_array($method, array $args)
/**
* @param mixed[] $args
*/
private static function call_array(string $method, array $args) : string
{
return 'c.' . $method . '(' . \implode(', ', $args) . ');';
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -20,40 +21,47 @@ use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
* sending one per log message.
*
* @author Christophe Coevoet <stof@notk.org>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
class BufferHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
class BufferHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler implements \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface, \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface
{
use ProcessableHandlerTrait;
/** @var HandlerInterface */
protected $handler;
/** @var int */
protected $bufferSize = 0;
/** @var int */
protected $bufferLimit;
/** @var bool */
protected $flushOnOverflow;
protected $buffer = array();
/** @var Record[] */
protected $buffer = [];
/** @var bool */
protected $initialized = \false;
/**
* @param HandlerInterface $handler Handler.
* @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
*/
public function __construct(\WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface $handler, $bufferLimit = 0, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true, $flushOnOverflow = \false)
public function __construct(\WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface $handler, int $bufferLimit = 0, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, bool $flushOnOverflow = \false)
{
parent::__construct($level, $bubble);
$this->handler = $handler;
$this->bufferLimit = (int) $bufferLimit;
$this->bufferLimit = $bufferLimit;
$this->flushOnOverflow = $flushOnOverflow;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handle(array $record)
public function handle(array $record) : bool
{
if ($record['level'] < $this->level) {
return \false;
}
if (!$this->initialized) {
// __destructor() doesn't get called on Fatal errors
\register_shutdown_function(array($this, 'close'));
\register_shutdown_function([$this, 'close']);
$this->initialized = \true;
}
if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) {
@@ -65,15 +73,14 @@ class BufferHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
}
}
if ($this->processors) {
foreach ($this->processors as $processor) {
$record = \call_user_func($processor, $record);
}
/** @var Record $record */
$record = $this->processRecord($record);
}
$this->buffer[] = $record;
$this->bufferSize++;
return \false === $this->bubble;
}
public function flush()
public function flush() : void
{
if ($this->bufferSize === 0) {
return;
@@ -88,41 +95,49 @@ class BufferHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
// GC'd until the end of the request
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function close()
public function close() : void
{
$this->flush();
$this->handler->close();
}
/**
* Clears the buffer without flushing any messages down to the wrapped handler.
*/
public function clear()
public function clear() : void
{
$this->bufferSize = 0;
$this->buffer = array();
$this->buffer = [];
}
public function reset()
{
$this->flush();
parent::reset();
$this->resetProcessors();
if ($this->handler instanceof \WPMailSMTP\Vendor\Monolog\ResettableInterface) {
$this->handler->reset();
}
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
$this->handler->setFormatter($formatter);
return $this;
if ($this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
$this->handler->setFormatter($formatter);
return $this;
}
throw new \UnexpectedValueException('The nested handler of type ' . \get_class($this->handler) . ' does not support formatters.');
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getFormatter()
public function getFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return $this->handler->getFormatter();
if ($this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
return $this->handler->getFormatter();
}
throw new \UnexpectedValueException('The nested handler of type ' . \get_class($this->handler) . ' does not support formatters.');
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,6 +12,7 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\ChromePHPFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
/**
@@ -19,21 +21,25 @@ use WPMailSMTP\Vendor\Monolog\Utils;
* This also works out of the box with Firefox 43+
*
* @author Christophe Coevoet <stof@notk.org>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
class ChromePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
use WebRequestRecognizerTrait;
/**
* Version of the extension
*/
const VERSION = '4.0';
protected const VERSION = '4.0';
/**
* Header name
*/
const HEADER_NAME = 'X-ChromeLogger-Data';
protected const HEADER_NAME = 'X-ChromeLogger-Data';
/**
* Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+)
*/
const USER_AGENT_REGEX = '{\\b(?:Chrome/\\d+(?:\\.\\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\\d|\\d{3,})(?:\\.\\d)*)\\b}';
protected const USER_AGENT_REGEX = '{\\b(?:Chrome/\\d+(?:\\.\\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\\d|\\d{3,})(?:\\.\\d)*)\\b}';
/** @var bool */
protected static $initialized = \false;
/**
* Tracks whether we sent too much data
@@ -43,13 +49,11 @@ class ChromePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProces
* @var bool
*/
protected static $overflowed = \false;
protected static $json = array('version' => self::VERSION, 'columns' => array('label', 'log', 'backtrace', 'type'), 'rows' => array());
/** @var mixed[] */
protected static $json = ['version' => self::VERSION, 'columns' => ['label', 'log', 'backtrace', 'type'], 'rows' => []];
/** @var bool */
protected static $sendHeaders = \true;
/**
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct($level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
parent::__construct($level, $bubble);
if (!\function_exists('json_encode')) {
@@ -57,16 +61,21 @@ class ChromePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProces
}
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handleBatch(array $records)
public function handleBatch(array $records) : void
{
$messages = array();
if (!$this->isWebRequest()) {
return;
}
$messages = [];
foreach ($records as $record) {
if ($record['level'] < $this->level) {
continue;
}
$messages[] = $this->processRecord($record);
/** @var Record $message */
$message = $this->processRecord($record);
$messages[] = $message;
}
if (!empty($messages)) {
$messages = $this->getFormatter()->formatBatch($messages);
@@ -77,7 +86,7 @@ class ChromePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProces
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\ChromePHPFormatter();
}
@@ -86,10 +95,12 @@ class ChromePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProces
*
* @see sendHeader()
* @see send()
* @param array $record
*/
protected function write(array $record)
protected function write(array $record) : void
{
if (!$this->isWebRequest()) {
return;
}
self::$json['rows'][] = $record['formatted'];
$this->send();
}
@@ -98,7 +109,7 @@ class ChromePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProces
*
* @see sendHeader()
*/
protected function send()
protected function send() : void
{
if (self::$overflowed || !self::$sendHeaders) {
return;
@@ -109,28 +120,25 @@ class ChromePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProces
if (!self::$sendHeaders) {
return;
}
self::$json['request_uri'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
self::$json['request_uri'] = $_SERVER['REQUEST_URI'] ?? '';
}
$json = \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode(self::$json, null, \true);
$data = \base64_encode(\utf8_encode($json));
$json = \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode(self::$json, \WPMailSMTP\Vendor\Monolog\Utils::DEFAULT_JSON_FLAGS & ~\JSON_UNESCAPED_UNICODE, \true);
$data = \base64_encode($json);
if (\strlen($data) > 3 * 1024) {
self::$overflowed = \true;
$record = array('message' => 'Incomplete logs, chrome header size limit reached', 'context' => array(), 'level' => \WPMailSMTP\Vendor\Monolog\Logger::WARNING, 'level_name' => \WPMailSMTP\Vendor\Monolog\Logger::getLevelName(\WPMailSMTP\Vendor\Monolog\Logger::WARNING), 'channel' => 'monolog', 'datetime' => new \DateTime(), 'extra' => array());
$record = ['message' => 'Incomplete logs, chrome header size limit reached', 'context' => [], 'level' => \WPMailSMTP\Vendor\Monolog\Logger::WARNING, 'level_name' => \WPMailSMTP\Vendor\Monolog\Logger::getLevelName(\WPMailSMTP\Vendor\Monolog\Logger::WARNING), 'channel' => 'monolog', 'datetime' => new \DateTimeImmutable(), 'extra' => []];
self::$json['rows'][\count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
$json = \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode(self::$json, null, \true);
$data = \base64_encode(\utf8_encode($json));
$json = \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode(self::$json, \WPMailSMTP\Vendor\Monolog\Utils::DEFAULT_JSON_FLAGS & ~\JSON_UNESCAPED_UNICODE, \true);
$data = \base64_encode($json);
}
if (\trim($data) !== '') {
$this->sendHeader(self::HEADER_NAME, $data);
$this->sendHeader(static::HEADER_NAME, $data);
}
}
/**
* Send header string to the client
*
* @param string $header
* @param string $content
*/
protected function sendHeader($header, $content)
protected function sendHeader(string $header, string $content) : void
{
if (!\headers_sent() && self::$sendHeaders) {
\header(\sprintf('%s: %s', $header, $content));
@@ -138,34 +146,12 @@ class ChromePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProces
}
/**
* Verifies if the headers are accepted by the current user agent
*
* @return bool
*/
protected function headersAccepted()
protected function headersAccepted() : bool
{
if (empty($_SERVER['HTTP_USER_AGENT'])) {
return \false;
}
return \preg_match(self::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']);
}
/**
* BC getter for the sendHeaders property that has been made static
*/
public function __get($property)
{
if ('sendHeaders' !== $property) {
throw new \InvalidArgumentException('Undefined property ' . $property);
}
return static::$sendHeaders;
}
/**
* BC setter for the sendHeaders property that has been made static
*/
public function __set($property, $value)
{
if ('sendHeaders' !== $property) {
throw new \InvalidArgumentException('Undefined property ' . $property);
}
static::$sendHeaders = $value;
return \preg_match(static::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']) === 1;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,6 +11,7 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\JsonFormatter;
use WPMailSMTP\Vendor\Monolog\Logger;
/**
@@ -19,31 +21,35 @@ use WPMailSMTP\Vendor\Monolog\Logger;
*/
class CouchDBHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/** @var mixed[] */
private $options;
public function __construct(array $options = array(), $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
/**
* @param mixed[] $options
*/
public function __construct(array $options = [], $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
$this->options = \array_merge(array('host' => 'localhost', 'port' => 5984, 'dbname' => 'logger', 'username' => null, 'password' => null), $options);
$this->options = \array_merge(['host' => 'localhost', 'port' => 5984, 'dbname' => 'logger', 'username' => null, 'password' => null], $options);
parent::__construct($level, $bubble);
}
/**
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$basicAuth = null;
if ($this->options['username']) {
$basicAuth = \sprintf('%s:%s@', $this->options['username'], $this->options['password']);
}
$url = 'http://' . $basicAuth . $this->options['host'] . ':' . $this->options['port'] . '/' . $this->options['dbname'];
$context = \stream_context_create(array('http' => array('method' => 'POST', 'content' => $record['formatted'], 'ignore_errors' => \true, 'max_redirects' => 0, 'header' => 'Content-type: application/json')));
if (\false === @\file_get_contents($url, null, $context)) {
$context = \stream_context_create(['http' => ['method' => 'POST', 'content' => $record['formatted'], 'ignore_errors' => \true, 'max_redirects' => 0, 'header' => 'Content-type: application/json']]);
if (\false === @\file_get_contents($url, \false, $context)) {
throw new \RuntimeException(\sprintf('Could not connect to %s', $url));
}
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\JsonFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\JsonFormatter::BATCH_MODE_JSON, \false);
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -15,17 +16,24 @@ use WPMailSMTP\Vendor\Monolog\Utils;
/**
* Logs to Cube.
*
* @link http://square.github.com/cube/
* @link https://github.com/square/cube/wiki
* @author Wan Chen <kami@kamisama.me>
* @deprecated Since 2.8.0 and 3.2.0, Cube appears abandoned and thus we will drop this handler in Monolog 4
*/
class CubeHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
private $udpConnection;
private $httpConnection;
/** @var resource|\Socket|null */
private $udpConnection = null;
/** @var resource|\CurlHandle|null */
private $httpConnection = null;
/** @var string */
private $scheme;
/** @var string */
private $host;
/** @var int */
private $port;
private $acceptedSchemes = array('http', 'udp');
/** @var string[] */
private $acceptedSchemes = ['http', 'udp'];
/**
* Create a Cube handler
*
@@ -33,10 +41,10 @@ class CubeHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingH
* A valid url must consist of three parts : protocol://host:port
* Only valid protocols used by Cube are http and udp
*/
public function __construct($url, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct(string $url, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
$urlInfo = \parse_url($url);
if (!isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) {
if ($urlInfo === \false || !isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) {
throw new \UnexpectedValueException('URL "' . $url . '" is not valid');
}
if (!\in_array($urlInfo['scheme'], $this->acceptedSchemes)) {
@@ -44,7 +52,7 @@ class CubeHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingH
}
$this->scheme = $urlInfo['scheme'];
$this->host = $urlInfo['host'];
$this->port = $urlInfo['port'];
$this->port = (int) $urlInfo['port'];
parent::__construct($level, $bubble);
}
/**
@@ -53,42 +61,46 @@ class CubeHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingH
* @throws \LogicException when unable to connect to the socket
* @throws MissingExtensionException when there is no socket extension
*/
protected function connectUdp()
protected function connectUdp() : void
{
if (!\extension_loaded('sockets')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler');
}
$this->udpConnection = \socket_create(\AF_INET, \SOCK_DGRAM, 0);
if (!$this->udpConnection) {
$udpConnection = \socket_create(\AF_INET, \SOCK_DGRAM, 0);
if (\false === $udpConnection) {
throw new \LogicException('Unable to create a socket');
}
$this->udpConnection = $udpConnection;
if (!\socket_connect($this->udpConnection, $this->host, $this->port)) {
throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port);
}
}
/**
* Establish a connection to a http server
* @throws \LogicException when no curl extension
* Establish a connection to an http server
*
* @throws \LogicException when unable to connect to the socket
* @throws MissingExtensionException when no curl extension
*/
protected function connectHttp()
protected function connectHttp() : void
{
if (!\extension_loaded('curl')) {
throw new \LogicException('The curl extension is needed to use http URLs with the CubeHandler');
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The curl extension is required to use http URLs with the CubeHandler');
}
$this->httpConnection = \curl_init('http://' . $this->host . ':' . $this->port . '/1.0/event/put');
if (!$this->httpConnection) {
$httpConnection = \curl_init('http://' . $this->host . ':' . $this->port . '/1.0/event/put');
if (\false === $httpConnection) {
throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port);
}
$this->httpConnection = $httpConnection;
\curl_setopt($this->httpConnection, \CURLOPT_CUSTOMREQUEST, "POST");
\curl_setopt($this->httpConnection, \CURLOPT_RETURNTRANSFER, \true);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$date = $record['datetime'];
$data = array('time' => $date->format('Y-m-d\\TH:i:s.uO'));
$data = ['time' => $date->format('Y-m-d\\TH:i:s.uO')];
unset($record['datetime']);
if (isset($record['context']['type'])) {
$data['type'] = $record['context']['type'];
@@ -104,20 +116,23 @@ class CubeHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingH
$this->writeUdp(\WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($data));
}
}
private function writeUdp($data)
private function writeUdp(string $data) : void
{
if (!$this->udpConnection) {
$this->connectUdp();
}
\socket_send($this->udpConnection, $data, \strlen($data), 0);
}
private function writeHttp($data)
private function writeHttp(string $data) : void
{
if (!$this->httpConnection) {
$this->connectHttp();
}
if (null === $this->httpConnection) {
throw new \LogicException('No connection could be established');
}
\curl_setopt($this->httpConnection, \CURLOPT_POSTFIELDS, '[' . $data . ']');
\curl_setopt($this->httpConnection, \CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Content-Length: ' . \strlen('[' . $data . ']')));
\curl_setopt($this->httpConnection, \CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Content-Length: ' . \strlen('[' . $data . ']')]);
\WPMailSMTP\Vendor\Monolog\Handler\Curl\Util::execute($this->httpConnection, 5, \false);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,33 +11,44 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler\Curl;
class Util
use CurlHandle;
/**
* This class is marked as internal and it is not under the BC promise of the package.
*
* @internal
*/
final class Util
{
private static $retriableErrorCodes = array(\CURLE_COULDNT_RESOLVE_HOST, \CURLE_COULDNT_CONNECT, \CURLE_HTTP_NOT_FOUND, \CURLE_READ_ERROR, \CURLE_OPERATION_TIMEOUTED, \CURLE_HTTP_POST_ERROR, \CURLE_SSL_CONNECT_ERROR);
/** @var array<int> */
private static $retriableErrorCodes = [\CURLE_COULDNT_RESOLVE_HOST, \CURLE_COULDNT_CONNECT, \CURLE_HTTP_NOT_FOUND, \CURLE_READ_ERROR, \CURLE_OPERATION_TIMEOUTED, \CURLE_HTTP_POST_ERROR, \CURLE_SSL_CONNECT_ERROR];
/**
* Executes a CURL request with optional retries and exception on failure
*
* @param resource $ch curl handler
* @throws \RuntimeException
* @param resource|CurlHandle $ch curl handler
* @param int $retries
* @param bool $closeAfterDone
* @return bool|string @see curl_exec
*/
public static function execute($ch, $retries = 5, $closeAfterDone = \true)
public static function execute($ch, int $retries = 5, bool $closeAfterDone = \true)
{
while ($retries--) {
if (\curl_exec($ch) === \false) {
$curlResponse = \curl_exec($ch);
if ($curlResponse === \false) {
$curlErrno = \curl_errno($ch);
if (\false === \in_array($curlErrno, self::$retriableErrorCodes, \true) || !$retries) {
$curlError = \curl_error($ch);
if ($closeAfterDone) {
\curl_close($ch);
}
throw new \RuntimeException(\sprintf('Curl error (code %s): %s', $curlErrno, $curlError));
throw new \RuntimeException(\sprintf('Curl error (code %d): %s', $curlErrno, $curlError));
}
continue;
}
if ($closeAfterDone) {
\curl_close($ch);
}
break;
return $curlResponse;
}
return \false;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,6 +12,7 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
/**
* Simple handler wrapper that deduplicates log records across multiple requests
*
@@ -30,6 +32,10 @@ use WPMailSMTP\Vendor\Monolog\Logger;
* same way.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type LevelName from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger
*/
class DeduplicationHandler extends \WPMailSMTP\Vendor\Monolog\Handler\BufferHandler
{
@@ -38,7 +44,7 @@ class DeduplicationHandler extends \WPMailSMTP\Vendor\Monolog\Handler\BufferHand
*/
protected $deduplicationStore;
/**
* @var int
* @var Level
*/
protected $deduplicationLevel;
/**
@@ -52,18 +58,20 @@ class DeduplicationHandler extends \WPMailSMTP\Vendor\Monolog\Handler\BufferHand
/**
* @param HandlerInterface $handler Handler.
* @param string $deduplicationStore The file/path where the deduplication log should be kept
* @param int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
* @param string|int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
* @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*
* @phpstan-param Level|LevelName|LogLevel::* $deduplicationLevel
*/
public function __construct(\WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface $handler, $deduplicationStore = null, $deduplicationLevel = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, $time = 60, $bubble = \true)
public function __construct(\WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface $handler, ?string $deduplicationStore = null, $deduplicationLevel = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, int $time = 60, bool $bubble = \true)
{
parent::__construct($handler, 0, \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble, \false);
$this->deduplicationStore = $deduplicationStore === null ? \sys_get_temp_dir() . '/monolog-dedup-' . \substr(\md5(__FILE__), 0, 20) . '.log' : $deduplicationStore;
$this->deduplicationLevel = \WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($deduplicationLevel);
$this->time = $time;
}
public function flush()
public function flush() : void
{
if ($this->bufferSize === 0) {
return;
@@ -86,7 +94,10 @@ class DeduplicationHandler extends \WPMailSMTP\Vendor\Monolog\Handler\BufferHand
$this->collectLogs();
}
}
private function isDuplicate(array $record)
/**
* @phpstan-param Record $record
*/
private function isDuplicate(array $record) : bool
{
if (!\file_exists($this->deduplicationStore)) {
return \false;
@@ -109,18 +120,21 @@ class DeduplicationHandler extends \WPMailSMTP\Vendor\Monolog\Handler\BufferHand
}
return \false;
}
private function collectLogs()
private function collectLogs() : void
{
if (!\file_exists($this->deduplicationStore)) {
return \false;
return;
}
$handle = \fopen($this->deduplicationStore, 'rw+');
if (!$handle) {
throw new \RuntimeException('Failed to open file for reading and writing: ' . $this->deduplicationStore);
}
\flock($handle, \LOCK_EX);
$validLogs = array();
$validLogs = [];
$timestampValidity = \time() - $this->time;
while (!\feof($handle)) {
$log = \fgets($handle);
if (\substr($log, 0, 10) >= $timestampValidity) {
if ($log && \substr($log, 0, 10) >= $timestampValidity) {
$validLogs[] = $log;
}
}
@@ -133,7 +147,10 @@ class DeduplicationHandler extends \WPMailSMTP\Vendor\Monolog\Handler\BufferHand
\fclose($handle);
$this->gc = \false;
}
private function appendRecord(array $record)
/**
* @phpstan-param Record $record
*/
private function appendRecord(array $record) : void
{
\file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . \preg_replace('{[\\r\\n].*}', '', $record['message']) . "\n", \FILE_APPEND);
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -12,6 +13,7 @@ namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Doctrine\CouchDB\CouchDBClient;
/**
* CouchDB handler for Doctrine CouchDB ODM
@@ -20,8 +22,9 @@ use WPMailSMTP\Vendor\Doctrine\CouchDB\CouchDBClient;
*/
class DoctrineCouchDBHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/** @var CouchDBClient */
private $client;
public function __construct(\WPMailSMTP\Vendor\Doctrine\CouchDB\CouchDBClient $client, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct(\WPMailSMTP\Vendor\Doctrine\CouchDB\CouchDBClient $client, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
$this->client = $client;
parent::__construct($level, $bubble);
@@ -29,11 +32,11 @@ class DoctrineCouchDBHandler extends \WPMailSMTP\Vendor\Monolog\Handler\Abstract
/**
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$this->client->postDocument($record['formatted']);
}
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter();
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -12,6 +13,7 @@ namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Aws\Sdk;
use WPMailSMTP\Vendor\Aws\DynamoDb\DynamoDbClient;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Aws\DynamoDb\Marshaler;
use WPMailSMTP\Vendor\Monolog\Formatter\ScalarFormatter;
use WPMailSMTP\Vendor\Monolog\Logger;
@@ -23,7 +25,7 @@ use WPMailSMTP\Vendor\Monolog\Logger;
*/
class DynamoDbHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
const DATE_FORMAT = 'Y-m-d\\TH:i:s.uO';
public const DATE_FORMAT = 'Y-m-d\\TH:i:s.uO';
/**
* @var DynamoDbClient
*/
@@ -40,14 +42,9 @@ class DynamoDbHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
* @var Marshaler
*/
protected $marshaler;
/**
* @param DynamoDbClient $client
* @param string $table
* @param int $level
* @param bool $bubble
*/
public function __construct(\WPMailSMTP\Vendor\Aws\DynamoDb\DynamoDbClient $client, $table, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct(\WPMailSMTP\Vendor\Aws\DynamoDb\DynamoDbClient $client, string $table, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
/** @phpstan-ignore-next-line */
if (\defined('Aws\\Sdk::VERSION') && \version_compare(\WPMailSMTP\Vendor\Aws\Sdk::VERSION, '3.0', '>=')) {
$this->version = 3;
$this->marshaler = new \WPMailSMTP\Vendor\Aws\DynamoDb\Marshaler();
@@ -59,9 +56,9 @@ class DynamoDbHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
parent::__construct($level, $bubble);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$filtered = $this->filterEmptyFields($record['formatted']);
if ($this->version === 3) {
@@ -70,22 +67,22 @@ class DynamoDbHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
/** @phpstan-ignore-next-line */
$formatted = $this->client->formatAttributes($filtered);
}
$this->client->putItem(array('TableName' => $this->table, 'Item' => $formatted));
$this->client->putItem(['TableName' => $this->table, 'Item' => $formatted]);
}
/**
* @param array $record
* @return array
* @param mixed[] $record
* @return mixed[]
*/
protected function filterEmptyFields(array $record)
protected function filterEmptyFields(array $record) : array
{
return \array_filter($record, function ($value) {
return !empty($value) || \false === $value || 0 === $value;
});
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\ScalarFormatter(self::DATE_FORMAT);
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,6 +11,7 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Elastica\Document;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\ElasticaFormatter;
use WPMailSMTP\Vendor\Monolog\Logger;
@@ -23,88 +25,87 @@ use WPMailSMTP\Vendor\Elastica\Exception\ExceptionInterface;
* $client = new \Elastica\Client();
* $options = array(
* 'index' => 'elastic_index_name',
* 'type' => 'elastic_doc_type',
* 'type' => 'elastic_doc_type', Types have been removed in Elastica 7
* );
* $handler = new ElasticSearchHandler($client, $options);
* $handler = new ElasticaHandler($client, $options);
* $log = new Logger('application');
* $log->pushHandler($handler);
*
* @author Jelle Vink <jelle.vink@gmail.com>
*/
class ElasticSearchHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
class ElasticaHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/**
* @var Client
*/
protected $client;
/**
* @var array Handler config options
* @var mixed[] Handler config options
*/
protected $options = array();
protected $options = [];
/**
* @param Client $client Elastica Client object
* @param array $options Handler configuration
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param Client $client Elastica Client object
* @param mixed[] $options Handler configuration
*/
public function __construct(\WPMailSMTP\Vendor\Elastica\Client $client, array $options = array(), $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct(\WPMailSMTP\Vendor\Elastica\Client $client, array $options = [], $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
parent::__construct($level, $bubble);
$this->client = $client;
$this->options = \array_merge(array(
$this->options = \array_merge([
'index' => 'monolog',
// Elastic index name
'type' => 'record',
// Elastic document type
'ignore_error' => \false,
), $options);
], $options);
}
/**
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$this->bulkSend(array($record['formatted']));
$this->bulkSend([$record['formatted']]);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
if ($formatter instanceof \WPMailSMTP\Vendor\Monolog\Formatter\ElasticaFormatter) {
return parent::setFormatter($formatter);
}
throw new \InvalidArgumentException('ElasticSearchHandler is only compatible with ElasticaFormatter');
throw new \InvalidArgumentException('ElasticaHandler is only compatible with ElasticaFormatter');
}
/**
* Getter options
* @return array
* @return mixed[]
*/
public function getOptions()
public function getOptions() : array
{
return $this->options;
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\ElasticaFormatter($this->options['index'], $this->options['type']);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handleBatch(array $records)
public function handleBatch(array $records) : void
{
$documents = $this->getFormatter()->formatBatch($records);
$this->bulkSend($documents);
}
/**
* Use Elasticsearch bulk API to send list of documents
* @param array $documents
*
* @param Document[] $documents
*
* @throws \RuntimeException
*/
protected function bulkSend(array $documents)
protected function bulkSend(array $documents) : void
{
try {
$this->client->addDocuments($documents);

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,7 +12,9 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
/**
* Stores to PHP error_log() handler.
*
@@ -19,20 +22,20 @@ use WPMailSMTP\Vendor\Monolog\Logger;
*/
class ErrorLogHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
const OPERATING_SYSTEM = 0;
const SAPI = 4;
public const OPERATING_SYSTEM = 0;
public const SAPI = 4;
/** @var int */
protected $messageType;
/** @var bool */
protected $expandNewlines;
/**
* @param int $messageType Says where the error should go.
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
*/
public function __construct($messageType = self::OPERATING_SYSTEM, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true, $expandNewlines = \false)
public function __construct(int $messageType = self::OPERATING_SYSTEM, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, bool $expandNewlines = \false)
{
parent::__construct($level, $bubble);
if (\false === \in_array($messageType, self::getAvailableTypes())) {
if (\false === \in_array($messageType, self::getAvailableTypes(), \true)) {
$message = \sprintf('The given message type "%s" is not supported', \print_r($messageType, \true));
throw new \InvalidArgumentException($message);
}
@@ -40,31 +43,35 @@ class ErrorLogHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
$this->expandNewlines = $expandNewlines;
}
/**
* @return array With all available types
* @return int[] With all available types
*/
public static function getAvailableTypes()
public static function getAvailableTypes() : array
{
return array(self::OPERATING_SYSTEM, self::SAPI);
return [self::OPERATING_SYSTEM, self::SAPI];
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%');
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
if ($this->expandNewlines) {
$lines = \preg_split('{[\\r\\n]+}', (string) $record['formatted']);
foreach ($lines as $line) {
\error_log($line, $this->messageType);
}
} else {
if (!$this->expandNewlines) {
\error_log((string) $record['formatted'], $this->messageType);
return;
}
$lines = \preg_split('{[\\r\\n]+}', (string) $record['formatted']);
if ($lines === \false) {
$pcreErrorCode = \preg_last_error();
throw new \RuntimeException('Failed to preg_split formatted string: ' . $pcreErrorCode . ' / ' . \WPMailSMTP\Vendor\Monolog\Utils::pcreLastErrorMessage($pcreErrorCode));
}
foreach ($lines as $line) {
\error_log($line, $this->messageType);
}
}
}

View File

@@ -0,0 +1,67 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use Throwable;
/**
* Forwards records to at most one handler
*
* If a handler fails, the exception is suppressed and the record is forwarded to the next handler.
*
* As soon as one handler handles a record successfully, the handling stops there.
*
* @phpstan-import-type Record from \Monolog\Logger
*/
class FallbackGroupHandler extends \WPMailSMTP\Vendor\Monolog\Handler\GroupHandler
{
/**
* {@inheritDoc}
*/
public function handle(array $record) : bool
{
if ($this->processors) {
/** @var Record $record */
$record = $this->processRecord($record);
}
foreach ($this->handlers as $handler) {
try {
$handler->handle($record);
break;
} catch (\Throwable $e) {
// What throwable?
}
}
return \false === $this->bubble;
}
/**
* {@inheritDoc}
*/
public function handleBatch(array $records) : void
{
if ($this->processors) {
$processed = [];
foreach ($records as $record) {
$processed[] = $this->processRecord($record);
}
/** @var Record[] $records */
$records = $processed;
}
foreach ($this->handlers as $handler) {
try {
$handler->handleBatch($records);
break;
} catch (\Throwable $e) {
// What throwable?
}
}
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,7 +12,9 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\ResettableInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
/**
* Simple handler wrapper that filters records based on a list of levels
*
@@ -19,19 +22,26 @@ use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
*
* @author Hennadiy Verkh
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger
* @phpstan-import-type LevelName from \Monolog\Logger
*/
class FilterHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
class FilterHandler extends \WPMailSMTP\Vendor\Monolog\Handler\Handler implements \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface, \WPMailSMTP\Vendor\Monolog\ResettableInterface, \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface
{
use ProcessableHandlerTrait;
/**
* Handler or factory callable($record, $this)
*
* @var callable|\Monolog\Handler\HandlerInterface
* @var callable|HandlerInterface
* @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface
*/
protected $handler;
/**
* Minimum level for logs that are passed to handler
*
* @var int[]
* @phpstan-var array<Level, int>
*/
protected $acceptedLevels;
/**
@@ -41,12 +51,17 @@ class FilterHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
*/
protected $bubble;
/**
* @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler
*
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $filterHandler).
* @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
* @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
* @param int|string $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*
* @phpstan-param Level|LevelName|LogLevel::*|array<Level|LevelName|LogLevel::*> $minLevelOrList
* @phpstan-param Level|LevelName|LogLevel::* $maxLevel
*/
public function __construct($handler, $minLevelOrList = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $maxLevel = \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY, $bubble = \true)
public function __construct($handler, $minLevelOrList = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $maxLevel = \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY, bool $bubble = \true)
{
$this->handler = $handler;
$this->bubble = $bubble;
@@ -56,17 +71,20 @@ class FilterHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
}
}
/**
* @return array
* @phpstan-return array<int, Level>
*/
public function getAcceptedLevels()
public function getAcceptedLevels() : array
{
return \array_flip($this->acceptedLevels);
}
/**
* @param int|string|array $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided
* @param int|string $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array
*
* @phpstan-param Level|LevelName|LogLevel::*|array<Level|LevelName|LogLevel::*> $minLevelOrList
* @phpstan-param Level|LevelName|LogLevel::* $maxLevel
*/
public function setAcceptedLevels($minLevelOrList = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $maxLevel = \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY)
public function setAcceptedLevels($minLevelOrList = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $maxLevel = \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY) : self
{
if (\is_array($minLevelOrList)) {
$acceptedLevels = \array_map('WPMailSMTP\\Vendor\\Monolog\\Logger::toMonologLevel', $minLevelOrList);
@@ -78,36 +96,36 @@ class FilterHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
}));
}
$this->acceptedLevels = \array_flip($acceptedLevels);
return $this;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function isHandling(array $record)
public function isHandling(array $record) : bool
{
return isset($this->acceptedLevels[$record['level']]);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handle(array $record)
public function handle(array $record) : bool
{
if (!$this->isHandling($record)) {
return \false;
}
if ($this->processors) {
foreach ($this->processors as $processor) {
$record = \call_user_func($processor, $record);
}
/** @var Record $record */
$record = $this->processRecord($record);
}
$this->getHandler($record)->handle($record);
return \false === $this->bubble;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handleBatch(array $records)
public function handleBatch(array $records) : void
{
$filtered = array();
$filtered = [];
foreach ($records as $record) {
if ($this->isHandling($record)) {
$filtered[] = $record;
@@ -123,11 +141,13 @@ class FilterHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
*
* @return HandlerInterface
*
* @phpstan-param Record $record
*/
public function getHandler(array $record = null)
public function getHandler(?array $record = null)
{
if (!$this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface) {
$this->handler = \call_user_func($this->handler, $record, $this);
$this->handler = ($this->handler)($record, $this);
if (!$this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
@@ -135,18 +155,33 @@ class FilterHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
return $this->handler;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
$this->getHandler()->setFormatter($formatter);
return $this;
$handler = $this->getHandler();
if ($handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
$handler->setFormatter($formatter);
return $this;
}
throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getFormatter()
public function getFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return $this->getHandler()->getFormatter();
$handler = $this->getHandler();
if ($handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
return $handler->getFormatter();
}
throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
}
public function reset()
{
$this->resetProcessors();
if ($this->getHandler() instanceof \WPMailSMTP\Vendor\Monolog\ResettableInterface) {
$this->getHandler()->reset();
}
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -14,14 +15,15 @@ namespace WPMailSMTP\Vendor\Monolog\Handler\FingersCrossed;
* Interface for activation strategies for the FingersCrossedHandler.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
interface ActivationStrategyInterface
{
/**
* Returns whether the given record activates the handler.
*
* @param array $record
* @return bool
* @phpstan-param Record $record
*/
public function isHandlerActivated(array $record);
public function isHandlerActivated(array $record) : bool;
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,6 +12,7 @@
namespace WPMailSMTP\Vendor\Monolog\Handler\FingersCrossed;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
/**
* Channel and Error level based monolog activation strategy. Allows to trigger activation
* based on level per channel. e.g. trigger activation on level 'ERROR' by default, except
@@ -30,21 +32,37 @@ use WPMailSMTP\Vendor\Monolog\Logger;
* </code>
*
* @author Mike Meessen <netmikey@gmail.com>
*
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger
* @phpstan-import-type LevelName from \Monolog\Logger
*/
class ChannelLevelActivationStrategy implements \WPMailSMTP\Vendor\Monolog\Handler\FingersCrossed\ActivationStrategyInterface
{
/**
* @var Level
*/
private $defaultActionLevel;
/**
* @var array<string, Level>
*/
private $channelToActionLevel;
/**
* @param int $defaultActionLevel The default action level to be used if the record's category doesn't match any
* @param array $channelToActionLevel An array that maps channel names to action levels.
* @param int|string $defaultActionLevel The default action level to be used if the record's category doesn't match any
* @param array<string, int> $channelToActionLevel An array that maps channel names to action levels.
*
* @phpstan-param array<string, Level> $channelToActionLevel
* @phpstan-param Level|LevelName|LogLevel::* $defaultActionLevel
*/
public function __construct($defaultActionLevel, $channelToActionLevel = array())
public function __construct($defaultActionLevel, array $channelToActionLevel = [])
{
$this->defaultActionLevel = \WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($defaultActionLevel);
$this->channelToActionLevel = \array_map('WPMailSMTP\\Vendor\\Monolog\\Logger::toMonologLevel', $channelToActionLevel);
}
public function isHandlerActivated(array $record)
/**
* @phpstan-param Record $record
*/
public function isHandlerActivated(array $record) : bool
{
if (isset($this->channelToActionLevel[$record['channel']])) {
return $record['level'] >= $this->channelToActionLevel[$record['channel']];

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,19 +12,31 @@
namespace WPMailSMTP\Vendor\Monolog\Handler\FingersCrossed;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
/**
* Error level based activation strategy.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*
* @phpstan-import-type Level from \Monolog\Logger
* @phpstan-import-type LevelName from \Monolog\Logger
*/
class ErrorLevelActivationStrategy implements \WPMailSMTP\Vendor\Monolog\Handler\FingersCrossed\ActivationStrategyInterface
{
/**
* @var Level
*/
private $actionLevel;
/**
* @param int|string $actionLevel Level or name or value
*
* @phpstan-param Level|LevelName|LogLevel::* $actionLevel
*/
public function __construct($actionLevel)
{
$this->actionLevel = \WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($actionLevel);
}
public function isHandlerActivated(array $record)
public function isHandlerActivated(array $record) : bool
{
return $record['level'] >= $this->actionLevel;
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -15,6 +16,7 @@ use WPMailSMTP\Vendor\Monolog\Handler\FingersCrossed\ActivationStrategyInterface
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\ResettableInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
/**
* Buffers all records until a certain level is reached
*
@@ -22,29 +24,58 @@ use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
* Only requests which actually trigger an error (or whatever your actionLevel is) will be
* in the logs, but they will contain all records, not only those above the level threshold.
*
* You can then have a passthruLevel as well which means that at the end of the request,
* even if it did not get activated, it will still send through log records of e.g. at least a
* warning level.
*
* You can find the various activation strategies in the
* Monolog\Handler\FingersCrossed\ namespace.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger
* @phpstan-import-type LevelName from \Monolog\Logger
*/
class FingersCrossedHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
class FingersCrossedHandler extends \WPMailSMTP\Vendor\Monolog\Handler\Handler implements \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface, \WPMailSMTP\Vendor\Monolog\ResettableInterface, \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface
{
protected $handler;
protected $activationStrategy;
protected $buffering = \true;
protected $bufferSize;
protected $buffer = array();
protected $stopBuffering;
protected $passthruLevel;
use ProcessableHandlerTrait;
/**
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $fingersCrossedHandler).
* @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action
* @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
* @param int $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
* @var callable|HandlerInterface
* @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface
*/
public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = \true, $stopBuffering = \true, $passthruLevel = null)
protected $handler;
/** @var ActivationStrategyInterface */
protected $activationStrategy;
/** @var bool */
protected $buffering = \true;
/** @var int */
protected $bufferSize;
/** @var Record[] */
protected $buffer = [];
/** @var bool */
protected $stopBuffering;
/**
* @var ?int
* @phpstan-var ?Level
*/
protected $passthruLevel;
/** @var bool */
protected $bubble;
/**
* @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler
*
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $fingersCrossedHandler).
* @param int|string|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated
* @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
* @param int|string $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
*
* @phpstan-param Level|LevelName|LogLevel::* $passthruLevel
* @phpstan-param Level|LevelName|LogLevel::*|ActivationStrategyInterface $activationStrategy
*/
public function __construct($handler, $activationStrategy = null, int $bufferSize = 0, bool $bubble = \true, bool $stopBuffering = \true, $passthruLevel = null)
{
if (null === $activationStrategy) {
$activationStrategy = new \WPMailSMTP\Vendor\Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy(\WPMailSMTP\Vendor\Monolog\Logger::WARNING);
@@ -66,32 +97,31 @@ class FingersCrossedHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractH
}
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function isHandling(array $record)
public function isHandling(array $record) : bool
{
return \true;
}
/**
* Manually activate this logger regardless of the activation strategy
*/
public function activate()
public function activate() : void
{
if ($this->stopBuffering) {
$this->buffering = \false;
}
$this->getHandler(\end($this->buffer) ?: null)->handleBatch($this->buffer);
$this->buffer = array();
$this->buffer = [];
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handle(array $record)
public function handle(array $record) : bool
{
if ($this->processors) {
foreach ($this->processors as $processor) {
$record = \call_user_func($processor, $record);
}
/** @var Record $record */
$record = $this->processRecord($record);
}
if ($this->buffering) {
$this->buffer[] = $record;
@@ -107,16 +137,17 @@ class FingersCrossedHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractH
return \false === $this->bubble;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function close()
public function close() : void
{
$this->flushBuffer();
$this->getHandler()->close();
}
public function reset()
{
$this->flushBuffer();
parent::reset();
$this->resetProcessors();
if ($this->getHandler() instanceof \WPMailSMTP\Vendor\Monolog\ResettableInterface) {
$this->getHandler()->reset();
}
@@ -126,15 +157,15 @@ class FingersCrossedHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractH
*
* It also resets the handler to its initial buffering state.
*/
public function clear()
public function clear() : void
{
$this->buffer = array();
$this->buffer = [];
$this->reset();
}
/**
* Resets the state of the handler. Stops forwarding records to the wrapped handler.
*/
private function flushBuffer()
private function flushBuffer() : void
{
if (null !== $this->passthruLevel) {
$level = $this->passthruLevel;
@@ -142,10 +173,10 @@ class FingersCrossedHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractH
return $record['level'] >= $level;
});
if (\count($this->buffer) > 0) {
$this->getHandler(\end($this->buffer) ?: null)->handleBatch($this->buffer);
$this->getHandler(\end($this->buffer))->handleBatch($this->buffer);
}
}
$this->buffer = array();
$this->buffer = [];
$this->buffering = \true;
}
/**
@@ -154,11 +185,13 @@ class FingersCrossedHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractH
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
*
* @return HandlerInterface
*
* @phpstan-param Record $record
*/
public function getHandler(array $record = null)
public function getHandler(?array $record = null)
{
if (!$this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface) {
$this->handler = \call_user_func($this->handler, $record, $this);
$this->handler = ($this->handler)($record, $this);
if (!$this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
@@ -166,18 +199,26 @@ class FingersCrossedHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractH
return $this->handler;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
$this->getHandler()->setFormatter($formatter);
return $this;
$handler = $this->getHandler();
if ($handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
$handler->setFormatter($formatter);
return $this;
}
throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getFormatter()
public function getFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return $this->getHandler()->getFormatter();
$handler = $this->getHandler();
if ($handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
return $handler->getFormatter();
}
throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,31 +12,36 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\WildfireFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
/**
* Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol.
*
* @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
*
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class FirePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
use WebRequestRecognizerTrait;
/**
* WildFire JSON header message format
*/
const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2';
protected const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2';
/**
* FirePHP structure for parsing messages & their presentation
*/
const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1';
protected const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1';
/**
* Must reference a "known" plugin, otherwise headers won't display in FirePHP
*/
const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3';
protected const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3';
/**
* Header prefix for Wildfire to recognize & parse headers
*/
const HEADER_PREFIX = 'X-Wf';
protected const HEADER_PREFIX = 'X-Wf';
/**
* Whether or not Wildfire vendor-specific headers have been generated & sent yet
* @var bool
*/
protected static $initialized = \false;
/**
@@ -43,36 +49,44 @@ class FirePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessi
* @var int
*/
protected static $messageIndex = 1;
/** @var bool */
protected static $sendHeaders = \true;
/**
* Base header creation function used by init headers & record headers
*
* @param array $meta Wildfire Plugin, Protocol & Structure Indexes
* @param string $message Log message
* @return array Complete header string ready for the client as key and message as value
* @param array<int|string> $meta Wildfire Plugin, Protocol & Structure Indexes
* @param string $message Log message
*
* @return array<string, string> Complete header string ready for the client as key and message as value
*
* @phpstan-return non-empty-array<string, string>
*/
protected function createHeader(array $meta, $message)
protected function createHeader(array $meta, string $message) : array
{
$header = \sprintf('%s-%s', self::HEADER_PREFIX, \join('-', $meta));
return array($header => $message);
$header = \sprintf('%s-%s', static::HEADER_PREFIX, \join('-', $meta));
return [$header => $message];
}
/**
* Creates message header from record
*
* @return array<string, string>
*
* @phpstan-return non-empty-array<string, string>
*
* @see createHeader()
* @param array $record
* @return array
*
* @phpstan-param FormattedRecord $record
*/
protected function createRecordHeader(array $record)
protected function createRecordHeader(array $record) : array
{
// Wildfire is extensible to support multiple protocols & plugins in a single request,
// but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake.
return $this->createHeader(array(1, 1, 1, self::$messageIndex++), $record['formatted']);
return $this->createHeader([1, 1, 1, self::$messageIndex++], $record['formatted']);
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\WildfireFormatter();
}
@@ -81,20 +95,18 @@ class FirePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessi
*
* @see createHeader()
* @see sendHeader()
* @return array
*
* @return array<string, string>
*/
protected function getInitHeaders()
protected function getInitHeaders() : array
{
// Initial payload consists of required headers for Wildfire
return \array_merge($this->createHeader(array('Protocol', 1), self::PROTOCOL_URI), $this->createHeader(array(1, 'Structure', 1), self::STRUCTURE_URI), $this->createHeader(array(1, 'Plugin', 1), self::PLUGIN_URI));
return \array_merge($this->createHeader(['Protocol', 1], static::PROTOCOL_URI), $this->createHeader([1, 'Structure', 1], static::STRUCTURE_URI), $this->createHeader([1, 'Plugin', 1], static::PLUGIN_URI));
}
/**
* Send header string to the client
*
* @param string $header
* @param string $content
*/
protected function sendHeader($header, $content)
protected function sendHeader(string $header, string $content) : void
{
if (!\headers_sent() && self::$sendHeaders) {
\header(\sprintf('%s: %s', $header, $content));
@@ -105,11 +117,10 @@ class FirePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessi
*
* @see sendHeader()
* @see sendInitHeaders()
* @param array $record
*/
protected function write(array $record)
protected function write(array $record) : void
{
if (!self::$sendHeaders) {
if (!self::$sendHeaders || !$this->isWebRequest()) {
return;
}
// WildFire-specific headers must be sent prior to any messages
@@ -130,34 +141,12 @@ class FirePHPHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessi
}
/**
* Verifies if the headers are accepted by the current user agent
*
* @return bool
*/
protected function headersAccepted()
protected function headersAccepted() : bool
{
if (!empty($_SERVER['HTTP_USER_AGENT']) && \preg_match('{\\bFirePHP/\\d+\\.\\d+\\b}', $_SERVER['HTTP_USER_AGENT'])) {
return \true;
}
return isset($_SERVER['HTTP_X_FIREPHP_VERSION']);
}
/**
* BC getter for the sendHeaders property that has been made static
*/
public function __get($property)
{
if ('sendHeaders' !== $property) {
throw new \InvalidArgumentException('Undefined property ' . $property);
}
return static::$sendHeaders;
}
/**
* BC setter for the sendHeaders property that has been made static
*/
public function __set($property, $value)
{
if ('sendHeaders' !== $property) {
throw new \InvalidArgumentException('Undefined property ' . $property);
}
static::$sendHeaders = $value;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,6 +11,7 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
use WPMailSMTP\Vendor\Monolog\Logger;
/**
@@ -19,11 +21,13 @@ use WPMailSMTP\Vendor\Monolog\Logger;
*
* @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation
* @author Ando Roots <ando@sqroot.eu>
*
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class FleepHookHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
{
const FLEEP_HOST = 'fleep.io';
const FLEEP_HOOK_URI = '/hook/';
protected const FLEEP_HOST = 'fleep.io';
protected const FLEEP_HOOK_URI = '/hook/';
/**
* @var string Webhook token (specifies the conversation where logs are sent)
*/
@@ -35,18 +39,16 @@ class FleepHookHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
* see https://fleep.io/integrations/webhooks/
*
* @param string $token Webhook token
* @param bool|int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @throws MissingExtensionException
*/
public function __construct($token, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct(string $token, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
{
if (!\extension_loaded('openssl')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler');
}
$this->token = $token;
$connectionString = 'ssl://' . self::FLEEP_HOST . ':443';
parent::__construct($connectionString, $level, $bubble);
$connectionString = 'ssl://' . static::FLEEP_HOST . ':443';
parent::__construct($connectionString, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
}
/**
* Returns the default formatter to use with this handler
@@ -55,41 +57,33 @@ class FleepHookHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
*
* @return LineFormatter
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter(null, null, \true, \true);
}
/**
* Handles a log record
*
* @param array $record
*/
public function write(array $record)
public function write(array $record) : void
{
parent::write($record);
$this->closeSocket();
}
/**
* {@inheritdoc}
*
* @param array $record
* @return string
* {@inheritDoc}
*/
protected function generateDataStream($record)
protected function generateDataStream(array $record) : string
{
$content = $this->buildContent($record);
return $this->buildHeader($content) . $content;
}
/**
* Builds the header of the API Call
*
* @param string $content
* @return string
*/
private function buildHeader($content)
private function buildHeader(string $content) : string
{
$header = "POST " . self::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n";
$header .= "Host: " . self::FLEEP_HOST . "\r\n";
$header = "POST " . static::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n";
$header .= "Host: " . static::FLEEP_HOST . "\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . \strlen($content) . "\r\n";
$header .= "\r\n";
@@ -98,12 +92,11 @@ class FleepHookHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
/**
* Builds the body of API call
*
* @param array $record
* @return string
* @phpstan-param FormattedRecord $record
*/
private function buildContent($record)
private function buildContent(array $record) : string
{
$dataArray = array('message' => $record['formatted']);
$dataArray = ['message' => $record['formatted']];
return \http_build_query($dataArray);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -24,6 +25,9 @@ use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
*
* @author Dominik Liebler <liebler.dominik@gmail.com>
* @see https://www.flowdock.com/api/push
*
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
* @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4
*/
class FlowdockHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
{
@@ -32,24 +36,20 @@ class FlowdockHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
*/
protected $apiToken;
/**
* @param string $apiToken
* @param bool|int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*
* @throws MissingExtensionException if OpenSSL is missing
*/
public function __construct($apiToken, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct(string $apiToken, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
{
if (!\extension_loaded('openssl')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler');
}
parent::__construct('ssl://api.flowdock.com:443', $level, $bubble);
parent::__construct('ssl://api.flowdock.com:443', $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
$this->apiToken = $apiToken;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
if (!$formatter instanceof \WPMailSMTP\Vendor\Monolog\Formatter\FlowdockFormatter) {
throw new \InvalidArgumentException('The FlowdockHandler requires an instance of Monolog\\Formatter\\FlowdockFormatter to function correctly');
@@ -58,30 +58,23 @@ class FlowdockHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
}
/**
* Gets the default formatter.
*
* @return FormatterInterface
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
throw new \InvalidArgumentException('The FlowdockHandler must be configured (via setFormatter) with an instance of Monolog\\Formatter\\FlowdockFormatter to function correctly');
}
/**
* {@inheritdoc}
*
* @param array $record
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
parent::write($record);
$this->closeSocket();
}
/**
* {@inheritdoc}
*
* @param array $record
* @return string
* {@inheritDoc}
*/
protected function generateDataStream($record)
protected function generateDataStream(array $record) : string
{
$content = $this->buildContent($record);
return $this->buildHeader($content) . $content;
@@ -89,20 +82,16 @@ class FlowdockHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
/**
* Builds the body of API call
*
* @param array $record
* @return string
* @phpstan-param FormattedRecord $record
*/
private function buildContent($record)
private function buildContent(array $record) : string
{
return \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($record['formatted']['flowdock']);
}
/**
* Builds the header of the API Call
*
* @param string $content
* @return string
*/
private function buildHeader($content)
private function buildHeader(string $content) : string
{
$header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n";
$header .= "Host: api.flowdock.com\r\n";

View File

@@ -15,8 +15,6 @@ use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
/**
* Interface to describe loggers that have a formatter
*
* This interface is present in monolog 1.x to ease forward compatibility.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
interface FormattableHandlerInterface

View File

@@ -16,19 +16,16 @@ use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
/**
* Helper trait for implementing FormattableInterface
*
* This trait is present in monolog 1.x to ease forward compatibility.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
trait FormattableHandlerTrait
{
/**
* @var FormatterInterface
* @var ?FormatterInterface
*/
protected $formatter;
/**
* {@inheritdoc}
* @suppress PhanTypeMismatchReturn
* {@inheritDoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
@@ -36,7 +33,7 @@ trait FormattableHandlerTrait
return $this;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,12 +11,10 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Gelf\IMessagePublisher;
use WPMailSMTP\Vendor\Gelf\PublisherInterface;
use WPMailSMTP\Vendor\Gelf\Publisher;
use InvalidArgumentException;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Formatter\GelfMessageFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
/**
* Handler to send messages to a Graylog2 (http://www.graylog2.org) server
*
@@ -25,33 +24,28 @@ use WPMailSMTP\Vendor\Monolog\Formatter\GelfMessageFormatter;
class GelfHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/**
* @var Publisher|PublisherInterface|IMessagePublisher the publisher object that sends the message to the server
* @var PublisherInterface the publisher object that sends the message to the server
*/
protected $publisher;
/**
* @param PublisherInterface|IMessagePublisher|Publisher $publisher a publisher object
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param PublisherInterface $publisher a gelf publisher object
*/
public function __construct($publisher, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct(\WPMailSMTP\Vendor\Gelf\PublisherInterface $publisher, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
parent::__construct($level, $bubble);
if (!$publisher instanceof \WPMailSMTP\Vendor\Gelf\Publisher && !$publisher instanceof \WPMailSMTP\Vendor\Gelf\IMessagePublisher && !$publisher instanceof \WPMailSMTP\Vendor\Gelf\PublisherInterface) {
throw new \InvalidArgumentException('Invalid publisher, expected a Gelf\\Publisher, Gelf\\IMessagePublisher or Gelf\\PublisherInterface instance');
}
$this->publisher = $publisher;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$this->publisher->publish($record['formatted']);
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\GelfMessageFormatter();
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -16,15 +17,21 @@ use WPMailSMTP\Vendor\Monolog\ResettableInterface;
* Forwards records to multiple handlers
*
* @author Lenar Lõhmus <lenar@city.ee>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
class GroupHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
class GroupHandler extends \WPMailSMTP\Vendor\Monolog\Handler\Handler implements \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface, \WPMailSMTP\Vendor\Monolog\ResettableInterface
{
use ProcessableHandlerTrait;
/** @var HandlerInterface[] */
protected $handlers;
/** @var bool */
protected $bubble;
/**
* @param array $handlers Array of Handlers.
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param HandlerInterface[] $handlers Array of Handlers.
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(array $handlers, $bubble = \true)
public function __construct(array $handlers, bool $bubble = \true)
{
foreach ($handlers as $handler) {
if (!$handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface) {
@@ -35,9 +42,9 @@ class GroupHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
$this->bubble = $bubble;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function isHandling(array $record)
public function isHandling(array $record) : bool
{
foreach ($this->handlers as $handler) {
if ($handler->isHandling($record)) {
@@ -47,14 +54,13 @@ class GroupHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
return \false;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handle(array $record)
public function handle(array $record) : bool
{
if ($this->processors) {
foreach ($this->processors as $processor) {
$record = \call_user_func($processor, $record);
}
/** @var Record $record */
$record = $this->processRecord($record);
}
foreach ($this->handlers as $handler) {
$handler->handle($record);
@@ -62,18 +68,16 @@ class GroupHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
return \false === $this->bubble;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handleBatch(array $records)
public function handleBatch(array $records) : void
{
if ($this->processors) {
$processed = array();
$processed = [];
foreach ($records as $record) {
foreach ($this->processors as $processor) {
$record = \call_user_func($processor, $record);
}
$processed[] = $record;
$processed[] = $this->processRecord($record);
}
/** @var Record[] $records */
$records = $processed;
}
foreach ($this->handlers as $handler) {
@@ -82,20 +86,29 @@ class GroupHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
}
public function reset()
{
parent::reset();
$this->resetProcessors();
foreach ($this->handlers as $handler) {
if ($handler instanceof \WPMailSMTP\Vendor\Monolog\ResettableInterface) {
$handler->reset();
}
}
}
public function close() : void
{
parent::close();
foreach ($this->handlers as $handler) {
$handler->close();
}
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
foreach ($this->handlers as $handler) {
$handler->setFormatter($formatter);
if ($handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
$handler->setFormatter($formatter);
}
}
return $this;
}

View File

@@ -0,0 +1,56 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
/**
* Base Handler class providing basic close() support as well as handleBatch
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
abstract class Handler implements \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
/**
* {@inheritDoc}
*/
public function handleBatch(array $records) : void
{
foreach ($records as $record) {
$this->handle($record);
}
}
/**
* {@inheritDoc}
*/
public function close() : void
{
}
public function __destruct()
{
try {
$this->close();
} catch (\Throwable $e) {
// do nothing
}
}
public function __sleep()
{
$this->close();
$reflClass = new \ReflectionClass($this);
$keys = [];
foreach ($reflClass->getProperties() as $reflProp) {
if (!$reflProp->isStatic()) {
$keys[] = $reflProp->getName();
}
}
return $keys;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,11 +11,13 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
/**
* Interface that all Monolog Handlers must implement
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger
*/
interface HandlerInterface
{
@@ -30,8 +33,10 @@ interface HandlerInterface
* @param array $record Partial log record containing only a level key
*
* @return bool
*
* @phpstan-param array{level: Level} $record
*/
public function isHandling(array $record);
public function isHandling(array $record) : bool;
/**
* Handles a record.
*
@@ -42,41 +47,36 @@ interface HandlerInterface
* Unless the bubbling is interrupted (by returning true), the Logger class will keep on
* calling further handlers in the stack with a given log record.
*
* @param array $record The record to handle
* @return bool true means that this handler handled the record, and that bubbling is not permitted.
* false means the record was either not processed or that this handler allows bubbling.
* @param array $record The record to handle
* @return bool true means that this handler handled the record, and that bubbling is not permitted.
* false means the record was either not processed or that this handler allows bubbling.
*
* @phpstan-param Record $record
*/
public function handle(array $record);
public function handle(array $record) : bool;
/**
* Handles a set of records at once.
*
* @param array $records The records to handle (an array of record arrays)
*/
public function handleBatch(array $records);
/**
* Adds a processor in the stack.
*
* @param callable $callback
* @return self
* @phpstan-param Record[] $records
*/
public function pushProcessor($callback);
public function handleBatch(array $records) : void;
/**
* Removes the processor on top of the stack and returns it.
* Closes the handler.
*
* @return callable
*/
public function popProcessor();
/**
* Sets the formatter.
* Ends a log cycle and frees all resources used by the handler.
*
* @param FormatterInterface $formatter
* @return self
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter);
/**
* Gets the formatter.
* Closing a Handler means flushing all buffers and freeing any open resources/handles.
*
* @return FormatterInterface
* Implementations have to be idempotent (i.e. it should be possible to call close several times without breakage)
* and ideally handlers should be able to reopen themselves on handle() after they have been closed.
*
* This is useful at the end of a request and will be called automatically when the object
* is destroyed if you extend Monolog\Handler\Handler.
*
* If you are thinking of calling this method yourself, most likely you should be
* calling ResettableInterface::reset instead. Have a look.
*/
public function getFormatter();
public function close() : void;
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -29,75 +30,90 @@ use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
*
* @author Alexey Karapetov <alexey@karapetov.com>
*/
class HandlerWrapper implements \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface, \WPMailSMTP\Vendor\Monolog\ResettableInterface
class HandlerWrapper implements \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface, \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface, \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface, \WPMailSMTP\Vendor\Monolog\ResettableInterface
{
/**
* @var HandlerInterface
*/
protected $handler;
/**
* HandlerWrapper constructor.
* @param HandlerInterface $handler
*/
public function __construct(\WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface $handler)
{
$this->handler = $handler;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function isHandling(array $record)
public function isHandling(array $record) : bool
{
return $this->handler->isHandling($record);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handle(array $record)
public function handle(array $record) : bool
{
return $this->handler->handle($record);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handleBatch(array $records)
public function handleBatch(array $records) : void
{
return $this->handler->handleBatch($records);
$this->handler->handleBatch($records);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function pushProcessor($callback)
public function close() : void
{
$this->handler->pushProcessor($callback);
return $this;
$this->handler->close();
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function popProcessor()
public function pushProcessor(callable $callback) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
return $this->handler->popProcessor();
if ($this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface) {
$this->handler->pushProcessor($callback);
return $this;
}
throw new \LogicException('The wrapped handler does not implement ' . \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface::class);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function popProcessor() : callable
{
$this->handler->setFormatter($formatter);
return $this;
if ($this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface) {
return $this->handler->popProcessor();
}
throw new \LogicException('The wrapped handler does not implement ' . \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface::class);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getFormatter()
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
return $this->handler->getFormatter();
if ($this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
$this->handler->setFormatter($formatter);
return $this;
}
throw new \LogicException('The wrapped handler does not implement ' . \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface::class);
}
/**
* {@inheritDoc}
*/
public function getFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
if ($this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
return $this->handler->getFormatter();
}
throw new \LogicException('The wrapped handler does not implement ' . \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface::class);
}
public function reset()
{
if ($this->handler instanceof \WPMailSMTP\Vendor\Monolog\ResettableInterface) {
return $this->handler->reset();
$this->handler->reset();
}
}
}

View File

@@ -1,300 +0,0 @@
<?php
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
/**
* Sends notifications through the hipchat api to a hipchat room
*
* Notes:
* API token - HipChat API token
* Room - HipChat Room Id or name, where messages are sent
* Name - Name used to send the message (from)
* notify - Should the message trigger a notification in the clients
* version - The API version to use (HipChatHandler::API_V1 | HipChatHandler::API_V2)
*
* @author Rafael Dohms <rafael@doh.ms>
* @see https://www.hipchat.com/docs/api
*/
class HipChatHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
{
/**
* Use API version 1
*/
const API_V1 = 'v1';
/**
* Use API version v2
*/
const API_V2 = 'v2';
/**
* The maximum allowed length for the name used in the "from" field.
*/
const MAXIMUM_NAME_LENGTH = 15;
/**
* The maximum allowed length for the message.
*/
const MAXIMUM_MESSAGE_LENGTH = 9500;
/**
* @var string
*/
private $token;
/**
* @var string
*/
private $room;
/**
* @var string
*/
private $name;
/**
* @var bool
*/
private $notify;
/**
* @var string
*/
private $format;
/**
* @var string
*/
private $host;
/**
* @var string
*/
private $version;
/**
* @param string $token HipChat API Token
* @param string $room The room that should be alerted of the message (Id or Name)
* @param string $name Name used in the "from" field.
* @param bool $notify Trigger a notification in clients or not
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $useSSL Whether to connect via SSL.
* @param string $format The format of the messages (default to text, can be set to html if you have html in the messages)
* @param string $host The HipChat server hostname.
* @param string $version The HipChat API version (default HipChatHandler::API_V1)
*/
public function __construct($token, $room, $name = 'Monolog', $notify = \false, $level = \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL, $bubble = \true, $useSSL = \true, $format = 'text', $host = 'api.hipchat.com', $version = self::API_V1)
{
@\trigger_error('The Monolog\\Handler\\HipChatHandler class is deprecated. You should migrate to Slack and the SlackWebhookHandler / SlackbotHandler, see https://www.atlassian.com/partnerships/slack', \E_USER_DEPRECATED);
if ($version == self::API_V1 && !$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) {
throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.');
}
$connectionString = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80';
parent::__construct($connectionString, $level, $bubble);
$this->token = $token;
$this->name = $name;
$this->notify = $notify;
$this->room = $room;
$this->format = $format;
$this->host = $host;
$this->version = $version;
}
/**
* {@inheritdoc}
*
* @param array $record
* @return string
*/
protected function generateDataStream($record)
{
$content = $this->buildContent($record);
return $this->buildHeader($content) . $content;
}
/**
* Builds the body of API call
*
* @param array $record
* @return string
*/
private function buildContent($record)
{
$dataArray = array('notify' => $this->version == self::API_V1 ? $this->notify ? 1 : 0 : ($this->notify ? 'true' : 'false'), 'message' => $record['formatted'], 'message_format' => $this->format, 'color' => $this->getAlertColor($record['level']));
if (!$this->validateStringLength($dataArray['message'], static::MAXIMUM_MESSAGE_LENGTH)) {
if (\function_exists('mb_substr')) {
$dataArray['message'] = \mb_substr($dataArray['message'], 0, static::MAXIMUM_MESSAGE_LENGTH) . ' [truncated]';
} else {
$dataArray['message'] = \substr($dataArray['message'], 0, static::MAXIMUM_MESSAGE_LENGTH) . ' [truncated]';
}
}
// if we are using the legacy API then we need to send some additional information
if ($this->version == self::API_V1) {
$dataArray['room_id'] = $this->room;
}
// append the sender name if it is set
// always append it if we use the v1 api (it is required in v1)
if ($this->version == self::API_V1 || $this->name !== null) {
$dataArray['from'] = (string) $this->name;
}
return \http_build_query($dataArray);
}
/**
* Builds the header of the API Call
*
* @param string $content
* @return string
*/
private function buildHeader($content)
{
if ($this->version == self::API_V1) {
$header = "POST /v1/rooms/message?format=json&auth_token={$this->token} HTTP/1.1\r\n";
} else {
// needed for rooms with special (spaces, etc) characters in the name
$room = \rawurlencode($this->room);
$header = "POST /v2/room/{$room}/notification?auth_token={$this->token} HTTP/1.1\r\n";
}
$header .= "Host: {$this->host}\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . \strlen($content) . "\r\n";
$header .= "\r\n";
return $header;
}
/**
* Assigns a color to each level of log records.
*
* @param int $level
* @return string
*/
protected function getAlertColor($level)
{
switch (\true) {
case $level >= \WPMailSMTP\Vendor\Monolog\Logger::ERROR:
return 'red';
case $level >= \WPMailSMTP\Vendor\Monolog\Logger::WARNING:
return 'yellow';
case $level >= \WPMailSMTP\Vendor\Monolog\Logger::INFO:
return 'green';
case $level == \WPMailSMTP\Vendor\Monolog\Logger::DEBUG:
return 'gray';
default:
return 'yellow';
}
}
/**
* {@inheritdoc}
*
* @param array $record
*/
protected function write(array $record)
{
parent::write($record);
$this->finalizeWrite();
}
/**
* Finalizes the request by reading some bytes and then closing the socket
*
* If we do not read some but close the socket too early, hipchat sometimes
* drops the request entirely.
*/
protected function finalizeWrite()
{
$res = $this->getResource();
if (\is_resource($res)) {
@\fread($res, 2048);
}
$this->closeSocket();
}
/**
* {@inheritdoc}
*/
public function handleBatch(array $records)
{
if (\count($records) == 0) {
return \true;
}
$batchRecords = $this->combineRecords($records);
$handled = \false;
foreach ($batchRecords as $batchRecord) {
if ($this->isHandling($batchRecord)) {
$this->write($batchRecord);
$handled = \true;
}
}
if (!$handled) {
return \false;
}
return \false === $this->bubble;
}
/**
* Combines multiple records into one. Error level of the combined record
* will be the highest level from the given records. Datetime will be taken
* from the first record.
*
* @param array $records
* @return array
*/
private function combineRecords(array $records)
{
$batchRecord = null;
$batchRecords = array();
$messages = array();
$formattedMessages = array();
$level = 0;
$levelName = null;
$datetime = null;
foreach ($records as $record) {
$record = $this->processRecord($record);
if ($record['level'] > $level) {
$level = $record['level'];
$levelName = $record['level_name'];
}
if (null === $datetime) {
$datetime = $record['datetime'];
}
$messages[] = $record['message'];
$messageStr = \implode(\PHP_EOL, $messages);
$formattedMessages[] = $this->getFormatter()->format($record);
$formattedMessageStr = \implode('', $formattedMessages);
$batchRecord = array('message' => $messageStr, 'formatted' => $formattedMessageStr, 'context' => array(), 'extra' => array());
if (!$this->validateStringLength($batchRecord['formatted'], static::MAXIMUM_MESSAGE_LENGTH)) {
// Pop the last message and implode the remaining messages
$lastMessage = \array_pop($messages);
$lastFormattedMessage = \array_pop($formattedMessages);
$batchRecord['message'] = \implode(\PHP_EOL, $messages);
$batchRecord['formatted'] = \implode('', $formattedMessages);
$batchRecords[] = $batchRecord;
$messages = array($lastMessage);
$formattedMessages = array($lastFormattedMessage);
$batchRecord = null;
}
}
if (null !== $batchRecord) {
$batchRecords[] = $batchRecord;
}
// Set the max level and datetime for all records
foreach ($batchRecords as &$batchRecord) {
$batchRecord = \array_merge($batchRecord, array('level' => $level, 'level_name' => $levelName, 'datetime' => $datetime));
}
return $batchRecords;
}
/**
* Validates the length of a string.
*
* If the `mb_strlen()` function is available, it will use that, as HipChat
* allows UTF-8 characters. Otherwise, it will fall back to `strlen()`.
*
* Note that this might cause false failures in the specific case of using
* a valid name with less than 16 characters, but 16 or more bytes, on a
* system where `mb_strlen()` is unavailable.
*
* @param string $str
* @param int $length
*
* @return bool
*/
private function validateStringLength($str, $length)
{
if (\function_exists('mb_strlen')) {
return \mb_strlen($str) <= $length;
}
return \strlen($str) <= $length;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -25,33 +26,36 @@ use WPMailSMTP\Vendor\Monolog\Utils;
*/
class IFTTTHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/** @var string */
private $eventName;
/** @var string */
private $secretKey;
/**
* @param string $eventName The name of the IFTTT Maker event that should be triggered
* @param string $secretKey A valid IFTTT secret key
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($eventName, $secretKey, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, $bubble = \true)
public function __construct(string $eventName, string $secretKey, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, bool $bubble = \true)
{
if (!\extension_loaded('curl')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The curl extension is needed to use the IFTTTHandler');
}
$this->eventName = $eventName;
$this->secretKey = $secretKey;
parent::__construct($level, $bubble);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function write(array $record)
public function write(array $record) : void
{
$postData = array("value1" => $record["channel"], "value2" => $record["level_name"], "value3" => $record["message"]);
$postData = ["value1" => $record["channel"], "value2" => $record["level_name"], "value3" => $record["message"]];
$postString = \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($postData);
$ch = \curl_init();
\curl_setopt($ch, \CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey);
\curl_setopt($ch, \CURLOPT_POST, \true);
\curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
\curl_setopt($ch, \CURLOPT_POSTFIELDS, $postString);
\curl_setopt($ch, \CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
\curl_setopt($ch, \CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
\WPMailSMTP\Vendor\Monolog\Handler\Curl\Util::execute($ch);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -24,30 +25,25 @@ class InsightOpsHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
*/
protected $logToken;
/**
* @param string $token Log token supplied by InsightOps
* @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
* @param bool $useSSL Whether or not SSL encryption should be used
* @param int $level The minimum logging level to trigger this handler
* @param bool $bubble Whether or not messages that are handled should bubble up the stack.
* @param string $token Log token supplied by InsightOps
* @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
* @param bool $useSSL Whether or not SSL encryption should be used
*
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
*/
public function __construct($token, $region = 'us', $useSSL = \true, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct(string $token, string $region = 'us', bool $useSSL = \true, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
{
if ($useSSL && !\extension_loaded('openssl')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for InsightOpsHandler');
}
$endpoint = $useSSL ? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443' : $region . '.data.logs.insight.rapid7.com:80';
parent::__construct($endpoint, $level, $bubble);
parent::__construct($endpoint, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
$this->logToken = $token;
}
/**
* {@inheritdoc}
*
* @param array $record
* @return string
* {@inheritDoc}
*/
protected function generateDataStream($record)
protected function generateDataStream(array $record) : string
{
return $this->logToken . ' ' . $record['formatted'];
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -21,29 +22,25 @@ class LogEntriesHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
*/
protected $logToken;
/**
* @param string $token Log token supplied by LogEntries
* @param bool $useSSL Whether or not SSL encryption should be used.
* @param int $level The minimum logging level to trigger this handler
* @param bool $bubble Whether or not messages that are handled should bubble up the stack.
* @param string $token Log token supplied by LogEntries
* @param bool $useSSL Whether or not SSL encryption should be used.
* @param string $host Custom hostname to send the data to if needed
*
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
*/
public function __construct($token, $useSSL = \true, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true, $host = 'data.logentries.com')
public function __construct(string $token, bool $useSSL = \true, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, string $host = 'data.logentries.com', bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
{
if ($useSSL && !\extension_loaded('openssl')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler');
}
$endpoint = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80';
parent::__construct($endpoint, $level, $bubble);
parent::__construct($endpoint, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
$this->logToken = $token;
}
/**
* {@inheritdoc}
*
* @param array $record
* @return string
* {@inheritDoc}
*/
protected function generateDataStream($record)
protected function generateDataStream(array $record) : string
{
return $this->logToken . ' ' . $record['formatted'];
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,7 +12,10 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\LogglyFormatter;
use function array_key_exists;
use CurlHandle;
/**
* Sends errors to Loggly.
*
@@ -21,61 +25,108 @@ use WPMailSMTP\Vendor\Monolog\Formatter\LogglyFormatter;
*/
class LogglyHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
const HOST = 'logs-01.loggly.com';
const ENDPOINT_SINGLE = 'inputs';
const ENDPOINT_BATCH = 'bulk';
protected const HOST = 'logs-01.loggly.com';
protected const ENDPOINT_SINGLE = 'inputs';
protected const ENDPOINT_BATCH = 'bulk';
/**
* Caches the curl handlers for every given endpoint.
*
* @var resource[]|CurlHandle[]
*/
protected $curlHandlers = [];
/** @var string */
protected $token;
protected $tag = array();
public function __construct($token, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
/** @var string[] */
protected $tag = [];
/**
* @param string $token API token supplied by Loggly
*
* @throws MissingExtensionException If the curl extension is missing
*/
public function __construct(string $token, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
if (!\extension_loaded('curl')) {
throw new \LogicException('The curl extension is needed to use the LogglyHandler');
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The curl extension is needed to use the LogglyHandler');
}
$this->token = $token;
parent::__construct($level, $bubble);
}
public function setTag($tag)
/**
* Loads and returns the shared curl handler for the given endpoint.
*
* @param string $endpoint
*
* @return resource|CurlHandle
*/
protected function getCurlHandler(string $endpoint)
{
$tag = !empty($tag) ? $tag : array();
$this->tag = \is_array($tag) ? $tag : array($tag);
if (!\array_key_exists($endpoint, $this->curlHandlers)) {
$this->curlHandlers[$endpoint] = $this->loadCurlHandle($endpoint);
}
return $this->curlHandlers[$endpoint];
}
public function addTag($tag)
/**
* Starts a fresh curl session for the given endpoint and returns its handler.
*
* @param string $endpoint
*
* @return resource|CurlHandle
*/
private function loadCurlHandle(string $endpoint)
{
$url = \sprintf("https://%s/%s/%s/", static::HOST, $endpoint, $this->token);
$ch = \curl_init();
\curl_setopt($ch, \CURLOPT_URL, $url);
\curl_setopt($ch, \CURLOPT_POST, \true);
\curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
return $ch;
}
/**
* @param string[]|string $tag
*/
public function setTag($tag) : self
{
$tag = !empty($tag) ? $tag : [];
$this->tag = \is_array($tag) ? $tag : [$tag];
return $this;
}
/**
* @param string[]|string $tag
*/
public function addTag($tag) : self
{
if (!empty($tag)) {
$tag = \is_array($tag) ? $tag : array($tag);
$tag = \is_array($tag) ? $tag : [$tag];
$this->tag = \array_unique(\array_merge($this->tag, $tag));
}
return $this;
}
protected function write(array $record)
protected function write(array $record) : void
{
$this->send($record["formatted"], self::ENDPOINT_SINGLE);
$this->send($record["formatted"], static::ENDPOINT_SINGLE);
}
public function handleBatch(array $records)
public function handleBatch(array $records) : void
{
$level = $this->level;
$records = \array_filter($records, function ($record) use($level) {
return $record['level'] >= $level;
});
if ($records) {
$this->send($this->getFormatter()->formatBatch($records), self::ENDPOINT_BATCH);
$this->send($this->getFormatter()->formatBatch($records), static::ENDPOINT_BATCH);
}
}
protected function send($data, $endpoint)
protected function send(string $data, string $endpoint) : void
{
$url = \sprintf("https://%s/%s/%s/", self::HOST, $endpoint, $this->token);
$headers = array('Content-Type: application/json');
$ch = $this->getCurlHandler($endpoint);
$headers = ['Content-Type: application/json'];
if (!empty($this->tag)) {
$headers[] = 'X-LOGGLY-TAG: ' . \implode(',', $this->tag);
}
$ch = \curl_init();
\curl_setopt($ch, \CURLOPT_URL, $url);
\curl_setopt($ch, \CURLOPT_POST, \true);
\curl_setopt($ch, \CURLOPT_POSTFIELDS, $data);
\curl_setopt($ch, \CURLOPT_HTTPHEADER, $headers);
\curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
\WPMailSMTP\Vendor\Monolog\Handler\Curl\Util::execute($ch);
\WPMailSMTP\Vendor\Monolog\Handler\Curl\Util::execute($ch, 5, \false);
}
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LogglyFormatter();
}

View File

@@ -0,0 +1,75 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\LogmaticFormatter;
/**
* @author Julien Breux <julien.breux@gmail.com>
*/
class LogmaticHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
{
/**
* @var string
*/
private $logToken;
/**
* @var string
*/
private $hostname;
/**
* @var string
*/
private $appname;
/**
* @param string $token Log token supplied by Logmatic.
* @param string $hostname Host name supplied by Logmatic.
* @param string $appname Application name supplied by Logmatic.
* @param bool $useSSL Whether or not SSL encryption should be used.
*
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
*/
public function __construct(string $token, string $hostname = '', string $appname = '', bool $useSSL = \true, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
{
if ($useSSL && !\extension_loaded('openssl')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The OpenSSL PHP extension is required to use SSL encrypted connection for LogmaticHandler');
}
$endpoint = $useSSL ? 'ssl://api.logmatic.io:10515' : 'api.logmatic.io:10514';
$endpoint .= '/v1/';
parent::__construct($endpoint, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
$this->logToken = $token;
$this->hostname = $hostname;
$this->appname = $appname;
}
/**
* {@inheritDoc}
*/
protected function generateDataStream(array $record) : string
{
return $this->logToken . ' ' . $record['formatted'];
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
$formatter = new \WPMailSMTP\Vendor\Monolog\Formatter\LogmaticFormatter();
if (!empty($this->hostname)) {
$formatter->setHostname($this->hostname);
}
if (!empty($this->appname)) {
$formatter->setAppname($this->appname);
}
return $formatter;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,24 +11,30 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\HtmlFormatter;
/**
* Base class for all mail handlers
*
* @author Gyula Sallai
*
* @phpstan-import-type Record from \Monolog\Logger
*/
abstract class MailHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handleBatch(array $records)
public function handleBatch(array $records) : void
{
$messages = array();
$messages = [];
foreach ($records as $record) {
if ($record['level'] < $this->level) {
continue;
}
$messages[] = $this->processRecord($record);
/** @var Record $message */
$message = $this->processRecord($record);
$messages[] = $message;
}
if (!empty($messages)) {
$this->send((string) $this->getFormatter()->formatBatch($messages), $messages);
@@ -38,16 +45,22 @@ abstract class MailHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractPr
*
* @param string $content formatted email body to be sent
* @param array $records the array of log records that formed this content
*
* @phpstan-param Record[] $records
*/
protected abstract function send($content, array $records);
protected abstract function send(string $content, array $records) : void;
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$this->send((string) $record['formatted'], array($record));
$this->send((string) $record['formatted'], [$record]);
}
protected function getHighestRecord(array $records)
/**
* @phpstan-param non-empty-array<Record> $records
* @phpstan-return Record
*/
protected function getHighestRecord(array $records) : array
{
$highestRecord = null;
foreach ($records as $record) {
@@ -57,4 +70,17 @@ abstract class MailHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractPr
}
return $highestRecord;
}
protected function isHtmlBody(string $body) : bool
{
return ($body[0] ?? null) === '<';
}
/**
* Gets the default formatter.
*
* @return FormatterInterface
*/
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\HtmlFormatter();
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,6 +12,8 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Swift;
use WPMailSMTP\Vendor\Swift_Message;
/**
* MandrillHandler uses cURL to send the emails to the Mandrill API
*
@@ -18,19 +21,21 @@ use WPMailSMTP\Vendor\Monolog\Logger;
*/
class MandrillHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
{
/** @var Swift_Message */
protected $message;
/** @var string */
protected $apiKey;
/**
* @param string $apiKey A valid Mandrill API key
* @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @psalm-param Swift_Message|callable(): Swift_Message $message
*
* @param string $apiKey A valid Mandrill API key
* @param callable|Swift_Message $message An example message for real messages, only the body will be replaced
*/
public function __construct($apiKey, $message, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, $bubble = \true)
public function __construct(string $apiKey, $message, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, bool $bubble = \true)
{
parent::__construct($level, $bubble);
if (!$message instanceof \WPMailSMTP\Vendor\Swift_Message && \is_callable($message)) {
$message = \call_user_func($message);
$message = $message();
}
if (!$message instanceof \WPMailSMTP\Vendor\Swift_Message) {
throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it');
@@ -39,22 +44,28 @@ class MandrillHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
$this->apiKey = $apiKey;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function send($content, array $records)
protected function send(string $content, array $records) : void
{
$mime = 'text/plain';
if ($this->isHtmlBody($content)) {
$mime = 'text/html';
}
$message = clone $this->message;
$message->setBody($content);
$message->setBody($content, $mime);
/** @phpstan-ignore-next-line */
if (\version_compare(\WPMailSMTP\Vendor\Swift::VERSION, '6.0.0', '>=')) {
$message->setDate(new \DateTimeImmutable());
} else {
/** @phpstan-ignore-next-line */
$message->setDate(\time());
}
$ch = \curl_init();
\curl_setopt($ch, \CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json');
\curl_setopt($ch, \CURLOPT_POST, 1);
\curl_setopt($ch, \CURLOPT_RETURNTRANSFER, 1);
\curl_setopt($ch, \CURLOPT_POSTFIELDS, \http_build_query(array('key' => $this->apiKey, 'raw_message' => (string) $message, 'async' => \false)));
\curl_setopt($ch, \CURLOPT_POSTFIELDS, \http_build_query(['key' => $this->apiKey, 'raw_message' => (string) $message, 'async' => \false]));
\WPMailSMTP\Vendor\Monolog\Handler\Curl\Util::execute($ch);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,9 +12,9 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
/**
* Exception can be thrown if an extension for an handler is missing
* Exception can be thrown if an extension for a handler is missing
*
* @author Christian Bergau <cbergau86@gmail.com>
* @author Christian Bergau <cbergau86@gmail.com>
*/
class MissingExtensionException extends \Exception
{

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,43 +11,69 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\Manager;
use WPMailSMTP\Vendor\MongoDB\Client;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\MongoDBFormatter;
/**
* Logs to a MongoDB database.
*
* usage example:
* Usage example:
*
* $log = new Logger('application');
* $mongodb = new MongoDBHandler(new \Mongo("mongodb://localhost:27017"), "logs", "prod");
* $log = new \Monolog\Logger('application');
* $client = new \MongoDB\Client('mongodb://localhost:27017');
* $mongodb = new \Monolog\Handler\MongoDBHandler($client, 'logs', 'prod');
* $log->pushHandler($mongodb);
*
* @author Thomas Tourlourat <thomas@tourlourat.com>
* The above examples uses the MongoDB PHP library's client class; however, the
* MongoDB\Driver\Manager class from ext-mongodb is also supported.
*/
class MongoDBHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
protected $mongoCollection;
public function __construct($mongo, $database, $collection, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
/** @var \MongoDB\Collection */
private $collection;
/** @var Client|Manager */
private $manager;
/** @var string */
private $namespace;
/**
* Constructor.
*
* @param Client|Manager $mongodb MongoDB library or driver client
* @param string $database Database name
* @param string $collection Collection name
*/
public function __construct($mongodb, string $database, string $collection, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo || $mongo instanceof \WPMailSMTP\Vendor\MongoDB\Client)) {
throw new \InvalidArgumentException('MongoClient, Mongo or MongoDB\\Client instance required');
if (!($mongodb instanceof \WPMailSMTP\Vendor\MongoDB\Client || $mongodb instanceof \MongoDB\Driver\Manager)) {
throw new \InvalidArgumentException('MongoDB\\Client or MongoDB\\Driver\\Manager instance required');
}
if ($mongodb instanceof \WPMailSMTP\Vendor\MongoDB\Client) {
$this->collection = $mongodb->selectCollection($database, $collection);
} else {
$this->manager = $mongodb;
$this->namespace = $database . '.' . $collection;
}
$this->mongoCollection = $mongo->selectCollection($database, $collection);
parent::__construct($level, $bubble);
}
protected function write(array $record)
protected function write(array $record) : void
{
if ($this->mongoCollection instanceof \WPMailSMTP\Vendor\MongoDB\Collection) {
$this->mongoCollection->insertOne($record["formatted"]);
} else {
$this->mongoCollection->save($record["formatted"]);
if (isset($this->collection)) {
$this->collection->insertOne($record['formatted']);
}
if (isset($this->manager, $this->namespace)) {
$bulk = new \MongoDB\Driver\BulkWrite();
$bulk->insert($record["formatted"]);
$this->manager->executeBulkWrite($this->namespace, $bulk);
}
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter();
return new \WPMailSMTP\Vendor\Monolog\Formatter\MongoDBFormatter();
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -22,7 +23,7 @@ class NativeMailerHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
{
/**
* The email addresses to which the message will be sent
* @var array
* @var string[]
*/
protected $to;
/**
@@ -32,14 +33,14 @@ class NativeMailerHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
protected $subject;
/**
* Optional headers for the message
* @var array
* @var string[]
*/
protected $headers = array();
protected $headers = [];
/**
* Optional parameters for the message
* @var array
* @var string[]
*/
protected $parameters = array();
protected $parameters = [];
/**
* The wordwrap length for the message
* @var int
@@ -47,26 +48,24 @@ class NativeMailerHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
protected $maxColumnWidth;
/**
* The Content-type for the message
* @var string
* @var string|null
*/
protected $contentType = 'text/plain';
protected $contentType;
/**
* The encoding for the message
* @var string
*/
protected $encoding = 'utf-8';
/**
* @param string|array $to The receiver of the mail
* @param string $subject The subject of the mail
* @param string $from The sender of the mail
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int $maxColumnWidth The maximum column width that the message lines will have
* @param string|string[] $to The receiver of the mail
* @param string $subject The subject of the mail
* @param string $from The sender of the mail
* @param int $maxColumnWidth The maximum column width that the message lines will have
*/
public function __construct($to, $subject, $from, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, $bubble = \true, $maxColumnWidth = 70)
public function __construct($to, string $subject, string $from, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, bool $bubble = \true, int $maxColumnWidth = 70)
{
parent::__construct($level, $bubble);
$this->to = \is_array($to) ? $to : array($to);
$this->to = (array) $to;
$this->subject = $subject;
$this->addHeader(\sprintf('From: %s', $from));
$this->maxColumnWidth = $maxColumnWidth;
@@ -74,10 +73,9 @@ class NativeMailerHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
/**
* Add headers to the message
*
* @param string|array $headers Custom added headers
* @return self
* @param string|string[] $headers Custom added headers
*/
public function addHeader($headers)
public function addHeader($headers) : self
{
foreach ((array) $headers as $header) {
if (\strpos($header, "\n") !== \false || \strpos($header, "\r") !== \false) {
@@ -90,23 +88,25 @@ class NativeMailerHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
/**
* Add parameters to the message
*
* @param string|array $parameters Custom added parameters
* @return self
* @param string|string[] $parameters Custom added parameters
*/
public function addParameter($parameters)
public function addParameter($parameters) : self
{
$this->parameters = \array_merge($this->parameters, (array) $parameters);
return $this;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function send($content, array $records)
protected function send(string $content, array $records) : void
{
$content = \wordwrap($content, $this->maxColumnWidth);
$contentType = $this->getContentType() ?: ($this->isHtmlBody($content) ? 'text/html' : 'text/plain');
if ($contentType !== 'text/html') {
$content = \wordwrap($content, $this->maxColumnWidth);
}
$headers = \ltrim(\implode("\r\n", $this->headers) . "\r\n", "\r\n");
$headers .= 'Content-type: ' . $this->getContentType() . '; charset=' . $this->getEncoding() . "\r\n";
if ($this->getContentType() == 'text/html' && \false === \strpos($headers, 'MIME-Version:')) {
$headers .= 'Content-type: ' . $contentType . '; charset=' . $this->getEncoding() . "\r\n";
if ($contentType === 'text/html' && \false === \strpos($headers, 'MIME-Version:')) {
$headers .= 'MIME-Version: 1.0' . "\r\n";
}
$subject = $this->subject;
@@ -119,26 +119,18 @@ class NativeMailerHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
\mail($to, $subject, $content, $headers, $parameters);
}
}
/**
* @return string $contentType
*/
public function getContentType()
public function getContentType() : ?string
{
return $this->contentType;
}
/**
* @return string $encoding
*/
public function getEncoding()
public function getEncoding() : string
{
return $this->encoding;
}
/**
* @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML
* messages.
* @return self
* @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML messages.
*/
public function setContentType($contentType)
public function setContentType(string $contentType) : self
{
if (\strpos($contentType, "\n") !== \false || \strpos($contentType, "\r") !== \false) {
throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection');
@@ -146,11 +138,7 @@ class NativeMailerHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
$this->contentType = $contentType;
return $this;
}
/**
* @param string $encoding
* @return self
*/
public function setEncoding($encoding)
public function setEncoding(string $encoding) : self
{
if (\strpos($encoding, "\n") !== \false || \strpos($encoding, "\r") !== \false) {
throw new \InvalidArgumentException('The encoding can not contain newline characters to prevent email header injection');

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -13,6 +14,7 @@ namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
use WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
/**
* Class to record a log on a NewRelic application.
* Enabling New Relic High Security mode may prevent capture of useful information.
@@ -27,13 +29,13 @@ class NewRelicHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
/**
* Name of the New Relic application that will receive logs from this handler.
*
* @var string
* @var ?string
*/
protected $appName;
/**
* Name of the current transaction
*
* @var string
* @var ?string
*/
protected $transactionName;
/**
@@ -46,11 +48,11 @@ class NewRelicHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
/**
* {@inheritDoc}
*
* @param string $appName
* @param bool $explodeArrays
* @param string $transactionName
* @param string|null $appName
* @param bool $explodeArrays
* @param string|null $transactionName
*/
public function __construct($level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, $bubble = \true, $appName = null, $explodeArrays = \false, $transactionName = null)
public function __construct($level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, bool $bubble = \true, ?string $appName = null, bool $explodeArrays = \false, ?string $transactionName = null)
{
parent::__construct($level, $bubble);
$this->appName = $appName;
@@ -60,7 +62,7 @@ class NewRelicHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
/**
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
if (!$this->isNewRelicEnabled()) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
@@ -72,7 +74,7 @@ class NewRelicHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
$this->setNewRelicTransactionName($transactionName);
unset($record['formatted']['context']['transaction_name']);
}
if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || \PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable)) {
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
\newrelic_notice_error($record['message'], $record['context']['exception']);
unset($record['formatted']['context']['exception']);
} else {
@@ -106,7 +108,7 @@ class NewRelicHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
*
* @return bool
*/
protected function isNewRelicEnabled()
protected function isNewRelicEnabled() : bool
{
return \extension_loaded('newrelic');
}
@@ -114,10 +116,9 @@ class NewRelicHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
* Returns the appname where this log should be sent. Each log can override the default appname, set in this
* handler's constructor, by providing the appname in it's context.
*
* @param array $context
* @return null|string
* @param mixed[] $context
*/
protected function getAppName(array $context)
protected function getAppName(array $context) : ?string
{
if (isset($context['appname'])) {
return $context['appname'];
@@ -128,11 +129,9 @@ class NewRelicHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
* Returns the name of the current transaction. Each log can override the default transaction name, set in this
* handler's constructor, by providing the transaction_name in it's context
*
* @param array $context
*
* @return null|string
* @param mixed[] $context
*/
protected function getTransactionName(array $context)
protected function getTransactionName(array $context) : ?string
{
if (isset($context['transaction_name'])) {
return $context['transaction_name'];
@@ -141,19 +140,15 @@ class NewRelicHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
}
/**
* Sets the NewRelic application that should receive this log.
*
* @param string $appName
*/
protected function setNewRelicAppName($appName)
protected function setNewRelicAppName(string $appName) : void
{
\newrelic_set_appname($appName);
}
/**
* Overwrites the name of the current transaction
*
* @param string $transactionName
*/
protected function setNewRelicTransactionName($transactionName)
protected function setNewRelicTransactionName(string $transactionName) : void
{
\newrelic_name_transaction($transactionName);
}
@@ -161,7 +156,7 @@ class NewRelicHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
* @param string $key
* @param mixed $value
*/
protected function setNewRelicParameter($key, $value)
protected function setNewRelicParameter(string $key, $value) : void
{
if (null === $value || \is_scalar($value)) {
\newrelic_add_custom_parameter($key, $value);
@@ -172,7 +167,7 @@ class NewRelicHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcess
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter();
}

View File

@@ -0,0 +1,39 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
/**
* No-op
*
* This handler handles anything, but does nothing, and does not stop bubbling to the rest of the stack.
* This can be used for testing, or to disable a handler when overriding a configuration without
* influencing the rest of the stack.
*
* @author Roel Harbers <roelharbers@gmail.com>
*/
class NoopHandler extends \WPMailSMTP\Vendor\Monolog\Handler\Handler
{
/**
* {@inheritDoc}
*/
public function isHandling(array $record) : bool
{
return \true;
}
/**
* {@inheritDoc}
*/
public function handle(array $record) : bool
{
return \false;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,6 +12,7 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
/**
* Blackhole
*
@@ -18,24 +20,37 @@ use WPMailSMTP\Vendor\Monolog\Logger;
* to put on top of an existing stack to override it temporarily.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Level from \Monolog\Logger
* @phpstan-import-type LevelName from \Monolog\Logger
*/
class NullHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
class NullHandler extends \WPMailSMTP\Vendor\Monolog\Handler\Handler
{
/**
* @param int $level The minimum logging level at which this handler will be triggered
* @var int
*/
private $level;
/**
* @param string|int $level The minimum logging level at which this handler will be triggered
*
* @phpstan-param Level|LevelName|LogLevel::* $level
*/
public function __construct($level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG)
{
parent::__construct($level, \false);
$this->level = \WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($level);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handle(array $record)
public function isHandling(array $record) : bool
{
if ($record['level'] < $this->level) {
return \false;
}
return \true;
return $record['level'] >= $this->level;
}
/**
* {@inheritDoc}
*/
public function handle(array $record) : bool
{
return $record['level'] >= $this->level;
}
}

View File

@@ -0,0 +1,119 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
/**
* Handler to only pass log messages when a certain threshold of number of messages is reached.
*
* This can be useful in cases of processing a batch of data, but you're for example only interested
* in case it fails catastrophically instead of a warning for 1 or 2 events. Worse things can happen, right?
*
* Usage example:
*
* ```
* $log = new Logger('application');
* $handler = new SomeHandler(...)
*
* // Pass all warnings to the handler when more than 10 & all error messages when more then 5
* $overflow = new OverflowHandler($handler, [Logger::WARNING => 10, Logger::ERROR => 5]);
*
* $log->pushHandler($overflow);
*```
*
* @author Kris Buist <krisbuist@gmail.com>
*/
class OverflowHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler implements \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface
{
/** @var HandlerInterface */
private $handler;
/** @var int[] */
private $thresholdMap = [\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => 0, \WPMailSMTP\Vendor\Monolog\Logger::INFO => 0, \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => 0, \WPMailSMTP\Vendor\Monolog\Logger::WARNING => 0, \WPMailSMTP\Vendor\Monolog\Logger::ERROR => 0, \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => 0, \WPMailSMTP\Vendor\Monolog\Logger::ALERT => 0, \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => 0];
/**
* Buffer of all messages passed to the handler before the threshold was reached
*
* @var mixed[][]
*/
private $buffer = [];
/**
* @param HandlerInterface $handler
* @param int[] $thresholdMap Dictionary of logger level => threshold
*/
public function __construct(\WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface $handler, array $thresholdMap = [], $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
$this->handler = $handler;
foreach ($thresholdMap as $thresholdLevel => $threshold) {
$this->thresholdMap[$thresholdLevel] = $threshold;
}
parent::__construct($level, $bubble);
}
/**
* Handles a record.
*
* All records may be passed to this method, and the handler should discard
* those that it does not want to handle.
*
* The return value of this function controls the bubbling process of the handler stack.
* Unless the bubbling is interrupted (by returning true), the Logger class will keep on
* calling further handlers in the stack with a given log record.
*
* {@inheritDoc}
*/
public function handle(array $record) : bool
{
if ($record['level'] < $this->level) {
return \false;
}
$level = $record['level'];
if (!isset($this->thresholdMap[$level])) {
$this->thresholdMap[$level] = 0;
}
if ($this->thresholdMap[$level] > 0) {
// The overflow threshold is not yet reached, so we're buffering the record and lowering the threshold by 1
$this->thresholdMap[$level]--;
$this->buffer[$level][] = $record;
return \false === $this->bubble;
}
if ($this->thresholdMap[$level] == 0) {
// This current message is breaking the threshold. Flush the buffer and continue handling the current record
foreach ($this->buffer[$level] ?? [] as $buffered) {
$this->handler->handle($buffered);
}
$this->thresholdMap[$level]--;
unset($this->buffer[$level]);
}
$this->handler->handle($record);
return \false === $this->bubble;
}
/**
* {@inheritDoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
if ($this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
$this->handler->setFormatter($formatter);
return $this;
}
throw new \UnexpectedValueException('The nested handler of type ' . \get_class($this->handler) . ' does not support formatters.');
}
/**
* {@inheritDoc}
*/
public function getFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
if ($this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
return $this->handler->getFormatter();
}
throw new \UnexpectedValueException('The nested handler of type ' . \get_class($this->handler) . ' does not support formatters.');
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,12 +11,12 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use Exception;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
use WPMailSMTP\Vendor\PhpConsole\Connector;
use WPMailSMTP\Vendor\PhpConsole\Handler;
use WPMailSMTP\Vendor\PhpConsole\Handler as VendorPhpConsoleHandler;
use WPMailSMTP\Vendor\PhpConsole\Helper;
/**
* Monolog handler for Google Chrome extension "PHP Console"
@@ -23,7 +24,7 @@ use WPMailSMTP\Vendor\PhpConsole\Helper;
* Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely
*
* Usage:
* 1. Install Google Chrome extension https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef
* 1. Install Google Chrome extension [now dead and removed from the chrome store]
* 2. See overview https://github.com/barbushin/php-console#overview
* 3. Install PHP Console library https://github.com/barbushin/php-console#installation
* 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png)
@@ -31,19 +32,23 @@ use WPMailSMTP\Vendor\PhpConsole\Helper;
* $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler()));
* \Monolog\ErrorHandler::register($logger);
* echo $undefinedVar;
* $logger->addDebug('SELECT * FROM users', array('db', 'time' => 0.012));
* $logger->debug('SELECT * FROM users', array('db', 'time' => 0.012));
* PC::debug($_SERVER); // PHP Console debugger for any type of vars
*
* @author Sergey Barbushin https://www.linkedin.com/in/barbushin
*
* @phpstan-import-type Record from \Monolog\Logger
* @deprecated Since 2.8.0 and 3.2.0, PHPConsole is abandoned and thus we will drop this handler in Monolog 4
*/
class PHPConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
private $options = array(
/** @var array<string, mixed> */
private $options = [
'enabled' => \true,
// bool Is PHP Console server enabled
'classesPartialsTraceIgnore' => array('WPMailSMTP\\Vendor\\Monolog\\'),
'classesPartialsTraceIgnore' => ['WPMailSMTP\\Vendor\\Monolog\\'],
// array Hide calls of classes started with...
'debugTagsKeysInContext' => array(0, 'tag'),
'debugTagsKeysInContext' => [0, 'tag'],
// bool Is PHP Console server enabled
'useOwnErrorsHandler' => \false,
// bool Enable errors handling
@@ -61,7 +66,7 @@ class PHPConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProce
// string|null Protect PHP Console connection by password
'enableSslOnlyMode' => \false,
// bool Force connection by SSL for clients with PHP Console installed
'ipMasks' => array(),
'ipMasks' => [],
// array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1')
'enableEvalListener' => \false,
// bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required)
@@ -78,34 +83,37 @@ class PHPConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProce
'detectDumpTraceAndSource' => \false,
// bool Autodetect and append trace data to debug
'dataStorage' => null,
);
];
/** @var Connector */
private $connector;
/**
* @param array $options See \Monolog\Handler\PHPConsoleHandler::$options for more details
* @param Connector|null $connector Instance of \PhpConsole\Connector class (optional)
* @param int $level
* @param bool $bubble
* @throws Exception
* @param array<string, mixed> $options See \Monolog\Handler\PHPConsoleHandler::$options for more details
* @param Connector|null $connector Instance of \PhpConsole\Connector class (optional)
* @throws \RuntimeException
*/
public function __construct(array $options = array(), \WPMailSMTP\Vendor\PhpConsole\Connector $connector = null, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct(array $options = [], ?\WPMailSMTP\Vendor\PhpConsole\Connector $connector = null, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
if (!\class_exists('WPMailSMTP\\Vendor\\PhpConsole\\Connector')) {
throw new \Exception('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
throw new \RuntimeException('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
}
parent::__construct($level, $bubble);
$this->options = $this->initOptions($options);
$this->connector = $this->initConnector($connector);
}
private function initOptions(array $options)
/**
* @param array<string, mixed> $options
*
* @return array<string, mixed>
*/
private function initOptions(array $options) : array
{
$wrongOptions = \array_diff(\array_keys($options), \array_keys($this->options));
if ($wrongOptions) {
throw new \Exception('Unknown options: ' . \implode(', ', $wrongOptions));
throw new \RuntimeException('Unknown options: ' . \implode(', ', $wrongOptions));
}
return \array_replace($this->options, $options);
}
private function initConnector(\WPMailSMTP\Vendor\PhpConsole\Connector $connector = null)
private function initConnector(?\WPMailSMTP\Vendor\PhpConsole\Connector $connector = null) : \WPMailSMTP\Vendor\PhpConsole\Connector
{
if (!$connector) {
if ($this->options['dataStorage']) {
@@ -156,15 +164,18 @@ class PHPConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProce
}
return $connector;
}
public function getConnector()
public function getConnector() : \WPMailSMTP\Vendor\PhpConsole\Connector
{
return $this->connector;
}
public function getOptions()
/**
* @return array<string, mixed>
*/
public function getOptions() : array
{
return $this->options;
}
public function handle(array $record)
public function handle(array $record) : bool
{
if ($this->options['enabled'] && $this->connector->isActiveClient()) {
return parent::handle($record);
@@ -173,21 +184,21 @@ class PHPConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProce
}
/**
* Writes the record down to the log of the implementing handler
*
* @param array $record
* @return void
*/
protected function write(array $record)
protected function write(array $record) : void
{
if ($record['level'] < \WPMailSMTP\Vendor\Monolog\Logger::NOTICE) {
$this->handleDebugRecord($record);
} elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) {
} elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
$this->handleExceptionRecord($record);
} else {
$this->handleErrorRecord($record);
}
}
private function handleDebugRecord(array $record)
/**
* @phpstan-param Record $record
*/
private function handleDebugRecord(array $record) : void
{
$tags = $this->getRecordTags($record);
$message = $record['message'];
@@ -196,15 +207,25 @@ class PHPConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProce
}
$this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
}
private function handleExceptionRecord(array $record)
/**
* @phpstan-param Record $record
*/
private function handleExceptionRecord(array $record) : void
{
$this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']);
}
private function handleErrorRecord(array $record)
/**
* @phpstan-param Record $record
*/
private function handleErrorRecord(array $record) : void
{
$context = $record['context'];
$this->connector->getErrorsDispatcher()->dispatchError(isset($context['code']) ? $context['code'] : null, isset($context['message']) ? $context['message'] : $record['message'], isset($context['file']) ? $context['file'] : null, isset($context['line']) ? $context['line'] : null, $this->options['classesPartialsTraceIgnore']);
$this->connector->getErrorsDispatcher()->dispatchError($context['code'] ?? null, $context['message'] ?? $record['message'], $context['file'] ?? null, $context['line'] ?? null, $this->options['classesPartialsTraceIgnore']);
}
/**
* @phpstan-param Record $record
* @return string
*/
private function getRecordTags(array &$record)
{
$tags = null;
@@ -227,7 +248,7 @@ class PHPConsoleHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProce
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter('%message%');
}

View File

@@ -0,0 +1,168 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
/**
* Stores to STDIN of any process, specified by a command.
*
* Usage example:
* <pre>
* $log = new Logger('myLogger');
* $log->pushHandler(new ProcessHandler('/usr/bin/php /var/www/monolog/someScript.php'));
* </pre>
*
* @author Kolja Zuelsdorf <koljaz@web.de>
*/
class ProcessHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/**
* Holds the process to receive data on its STDIN.
*
* @var resource|bool|null
*/
private $process;
/**
* @var string
*/
private $command;
/**
* @var string|null
*/
private $cwd;
/**
* @var resource[]
*/
private $pipes = [];
/**
* @var array<int, string[]>
*/
protected const DESCRIPTOR_SPEC = [
0 => ['pipe', 'r'],
// STDIN is a pipe that the child will read from
1 => ['pipe', 'w'],
// STDOUT is a pipe that the child will write to
2 => ['pipe', 'w'],
];
/**
* @param string $command Command for the process to start. Absolute paths are recommended,
* especially if you do not use the $cwd parameter.
* @param string|null $cwd "Current working directory" (CWD) for the process to be executed in.
* @throws \InvalidArgumentException
*/
public function __construct(string $command, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, ?string $cwd = null)
{
if ($command === '') {
throw new \InvalidArgumentException('The command argument must be a non-empty string.');
}
if ($cwd === '') {
throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string or null.');
}
parent::__construct($level, $bubble);
$this->command = $command;
$this->cwd = $cwd;
}
/**
* Writes the record down to the log of the implementing handler
*
* @throws \UnexpectedValueException
*/
protected function write(array $record) : void
{
$this->ensureProcessIsStarted();
$this->writeProcessInput($record['formatted']);
$errors = $this->readProcessErrors();
if (empty($errors) === \false) {
throw new \UnexpectedValueException(\sprintf('Errors while writing to process: %s', $errors));
}
}
/**
* Makes sure that the process is actually started, and if not, starts it,
* assigns the stream pipes, and handles startup errors, if any.
*/
private function ensureProcessIsStarted() : void
{
if (\is_resource($this->process) === \false) {
$this->startProcess();
$this->handleStartupErrors();
}
}
/**
* Starts the actual process and sets all streams to non-blocking.
*/
private function startProcess() : void
{
$this->process = \proc_open($this->command, static::DESCRIPTOR_SPEC, $this->pipes, $this->cwd);
foreach ($this->pipes as $pipe) {
\stream_set_blocking($pipe, \false);
}
}
/**
* Selects the STDERR stream, handles upcoming startup errors, and throws an exception, if any.
*
* @throws \UnexpectedValueException
*/
private function handleStartupErrors() : void
{
$selected = $this->selectErrorStream();
if (\false === $selected) {
throw new \UnexpectedValueException('Something went wrong while selecting a stream.');
}
$errors = $this->readProcessErrors();
if (\is_resource($this->process) === \false || empty($errors) === \false) {
throw new \UnexpectedValueException(\sprintf('The process "%s" could not be opened: ' . $errors, $this->command));
}
}
/**
* Selects the STDERR stream.
*
* @return int|bool
*/
protected function selectErrorStream()
{
$empty = [];
$errorPipes = [$this->pipes[2]];
return \stream_select($errorPipes, $empty, $empty, 1);
}
/**
* Reads the errors of the process, if there are any.
*
* @codeCoverageIgnore
* @return string Empty string if there are no errors.
*/
protected function readProcessErrors() : string
{
return (string) \stream_get_contents($this->pipes[2]);
}
/**
* Writes to the input stream of the opened process.
*
* @codeCoverageIgnore
*/
protected function writeProcessInput(string $string) : void
{
\fwrite($this->pipes[0], $string);
}
/**
* {@inheritDoc}
*/
public function close() : void
{
if (\is_resource($this->process)) {
foreach ($this->pipes as $pipe) {
\fclose($pipe);
}
\proc_close($this->process);
$this->process = null;
}
}
}

View File

@@ -15,24 +15,28 @@ use WPMailSMTP\Vendor\Monolog\Processor\ProcessorInterface;
/**
* Interface to describe loggers that have processors
*
* This interface is present in monolog 1.x to ease forward compatibility.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
interface ProcessableHandlerInterface
{
/**
* Adds a processor in the stack.
*
* @psalm-param ProcessorInterface|callable(Record): Record $callback
*
* @param ProcessorInterface|callable $callback
* @return HandlerInterface self
*/
public function pushProcessor($callback) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface;
public function pushProcessor(callable $callback) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface;
/**
* Removes the processor on top of the stack and returns it.
*
* @throws \LogicException In case the processor stack is empty
* @return callable
* @psalm-return ProcessorInterface|callable(Record): Record $callback
*
* @throws \LogicException In case the processor stack is empty
* @return callable|ProcessorInterface
*/
public function popProcessor() : callable;
}

View File

@@ -12,30 +12,31 @@ declare (strict_types=1);
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\ResettableInterface;
use WPMailSMTP\Vendor\Monolog\Processor\ProcessorInterface;
/**
* Helper trait for implementing ProcessableInterface
*
* This trait is present in monolog 1.x to ease forward compatibility.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
trait ProcessableHandlerTrait
{
/**
* @var callable[]
* @phpstan-var array<ProcessorInterface|callable(Record): Record>
*/
protected $processors = [];
/**
* {@inheritdoc}
* @suppress PhanTypeMismatchReturn
* {@inheritDoc}
*/
public function pushProcessor($callback) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
public function pushProcessor(callable $callback) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
\array_unshift($this->processors, $callback);
return $this;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function popProcessor() : callable
{
@@ -46,6 +47,9 @@ trait ProcessableHandlerTrait
}
/**
* Processes a record.
*
* @phpstan-param Record $record
* @phpstan-return Record
*/
protected function processRecord(array $record) : array
{

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -12,12 +13,17 @@ namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Psr\Log\LoggerInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
/**
* Proxies log messages to an existing PSR-3 compliant logger.
*
* If a formatter is configured, the formatter's output MUST be a string and the
* formatted message will be fed to the wrapped PSR logger instead of the original
* log record's message.
*
* @author Michael Moussa <michael.moussa@gmail.com>
*/
class PsrHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
class PsrHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler implements \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface
{
/**
* PSR-3 compliant logger
@@ -26,11 +32,13 @@ class PsrHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
*/
protected $logger;
/**
* @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @var FormatterInterface|null
*/
public function __construct(\WPMailSMTP\Vendor\Psr\Log\LoggerInterface $logger, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
protected $formatter;
/**
* @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
*/
public function __construct(\WPMailSMTP\Vendor\Psr\Log\LoggerInterface $logger, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
parent::__construct($level, $bubble);
$this->logger = $logger;
@@ -38,12 +46,39 @@ class PsrHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
/**
* {@inheritDoc}
*/
public function handle(array $record)
public function handle(array $record) : bool
{
if (!$this->isHandling($record)) {
return \false;
}
$this->logger->log(\strtolower($record['level_name']), $record['message'], $record['context']);
if ($this->formatter) {
$formatted = $this->formatter->format($record);
$this->logger->log(\strtolower($record['level_name']), (string) $formatted, $record['context']);
} else {
$this->logger->log(\strtolower($record['level_name']), $record['message'], $record['context']);
}
return \false === $this->bubble;
}
/**
* Sets the formatter.
*
* @param FormatterInterface $formatter
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
$this->formatter = $formatter;
return $this;
}
/**
* Gets the formatter.
*
* @return FormatterInterface
*/
public function getFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
if (!$this->formatter) {
throw new \LogicException('No formatter has been set and this handler does not have a default formatter');
}
return $this->formatter;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,75 +12,97 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
/**
* Sends notifications through the pushover api to mobile phones
*
* @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com>
* @see https://www.pushover.net/api
*
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
* @phpstan-import-type Level from \Monolog\Logger
* @phpstan-import-type LevelName from \Monolog\Logger
*/
class PushoverHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
{
/** @var string */
private $token;
/** @var array<int|string> */
private $users;
/** @var string */
private $title;
private $user;
/** @var string|int|null */
private $user = null;
/** @var int */
private $retry;
/** @var int */
private $expire;
/** @var int */
private $highPriorityLevel;
/** @var int */
private $emergencyLevel;
/** @var bool */
private $useFormattedMessage = \false;
/**
* All parameters that can be sent to Pushover
* @see https://pushover.net/api
* @var array
* @var array<string, bool>
*/
private $parameterNames = array('token' => \true, 'user' => \true, 'message' => \true, 'device' => \true, 'title' => \true, 'url' => \true, 'url_title' => \true, 'priority' => \true, 'timestamp' => \true, 'sound' => \true, 'retry' => \true, 'expire' => \true, 'callback' => \true);
private $parameterNames = ['token' => \true, 'user' => \true, 'message' => \true, 'device' => \true, 'title' => \true, 'url' => \true, 'url_title' => \true, 'priority' => \true, 'timestamp' => \true, 'sound' => \true, 'retry' => \true, 'expire' => \true, 'callback' => \true];
/**
* Sounds the api supports by default
* @see https://pushover.net/api#sounds
* @var array
* @var string[]
*/
private $sounds = array('pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', 'persistent', 'echo', 'updown', 'none');
private $sounds = ['pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', 'persistent', 'echo', 'updown', 'none'];
/**
* @param string $token Pushover api token
* @param string|array $users Pushover user id or array of ids the message will be sent to
* @param string $title Title sent to the Pushover API
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param string|null $title Title sent to the Pushover API
* @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
* the pushover.net app owner. OpenSSL is required for this option.
* @param int $highPriorityLevel The minimum logging level at which this handler will start
* @param string|int $highPriorityLevel The minimum logging level at which this handler will start
* sending "high priority" requests to the Pushover API
* @param int $emergencyLevel The minimum logging level at which this handler will start
* @param string|int $emergencyLevel The minimum logging level at which this handler will start
* sending "emergency" requests to the Pushover API
* @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will send the same notification to the user.
* @param int $expire The expire parameter specifies how many seconds your notification will continue to be retried for (every retry seconds).
* @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will
* send the same notification to the user.
* @param int $expire The expire parameter specifies how many seconds your notification will continue
* to be retried for (every retry seconds).
*
* @phpstan-param string|array<int|string> $users
* @phpstan-param Level|LevelName|LogLevel::* $highPriorityLevel
* @phpstan-param Level|LevelName|LogLevel::* $emergencyLevel
*/
public function __construct($token, $users, $title = null, $level = \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL, $bubble = \true, $useSSL = \true, $highPriorityLevel = \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL, $emergencyLevel = \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY, $retry = 30, $expire = 25200)
public function __construct(string $token, $users, ?string $title = null, $level = \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL, bool $bubble = \true, bool $useSSL = \true, $highPriorityLevel = \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL, $emergencyLevel = \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY, int $retry = 30, int $expire = 25200, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
{
$connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80';
parent::__construct($connectionString, $level, $bubble);
parent::__construct($connectionString, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
$this->token = $token;
$this->users = (array) $users;
$this->title = $title ?: \gethostname();
$this->title = $title ?: (string) \gethostname();
$this->highPriorityLevel = \WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($highPriorityLevel);
$this->emergencyLevel = \WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($emergencyLevel);
$this->retry = $retry;
$this->expire = $expire;
}
protected function generateDataStream($record)
protected function generateDataStream(array $record) : string
{
$content = $this->buildContent($record);
return $this->buildHeader($content) . $content;
}
private function buildContent($record)
/**
* @phpstan-param FormattedRecord $record
*/
private function buildContent(array $record) : string
{
// Pushover has a limit of 512 characters on title and message combined.
$maxMessageLength = 512 - \strlen($this->title);
$message = $this->useFormattedMessage ? $record['formatted'] : $record['message'];
$message = \substr($message, 0, $maxMessageLength);
$message = \WPMailSMTP\Vendor\Monolog\Utils::substr($message, 0, $maxMessageLength);
$timestamp = $record['datetime']->getTimestamp();
$dataArray = array('token' => $this->token, 'user' => $this->user, 'message' => $message, 'title' => $this->title, 'timestamp' => $timestamp);
$dataArray = ['token' => $this->token, 'user' => $this->user, 'message' => $message, 'title' => $this->title, 'timestamp' => $timestamp];
if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) {
$dataArray['priority'] = 2;
$dataArray['retry'] = $this->retry;
@@ -98,7 +121,7 @@ class PushoverHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
}
return \http_build_query($dataArray);
}
private function buildHeader($content)
private function buildHeader(string $content) : string
{
$header = "POST /1/messages.json HTTP/1.1\r\n";
$header .= "Host: api.pushover.net\r\n";
@@ -107,7 +130,7 @@ class PushoverHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
$header .= "\r\n";
return $header;
}
protected function write(array $record)
protected function write(array $record) : void
{
foreach ($this->users as $user) {
$this->user = $user;
@@ -116,20 +139,32 @@ class PushoverHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
}
$this->user = null;
}
public function setHighPriorityLevel($value)
/**
* @param int|string $value
*
* @phpstan-param Level|LevelName|LogLevel::* $value
*/
public function setHighPriorityLevel($value) : self
{
$this->highPriorityLevel = $value;
$this->highPriorityLevel = \WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($value);
return $this;
}
public function setEmergencyLevel($value)
/**
* @param int|string $value
*
* @phpstan-param Level|LevelName|LogLevel::* $value
*/
public function setEmergencyLevel($value) : self
{
$this->emergencyLevel = $value;
$this->emergencyLevel = \WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($value);
return $this;
}
/**
* Use the formatted message?
* @param bool $value
*/
public function useFormattedMessage($value)
public function useFormattedMessage(bool $value) : self
{
$this->useFormattedMessage = (bool) $value;
$this->useFormattedMessage = $value;
return $this;
}
}

View File

@@ -1,197 +0,0 @@
<?php
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Raven_Client;
/**
* Handler to send messages to a Sentry (https://github.com/getsentry/sentry) server
* using sentry-php (https://github.com/getsentry/sentry-php)
*
* @author Marc Abramowitz <marc@marc-abramowitz.com>
*/
class RavenHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/**
* Translates Monolog log levels to Raven log levels.
*/
protected $logLevels = array(\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => \WPMailSMTP\Vendor\Raven_Client::DEBUG, \WPMailSMTP\Vendor\Monolog\Logger::INFO => \WPMailSMTP\Vendor\Raven_Client::INFO, \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => \WPMailSMTP\Vendor\Raven_Client::INFO, \WPMailSMTP\Vendor\Monolog\Logger::WARNING => \WPMailSMTP\Vendor\Raven_Client::WARNING, \WPMailSMTP\Vendor\Monolog\Logger::ERROR => \WPMailSMTP\Vendor\Raven_Client::ERROR, \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => \WPMailSMTP\Vendor\Raven_Client::FATAL, \WPMailSMTP\Vendor\Monolog\Logger::ALERT => \WPMailSMTP\Vendor\Raven_Client::FATAL, \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => \WPMailSMTP\Vendor\Raven_Client::FATAL);
/**
* @var string should represent the current version of the calling
* software. Can be any string (git commit, version number)
*/
protected $release;
/**
* @var Raven_Client the client object that sends the message to the server
*/
protected $ravenClient;
/**
* @var FormatterInterface The formatter to use for the logs generated via handleBatch()
*/
protected $batchFormatter;
/**
* @param Raven_Client $ravenClient
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(\WPMailSMTP\Vendor\Raven_Client $ravenClient, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
{
@\trigger_error('The Monolog\\Handler\\RavenHandler class is deprecated. You should rather upgrade to the sentry/sentry 2.x and use Sentry\\Monolog\\Handler, see https://github.com/getsentry/sentry-php/blob/master/src/Monolog/Handler.php', \E_USER_DEPRECATED);
parent::__construct($level, $bubble);
$this->ravenClient = $ravenClient;
}
/**
* {@inheritdoc}
*/
public function handleBatch(array $records)
{
$level = $this->level;
// filter records based on their level
$records = \array_filter($records, function ($record) use($level) {
return $record['level'] >= $level;
});
if (!$records) {
return;
}
// the record with the highest severity is the "main" one
$record = \array_reduce($records, function ($highest, $record) {
if (null === $highest || $record['level'] > $highest['level']) {
return $record;
}
return $highest;
});
// the other ones are added as a context item
$logs = array();
foreach ($records as $r) {
$logs[] = $this->processRecord($r);
}
if ($logs) {
$record['context']['logs'] = (string) $this->getBatchFormatter()->formatBatch($logs);
}
$this->handle($record);
}
/**
* Sets the formatter for the logs generated by handleBatch().
*
* @param FormatterInterface $formatter
*/
public function setBatchFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
{
$this->batchFormatter = $formatter;
}
/**
* Gets the formatter for the logs generated by handleBatch().
*
* @return FormatterInterface
*/
public function getBatchFormatter()
{
if (!$this->batchFormatter) {
$this->batchFormatter = $this->getDefaultBatchFormatter();
}
return $this->batchFormatter;
}
/**
* {@inheritdoc}
*/
protected function write(array $record)
{
$previousUserContext = \false;
$options = array();
$options['level'] = $this->logLevels[$record['level']];
$options['tags'] = array();
if (!empty($record['extra']['tags'])) {
$options['tags'] = \array_merge($options['tags'], $record['extra']['tags']);
unset($record['extra']['tags']);
}
if (!empty($record['context']['tags'])) {
$options['tags'] = \array_merge($options['tags'], $record['context']['tags']);
unset($record['context']['tags']);
}
if (!empty($record['context']['fingerprint'])) {
$options['fingerprint'] = $record['context']['fingerprint'];
unset($record['context']['fingerprint']);
}
if (!empty($record['context']['logger'])) {
$options['logger'] = $record['context']['logger'];
unset($record['context']['logger']);
} else {
$options['logger'] = $record['channel'];
}
foreach ($this->getExtraParameters() as $key) {
foreach (array('extra', 'context') as $source) {
if (!empty($record[$source][$key])) {
$options[$key] = $record[$source][$key];
unset($record[$source][$key]);
}
}
}
if (!empty($record['context'])) {
$options['extra']['context'] = $record['context'];
if (!empty($record['context']['user'])) {
$previousUserContext = $this->ravenClient->context->user;
$this->ravenClient->user_context($record['context']['user']);
unset($options['extra']['context']['user']);
}
}
if (!empty($record['extra'])) {
$options['extra']['extra'] = $record['extra'];
}
if (!empty($this->release) && !isset($options['release'])) {
$options['release'] = $this->release;
}
if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || \PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable)) {
$options['message'] = $record['formatted'];
$this->ravenClient->captureException($record['context']['exception'], $options);
} else {
$this->ravenClient->captureMessage($record['formatted'], array(), $options);
}
if ($previousUserContext !== \false) {
$this->ravenClient->user_context($previousUserContext);
}
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter('[%channel%] %message%');
}
/**
* Gets the default formatter for the logs generated by handleBatch().
*
* @return FormatterInterface
*/
protected function getDefaultBatchFormatter()
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter();
}
/**
* Gets extra parameters supported by Raven that can be found in "extra" and "context"
*
* @return array
*/
protected function getExtraParameters()
{
return array('contexts', 'checksum', 'release', 'event_id');
}
/**
* @param string $value
* @return self
*/
public function setRelease($value)
{
$this->release = $value;
return $this;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,6 +12,7 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Logger;
/**
* Logs to a Redis key using rpush
@@ -22,20 +24,23 @@ use WPMailSMTP\Vendor\Monolog\Logger;
* $log->pushHandler($redis);
*
* @author Thomas Tourlourat <thomas@tourlourat.com>
*
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class RedisHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/** @var \Predis\Client<\Predis\Client>|\Redis */
private $redisClient;
/** @var string */
private $redisKey;
/** @var int */
protected $capSize;
/**
* @param \Predis\Client|\Redis $redis The redis instance
* @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance
* @param string $key The key name to push records to
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int|false $capSize Number of entries to limit list size to
* @param int $capSize Number of entries to limit list size to, 0 = unlimited
*/
public function __construct($redis, $key, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true, $capSize = \false)
public function __construct($redis, string $key, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, int $capSize = 0)
{
if (!($redis instanceof \WPMailSMTP\Vendor\Predis\Client || $redis instanceof \Redis)) {
throw new \InvalidArgumentException('Predis\\Client or Redis instance required');
@@ -48,7 +53,7 @@ class RedisHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessing
/**
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
if ($this->capSize) {
$this->writeCapped($record);
@@ -60,10 +65,9 @@ class RedisHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessing
* Write and cap the collection
* Writes the record to the redis list and caps its
*
* @param array $record associative record array
* @return void
* @phpstan-param FormattedRecord $record
*/
protected function writeCapped(array $record)
protected function writeCapped(array $record) : void
{
if ($this->redisClient instanceof \Redis) {
$mode = \defined('\\Redis::MULTI') ? \Redis::MULTI : 1;
@@ -80,7 +84,7 @@ class RedisHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessing
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter()
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter();
}

View File

@@ -0,0 +1,61 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Logger;
/**
* Sends the message to a Redis Pub/Sub channel using PUBLISH
*
* usage example:
*
* $log = new Logger('application');
* $redis = new RedisPubSubHandler(new Predis\Client("tcp://localhost:6379"), "logs", Logger::WARNING);
* $log->pushHandler($redis);
*
* @author Gaëtan Faugère <gaetan@fauge.re>
*/
class RedisPubSubHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/** @var \Predis\Client<\Predis\Client>|\Redis */
private $redisClient;
/** @var string */
private $channelKey;
/**
* @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance
* @param string $key The channel key to publish records to
*/
public function __construct($redis, string $key, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
if (!($redis instanceof \WPMailSMTP\Vendor\Predis\Client || $redis instanceof \Redis)) {
throw new \InvalidArgumentException('Predis\\Client or Redis instance required');
}
$this->redisClient = $redis;
$this->channelKey = $key;
parent::__construct($level, $bubble);
}
/**
* {@inheritDoc}
*/
protected function write(array $record) : void
{
$this->redisClient->publish($this->channelKey, $record["formatted"]);
}
/**
* {@inheritDoc}
*/
protected function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter();
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,14 +11,14 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\RollbarNotifier;
use Exception;
use WPMailSMTP\Vendor\Rollbar\RollbarLogger;
use Throwable;
use WPMailSMTP\Vendor\Monolog\Logger;
/**
* Sends errors to Rollbar
*
* If the context data contains a `payload` key, that is used as an array
* of payload options to RollbarNotifier's report_message/report_exception methods.
* of payload options to RollbarLogger's log method.
*
* Rollbar's context info will contain the context + extra keys from the log record
* merged, and then on top of that a few keys:
@@ -32,33 +33,31 @@ use WPMailSMTP\Vendor\Monolog\Logger;
class RollbarHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/**
* Rollbar notifier
*
* @var RollbarNotifier
* @var RollbarLogger
*/
protected $rollbarNotifier;
protected $levelMap = array(\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => 'debug', \WPMailSMTP\Vendor\Monolog\Logger::INFO => 'info', \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => 'info', \WPMailSMTP\Vendor\Monolog\Logger::WARNING => 'warning', \WPMailSMTP\Vendor\Monolog\Logger::ERROR => 'error', \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => 'critical', \WPMailSMTP\Vendor\Monolog\Logger::ALERT => 'critical', \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => 'critical');
protected $rollbarLogger;
/** @var string[] */
protected $levelMap = [\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => 'debug', \WPMailSMTP\Vendor\Monolog\Logger::INFO => 'info', \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => 'info', \WPMailSMTP\Vendor\Monolog\Logger::WARNING => 'warning', \WPMailSMTP\Vendor\Monolog\Logger::ERROR => 'error', \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => 'critical', \WPMailSMTP\Vendor\Monolog\Logger::ALERT => 'critical', \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => 'critical'];
/**
* Records whether any log records have been added since the last flush of the rollbar notifier
*
* @var bool
*/
private $hasRecords = \false;
/** @var bool */
protected $initialized = \false;
/**
* @param RollbarNotifier $rollbarNotifier RollbarNotifier object constructed with valid token
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param RollbarLogger $rollbarLogger RollbarLogger object constructed with valid token
*/
public function __construct(\WPMailSMTP\Vendor\RollbarNotifier $rollbarNotifier, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, $bubble = \true)
public function __construct(\WPMailSMTP\Vendor\Rollbar\RollbarLogger $rollbarLogger, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, bool $bubble = \true)
{
$this->rollbarNotifier = $rollbarNotifier;
$this->rollbarLogger = $rollbarLogger;
parent::__construct($level, $bubble);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
if (!$this->initialized) {
// __destructor() doesn't get called on Fatal errors
@@ -66,38 +65,34 @@ class RollbarHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessi
$this->initialized = \true;
}
$context = $record['context'];
$payload = array();
if (isset($context['payload'])) {
$payload = $context['payload'];
unset($context['payload']);
}
$context = \array_merge($context, $record['extra'], array('level' => $this->levelMap[$record['level']], 'monolog_level' => $record['level_name'], 'channel' => $record['channel'], 'datetime' => $record['datetime']->format('U')));
if (isset($context['exception']) && $context['exception'] instanceof \Exception) {
$payload['level'] = $context['level'];
$context = \array_merge($context, $record['extra'], ['level' => $this->levelMap[$record['level']], 'monolog_level' => $record['level_name'], 'channel' => $record['channel'], 'datetime' => $record['datetime']->format('U')]);
if (isset($context['exception']) && $context['exception'] instanceof \Throwable) {
$exception = $context['exception'];
unset($context['exception']);
$this->rollbarNotifier->report_exception($exception, $context, $payload);
$toLog = $exception;
} else {
$this->rollbarNotifier->report_message($record['message'], $context['level'], $context, $payload);
$toLog = $record['message'];
}
// @phpstan-ignore-next-line
$this->rollbarLogger->log($context['level'], $toLog, $context);
$this->hasRecords = \true;
}
public function flush()
public function flush() : void
{
if ($this->hasRecords) {
$this->rollbarNotifier->flush();
$this->rollbarLogger->flush();
$this->hasRecords = \false;
}
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function close()
public function close() : void
{
$this->flush();
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function reset()
{

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,6 +11,7 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use InvalidArgumentException;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
/**
@@ -23,36 +25,40 @@ use WPMailSMTP\Vendor\Monolog\Utils;
*/
class RotatingFileHandler extends \WPMailSMTP\Vendor\Monolog\Handler\StreamHandler
{
const FILE_PER_DAY = 'Y-m-d';
const FILE_PER_MONTH = 'Y-m';
const FILE_PER_YEAR = 'Y';
public const FILE_PER_DAY = 'Y-m-d';
public const FILE_PER_MONTH = 'Y-m';
public const FILE_PER_YEAR = 'Y';
/** @var string */
protected $filename;
/** @var int */
protected $maxFiles;
/** @var bool */
protected $mustRotate;
/** @var \DateTimeImmutable */
protected $nextRotation;
/** @var string */
protected $filenameFormat;
/** @var string */
protected $dateFormat;
/**
* @param string $filename
* @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
* @param bool $useLocking Try to lock log file before doing any writes
* @param string $filename
* @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
* @param bool $useLocking Try to lock log file before doing any writes
*/
public function __construct($filename, $maxFiles = 0, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true, $filePermission = null, $useLocking = \false)
public function __construct(string $filename, int $maxFiles = 0, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, ?int $filePermission = null, bool $useLocking = \false)
{
$this->filename = \WPMailSMTP\Vendor\Monolog\Utils::canonicalizePath($filename);
$this->maxFiles = (int) $maxFiles;
$this->nextRotation = new \DateTime('tomorrow');
$this->maxFiles = $maxFiles;
$this->nextRotation = new \DateTimeImmutable('tomorrow');
$this->filenameFormat = '{filename}-{date}';
$this->dateFormat = 'Y-m-d';
$this->dateFormat = static::FILE_PER_DAY;
parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function close()
public function close() : void
{
parent::close();
if (\true === $this->mustRotate) {
@@ -60,7 +66,7 @@ class RotatingFileHandler extends \WPMailSMTP\Vendor\Monolog\Handler\StreamHandl
}
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function reset()
{
@@ -69,29 +75,30 @@ class RotatingFileHandler extends \WPMailSMTP\Vendor\Monolog\Handler\StreamHandl
$this->rotate();
}
}
public function setFilenameFormat($filenameFormat, $dateFormat)
public function setFilenameFormat(string $filenameFormat, string $dateFormat) : self
{
if (!\preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
\trigger_error('Invalid date format - format must be one of ' . 'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") ' . 'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the ' . 'date formats using slashes, underscores and/or dots instead of dashes.', \E_USER_DEPRECATED);
if (!\preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
throw new \InvalidArgumentException('Invalid date format - format must be one of ' . 'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") ' . 'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the ' . 'date formats using slashes, underscores and/or dots instead of dashes.');
}
if (\substr_count($filenameFormat, '{date}') === 0) {
\trigger_error('Invalid filename format - format should contain at least `{date}`, because otherwise rotating is impossible.', \E_USER_DEPRECATED);
throw new \InvalidArgumentException('Invalid filename format - format must contain at least `{date}`, because otherwise rotating is impossible.');
}
$this->filenameFormat = $filenameFormat;
$this->dateFormat = $dateFormat;
$this->url = $this->getTimedFilename();
$this->close();
return $this;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
// on the first record written, if the log is new, we should rotate (once per day)
if (null === $this->mustRotate) {
$this->mustRotate = !\file_exists($this->url);
$this->mustRotate = null === $this->url || !\file_exists($this->url);
}
if ($this->nextRotation < $record['datetime']) {
if ($this->nextRotation <= $record['datetime']) {
$this->mustRotate = \true;
$this->close();
}
@@ -100,16 +107,20 @@ class RotatingFileHandler extends \WPMailSMTP\Vendor\Monolog\Handler\StreamHandl
/**
* Rotates the files.
*/
protected function rotate()
protected function rotate() : void
{
// update filename
$this->url = $this->getTimedFilename();
$this->nextRotation = new \DateTime('tomorrow');
$this->nextRotation = new \DateTimeImmutable('tomorrow');
// skip GC of old logs if files are unlimited
if (0 === $this->maxFiles) {
return;
}
$logFiles = \glob($this->getGlobPattern());
if (\false === $logFiles) {
// failed to glob
return;
}
if ($this->maxFiles >= \count($logFiles)) {
// no files to remove
return;
@@ -122,7 +133,8 @@ class RotatingFileHandler extends \WPMailSMTP\Vendor\Monolog\Handler\StreamHandl
if (\is_writable($file)) {
// suppress errors here as unlink() might fail if two processes
// are cleaning up/rotating at the same time
\set_error_handler(function ($errno, $errstr, $errfile, $errline) {
\set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) : bool {
return \false;
});
\unlink($file);
\restore_error_handler();
@@ -130,20 +142,20 @@ class RotatingFileHandler extends \WPMailSMTP\Vendor\Monolog\Handler\StreamHandl
}
$this->mustRotate = \false;
}
protected function getTimedFilename()
protected function getTimedFilename() : string
{
$fileInfo = \pathinfo($this->filename);
$timedFilename = \str_replace(array('{filename}', '{date}'), array($fileInfo['filename'], \date($this->dateFormat)), $fileInfo['dirname'] . '/' . $this->filenameFormat);
if (!empty($fileInfo['extension'])) {
$timedFilename = \str_replace(['{filename}', '{date}'], [$fileInfo['filename'], \date($this->dateFormat)], $fileInfo['dirname'] . '/' . $this->filenameFormat);
if (isset($fileInfo['extension'])) {
$timedFilename .= '.' . $fileInfo['extension'];
}
return $timedFilename;
}
protected function getGlobPattern()
protected function getGlobPattern() : string
{
$fileInfo = \pathinfo($this->filename);
$glob = \str_replace(array('{filename}', '{date}'), array($fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'), $fileInfo['dirname'] . '/' . $this->filenameFormat);
if (!empty($fileInfo['extension'])) {
$glob = \str_replace(['{filename}', '{date}'], [$fileInfo['filename'], \str_replace(['Y', 'y', 'm', 'd'], ['[0-9][0-9][0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]'], $this->dateFormat)], $fileInfo['dirname'] . '/' . $this->filenameFormat);
if (isset($fileInfo['extension'])) {
$glob .= '.' . $fileInfo['extension'];
}
return $glob;

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -24,11 +25,16 @@ use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
*
* @author Bryan Davis <bd808@wikimedia.org>
* @author Kunal Mehta <legoktm@gmail.com>
*
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger
*/
class SamplingHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
class SamplingHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler implements \WPMailSMTP\Vendor\Monolog\Handler\ProcessableHandlerInterface, \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface
{
use ProcessableHandlerTrait;
/**
* @var callable|HandlerInterface $handler
* @var HandlerInterface|callable
* @phpstan-var HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface
*/
protected $handler;
/**
@@ -36,10 +42,12 @@ class SamplingHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
*/
protected $factor;
/**
* @psalm-param HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface $handler
*
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler).
* @param int $factor Sample factor
* @param int $factor Sample factor (e.g. 10 means every ~10th record is sampled)
*/
public function __construct($handler, $factor)
public function __construct($handler, int $factor)
{
parent::__construct();
$this->handler = $handler;
@@ -48,17 +56,16 @@ class SamplingHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
throw new \RuntimeException("The given handler (" . \json_encode($this->handler) . ") is not a callable nor a Monolog\\Handler\\HandlerInterface object");
}
}
public function isHandling(array $record)
public function isHandling(array $record) : bool
{
return $this->getHandler($record)->isHandling($record);
}
public function handle(array $record)
public function handle(array $record) : bool
{
if ($this->isHandling($record) && \mt_rand(1, $this->factor) === 1) {
if ($this->processors) {
foreach ($this->processors as $processor) {
$record = \call_user_func($processor, $record);
}
/** @var Record $record */
$record = $this->processRecord($record);
}
$this->getHandler($record)->handle($record);
}
@@ -69,12 +76,14 @@ class SamplingHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
*
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
*
* @phpstan-param Record|array{level: Level}|null $record
*
* @return HandlerInterface
*/
public function getHandler(array $record = null)
public function getHandler(?array $record = null)
{
if (!$this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface) {
$this->handler = \call_user_func($this->handler, $record, $this);
$this->handler = ($this->handler)($record, $this);
if (!$this->handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
@@ -82,18 +91,26 @@ class SamplingHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractHandler
return $this->handler;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
$this->getHandler()->setFormatter($formatter);
return $this;
$handler = $this->getHandler();
if ($handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
$handler->setFormatter($formatter);
return $this;
}
throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getFormatter()
public function getFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return $this->getHandler()->getFormatter();
$handler = $this->getHandler();
if ($handler instanceof \WPMailSMTP\Vendor\Monolog\Handler\FormattableHandlerInterface) {
return $handler->getFormatter();
}
throw new \UnexpectedValueException('The nested handler of type ' . \get_class($handler) . ' does not support formatters.');
}
}

View File

@@ -0,0 +1,92 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
/**
* SendGridrHandler uses the SendGrid API v2 function to send Log emails, more information in https://sendgrid.com/docs/API_Reference/Web_API/mail.html
*
* @author Ricardo Fontanelli <ricardo.fontanelli@hotmail.com>
*/
class SendGridHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
{
/**
* The SendGrid API User
* @var string
*/
protected $apiUser;
/**
* The SendGrid API Key
* @var string
*/
protected $apiKey;
/**
* The email addresses to which the message will be sent
* @var string
*/
protected $from;
/**
* The email addresses to which the message will be sent
* @var string[]
*/
protected $to;
/**
* The subject of the email
* @var string
*/
protected $subject;
/**
* @param string $apiUser The SendGrid API User
* @param string $apiKey The SendGrid API Key
* @param string $from The sender of the email
* @param string|string[] $to The recipients of the email
* @param string $subject The subject of the mail
*/
public function __construct(string $apiUser, string $apiKey, string $from, $to, string $subject, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, bool $bubble = \true)
{
if (!\extension_loaded('curl')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The curl extension is needed to use the SendGridHandler');
}
parent::__construct($level, $bubble);
$this->apiUser = $apiUser;
$this->apiKey = $apiKey;
$this->from = $from;
$this->to = (array) $to;
$this->subject = $subject;
}
/**
* {@inheritDoc}
*/
protected function send(string $content, array $records) : void
{
$message = [];
$message['api_user'] = $this->apiUser;
$message['api_key'] = $this->apiKey;
$message['from'] = $this->from;
foreach ($this->to as $recipient) {
$message['to[]'] = $recipient;
}
$message['subject'] = $this->subject;
$message['date'] = \date('r');
if ($this->isHtmlBody($content)) {
$message['html'] = $content;
} else {
$message['text'] = $content;
}
$ch = \curl_init();
\curl_setopt($ch, \CURLOPT_URL, 'https://api.sendgrid.com/api/mail.send.json');
\curl_setopt($ch, \CURLOPT_POST, 1);
\curl_setopt($ch, \CURLOPT_RETURNTRANSFER, 1);
\curl_setopt($ch, \CURLOPT_POSTFIELDS, \http_build_query($message));
\WPMailSMTP\Vendor\Monolog\Handler\Curl\Util::execute($ch, 2);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -21,13 +22,16 @@ use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
* @author Haralan Dobrev <hkdobrev@gmail.com>
* @see https://api.slack.com/incoming-webhooks
* @see https://api.slack.com/docs/message-attachments
*
* @phpstan-import-type FormattedRecord from \Monolog\Handler\AbstractProcessingHandler
* @phpstan-import-type Record from \Monolog\Logger
*/
class SlackRecord
{
const COLOR_DANGER = 'danger';
const COLOR_WARNING = 'warning';
const COLOR_GOOD = 'good';
const COLOR_DEFAULT = '#e3e4e6';
public const COLOR_DANGER = 'danger';
public const COLOR_WARNING = 'warning';
public const COLOR_GOOD = 'good';
public const COLOR_DEFAULT = '#e3e4e6';
/**
* Slack channel (encoded ID or name)
* @var string|null
@@ -40,7 +44,7 @@ class SlackRecord
private $username;
/**
* User icon e.g. 'ghost', 'http://example.com/user.png'
* @var string
* @var string|null
*/
private $userIcon;
/**
@@ -60,35 +64,38 @@ class SlackRecord
private $includeContextAndExtra;
/**
* Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
* @var array
* @var string[]
*/
private $excludeFields;
/**
* @var FormatterInterface
* @var ?FormatterInterface
*/
private $formatter;
/**
* @var NormalizerFormatter
*/
private $normalizerFormatter;
public function __construct($channel = null, $username = null, $useAttachment = \true, $userIcon = null, $useShortAttachment = \false, $includeContextAndExtra = \false, array $excludeFields = array(), \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter = null)
/**
* @param string[] $excludeFields
*/
public function __construct(?string $channel = null, ?string $username = null, bool $useAttachment = \true, ?string $userIcon = null, bool $useShortAttachment = \false, bool $includeContextAndExtra = \false, array $excludeFields = array(), ?\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter = null)
{
$this->channel = $channel;
$this->username = $username;
$this->userIcon = \trim($userIcon, ':');
$this->useAttachment = $useAttachment;
$this->useShortAttachment = $useShortAttachment;
$this->includeContextAndExtra = $includeContextAndExtra;
$this->excludeFields = $excludeFields;
$this->formatter = $formatter;
$this->setChannel($channel)->setUsername($username)->useAttachment($useAttachment)->setUserIcon($userIcon)->useShortAttachment($useShortAttachment)->includeContextAndExtra($includeContextAndExtra)->excludeFields($excludeFields)->setFormatter($formatter);
if ($this->includeContextAndExtra) {
$this->normalizerFormatter = new \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter();
}
}
public function getSlackData(array $record)
/**
* Returns required data in format that Slack
* is expecting.
*
* @phpstan-param FormattedRecord $record
* @phpstan-return mixed[]
*/
public function getSlackData(array $record) : array
{
$dataArray = array();
$record = $this->excludeFields($record);
$record = $this->removeExcludedFields($record);
if ($this->username) {
$dataArray['username'] = $this->username;
}
@@ -96,12 +103,13 @@ class SlackRecord
$dataArray['channel'] = $this->channel;
}
if ($this->formatter && !$this->useAttachment) {
/** @phpstan-ignore-next-line */
$message = $this->formatter->format($record);
} else {
$message = $record['message'];
}
if ($this->useAttachment) {
$attachment = array('fallback' => $message, 'text' => $message, 'color' => $this->getAttachmentColor($record['level']), 'fields' => array(), 'mrkdwn_in' => array('fields'), 'ts' => $record['datetime']->getTimestamp());
$attachment = array('fallback' => $message, 'text' => $message, 'color' => $this->getAttachmentColor($record['level']), 'fields' => array(), 'mrkdwn_in' => array('fields'), 'ts' => $record['datetime']->getTimestamp(), 'footer' => $this->username, 'footer_icon' => $this->userIcon);
if ($this->useShortAttachment) {
$attachment['title'] = $record['level_name'];
} else {
@@ -114,7 +122,7 @@ class SlackRecord
continue;
}
if ($this->useShortAttachment) {
$attachment['fields'][] = $this->generateAttachmentField($key, $record[$key]);
$attachment['fields'][] = $this->generateAttachmentField((string) $key, $record[$key]);
} else {
// Add all extra fields as individual fields in attachment
$attachment['fields'] = \array_merge($attachment['fields'], $this->generateAttachmentFields($record[$key]));
@@ -135,89 +143,135 @@ class SlackRecord
return $dataArray;
}
/**
* Returned a Slack message attachment color associated with
* Returns a Slack message attachment color associated with
* provided level.
*
* @param int $level
* @return string
*/
public function getAttachmentColor($level)
public function getAttachmentColor(int $level) : string
{
switch (\true) {
case $level >= \WPMailSMTP\Vendor\Monolog\Logger::ERROR:
return self::COLOR_DANGER;
return static::COLOR_DANGER;
case $level >= \WPMailSMTP\Vendor\Monolog\Logger::WARNING:
return self::COLOR_WARNING;
return static::COLOR_WARNING;
case $level >= \WPMailSMTP\Vendor\Monolog\Logger::INFO:
return self::COLOR_GOOD;
return static::COLOR_GOOD;
default:
return self::COLOR_DEFAULT;
return static::COLOR_DEFAULT;
}
}
/**
* Stringifies an array of key/value pairs to be used in attachment fields
*
* @param array $fields
*
* @return string
* @param mixed[] $fields
*/
public function stringify($fields)
public function stringify(array $fields) : string
{
/** @var Record $fields */
$normalized = $this->normalizerFormatter->format($fields);
$prettyPrintFlag = \defined('JSON_PRETTY_PRINT') ? \JSON_PRETTY_PRINT : 128;
$flags = 0;
if (\PHP_VERSION_ID >= 50400) {
$flags = \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE;
}
$hasSecondDimension = \count(\array_filter($normalized, 'is_array'));
$hasNonNumericKeys = !\count(\array_filter(\array_keys($normalized), 'is_numeric'));
return $hasSecondDimension || $hasNonNumericKeys ? \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($normalized, $prettyPrintFlag | $flags) : \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($normalized, $flags);
return $hasSecondDimension || $hasNonNumericKeys ? \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($normalized, \JSON_PRETTY_PRINT | \WPMailSMTP\Vendor\Monolog\Utils::DEFAULT_JSON_FLAGS) : \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($normalized, \WPMailSMTP\Vendor\Monolog\Utils::DEFAULT_JSON_FLAGS);
}
/**
* Sets the formatter
* Channel used by the bot when posting
*
* @param FormatterInterface $formatter
* @param ?string $channel
*
* @return static
*/
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function setChannel(?string $channel = null) : self
{
$this->channel = $channel;
return $this;
}
/**
* Username used by the bot when posting
*
* @param ?string $username
*
* @return static
*/
public function setUsername(?string $username = null) : self
{
$this->username = $username;
return $this;
}
public function useAttachment(bool $useAttachment = \true) : self
{
$this->useAttachment = $useAttachment;
return $this;
}
public function setUserIcon(?string $userIcon = null) : self
{
$this->userIcon = $userIcon;
if (\is_string($userIcon)) {
$this->userIcon = \trim($userIcon, ':');
}
return $this;
}
public function useShortAttachment(bool $useShortAttachment = \false) : self
{
$this->useShortAttachment = $useShortAttachment;
return $this;
}
public function includeContextAndExtra(bool $includeContextAndExtra = \false) : self
{
$this->includeContextAndExtra = $includeContextAndExtra;
if ($this->includeContextAndExtra) {
$this->normalizerFormatter = new \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter();
}
return $this;
}
/**
* @param string[] $excludeFields
*/
public function excludeFields(array $excludeFields = []) : self
{
$this->excludeFields = $excludeFields;
return $this;
}
public function setFormatter(?\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter = null) : self
{
$this->formatter = $formatter;
return $this;
}
/**
* Generates attachment field
*
* @param string $title
* @param string|array $value
* @param string|mixed[] $value
*
* @return array
* @return array{title: string, value: string, short: false}
*/
private function generateAttachmentField($title, $value)
private function generateAttachmentField(string $title, $value) : array
{
$value = \is_array($value) ? \sprintf('```%s```', $this->stringify($value)) : $value;
$value = \is_array($value) ? \sprintf('```%s```', \substr($this->stringify($value), 0, 1990)) : $value;
return array('title' => \ucfirst($title), 'value' => $value, 'short' => \false);
}
/**
* Generates a collection of attachment fields from array
*
* @param array $data
* @param mixed[] $data
*
* @return array
* @return array<array{title: string, value: string, short: false}>
*/
private function generateAttachmentFields(array $data)
private function generateAttachmentFields(array $data) : array
{
/** @var Record $data */
$normalized = $this->normalizerFormatter->format($data);
$fields = array();
foreach ($this->normalizerFormatter->format($data) as $key => $value) {
$fields[] = $this->generateAttachmentField($key, $value);
foreach ($normalized as $key => $value) {
$fields[] = $this->generateAttachmentField((string) $key, $value);
}
return $fields;
}
/**
* Get a copy of record with fields excluded according to $this->excludeFields
*
* @param array $record
* @phpstan-param FormattedRecord $record
*
* @return array
* @return mixed[]
*/
private function excludeFields(array $record)
private function removeExcludedFields(array $record) : array
{
foreach ($this->excludeFields as $field) {
$keys = \explode('.', $field);

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -19,6 +20,8 @@ use WPMailSMTP\Vendor\Monolog\Handler\Slack\SlackRecord;
*
* @author Greg Kedzierski <greg@gregkedzierski.com>
* @see https://api.slack.com/
*
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class SlackHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
{
@@ -38,37 +41,32 @@ class SlackHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
* @param string|null $username Name of a bot
* @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
* @param string|null $iconEmoji The emoji name to use (or null)
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
* @param bool $useShortAttachment Whether the context/extra messages added to Slack as attachments are in a short style
* @param bool $includeContextAndExtra Whether the attachment should include context and extra data
* @param array $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
* @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
* @throws MissingExtensionException If no OpenSSL PHP extension configured
*/
public function __construct($token, $channel, $username = null, $useAttachment = \true, $iconEmoji = null, $level = \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL, $bubble = \true, $useShortAttachment = \false, $includeContextAndExtra = \false, array $excludeFields = array())
public function __construct(string $token, string $channel, ?string $username = null, bool $useAttachment = \true, ?string $iconEmoji = null, $level = \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL, bool $bubble = \true, bool $useShortAttachment = \false, bool $includeContextAndExtra = \false, array $excludeFields = array(), bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
{
if (!\extension_loaded('openssl')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler');
}
parent::__construct('ssl://slack.com:443', $level, $bubble);
$this->slackRecord = new \WPMailSMTP\Vendor\Monolog\Handler\Slack\SlackRecord($channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields, $this->formatter);
parent::__construct('ssl://slack.com:443', $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize);
$this->slackRecord = new \WPMailSMTP\Vendor\Monolog\Handler\Slack\SlackRecord($channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields);
$this->token = $token;
}
public function getSlackRecord()
public function getSlackRecord() : \WPMailSMTP\Vendor\Monolog\Handler\Slack\SlackRecord
{
return $this->slackRecord;
}
public function getToken()
public function getToken() : string
{
return $this->token;
}
/**
* {@inheritdoc}
*
* @param array $record
* @return string
* {@inheritDoc}
*/
protected function generateDataStream($record)
protected function generateDataStream(array $record) : string
{
$content = $this->buildContent($record);
return $this->buildHeader($content) . $content;
@@ -76,21 +74,18 @@ class SlackHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
/**
* Builds the body of API call
*
* @param array $record
* @return string
* @phpstan-param FormattedRecord $record
*/
private function buildContent($record)
private function buildContent(array $record) : string
{
$dataArray = $this->prepareContentData($record);
return \http_build_query($dataArray);
}
/**
* Prepares content data
*
* @param array $record
* @return array
* @phpstan-param FormattedRecord $record
* @return string[]
*/
protected function prepareContentData($record)
protected function prepareContentData(array $record) : array
{
$dataArray = $this->slackRecord->getSlackData($record);
$dataArray['token'] = $this->token;
@@ -101,11 +96,8 @@ class SlackHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
}
/**
* Builds the header of the API Call
*
* @param string $content
* @return string
*/
private function buildHeader($content)
private function buildHeader(string $content) : string
{
$header = "POST /api/chat.postMessage HTTP/1.1\r\n";
$header .= "Host: slack.com\r\n";
@@ -115,11 +107,9 @@ class SlackHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
return $header;
}
/**
* {@inheritdoc}
*
* @param array $record
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
parent::write($record);
$this->finalizeWrite();
@@ -130,7 +120,7 @@ class SlackHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
* If we do not read some but close the socket too early, slack sometimes
* drops the request entirely.
*/
protected function finalizeWrite()
protected function finalizeWrite() : void
{
$res = $this->getResource();
if (\is_resource($res)) {
@@ -138,41 +128,60 @@ class SlackHandler extends \WPMailSMTP\Vendor\Monolog\Handler\SocketHandler
}
$this->closeSocket();
}
/**
* Returned a Slack message attachment color associated with
* provided level.
*
* @param int $level
* @return string
* @deprecated Use underlying SlackRecord instead
*/
protected function getAttachmentColor($level)
{
\trigger_error('SlackHandler::getAttachmentColor() is deprecated. Use underlying SlackRecord instead.', \E_USER_DEPRECATED);
return $this->slackRecord->getAttachmentColor($level);
}
/**
* Stringifies an array of key/value pairs to be used in attachment fields
*
* @param array $fields
* @return string
* @deprecated Use underlying SlackRecord instead
*/
protected function stringify($fields)
{
\trigger_error('SlackHandler::stringify() is deprecated. Use underlying SlackRecord instead.', \E_USER_DEPRECATED);
return $this->slackRecord->stringify($fields);
}
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
parent::setFormatter($formatter);
$this->slackRecord->setFormatter($formatter);
return $this;
}
public function getFormatter()
public function getFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
$formatter = parent::getFormatter();
$this->slackRecord->setFormatter($formatter);
return $formatter;
}
/**
* Channel used by the bot when posting
*/
public function setChannel(string $channel) : self
{
$this->slackRecord->setChannel($channel);
return $this;
}
/**
* Username used by the bot when posting
*/
public function setUsername(string $username) : self
{
$this->slackRecord->setUsername($username);
return $this;
}
public function useAttachment(bool $useAttachment) : self
{
$this->slackRecord->useAttachment($useAttachment);
return $this;
}
public function setIconEmoji(string $iconEmoji) : self
{
$this->slackRecord->setUserIcon($iconEmoji);
return $this;
}
public function useShortAttachment(bool $useShortAttachment) : self
{
$this->slackRecord->useShortAttachment($useShortAttachment);
return $this;
}
public function includeContextAndExtra(bool $includeContextAndExtra) : self
{
$this->slackRecord->includeContextAndExtra($includeContextAndExtra);
return $this;
}
/**
* @param string[] $excludeFields
*/
public function excludeFields(array $excludeFields) : self
{
$this->slackRecord->excludeFields($excludeFields);
return $this;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -33,37 +34,36 @@ class SlackWebhookHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractPro
*/
private $slackRecord;
/**
* @param string $webhookUrl Slack Webhook URL
* @param string|null $channel Slack channel (encoded ID or name)
* @param string|null $username Name of a bot
* @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
* @param string|null $iconEmoji The emoji name to use (or null)
* @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
* @param bool $includeContextAndExtra Whether the attachment should include context and extra data
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param array $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
* @param string $webhookUrl Slack Webhook URL
* @param string|null $channel Slack channel (encoded ID or name)
* @param string|null $username Name of a bot
* @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
* @param string|null $iconEmoji The emoji name to use (or null)
* @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
* @param bool $includeContextAndExtra Whether the attachment should include context and extra data
* @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
*/
public function __construct($webhookUrl, $channel = null, $username = null, $useAttachment = \true, $iconEmoji = null, $useShortAttachment = \false, $includeContextAndExtra = \false, $level = \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL, $bubble = \true, array $excludeFields = array())
public function __construct(string $webhookUrl, ?string $channel = null, ?string $username = null, bool $useAttachment = \true, ?string $iconEmoji = null, bool $useShortAttachment = \false, bool $includeContextAndExtra = \false, $level = \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL, bool $bubble = \true, array $excludeFields = array())
{
if (!\extension_loaded('curl')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The curl extension is needed to use the SlackWebhookHandler');
}
parent::__construct($level, $bubble);
$this->webhookUrl = $webhookUrl;
$this->slackRecord = new \WPMailSMTP\Vendor\Monolog\Handler\Slack\SlackRecord($channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields, $this->formatter);
$this->slackRecord = new \WPMailSMTP\Vendor\Monolog\Handler\Slack\SlackRecord($channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields);
}
public function getSlackRecord()
public function getSlackRecord() : \WPMailSMTP\Vendor\Monolog\Handler\Slack\SlackRecord
{
return $this->slackRecord;
}
public function getWebhookUrl()
public function getWebhookUrl() : string
{
return $this->webhookUrl;
}
/**
* {@inheritdoc}
*
* @param array $record
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$postData = $this->slackRecord->getSlackData($record);
$postString = \WPMailSMTP\Vendor\Monolog\Utils::jsonEncode($postData);
@@ -75,13 +75,13 @@ class SlackWebhookHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractPro
\curl_setopt_array($ch, $options);
\WPMailSMTP\Vendor\Monolog\Handler\Curl\Util::execute($ch);
}
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter)
public function setFormatter(\WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface $formatter) : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
parent::setFormatter($formatter);
$this->slackRecord->setFormatter($formatter);
return $this;
}
public function getFormatter()
public function getFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
$formatter = parent::getFormatter();
$this->slackRecord->setFormatter($formatter);

View File

@@ -1,70 +0,0 @@
<?php
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
/**
* Sends notifications through Slack's Slackbot
*
* @author Haralan Dobrev <hkdobrev@gmail.com>
* @see https://slack.com/apps/A0F81R8ET-slackbot
* @deprecated According to Slack the API used on this handler it is deprecated.
* Therefore this handler will be removed on 2.x
* Slack suggests to use webhooks instead. Please contact slack for more information.
*/
class SlackbotHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/**
* The slug of the Slack team
* @var string
*/
private $slackTeam;
/**
* Slackbot token
* @var string
*/
private $token;
/**
* Slack channel name
* @var string
*/
private $channel;
/**
* @param string $slackTeam Slack team slug
* @param string $token Slackbot token
* @param string $channel Slack channel (encoded ID or name)
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($slackTeam, $token, $channel, $level = \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL, $bubble = \true)
{
@\trigger_error('SlackbotHandler is deprecated and will be removed on 2.x', \E_USER_DEPRECATED);
parent::__construct($level, $bubble);
$this->slackTeam = $slackTeam;
$this->token = $token;
$this->channel = $channel;
}
/**
* {@inheritdoc}
*
* @param array $record
*/
protected function write(array $record)
{
$slackbotUrl = \sprintf('https://%s.slack.com/services/hooks/slackbot?token=%s&channel=%s', $this->slackTeam, $this->token, $this->channel);
$ch = \curl_init();
\curl_setopt($ch, \CURLOPT_URL, $slackbotUrl);
\curl_setopt($ch, \CURLOPT_POST, \true);
\curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
\curl_setopt($ch, \CURLOPT_POSTFIELDS, $record['message']);
\WPMailSMTP\Vendor\Monolog\Handler\Curl\Util::execute($ch);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -16,40 +17,69 @@ use WPMailSMTP\Vendor\Monolog\Logger;
*
* @author Pablo de Leon Belloc <pablolb@gmail.com>
* @see http://php.net/manual/en/function.fsockopen.php
*
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/** @var string */
private $connectionString;
/** @var float */
private $connectionTimeout;
/** @var resource|null */
private $resource;
private $timeout = 0;
private $writingTimeout = 10;
/** @var float */
private $timeout;
/** @var float */
private $writingTimeout;
/** @var ?int */
private $lastSentBytes = null;
private $chunkSize = null;
private $persistent = \false;
private $errno;
private $errstr;
private $lastWritingAt;
/** @var ?int */
private $chunkSize;
/** @var bool */
private $persistent;
/** @var ?int */
private $errno = null;
/** @var ?string */
private $errstr = null;
/** @var ?float */
private $lastWritingAt = null;
/**
* @param string $connectionString Socket connection string
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param string $connectionString Socket connection string
* @param bool $persistent Flag to enable/disable persistent connections
* @param float $timeout Socket timeout to wait until the request is being aborted
* @param float $writingTimeout Socket timeout to wait until the request should've been sent/written
* @param float|null $connectionTimeout Socket connect timeout to wait until the connection should've been
* established
* @param int|null $chunkSize Sets the chunk size. Only has effect during connection in the writing cycle
*
* @throws \InvalidArgumentException If an invalid timeout value (less than 0) is passed.
*/
public function __construct($connectionString, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct(string $connectionString, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, bool $persistent = \false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null)
{
parent::__construct($level, $bubble);
$this->connectionString = $connectionString;
$this->connectionTimeout = (float) \ini_get('default_socket_timeout');
if ($connectionTimeout !== null) {
$this->validateTimeout($connectionTimeout);
}
$this->connectionTimeout = $connectionTimeout ?? (float) \ini_get('default_socket_timeout');
$this->persistent = $persistent;
$this->validateTimeout($timeout);
$this->timeout = $timeout;
$this->validateTimeout($writingTimeout);
$this->writingTimeout = $writingTimeout;
$this->chunkSize = $chunkSize;
}
/**
* Connect (if necessary) and write to the socket
*
* @param array $record
* {@inheritDoc}
*
* @throws \UnexpectedValueException
* @throws \RuntimeException
*/
protected function write(array $record)
protected function write(array $record) : void
{
$this->connectIfNotConnected();
$data = $this->generateDataStream($record);
@@ -58,7 +88,7 @@ class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
/**
* We will not close a PersistentSocket instance so it can be reused in other requests.
*/
public function close()
public function close() : void
{
if (!$this->isPersistent()) {
$this->closeSocket();
@@ -67,7 +97,7 @@ class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
/**
* Close socket, if open
*/
public function closeSocket()
public function closeSocket() : void
{
if (\is_resource($this->resource)) {
\fclose($this->resource);
@@ -75,90 +105,79 @@ class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
}
}
/**
* Set socket connection to nbe persistent. It only has effect before the connection is initiated.
*
* @param bool $persistent
* Set socket connection to be persistent. It only has effect before the connection is initiated.
*/
public function setPersistent($persistent)
public function setPersistent(bool $persistent) : self
{
$this->persistent = (bool) $persistent;
$this->persistent = $persistent;
return $this;
}
/**
* Set connection timeout. Only has effect before we connect.
*
* @param float $seconds
*
* @see http://php.net/manual/en/function.fsockopen.php
*/
public function setConnectionTimeout($seconds)
public function setConnectionTimeout(float $seconds) : self
{
$this->validateTimeout($seconds);
$this->connectionTimeout = (float) $seconds;
$this->connectionTimeout = $seconds;
return $this;
}
/**
* Set write timeout. Only has effect before we connect.
*
* @param float $seconds
*
* @see http://php.net/manual/en/function.stream-set-timeout.php
*/
public function setTimeout($seconds)
public function setTimeout(float $seconds) : self
{
$this->validateTimeout($seconds);
$this->timeout = (float) $seconds;
$this->timeout = $seconds;
return $this;
}
/**
* Set writing timeout. Only has effect during connection in the writing cycle.
*
* @param float $seconds 0 for no timeout
*/
public function setWritingTimeout($seconds)
public function setWritingTimeout(float $seconds) : self
{
$this->validateTimeout($seconds);
$this->writingTimeout = (float) $seconds;
$this->writingTimeout = $seconds;
return $this;
}
/**
* Set chunk size. Only has effect during connection in the writing cycle.
*
* @param float $bytes
*/
public function setChunkSize($bytes)
public function setChunkSize(int $bytes) : self
{
$this->chunkSize = $bytes;
return $this;
}
/**
* Get current connection string
*
* @return string
*/
public function getConnectionString()
public function getConnectionString() : string
{
return $this->connectionString;
}
/**
* Get persistent setting
*
* @return bool
*/
public function isPersistent()
public function isPersistent() : bool
{
return $this->persistent;
}
/**
* Get current connection timeout setting
*
* @return float
*/
public function getConnectionTimeout()
public function getConnectionTimeout() : float
{
return $this->connectionTimeout;
}
/**
* Get current in-transfer timeout
*
* @return float
*/
public function getTimeout()
public function getTimeout() : float
{
return $this->timeout;
}
@@ -167,16 +186,14 @@ class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
*
* @return float
*/
public function getWritingTimeout()
public function getWritingTimeout() : float
{
return $this->writingTimeout;
}
/**
* Get current chunk size
*
* @return float
*/
public function getChunkSize()
public function getChunkSize() : ?int
{
return $this->chunkSize;
}
@@ -184,16 +201,16 @@ class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
* Check to see if the socket is currently available.
*
* UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details.
*
* @return bool
*/
public function isConnected()
public function isConnected() : bool
{
return \is_resource($this->resource) && !\feof($this->resource);
// on TCP - other party can close connection.
}
/**
* Wrapper to allow mocking
*
* @return resource|false
*/
protected function pfsockopen()
{
@@ -201,6 +218,8 @@ class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
}
/**
* Wrapper to allow mocking
*
* @return resource|false
*/
protected function fsockopen()
{
@@ -210,51 +229,76 @@ class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
* Wrapper to allow mocking
*
* @see http://php.net/manual/en/function.stream-set-timeout.php
*
* @return bool
*/
protected function streamSetTimeout()
{
$seconds = \floor($this->timeout);
$microseconds = \round(($this->timeout - $seconds) * 1000000.0);
return \stream_set_timeout($this->resource, $seconds, $microseconds);
if (!\is_resource($this->resource)) {
throw new \LogicException('streamSetTimeout called but $this->resource is not a resource');
}
return \stream_set_timeout($this->resource, (int) $seconds, (int) $microseconds);
}
/**
* Wrapper to allow mocking
*
* @see http://php.net/manual/en/function.stream-set-chunk-size.php
*
* @return int|bool
*/
protected function streamSetChunkSize()
{
if (!\is_resource($this->resource)) {
throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource');
}
if (null === $this->chunkSize) {
throw new \LogicException('streamSetChunkSize called but $this->chunkSize is not set');
}
return \stream_set_chunk_size($this->resource, $this->chunkSize);
}
/**
* Wrapper to allow mocking
*
* @return int|bool
*/
protected function fwrite($data)
protected function fwrite(string $data)
{
if (!\is_resource($this->resource)) {
throw new \LogicException('fwrite called but $this->resource is not a resource');
}
return @\fwrite($this->resource, $data);
}
/**
* Wrapper to allow mocking
*
* @return mixed[]|bool
*/
protected function streamGetMetadata()
{
if (!\is_resource($this->resource)) {
throw new \LogicException('streamGetMetadata called but $this->resource is not a resource');
}
return \stream_get_meta_data($this->resource);
}
private function validateTimeout($value)
private function validateTimeout(float $value) : void
{
$ok = \filter_var($value, \FILTER_VALIDATE_FLOAT);
if ($ok === \false || $value < 0) {
if ($value < 0) {
throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got {$value})");
}
}
private function connectIfNotConnected()
private function connectIfNotConnected() : void
{
if ($this->isConnected()) {
return;
}
$this->connect();
}
protected function generateDataStream($record)
/**
* @phpstan-param FormattedRecord $record
*/
protected function generateDataStream(array $record) : string
{
return (string) $record['formatted'];
}
@@ -265,37 +309,37 @@ class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
{
return $this->resource;
}
private function connect()
private function connect() : void
{
$this->createSocketResource();
$this->setSocketTimeout();
$this->setStreamChunkSize();
}
private function createSocketResource()
private function createSocketResource() : void
{
if ($this->isPersistent()) {
$resource = $this->pfsockopen();
} else {
$resource = $this->fsockopen();
}
if (!$resource) {
if (\is_bool($resource)) {
throw new \UnexpectedValueException("Failed connecting to {$this->connectionString} ({$this->errno}: {$this->errstr})");
}
$this->resource = $resource;
}
private function setSocketTimeout()
private function setSocketTimeout() : void
{
if (!$this->streamSetTimeout()) {
throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()");
}
}
private function setStreamChunkSize()
private function setStreamChunkSize() : void
{
if ($this->chunkSize && !$this->streamSetChunkSize()) {
throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()");
}
}
private function writeToSocket($data)
private function writeToSocket(string $data) : void
{
$length = \strlen($data);
$sent = 0;
@@ -311,7 +355,7 @@ class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
}
$sent += $chunk;
$socketInfo = $this->streamGetMetadata();
if ($socketInfo['timed_out']) {
if (\is_array($socketInfo) && $socketInfo['timed_out']) {
throw new \RuntimeException("Write timed-out");
}
if ($this->writingIsTimedOut($sent)) {
@@ -322,20 +366,20 @@ class SocketHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent {$sent} of {$length})");
}
}
private function writingIsTimedOut($sent)
private function writingIsTimedOut(int $sent) : bool
{
$writingTimeout = (int) \floor($this->writingTimeout);
if (0 === $writingTimeout) {
// convert to ms
if (0.0 == $this->writingTimeout) {
return \false;
}
if ($sent !== $this->lastSentBytes) {
$this->lastWritingAt = \time();
$this->lastWritingAt = \microtime(\true);
$this->lastSentBytes = $sent;
return \false;
} else {
\usleep(100);
}
if (\time() - $this->lastWritingAt >= $writingTimeout) {
if (\microtime(\true) - $this->lastWritingAt >= $this->writingTimeout) {
$this->closeSocket();
return \true;
}

View File

@@ -0,0 +1,52 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Aws\Sqs\SqsClient;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
/**
* Writes to any sqs queue.
*
* @author Martijn van Calker <git@amvc.nl>
*/
class SqsHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/** 256 KB in bytes - maximum message size in SQS */
protected const MAX_MESSAGE_SIZE = 262144;
/** 100 KB in bytes - head message size for new error log */
protected const HEAD_MESSAGE_SIZE = 102400;
/** @var SqsClient */
private $client;
/** @var string */
private $queueUrl;
public function __construct(\WPMailSMTP\Vendor\Aws\Sqs\SqsClient $sqsClient, string $queueUrl, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
parent::__construct($level, $bubble);
$this->client = $sqsClient;
$this->queueUrl = $queueUrl;
}
/**
* {@inheritDoc}
*/
protected function write(array $record) : void
{
if (!isset($record['formatted']) || 'string' !== \gettype($record['formatted'])) {
throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string' . \WPMailSMTP\Vendor\Monolog\Utils::getRecordMessageForException($record));
}
$messageBody = $record['formatted'];
if (\strlen($messageBody) >= static::MAX_MESSAGE_SIZE) {
$messageBody = \WPMailSMTP\Vendor\Monolog\Utils::substr($messageBody, 0, static::HEAD_MESSAGE_SIZE);
}
$this->client->sendMessage(['QueueUrl' => $this->queueUrl, 'MessageBody' => $messageBody]);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -18,34 +19,54 @@ use WPMailSMTP\Vendor\Monolog\Utils;
* Can be used to store into php://stderr, remote and local files, etc.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class StreamHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/** @private 512KB */
const CHUNK_SIZE = 524288;
/** @const int */
protected const MAX_CHUNK_SIZE = 2147483647;
/** @const int 10MB */
protected const DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024;
/** @var int */
protected $streamChunkSize;
/** @var resource|null */
protected $stream;
protected $url;
private $errorMessage;
/** @var ?string */
protected $url = null;
/** @var ?string */
private $errorMessage = null;
/** @var ?int */
protected $filePermission;
/** @var bool */
protected $useLocking;
private $dirCreated;
/** @var true|null */
private $dirCreated = null;
/**
* @param resource|string $stream
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param resource|string $stream If a missing path can't be created, an UnexpectedValueException will be thrown on first write
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
* @param bool $useLocking Try to lock log file before doing any writes
*
* @throws \Exception If a missing directory is not buildable
* @throws \InvalidArgumentException If stream is not a resource or string
*/
public function __construct($stream, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true, $filePermission = null, $useLocking = \false)
public function __construct($stream, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, ?int $filePermission = null, bool $useLocking = \false)
{
parent::__construct($level, $bubble);
if (($phpMemoryLimit = \WPMailSMTP\Vendor\Monolog\Utils::expandIniShorthandBytes(\ini_get('memory_limit'))) !== \false) {
if ($phpMemoryLimit > 0) {
// use max 10% of allowed memory for the chunk size, and at least 100KB
$this->streamChunkSize = \min(static::MAX_CHUNK_SIZE, \max((int) ($phpMemoryLimit / 10), 100 * 1024));
} else {
// memory is unlimited, set to the default 10MB
$this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
}
} else {
// no memory limit information, set to the default 10MB
$this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
}
if (\is_resource($stream)) {
$this->stream = $stream;
$this->streamSetChunkSize();
\stream_set_chunk_size($this->stream, $this->streamChunkSize);
} elseif (\is_string($stream)) {
$this->url = \WPMailSMTP\Vendor\Monolog\Utils::canonicalizePath($stream);
} else {
@@ -55,9 +76,9 @@ class StreamHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
$this->useLocking = $useLocking;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function close()
public function close() : void
{
if ($this->url && \is_resource($this->stream)) {
\fclose($this->stream);
@@ -79,68 +100,75 @@ class StreamHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
*
* @return string|null
*/
public function getUrl()
public function getUrl() : ?string
{
return $this->url;
}
/**
* {@inheritdoc}
* @return int
*/
protected function write(array $record)
public function getStreamChunkSize() : int
{
return $this->streamChunkSize;
}
/**
* {@inheritDoc}
*/
protected function write(array $record) : void
{
if (!\is_resource($this->stream)) {
if (null === $this->url || '' === $this->url) {
throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
$url = $this->url;
if (null === $url || '' === $url) {
throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().' . \WPMailSMTP\Vendor\Monolog\Utils::getRecordMessageForException($record));
}
$this->createDir();
$this->createDir($url);
$this->errorMessage = null;
\set_error_handler(array($this, 'customErrorHandler'));
$this->stream = \fopen($this->url, 'a');
if ($this->filePermission !== null) {
@\chmod($this->url, $this->filePermission);
\set_error_handler([$this, 'customErrorHandler']);
try {
$stream = \fopen($url, 'a');
if ($this->filePermission !== null) {
@\chmod($url, $this->filePermission);
}
} finally {
\restore_error_handler();
}
\restore_error_handler();
if (!\is_resource($this->stream)) {
if (!\is_resource($stream)) {
$this->stream = null;
throw new \UnexpectedValueException(\sprintf('The stream or file "%s" could not be opened in append mode: ' . $this->errorMessage, $this->url));
throw new \UnexpectedValueException(\sprintf('The stream or file "%s" could not be opened in append mode: ' . $this->errorMessage, $url) . \WPMailSMTP\Vendor\Monolog\Utils::getRecordMessageForException($record));
}
$this->streamSetChunkSize();
\stream_set_chunk_size($stream, $this->streamChunkSize);
$this->stream = $stream;
}
$stream = $this->stream;
if (!\is_resource($stream)) {
throw new \LogicException('No stream was opened yet' . \WPMailSMTP\Vendor\Monolog\Utils::getRecordMessageForException($record));
}
if ($this->useLocking) {
// ignoring errors here, there's not much we can do about them
\flock($this->stream, \LOCK_EX);
\flock($stream, \LOCK_EX);
}
$this->streamWrite($this->stream, $record);
$this->streamWrite($stream, $record);
if ($this->useLocking) {
\flock($this->stream, \LOCK_UN);
\flock($stream, \LOCK_UN);
}
}
/**
* Write to stream
* @param resource $stream
* @param array $record
* @param array $record
*
* @phpstan-param FormattedRecord $record
*/
protected function streamWrite($stream, array $record)
protected function streamWrite($stream, array $record) : void
{
\fwrite($stream, (string) $record['formatted']);
}
protected function streamSetChunkSize()
{
if (\version_compare(\PHP_VERSION, '5.4.0', '>=')) {
return \stream_set_chunk_size($this->stream, self::CHUNK_SIZE);
}
return \false;
}
private function customErrorHandler($code, $msg)
private function customErrorHandler(int $code, string $msg) : bool
{
$this->errorMessage = \preg_replace('{^(fopen|mkdir)\\(.*?\\): }', '', $msg);
return \true;
}
/**
* @param string $stream
*
* @return null|string
*/
private function getDirFromStream($stream)
private function getDirFromStream(string $stream) : ?string
{
$pos = \strpos($stream, '://');
if ($pos === \false) {
@@ -151,20 +179,20 @@ class StreamHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessin
}
return null;
}
private function createDir()
private function createDir(string $url) : void
{
// Do not try to create dir if it has already been tried.
if ($this->dirCreated) {
return;
}
$dir = $this->getDirFromStream($this->url);
$dir = $this->getDirFromStream($url);
if (null !== $dir && !\is_dir($dir)) {
$this->errorMessage = null;
\set_error_handler(array($this, 'customErrorHandler'));
\set_error_handler([$this, 'customErrorHandler']);
$status = \mkdir($dir, 0777, \true);
\restore_error_handler();
if (\false === $status && !\is_dir($dir)) {
throw new \UnexpectedValueException(\sprintf('There is no existing directory at "%s" and its not buildable: ' . $this->errorMessage, $dir));
if (\false === $status && !\is_dir($dir) && \strpos((string) $this->errorMessage, 'File exists') === \false) {
throw new \UnexpectedValueException(\sprintf('There is no existing directory at "%s" and it could not be created: ' . $this->errorMessage, $dir));
}
}
$this->dirCreated = \true;

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,87 +12,92 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
use WPMailSMTP\Vendor\Swift_Message;
use WPMailSMTP\Vendor\Swift;
/**
* SwiftMailerHandler uses Swift_Mailer to send the emails
*
* @author Gyula Sallai
*
* @phpstan-import-type Record from \Monolog\Logger
* @deprecated Since Monolog 2.6. Use SymfonyMailerHandler instead.
*/
class SwiftMailerHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
{
/** @var \Swift_Mailer */
protected $mailer;
/** @var Swift_Message|callable(string, Record[]): Swift_Message */
private $messageTemplate;
/**
* @param \Swift_Mailer $mailer The mailer to use
* @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @psalm-param Swift_Message|callable(string, Record[]): Swift_Message $message
*
* @param \Swift_Mailer $mailer The mailer to use
* @param callable|Swift_Message $message An example message for real messages, only the body will be replaced
*/
public function __construct(\WPMailSMTP\Vendor\Swift_Mailer $mailer, $message, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, $bubble = \true)
public function __construct(\WPMailSMTP\Vendor\Swift_Mailer $mailer, $message, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, bool $bubble = \true)
{
parent::__construct($level, $bubble);
@\trigger_error('The SwiftMailerHandler is deprecated since Monolog 2.6. Use SymfonyMailerHandler instead.', \E_USER_DEPRECATED);
$this->mailer = $mailer;
$this->messageTemplate = $message;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function send($content, array $records)
protected function send(string $content, array $records) : void
{
$this->mailer->send($this->buildMessage($content, $records));
}
/**
* Gets the formatter for the Swift_Message subject.
*
* @param string $format The format of the subject
* @return FormatterInterface
* @param string|null $format The format of the subject
*/
protected function getSubjectFormatter($format)
protected function getSubjectFormatter(?string $format) : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter($format);
}
/**
* Creates instance of Swift_Message to be sent
*
* @param string $content formatted email body to be sent
* @param array $records Log records that formed the content
* @return \Swift_Message
* @param string $content formatted email body to be sent
* @param array $records Log records that formed the content
* @return Swift_Message
*
* @phpstan-param Record[] $records
*/
protected function buildMessage($content, array $records)
protected function buildMessage(string $content, array $records) : \WPMailSMTP\Vendor\Swift_Message
{
$message = null;
if ($this->messageTemplate instanceof \WPMailSMTP\Vendor\Swift_Message) {
$message = clone $this->messageTemplate;
$message->generateId();
} elseif (\is_callable($this->messageTemplate)) {
$message = \call_user_func($this->messageTemplate, $content, $records);
$message = ($this->messageTemplate)($content, $records);
}
if (!$message instanceof \WPMailSMTP\Vendor\Swift_Message) {
throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it');
$record = \reset($records);
throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it' . ($record ? \WPMailSMTP\Vendor\Monolog\Utils::getRecordMessageForException($record) : ''));
}
if ($records) {
$subjectFormatter = $this->getSubjectFormatter($message->getSubject());
$message->setSubject($subjectFormatter->format($this->getHighestRecord($records)));
}
$message->setBody($content);
$mime = 'text/plain';
if ($this->isHtmlBody($content)) {
$mime = 'text/html';
}
$message->setBody($content, $mime);
/** @phpstan-ignore-next-line */
if (\version_compare(\WPMailSMTP\Vendor\Swift::VERSION, '6.0.0', '>=')) {
$message->setDate(new \DateTimeImmutable());
} else {
/** @phpstan-ignore-next-line */
$message->setDate(\time());
}
return $message;
}
/**
* BC getter, to be removed in 2.0
*/
public function __get($name)
{
if ($name === 'message') {
\trigger_error('SwiftMailerHandler->message is deprecated, use ->buildMessage() instead to retrieve the message', \E_USER_DEPRECATED);
return $this->buildMessage(null, array());
}
throw new \InvalidArgumentException('Invalid property ' . $name);
}
}

View File

@@ -0,0 +1,101 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter;
use WPMailSMTP\Vendor\Symfony\Component\Mailer\MailerInterface;
use WPMailSMTP\Vendor\Symfony\Component\Mailer\Transport\TransportInterface;
use WPMailSMTP\Vendor\Symfony\Component\Mime\Email;
/**
* SymfonyMailerHandler uses Symfony's Mailer component to send the emails
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
class SymfonyMailerHandler extends \WPMailSMTP\Vendor\Monolog\Handler\MailHandler
{
/** @var MailerInterface|TransportInterface */
protected $mailer;
/** @var Email|callable(string, Record[]): Email */
private $emailTemplate;
/**
* @psalm-param Email|callable(string, Record[]): Email $email
*
* @param MailerInterface|TransportInterface $mailer The mailer to use
* @param callable|Email $email An email template, the subject/body will be replaced
*/
public function __construct($mailer, $email, $level = \WPMailSMTP\Vendor\Monolog\Logger::ERROR, bool $bubble = \true)
{
parent::__construct($level, $bubble);
$this->mailer = $mailer;
$this->emailTemplate = $email;
}
/**
* {@inheritDoc}
*/
protected function send(string $content, array $records) : void
{
$this->mailer->send($this->buildMessage($content, $records));
}
/**
* Gets the formatter for the Swift_Message subject.
*
* @param string|null $format The format of the subject
*/
protected function getSubjectFormatter(?string $format) : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\LineFormatter($format);
}
/**
* Creates instance of Email to be sent
*
* @param string $content formatted email body to be sent
* @param array $records Log records that formed the content
*
* @phpstan-param Record[] $records
*/
protected function buildMessage(string $content, array $records) : \WPMailSMTP\Vendor\Symfony\Component\Mime\Email
{
$message = null;
if ($this->emailTemplate instanceof \WPMailSMTP\Vendor\Symfony\Component\Mime\Email) {
$message = clone $this->emailTemplate;
} elseif (\is_callable($this->emailTemplate)) {
$message = ($this->emailTemplate)($content, $records);
}
if (!$message instanceof \WPMailSMTP\Vendor\Symfony\Component\Mime\Email) {
$record = \reset($records);
throw new \InvalidArgumentException('Could not resolve message as instance of Email or a callable returning it' . ($record ? \WPMailSMTP\Vendor\Monolog\Utils::getRecordMessageForException($record) : ''));
}
if ($records) {
$subjectFormatter = $this->getSubjectFormatter($message->getSubject());
$message->subject($subjectFormatter->format($this->getHighestRecord($records)));
}
if ($this->isHtmlBody($content)) {
if (null !== ($charset = $message->getHtmlCharset())) {
$message->html($content, $charset);
} else {
$message->html($content);
}
} else {
if (null !== ($charset = $message->getTextCharset())) {
$message->text($content, $charset);
} else {
$message->text($content);
}
}
return $message->date(new \DateTimeImmutable());
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -11,6 +12,7 @@
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
/**
* Logs to syslog service.
*
@@ -26,35 +28,35 @@ use WPMailSMTP\Vendor\Monolog\Logger;
*/
class SyslogHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractSyslogHandler
{
/** @var string */
protected $ident;
/** @var int */
protected $logopts;
/**
* @param string $ident
* @param mixed $facility
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
* @param string $ident
* @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
* @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
*/
public function __construct($ident, $facility = \LOG_USER, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true, $logopts = \LOG_PID)
public function __construct(string $ident, $facility = \LOG_USER, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, int $logopts = \LOG_PID)
{
parent::__construct($facility, $level, $bubble);
$this->ident = $ident;
$this->logopts = $logopts;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function close()
public function close() : void
{
\closelog();
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
if (!\openlog($this->ident, $this->logopts, $this->facility)) {
throw new \LogicException('Can\'t open syslog for ident "' . $this->ident . '" and facility "' . $this->facility . '"');
throw new \LogicException('Can\'t open syslog for ident "' . $this->ident . '" and facility "' . $this->facility . '"' . \WPMailSMTP\Vendor\Monolog\Utils::getRecordMessageForException($record));
}
\syslog($this->logLevels[$record['level']], (string) $record['formatted']);
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,39 +11,66 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler\SyslogUdp;
use WPMailSMTP\Vendor\Monolog\Utils;
use Socket;
class UdpSocket
{
const DATAGRAM_MAX_LENGTH = 65023;
protected const DATAGRAM_MAX_LENGTH = 65023;
/** @var string */
protected $ip;
/** @var int */
protected $port;
protected $socket;
public function __construct($ip, $port = 514)
/** @var resource|Socket|null */
protected $socket = null;
public function __construct(string $ip, int $port = 514)
{
$this->ip = $ip;
$this->port = $port;
$this->socket = \socket_create(\AF_INET, \SOCK_DGRAM, \SOL_UDP);
}
/**
* @param string $line
* @param string $header
* @return void
*/
public function write($line, $header = "")
{
$this->send($this->assembleMessage($line, $header));
}
public function close()
public function close() : void
{
if (\is_resource($this->socket)) {
if (\is_resource($this->socket) || $this->socket instanceof \Socket) {
\socket_close($this->socket);
$this->socket = null;
}
}
protected function send($chunk)
/**
* @return resource|Socket
*/
protected function getSocket()
{
if (!\is_resource($this->socket)) {
throw new \LogicException('The UdpSocket to ' . $this->ip . ':' . $this->port . ' has been closed and can not be written to anymore');
if (null !== $this->socket) {
return $this->socket;
}
\socket_sendto($this->socket, $chunk, \strlen($chunk), $flags = 0, $this->ip, $this->port);
$domain = \AF_INET;
$protocol = \SOL_UDP;
// Check if we are using unix sockets.
if ($this->port === 0) {
$domain = \AF_UNIX;
$protocol = \IPPROTO_IP;
}
$this->socket = \socket_create($domain, \SOCK_DGRAM, $protocol) ?: null;
if (null === $this->socket) {
throw new \RuntimeException('The UdpSocket to ' . $this->ip . ':' . $this->port . ' could not be opened via socket_create');
}
return $this->socket;
}
protected function assembleMessage($line, $header)
protected function send(string $chunk) : void
{
$chunkSize = self::DATAGRAM_MAX_LENGTH - \strlen($header);
return $header . \substr($line, 0, $chunkSize);
\socket_sendto($this->getSocket(), $chunk, \strlen($chunk), $flags = 0, $this->ip, $this->port);
}
protected function assembleMessage(string $line, string $header) : string
{
$chunkSize = static::DATAGRAM_MAX_LENGTH - \strlen($header);
return $header . \WPMailSMTP\Vendor\Monolog\Utils::substr($line, 0, $chunkSize);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,8 +11,10 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use DateTimeInterface;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Handler\SyslogUdp\UdpSocket;
use WPMailSMTP\Vendor\Monolog\Utils;
/**
* A Handler for logging to a remote syslogd server.
*
@@ -22,49 +25,68 @@ class SyslogUdpHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractSyslog
{
const RFC3164 = 0;
const RFC5424 = 1;
private $dateFormats = array(self::RFC3164 => 'M d H:i:s', self::RFC5424 => \DateTime::RFC3339);
const RFC5424e = 2;
/** @var array<self::RFC*, string> */
private $dateFormats = array(self::RFC3164 => 'M d H:i:s', self::RFC5424 => \DateTime::RFC3339, self::RFC5424e => \DateTime::RFC3339_EXTENDED);
/** @var UdpSocket */
protected $socket;
/** @var string */
protected $ident;
/** @var self::RFC* */
protected $rfc;
/**
* @param string $host
* @param int $port
* @param mixed $facility
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param string $ident Program name or tag for each log message.
* @param int $rfc RFC to format the message for.
* @param string $host Either IP/hostname or a path to a unix socket (port must be 0 then)
* @param int $port Port number, or 0 if $host is a unix socket
* @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param string $ident Program name or tag for each log message.
* @param int $rfc RFC to format the message for.
* @throws MissingExtensionException
*
* @phpstan-param self::RFC* $rfc
*/
public function __construct($host, $port = 514, $facility = \LOG_USER, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true, $ident = 'php', $rfc = self::RFC5424)
public function __construct(string $host, int $port = 514, $facility = \LOG_USER, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, string $ident = 'php', int $rfc = self::RFC5424)
{
if (!\extension_loaded('sockets')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The sockets extension is required to use the SyslogUdpHandler');
}
parent::__construct($facility, $level, $bubble);
$this->ident = $ident;
$this->rfc = $rfc;
$this->socket = new \WPMailSMTP\Vendor\Monolog\Handler\SyslogUdp\UdpSocket($host, $port ?: 514);
$this->socket = new \WPMailSMTP\Vendor\Monolog\Handler\SyslogUdp\UdpSocket($host, $port);
}
protected function write(array $record)
protected function write(array $record) : void
{
$lines = $this->splitMessageIntoLines($record['formatted']);
$header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']]);
$header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']], $record['datetime']);
foreach ($lines as $line) {
$this->socket->write($line, $header);
}
}
public function close()
public function close() : void
{
$this->socket->close();
}
private function splitMessageIntoLines($message)
/**
* @param string|string[] $message
* @return string[]
*/
private function splitMessageIntoLines($message) : array
{
if (\is_array($message)) {
$message = \implode("\n", $message);
}
return \preg_split('/$\\R?^/m', $message, -1, \PREG_SPLIT_NO_EMPTY);
$lines = \preg_split('/$\\R?^/m', (string) $message, -1, \PREG_SPLIT_NO_EMPTY);
if (\false === $lines) {
$pcreErrorCode = \preg_last_error();
throw new \RuntimeException('Could not preg_split: ' . $pcreErrorCode . ' / ' . \WPMailSMTP\Vendor\Monolog\Utils::pcreLastErrorMessage($pcreErrorCode));
}
return $lines;
}
/**
* Make common syslog header (see rfc5424 or rfc3164)
*/
protected function makeCommonSyslogHeader($severity)
protected function makeCommonSyslogHeader(int $severity, \DateTimeInterface $datetime) : string
{
$priority = $severity + $this->facility;
if (!($pid = \getmypid())) {
@@ -73,22 +95,22 @@ class SyslogUdpHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractSyslog
if (!($hostname = \gethostname())) {
$hostname = '-';
}
$date = $this->getDateTime();
if ($this->rfc === self::RFC3164) {
// see https://github.com/phpstan/phpstan/issues/5348
// @phpstan-ignore-next-line
$dateNew = $datetime->setTimezone(new \DateTimeZone('UTC'));
$date = $dateNew->format($this->dateFormats[$this->rfc]);
return "<{$priority}>" . $date . " " . $hostname . " " . $this->ident . "[" . $pid . "]: ";
} else {
return "<{$priority}>1 " . $date . " " . $hostname . " " . $this->ident . " " . $pid . " - - ";
}
}
protected function getDateTime()
{
return \date($this->dateFormats[$this->rfc]);
$date = $datetime->format($this->dateFormats[$this->rfc]);
return "<{$priority}>1 " . $date . " " . $hostname . " " . $this->ident . " " . $pid . " - - ";
}
/**
* Inject your own socket, mainly used for testing
*/
public function setSocket($socket)
public function setSocket(\WPMailSMTP\Vendor\Monolog\Handler\SyslogUdp\UdpSocket $socket) : self
{
$this->socket = $socket;
return $this;
}
}

View File

@@ -0,0 +1,216 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use RuntimeException;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Monolog\Utils;
/**
* Handler send logs to Telegram using Telegram Bot API.
*
* How to use:
* 1) Create telegram bot with https://telegram.me/BotFather
* 2) Create a telegram channel where logs will be recorded.
* 3) Add created bot from step 1 to the created channel from step 2.
*
* Use telegram bot API key from step 1 and channel name with '@' prefix from step 2 to create instance of TelegramBotHandler
*
* @link https://core.telegram.org/bots/api
*
* @author Mazur Alexandr <alexandrmazur96@gmail.com>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
class TelegramBotHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
private const BOT_API = 'https://api.telegram.org/bot';
/**
* The available values of parseMode according to the Telegram api documentation
*/
private const AVAILABLE_PARSE_MODES = ['HTML', 'MarkdownV2', 'Markdown'];
/**
* The maximum number of characters allowed in a message according to the Telegram api documentation
*/
private const MAX_MESSAGE_LENGTH = 4096;
/**
* Telegram bot access token provided by BotFather.
* Create telegram bot with https://telegram.me/BotFather and use access token from it.
* @var string
*/
private $apiKey;
/**
* Telegram channel name.
* Since to start with '@' symbol as prefix.
* @var string
*/
private $channel;
/**
* The kind of formatting that is used for the message.
* See available options at https://core.telegram.org/bots/api#formatting-options
* or in AVAILABLE_PARSE_MODES
* @var ?string
*/
private $parseMode;
/**
* Disables link previews for links in the message.
* @var ?bool
*/
private $disableWebPagePreview;
/**
* Sends the message silently. Users will receive a notification with no sound.
* @var ?bool
*/
private $disableNotification;
/**
* True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages.
* False - truncates a message that is too long.
* @var bool
*/
private $splitLongMessages;
/**
* Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests).
* @var bool
*/
private $delayBetweenMessages;
/**
* @param string $apiKey Telegram bot access token provided by BotFather
* @param string $channel Telegram channel name
* @param bool $splitLongMessages Split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages
* @param bool $delayBetweenMessages Adds delay between sending a split message according to Telegram API
* @throws MissingExtensionException
*/
public function __construct(string $apiKey, string $channel, $level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true, ?string $parseMode = null, ?bool $disableWebPagePreview = null, ?bool $disableNotification = null, bool $splitLongMessages = \false, bool $delayBetweenMessages = \false)
{
if (!\extension_loaded('curl')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('The curl extension is needed to use the TelegramBotHandler');
}
parent::__construct($level, $bubble);
$this->apiKey = $apiKey;
$this->channel = $channel;
$this->setParseMode($parseMode);
$this->disableWebPagePreview($disableWebPagePreview);
$this->disableNotification($disableNotification);
$this->splitLongMessages($splitLongMessages);
$this->delayBetweenMessages($delayBetweenMessages);
}
public function setParseMode(?string $parseMode = null) : self
{
if ($parseMode !== null && !\in_array($parseMode, self::AVAILABLE_PARSE_MODES)) {
throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . \implode(', ', self::AVAILABLE_PARSE_MODES) . '.');
}
$this->parseMode = $parseMode;
return $this;
}
public function disableWebPagePreview(?bool $disableWebPagePreview = null) : self
{
$this->disableWebPagePreview = $disableWebPagePreview;
return $this;
}
public function disableNotification(?bool $disableNotification = null) : self
{
$this->disableNotification = $disableNotification;
return $this;
}
/**
* True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages.
* False - truncates a message that is too long.
* @param bool $splitLongMessages
* @return $this
*/
public function splitLongMessages(bool $splitLongMessages = \false) : self
{
$this->splitLongMessages = $splitLongMessages;
return $this;
}
/**
* Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests).
* @param bool $delayBetweenMessages
* @return $this
*/
public function delayBetweenMessages(bool $delayBetweenMessages = \false) : self
{
$this->delayBetweenMessages = $delayBetweenMessages;
return $this;
}
/**
* {@inheritDoc}
*/
public function handleBatch(array $records) : void
{
/** @var Record[] $messages */
$messages = [];
foreach ($records as $record) {
if (!$this->isHandling($record)) {
continue;
}
if ($this->processors) {
/** @var Record $record */
$record = $this->processRecord($record);
}
$messages[] = $record;
}
if (!empty($messages)) {
$this->send((string) $this->getFormatter()->formatBatch($messages));
}
}
/**
* @inheritDoc
*/
protected function write(array $record) : void
{
$this->send($record['formatted']);
}
/**
* Send request to @link https://api.telegram.org/bot on SendMessage action.
* @param string $message
*/
protected function send(string $message) : void
{
$messages = $this->handleMessageLength($message);
foreach ($messages as $key => $msg) {
if ($this->delayBetweenMessages && $key > 0) {
\sleep(1);
}
$this->sendCurl($msg);
}
}
protected function sendCurl(string $message) : void
{
$ch = \curl_init();
$url = self::BOT_API . $this->apiKey . '/SendMessage';
\curl_setopt($ch, \CURLOPT_URL, $url);
\curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
\curl_setopt($ch, \CURLOPT_SSL_VERIFYPEER, \true);
\curl_setopt($ch, \CURLOPT_POSTFIELDS, \http_build_query(['text' => $message, 'chat_id' => $this->channel, 'parse_mode' => $this->parseMode, 'disable_web_page_preview' => $this->disableWebPagePreview, 'disable_notification' => $this->disableNotification]));
$result = \WPMailSMTP\Vendor\Monolog\Handler\Curl\Util::execute($ch);
if (!\is_string($result)) {
throw new \RuntimeException('Telegram API error. Description: No response');
}
$result = \json_decode($result, \true);
if ($result['ok'] === \false) {
throw new \RuntimeException('Telegram API error. Description: ' . $result['description']);
}
}
/**
* Handle a message that is too long: truncates or splits into several
* @param string $message
* @return string[]
*/
private function handleMessageLength(string $message) : array
{
$truncatedMarker = ' (...truncated)';
if (!$this->splitLongMessages && \strlen($message) > self::MAX_MESSAGE_LENGTH) {
return [\WPMailSMTP\Vendor\Monolog\Utils::substr($message, 0, self::MAX_MESSAGE_LENGTH - \strlen($truncatedMarker)) . $truncatedMarker];
}
return \str_split($message, self::MAX_MESSAGE_LENGTH);
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,6 +11,8 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Logger;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
/**
* Used for testing purposes.
*
@@ -61,40 +64,69 @@ namespace WPMailSMTP\Vendor\Monolog\Handler;
* @method bool hasNoticeThatPasses($message)
* @method bool hasInfoThatPasses($message)
* @method bool hasDebugThatPasses($message)
*
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger
* @phpstan-import-type LevelName from \Monolog\Logger
*/
class TestHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
protected $records = array();
protected $recordsByLevel = array();
/** @var Record[] */
protected $records = [];
/** @var array<Level, Record[]> */
protected $recordsByLevel = [];
/** @var bool */
private $skipReset = \false;
/**
* @return array
*
* @phpstan-return Record[]
*/
public function getRecords()
{
return $this->records;
}
/**
* @return void
*/
public function clear()
{
$this->records = array();
$this->recordsByLevel = array();
$this->records = [];
$this->recordsByLevel = [];
}
/**
* @return void
*/
public function reset()
{
if (!$this->skipReset) {
$this->clear();
}
}
public function setSkipReset($skipReset)
/**
* @return void
*/
public function setSkipReset(bool $skipReset)
{
$this->skipReset = $skipReset;
}
public function hasRecords($level)
/**
* @param string|int $level Logging level value or name
*
* @phpstan-param Level|LevelName|LogLevel::* $level
*/
public function hasRecords($level) : bool
{
return isset($this->recordsByLevel[$level]);
return isset($this->recordsByLevel[\WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($level)]);
}
/**
* @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records
* @param int $level Logger::LEVEL constant value
* @param string|int $level Logging level value or name
*
* @phpstan-param array{message: string, context?: mixed[]}|string $record
* @phpstan-param Level|LevelName|LogLevel::* $level
*/
public function hasRecord($record, $level)
public function hasRecord($record, $level) : bool
{
if (\is_string($record)) {
$record = array('message' => $record);
@@ -109,49 +141,70 @@ class TestHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingH
return \true;
}, $level);
}
public function hasRecordThatContains($message, $level)
/**
* @param string|int $level Logging level value or name
*
* @phpstan-param Level|LevelName|LogLevel::* $level
*/
public function hasRecordThatContains(string $message, $level) : bool
{
return $this->hasRecordThatPasses(function ($rec) use($message) {
return \strpos($rec['message'], $message) !== \false;
}, $level);
}
public function hasRecordThatMatches($regex, $level)
/**
* @param string|int $level Logging level value or name
*
* @phpstan-param Level|LevelName|LogLevel::* $level
*/
public function hasRecordThatMatches(string $regex, $level) : bool
{
return $this->hasRecordThatPasses(function ($rec) use($regex) {
return $this->hasRecordThatPasses(function (array $rec) use($regex) : bool {
return \preg_match($regex, $rec['message']) > 0;
}, $level);
}
public function hasRecordThatPasses($predicate, $level)
/**
* @param string|int $level Logging level value or name
* @return bool
*
* @psalm-param callable(Record, int): mixed $predicate
* @phpstan-param Level|LevelName|LogLevel::* $level
*/
public function hasRecordThatPasses(callable $predicate, $level)
{
if (!\is_callable($predicate)) {
throw new \InvalidArgumentException("Expected a callable for hasRecordThatSucceeds");
}
$level = \WPMailSMTP\Vendor\Monolog\Logger::toMonologLevel($level);
if (!isset($this->recordsByLevel[$level])) {
return \false;
}
foreach ($this->recordsByLevel[$level] as $i => $rec) {
if (\call_user_func($predicate, $rec, $i)) {
if ($predicate($rec, $i)) {
return \true;
}
}
return \false;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$this->recordsByLevel[$record['level']][] = $record;
$this->records[] = $record;
}
/**
* @param string $method
* @param mixed[] $args
* @return bool
*/
public function __call($method, $args)
{
if (\preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
$genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
$level = \constant('WPMailSMTP\\Vendor\\Monolog\\Logger::' . \strtoupper($matches[2]));
if (\method_exists($this, $genericMethod)) {
$callback = [$this, $genericMethod];
if (\is_callable($callback)) {
$args[] = $level;
return \call_user_func_array(array($this, $genericMethod), $args);
return \call_user_func_array($callback, $args);
}
}
throw new \BadMethodCallException('Call to undefined method ' . \get_class($this) . '::' . $method . '()');

View File

@@ -0,0 +1,24 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
trait WebRequestRecognizerTrait
{
/**
* Checks if PHP's serving a web request
* @return bool
*/
protected function isWebRequest() : bool
{
return 'cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -15,24 +16,23 @@ namespace WPMailSMTP\Vendor\Monolog\Handler;
* and continuing through to give every handler a chance to succeed.
*
* @author Craig D'Amelio <craig@damelio.ca>
*
* @phpstan-import-type Record from \Monolog\Logger
*/
class WhatFailureGroupHandler extends \WPMailSMTP\Vendor\Monolog\Handler\GroupHandler
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handle(array $record)
public function handle(array $record) : bool
{
if ($this->processors) {
foreach ($this->processors as $processor) {
$record = \call_user_func($processor, $record);
}
/** @var Record $record */
$record = $this->processRecord($record);
}
foreach ($this->handlers as $handler) {
try {
$handler->handle($record);
} catch (\Exception $e) {
// What failure?
} catch (\Throwable $e) {
// What failure?
}
@@ -40,25 +40,34 @@ class WhatFailureGroupHandler extends \WPMailSMTP\Vendor\Monolog\Handler\GroupHa
return \false === $this->bubble;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function handleBatch(array $records)
public function handleBatch(array $records) : void
{
if ($this->processors) {
$processed = array();
foreach ($records as $record) {
foreach ($this->processors as $processor) {
$record = \call_user_func($processor, $record);
}
$processed[] = $record;
$processed[] = $this->processRecord($record);
}
/** @var Record[] $records */
$records = $processed;
}
foreach ($this->handlers as $handler) {
try {
$handler->handleBatch($records);
} catch (\Exception $e) {
} catch (\Throwable $e) {
// What failure?
}
}
}
/**
* {@inheritDoc}
*/
public function close() : void
{
foreach ($this->handlers as $handler) {
try {
$handler->close();
} catch (\Throwable $e) {
// What failure?
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,6 +11,7 @@
*/
namespace WPMailSMTP\Vendor\Monolog\Handler;
use WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface;
use WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter;
use WPMailSMTP\Vendor\Monolog\Logger;
/**
@@ -17,62 +19,60 @@ use WPMailSMTP\Vendor\Monolog\Logger;
*
* @author Christian Bergau <cbergau86@gmail.com>
* @author Jason Davis <happydude@jasondavis.net>
*
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class ZendMonitorHandler extends \WPMailSMTP\Vendor\Monolog\Handler\AbstractProcessingHandler
{
/**
* Monolog level / ZendMonitor Custom Event priority map
*
* @var array
* @var array<int, int>
*/
protected $levelMap = array();
protected $levelMap = [];
/**
* Construct
*
* @param int $level
* @param bool $bubble
* @throws MissingExtensionException
*/
public function __construct($level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, $bubble = \true)
public function __construct($level = \WPMailSMTP\Vendor\Monolog\Logger::DEBUG, bool $bubble = \true)
{
if (!\function_exists('WPMailSMTP\\Vendor\\zend_monitor_custom_event')) {
throw new \WPMailSMTP\Vendor\Monolog\Handler\MissingExtensionException('You must have Zend Server installed with Zend Monitor enabled in order to use this handler');
}
//zend monitor constants are not defined if zend monitor is not enabled.
$this->levelMap = array(\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_INFO, \WPMailSMTP\Vendor\Monolog\Logger::INFO => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_INFO, \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_INFO, \WPMailSMTP\Vendor\Monolog\Logger::WARNING => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_WARNING, \WPMailSMTP\Vendor\Monolog\Logger::ERROR => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_ERROR, \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_ERROR, \WPMailSMTP\Vendor\Monolog\Logger::ALERT => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_ERROR, \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_ERROR);
$this->levelMap = [\WPMailSMTP\Vendor\Monolog\Logger::DEBUG => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_INFO, \WPMailSMTP\Vendor\Monolog\Logger::INFO => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_INFO, \WPMailSMTP\Vendor\Monolog\Logger::NOTICE => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_INFO, \WPMailSMTP\Vendor\Monolog\Logger::WARNING => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_WARNING, \WPMailSMTP\Vendor\Monolog\Logger::ERROR => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_ERROR, \WPMailSMTP\Vendor\Monolog\Logger::CRITICAL => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_ERROR, \WPMailSMTP\Vendor\Monolog\Logger::ALERT => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_ERROR, \WPMailSMTP\Vendor\Monolog\Logger::EMERGENCY => \WPMailSMTP\Vendor\ZEND_MONITOR_EVENT_SEVERITY_ERROR];
parent::__construct($level, $bubble);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function write(array $record)
protected function write(array $record) : void
{
$this->writeZendMonitorCustomEvent(\WPMailSMTP\Vendor\Monolog\Logger::getLevelName($record['level']), $record['message'], $record['formatted'], $this->levelMap[$record['level']]);
}
/**
* Write to Zend Monitor Events
* @param string $type Text displayed in "Class Name (custom)" field
* @param string $message Text displayed in "Error String"
* @param mixed $formatted Displayed in Custom Variables tab
* @param int $severity Set the event severity level (-1,0,1)
* @param string $type Text displayed in "Class Name (custom)" field
* @param string $message Text displayed in "Error String"
* @param array $formatted Displayed in Custom Variables tab
* @param int $severity Set the event severity level (-1,0,1)
*
* @phpstan-param FormattedRecord $formatted
*/
protected function writeZendMonitorCustomEvent($type, $message, $formatted, $severity)
protected function writeZendMonitorCustomEvent(string $type, string $message, array $formatted, int $severity) : void
{
zend_monitor_custom_event($type, $message, $formatted, $severity);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getDefaultFormatter()
public function getDefaultFormatter() : \WPMailSMTP\Vendor\Monolog\Formatter\FormatterInterface
{
return new \WPMailSMTP\Vendor\Monolog\Formatter\NormalizerFormatter();
}
/**
* Get the level map
*
* @return array
* @return array<int, int>
*/
public function getLevelMap()
public function getLevelMap() : array
{
return $this->levelMap;
}

View File

@@ -0,0 +1,33 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace WPMailSMTP\Vendor\Monolog;
use ArrayAccess;
/**
* Monolog log record interface for forward compatibility with Monolog 3.0
*
* This is just present in Monolog 2.4+ to allow interoperable code to be written against
* both versions by type-hinting arguments as `array|\Monolog\LogRecord $record`
*
* Do not rely on this interface for other purposes, and do not implement it.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @template-extends \ArrayAccess<'message'|'level'|'context'|'level_name'|'channel'|'datetime'|'extra'|'formatted', mixed>
* @phpstan-import-type Record from Logger
*/
interface LogRecord extends \ArrayAccess
{
/**
* @phpstan-return Record
*/
public function toArray() : array;
}

View File

@@ -1,5 +1,6 @@
<?php
declare (strict_types=1);
/*
* This file is part of the Monolog package.
*
@@ -10,11 +11,13 @@
*/
namespace WPMailSMTP\Vendor\Monolog;
use DateTimeZone;
use WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface;
use WPMailSMTP\Vendor\Monolog\Handler\StreamHandler;
use WPMailSMTP\Vendor\Psr\Log\LoggerInterface;
use WPMailSMTP\Vendor\Psr\Log\InvalidArgumentException;
use Exception;
use WPMailSMTP\Vendor\Psr\Log\LogLevel;
use Throwable;
use Stringable;
/**
* Monolog log channel
*
@@ -22,51 +25,55 @@ use Exception;
* and uses them to store records that are added to it.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-type Level Logger::DEBUG|Logger::INFO|Logger::NOTICE|Logger::WARNING|Logger::ERROR|Logger::CRITICAL|Logger::ALERT|Logger::EMERGENCY
* @phpstan-type LevelName 'DEBUG'|'INFO'|'NOTICE'|'WARNING'|'ERROR'|'CRITICAL'|'ALERT'|'EMERGENCY'
* @phpstan-type Record array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[]}
*/
class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\Vendor\Monolog\ResettableInterface
{
/**
* Detailed debug information
*/
const DEBUG = 100;
public const DEBUG = 100;
/**
* Interesting events
*
* Examples: User logs in, SQL logs.
*/
const INFO = 200;
public const INFO = 200;
/**
* Uncommon events
*/
const NOTICE = 250;
public const NOTICE = 250;
/**
* Exceptional occurrences that are not errors
*
* Examples: Use of deprecated APIs, poor use of an API,
* undesirable things that are not necessarily wrong.
*/
const WARNING = 300;
public const WARNING = 300;
/**
* Runtime errors
*/
const ERROR = 400;
public const ERROR = 400;
/**
* Critical conditions
*
* Example: Application component unavailable, unexpected exception.
*/
const CRITICAL = 500;
public const CRITICAL = 500;
/**
* Action must be taken immediately
*
* Example: Entire website down, database unavailable, etc.
* This should trigger the SMS alerts and wake you up.
*/
const ALERT = 550;
public const ALERT = 550;
/**
* Urgent alert.
*/
const EMERGENCY = 600;
public const EMERGENCY = 600;
/**
* Monolog API version
*
@@ -75,17 +82,21 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
*
* @var int
*/
const API = 1;
public const API = 2;
/**
* Logging levels from syslog protocol defined in RFC 5424
* This is a static variable and not a constant to serve as an extension point for custom levels
*
* @var array $levels Logging levels
* @var array<int, string> $levels Logging levels with the levels as key
*
* @phpstan-var array<Level, LevelName> $levels Logging levels with the levels as key
*/
protected static $levels = array(self::DEBUG => 'DEBUG', self::INFO => 'INFO', self::NOTICE => 'NOTICE', self::WARNING => 'WARNING', self::ERROR => 'ERROR', self::CRITICAL => 'CRITICAL', self::ALERT => 'ALERT', self::EMERGENCY => 'EMERGENCY');
protected static $levels = [self::DEBUG => 'DEBUG', self::INFO => 'INFO', self::NOTICE => 'NOTICE', self::WARNING => 'WARNING', self::ERROR => 'ERROR', self::CRITICAL => 'CRITICAL', self::ALERT => 'ALERT', self::EMERGENCY => 'EMERGENCY'];
/**
* @var \DateTimeZone
* Mapping between levels numbers defined in RFC 5424 and Monolog ones
*
* @phpstan-var array<int, Level> $rfc_5424_levels
*/
protected static $timezone;
private const RFC_5424_LEVELS = [7 => self::DEBUG, 6 => self::INFO, 5 => self::NOTICE, 4 => self::WARNING, 3 => self::ERROR, 2 => self::CRITICAL, 1 => self::ALERT, 0 => self::EMERGENCY];
/**
* @var string
*/
@@ -109,33 +120,56 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
*/
protected $microsecondTimestamps = \true;
/**
* @var callable
* @var DateTimeZone
*/
protected $timezone;
/**
* @var callable|null
*/
protected $exceptionHandler;
/**
* @param string $name The logging channel
* @var int Keeps track of depth to prevent infinite logging loops
*/
private $logDepth = 0;
/**
* @var \WeakMap<\Fiber, int>|null Keeps track of depth inside fibers to prevent infinite logging loops
*/
private $fiberLogDepth;
/**
* @var bool Whether to detect infinite logging loops
*
* This can be disabled via {@see useLoggingLoopDetection} if you have async handlers that do not play well with this
*/
private $detectCycles = \true;
/**
* @psalm-param array<callable(array): array> $processors
*
* @param string $name The logging channel, a simple descriptive name that is attached to all log records
* @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
* @param callable[] $processors Optional array of processors
* @param DateTimeZone|null $timezone Optional timezone, if not provided date_default_timezone_get() will be used
*/
public function __construct($name, array $handlers = array(), array $processors = array())
public function __construct(string $name, array $handlers = [], array $processors = [], ?\DateTimeZone $timezone = null)
{
$this->name = $name;
$this->setHandlers($handlers);
$this->processors = $processors;
$this->timezone = $timezone ?: new \DateTimeZone(\date_default_timezone_get() ?: 'UTC');
if (\PHP_VERSION_ID >= 80100) {
// Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412
/** @var \WeakMap<\Fiber, int> $fiberLogDepth */
$fiberLogDepth = new \WeakMap();
$this->fiberLogDepth = $fiberLogDepth;
}
}
/**
* @return string
*/
public function getName()
public function getName() : string
{
return $this->name;
}
/**
* Return a new cloned instance with the name changed
*
* @return static
*/
public function withName($name)
public function withName(string $name) : self
{
$new = clone $this;
$new->name = $name;
@@ -143,11 +177,8 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
}
/**
* Pushes a handler on to the stack.
*
* @param HandlerInterface $handler
* @return $this
*/
public function pushHandler(\WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface $handler)
public function pushHandler(\WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface $handler) : self
{
\array_unshift($this->handlers, $handler);
return $this;
@@ -155,9 +186,9 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
/**
* Pops a handler from the stack
*
* @return HandlerInterface
* @throws \LogicException If empty handler stack
*/
public function popHandler()
public function popHandler() : \WPMailSMTP\Vendor\Monolog\Handler\HandlerInterface
{
if (!$this->handlers) {
throw new \LogicException('You tried to pop from an empty handler stack.');
@@ -169,12 +200,11 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
*
* If a map is passed, keys will be ignored.
*
* @param HandlerInterface[] $handlers
* @return $this
* @param HandlerInterface[] $handlers
*/
public function setHandlers(array $handlers)
public function setHandlers(array $handlers) : self
{
$this->handlers = array();
$this->handlers = [];
foreach (\array_reverse($handlers) as $handler) {
$this->pushHandler($handler);
}
@@ -183,30 +213,25 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
/**
* @return HandlerInterface[]
*/
public function getHandlers()
public function getHandlers() : array
{
return $this->handlers;
}
/**
* Adds a processor on to the stack.
*
* @param callable $callback
* @return $this
*/
public function pushProcessor($callback)
public function pushProcessor(callable $callback) : self
{
if (!\is_callable($callback)) {
throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), ' . \var_export($callback, \true) . ' given');
}
\array_unshift($this->processors, $callback);
return $this;
}
/**
* Removes the processor on top of the stack and returns it.
*
* @throws \LogicException If empty processor stack
* @return callable
*/
public function popProcessor()
public function popProcessor() : callable
{
if (!$this->processors) {
throw new \LogicException('You tried to pop from an empty processor stack.');
@@ -216,7 +241,7 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
/**
* @return callable[]
*/
public function getProcessors()
public function getProcessors() : array
{
return $this->processors;
}
@@ -224,71 +249,95 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
* Control the use of microsecond resolution timestamps in the 'datetime'
* member of new records.
*
* Generating microsecond resolution timestamps by calling
* microtime(true), formatting the result via sprintf() and then parsing
* the resulting string via \DateTime::createFromFormat() can incur
* a measurable runtime overhead vs simple usage of DateTime to capture
* a second resolution timestamp in systems which generate a large number
* of log events.
* As of PHP7.1 microseconds are always included by the engine, so
* there is no performance penalty and Monolog 2 enabled microseconds
* by default. This function lets you disable them though in case you want
* to suppress microseconds from the output.
*
* @param bool $micro True to use microtime() to create timestamps
*/
public function useMicrosecondTimestamps($micro)
public function useMicrosecondTimestamps(bool $micro) : self
{
$this->microsecondTimestamps = (bool) $micro;
$this->microsecondTimestamps = $micro;
return $this;
}
public function useLoggingLoopDetection(bool $detectCycles) : self
{
$this->detectCycles = $detectCycles;
return $this;
}
/**
* Adds a log record.
*
* @param int $level The logging level
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param int $level The logging level (a Monolog or RFC 5424 level)
* @param string $message The log message
* @param mixed[] $context The log context
* @param DateTimeImmutable $datetime Optional log date to log into the past or future
* @return bool Whether the record has been processed
*
* @phpstan-param Level $level
*/
public function addRecord($level, $message, array $context = array())
public function addRecord(int $level, string $message, array $context = [], ?\WPMailSMTP\Vendor\Monolog\DateTimeImmutable $datetime = null) : bool
{
if (!$this->handlers) {
$this->pushHandler(new \WPMailSMTP\Vendor\Monolog\Handler\StreamHandler('php://stderr', static::DEBUG));
if (isset(self::RFC_5424_LEVELS[$level])) {
$level = self::RFC_5424_LEVELS[$level];
}
$levelName = static::getLevelName($level);
// check if any handler will handle this message so we can return early and save cycles
$handlerKey = null;
\reset($this->handlers);
while ($handler = \current($this->handlers)) {
if ($handler->isHandling(array('level' => $level))) {
$handlerKey = \key($this->handlers);
break;
if ($this->detectCycles) {
if (\PHP_VERSION_ID >= 80100 && ($fiber = \Fiber::getCurrent())) {
$this->fiberLogDepth[$fiber] = $this->fiberLogDepth[$fiber] ?? 0;
$logDepth = ++$this->fiberLogDepth[$fiber];
} else {
$logDepth = ++$this->logDepth;
}
\next($this->handlers);
} else {
$logDepth = 0;
}
if (null === $handlerKey) {
if ($logDepth === 3) {
$this->warning('A possible infinite logging loop was detected and aborted. It appears some of your handler code is triggering logging, see the previous log record for a hint as to what may be the cause.');
return \false;
} elseif ($logDepth >= 5) {
// log depth 4 is let through, so we can log the warning above
return \false;
}
if (!static::$timezone) {
static::$timezone = new \DateTimeZone(\date_default_timezone_get() ?: 'UTC');
}
// php7.1+ always has microseconds enabled, so we do not need this hack
if ($this->microsecondTimestamps && \PHP_VERSION_ID < 70100) {
$ts = \DateTime::createFromFormat('U.u', \sprintf('%.6F', \microtime(\true)), static::$timezone);
} else {
$ts = new \DateTime('now', static::$timezone);
}
$ts->setTimezone(static::$timezone);
$record = array('message' => (string) $message, 'context' => $context, 'level' => $level, 'level_name' => $levelName, 'channel' => $this->name, 'datetime' => $ts, 'extra' => array());
try {
foreach ($this->processors as $processor) {
$record = \call_user_func($processor, $record);
}
while ($handler = \current($this->handlers)) {
if (\true === $handler->handle($record)) {
break;
$record = null;
foreach ($this->handlers as $handler) {
if (null === $record) {
// skip creating the record as long as no handler is going to handle it
if (!$handler->isHandling(['level' => $level])) {
continue;
}
$levelName = static::getLevelName($level);
$record = ['message' => $message, 'context' => $context, 'level' => $level, 'level_name' => $levelName, 'channel' => $this->name, 'datetime' => $datetime ?? new \WPMailSMTP\Vendor\Monolog\DateTimeImmutable($this->microsecondTimestamps, $this->timezone), 'extra' => []];
try {
foreach ($this->processors as $processor) {
$record = $processor($record);
}
} catch (\Throwable $e) {
$this->handleException($e, $record);
return \true;
}
}
// once the record exists, send it to all handlers as long as the bubbling chain is not interrupted
try {
if (\true === $handler->handle($record)) {
break;
}
} catch (\Throwable $e) {
$this->handleException($e, $record);
return \true;
}
}
} finally {
if ($this->detectCycles) {
if (isset($fiber)) {
$this->fiberLogDepth[$fiber]--;
} else {
$this->logDepth--;
}
\next($this->handlers);
}
} catch (\Exception $e) {
$this->handleException($e, $record);
}
return \true;
return null !== $record;
}
/**
* Ends a log cycle and frees all resources used by handlers.
@@ -300,12 +349,10 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
* This is useful at the end of a request and will be called automatically on every handler
* when they get destructed.
*/
public function close()
public function close() : void
{
foreach ($this->handlers as $handler) {
if (\method_exists($handler, 'close')) {
$handler->close();
}
$handler->close();
}
}
/**
@@ -318,7 +365,7 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
* have a long running process like a worker or an application server serving multiple requests
* in one process.
*/
public function reset()
public function reset() : void
{
foreach ($this->handlers as $handler) {
if ($handler instanceof \WPMailSMTP\Vendor\Monolog\ResettableInterface) {
@@ -331,110 +378,25 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
}
}
}
/**
* Adds a log record at the DEBUG level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function addDebug($message, array $context = array())
{
return $this->addRecord(static::DEBUG, $message, $context);
}
/**
* Adds a log record at the INFO level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function addInfo($message, array $context = array())
{
return $this->addRecord(static::INFO, $message, $context);
}
/**
* Adds a log record at the NOTICE level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function addNotice($message, array $context = array())
{
return $this->addRecord(static::NOTICE, $message, $context);
}
/**
* Adds a log record at the WARNING level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function addWarning($message, array $context = array())
{
return $this->addRecord(static::WARNING, $message, $context);
}
/**
* Adds a log record at the ERROR level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function addError($message, array $context = array())
{
return $this->addRecord(static::ERROR, $message, $context);
}
/**
* Adds a log record at the CRITICAL level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function addCritical($message, array $context = array())
{
return $this->addRecord(static::CRITICAL, $message, $context);
}
/**
* Adds a log record at the ALERT level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function addAlert($message, array $context = array())
{
return $this->addRecord(static::ALERT, $message, $context);
}
/**
* Adds a log record at the EMERGENCY level.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function addEmergency($message, array $context = array())
{
return $this->addRecord(static::EMERGENCY, $message, $context);
}
/**
* Gets all supported logging levels.
*
* @return array Assoc array with human-readable level names => level codes.
* @return array<string, int> Assoc array with human-readable level names => level codes.
* @phpstan-return array<LevelName, Level>
*/
public static function getLevels()
public static function getLevels() : array
{
return \array_flip(static::$levels);
}
/**
* Gets the name of the logging level.
*
* @param int $level
* @return string
* @throws \Psr\Log\InvalidArgumentException If level is not defined
*
* @phpstan-param Level $level
* @phpstan-return LevelName
*/
public static function getLevelName($level)
public static function getLevelName(int $level) : string
{
if (!isset(static::$levels[$level])) {
throw new \WPMailSMTP\Vendor\Psr\Log\InvalidArgumentException('Level "' . $level . '" is not defined, use one of: ' . \implode(', ', \array_keys(static::$levels)));
@@ -444,30 +406,40 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
/**
* Converts PSR-3 levels to Monolog ones if necessary
*
* @param string|int $level Level number (monolog) or name (PSR-3)
* @return int
* @param string|int $level Level number (monolog) or name (PSR-3)
* @throws \Psr\Log\InvalidArgumentException If level is not defined
*
* @phpstan-param Level|LevelName|LogLevel::* $level
* @phpstan-return Level
*/
public static function toMonologLevel($level)
public static function toMonologLevel($level) : int
{
if (\is_string($level)) {
if (\is_numeric($level)) {
/** @phpstan-ignore-next-line */
return \intval($level);
}
// Contains chars of all log levels and avoids using strtoupper() which may have
// strange results depending on locale (for example, "i" will become "İ")
// strange results depending on locale (for example, "i" will become "İ" in Turkish locale)
$upper = \strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY');
if (\defined(__CLASS__ . '::' . $upper)) {
return \constant(__CLASS__ . '::' . $upper);
}
throw new \WPMailSMTP\Vendor\Psr\Log\InvalidArgumentException('Level "' . $level . '" is not defined, use one of: ' . \implode(', ', \array_keys(static::$levels) + static::$levels));
}
if (!\is_int($level)) {
throw new \WPMailSMTP\Vendor\Psr\Log\InvalidArgumentException('Level "' . \var_export($level, \true) . '" is not defined, use one of: ' . \implode(', ', \array_keys(static::$levels) + static::$levels));
}
return $level;
}
/**
* Checks whether the Logger has a handler that listens on the given level
*
* @param int $level
* @return bool
* @phpstan-param Level $level
*/
public function isHandling($level)
public function isHandling(int $level) : bool
{
$record = array('level' => $level);
$record = ['level' => $level];
foreach ($this->handlers as $handler) {
if ($handler->isHandling($record)) {
return \true;
@@ -476,217 +448,188 @@ class Logger implements \WPMailSMTP\Vendor\Psr\Log\LoggerInterface, \WPMailSMTP\
return \false;
}
/**
* Set a custom exception handler
* Set a custom exception handler that will be called if adding a new record fails
*
* @param callable $callback
* @return $this
* The callable will receive an exception object and the record that failed to be logged
*/
public function setExceptionHandler($callback)
public function setExceptionHandler(?callable $callback) : self
{
if (!\is_callable($callback)) {
throw new \InvalidArgumentException('Exception handler must be valid callable (callback or object with an __invoke method), ' . \var_export($callback, \true) . ' given');
}
$this->exceptionHandler = $callback;
return $this;
}
/**
* @return callable
*/
public function getExceptionHandler()
public function getExceptionHandler() : ?callable
{
return $this->exceptionHandler;
}
/**
* Delegates exception management to the custom exception handler,
* or throws the exception if no custom handler is set.
*/
protected function handleException(\Exception $e, array $record)
{
if (!$this->exceptionHandler) {
throw $e;
}
\call_user_func($this->exceptionHandler, $e, $record);
}
/**
* Adds a log record at an arbitrary level.
*
* This method allows for compatibility with common interfaces.
*
* @param mixed $level The log level
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param mixed $level The log level (a Monolog, PSR-3 or RFC 5424 level)
* @param string|Stringable $message The log message
* @param mixed[] $context The log context
*
* @phpstan-param Level|LevelName|LogLevel::* $level
*/
public function log($level, $message, array $context = array())
public function log($level, $message, array $context = []) : void
{
if (!\is_int($level) && !\is_string($level)) {
throw new \InvalidArgumentException('$level is expected to be a string or int');
}
if (isset(self::RFC_5424_LEVELS[$level])) {
$level = self::RFC_5424_LEVELS[$level];
}
$level = static::toMonologLevel($level);
return $this->addRecord($level, $message, $context);
$this->addRecord($level, (string) $message, $context);
}
/**
* Adds a log record at the DEBUG level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string|Stringable $message The log message
* @param mixed[] $context The log context
*/
public function debug($message, array $context = array())
public function debug($message, array $context = []) : void
{
return $this->addRecord(static::DEBUG, $message, $context);
$this->addRecord(static::DEBUG, (string) $message, $context);
}
/**
* Adds a log record at the INFO level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string|Stringable $message The log message
* @param mixed[] $context The log context
*/
public function info($message, array $context = array())
public function info($message, array $context = []) : void
{
return $this->addRecord(static::INFO, $message, $context);
$this->addRecord(static::INFO, (string) $message, $context);
}
/**
* Adds a log record at the NOTICE level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string|Stringable $message The log message
* @param mixed[] $context The log context
*/
public function notice($message, array $context = array())
public function notice($message, array $context = []) : void
{
return $this->addRecord(static::NOTICE, $message, $context);
$this->addRecord(static::NOTICE, (string) $message, $context);
}
/**
* Adds a log record at the WARNING level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string|Stringable $message The log message
* @param mixed[] $context The log context
*/
public function warn($message, array $context = array())
public function warning($message, array $context = []) : void
{
return $this->addRecord(static::WARNING, $message, $context);
}
/**
* Adds a log record at the WARNING level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function warning($message, array $context = array())
{
return $this->addRecord(static::WARNING, $message, $context);
$this->addRecord(static::WARNING, (string) $message, $context);
}
/**
* Adds a log record at the ERROR level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string|Stringable $message The log message
* @param mixed[] $context The log context
*/
public function err($message, array $context = array())
public function error($message, array $context = []) : void
{
return $this->addRecord(static::ERROR, $message, $context);
}
/**
* Adds a log record at the ERROR level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function error($message, array $context = array())
{
return $this->addRecord(static::ERROR, $message, $context);
$this->addRecord(static::ERROR, (string) $message, $context);
}
/**
* Adds a log record at the CRITICAL level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string|Stringable $message The log message
* @param mixed[] $context The log context
*/
public function crit($message, array $context = array())
public function critical($message, array $context = []) : void
{
return $this->addRecord(static::CRITICAL, $message, $context);
}
/**
* Adds a log record at the CRITICAL level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
*/
public function critical($message, array $context = array())
{
return $this->addRecord(static::CRITICAL, $message, $context);
$this->addRecord(static::CRITICAL, (string) $message, $context);
}
/**
* Adds a log record at the ALERT level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string|Stringable $message The log message
* @param mixed[] $context The log context
*/
public function alert($message, array $context = array())
public function alert($message, array $context = []) : void
{
return $this->addRecord(static::ALERT, $message, $context);
$this->addRecord(static::ALERT, (string) $message, $context);
}
/**
* Adds a log record at the EMERGENCY level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* @param string|Stringable $message The log message
* @param mixed[] $context The log context
*/
public function emerg($message, array $context = array())
public function emergency($message, array $context = []) : void
{
return $this->addRecord(static::EMERGENCY, $message, $context);
$this->addRecord(static::EMERGENCY, (string) $message, $context);
}
/**
* Adds a log record at the EMERGENCY level.
*
* This method allows for compatibility with common interfaces.
*
* @param string $message The log message
* @param array $context The log context
* @return bool Whether the record has been processed
* Sets the timezone to be used for the timestamp of log records.
*/
public function emergency($message, array $context = array())
public function setTimezone(\DateTimeZone $tz) : self
{
return $this->addRecord(static::EMERGENCY, $message, $context);
$this->timezone = $tz;
return $this;
}
/**
* Set the timezone to be used for the timestamp of log records.
*
* This is stored globally for all Logger instances
*
* @param \DateTimeZone $tz Timezone object
* Returns the timezone to be used for the timestamp of log records.
*/
public static function setTimezone(\DateTimeZone $tz)
public function getTimezone() : \DateTimeZone
{
self::$timezone = $tz;
return $this->timezone;
}
/**
* Delegates exception management to the custom exception handler,
* or throws the exception if no custom handler is set.
*
* @param array $record
* @phpstan-param Record $record
*/
protected function handleException(\Throwable $e, array $record) : void
{
if (!$this->exceptionHandler) {
throw $e;
}
($this->exceptionHandler)($e, $record);
}
/**
* @return array<string, mixed>
*/
public function __serialize() : array
{
return ['name' => $this->name, 'handlers' => $this->handlers, 'processors' => $this->processors, 'microsecondTimestamps' => $this->microsecondTimestamps, 'timezone' => $this->timezone, 'exceptionHandler' => $this->exceptionHandler, 'logDepth' => $this->logDepth, 'detectCycles' => $this->detectCycles];
}
/**
* @param array<string, mixed> $data
*/
public function __unserialize(array $data) : void
{
foreach (['name', 'handlers', 'processors', 'microsecondTimestamps', 'timezone', 'exceptionHandler', 'logDepth', 'detectCycles'] as $property) {
if (isset($data[$property])) {
$this->{$property} = $data[$property];
}
}
if (\PHP_VERSION_ID >= 80100) {
// Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412
/** @var \WeakMap<\Fiber, int> $fiberLogDepth */
$fiberLogDepth = new \WeakMap();
$this->fiberLogDepth = $fiberLogDepth;
}
}
}

Some files were not shown because too many files have changed in this diff Show More