Spade
Mini Shell
| Directory:~$ /home/lmsyaran/public_html/joomla4/ |
| [Home] [System Details] [Kill Me] |
PKe�[�GlAbstractLogger.phpnu�[���<?php
namespace Psr\Log;
/**
* This is a simple Logger implementation that other Loggers can inherit
from.
*
* It simply delegates all log-level-specific methods to the `log` method
to
* reduce boilerplate code that a simple Logger that does the same thing
with
* messages regardless of the error level has to implement.
*/
abstract class AbstractLogger implements LoggerInterface
{
/**
* System is unusable.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function emergency($message, array $context = array())
{
$this->log(LogLevel::EMERGENCY, $message, $context);
}
/**
* Action must be taken immediately.
*
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function alert($message, array $context = array())
{
$this->log(LogLevel::ALERT, $message, $context);
}
/**
* Critical conditions.
*
* Example: Application component unavailable, unexpected exception.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function critical($message, array $context = array())
{
$this->log(LogLevel::CRITICAL, $message, $context);
}
/**
* Runtime errors that do not require immediate action but should
typically
* be logged and monitored.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function error($message, array $context = array())
{
$this->log(LogLevel::ERROR, $message, $context);
}
/**
* Exceptional occurrences that are not errors.
*
* Example: Use of deprecated APIs, poor use of an API, undesirable
things
* that are not necessarily wrong.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function warning($message, array $context = array())
{
$this->log(LogLevel::WARNING, $message, $context);
}
/**
* Normal but significant events.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function notice($message, array $context = array())
{
$this->log(LogLevel::NOTICE, $message, $context);
}
/**
* Interesting events.
*
* Example: User logs in, SQL logs.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function info($message, array $context = array())
{
$this->log(LogLevel::INFO, $message, $context);
}
/**
* Detailed debug information.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function debug($message, array $context = array())
{
$this->log(LogLevel::DEBUG, $message, $context);
}
}
PKe�[ �X1``InvalidArgumentException.phpnu�[���<?php
namespace Psr\Log;
class InvalidArgumentException extends \InvalidArgumentException
{
}
PKe�[�j�))LoggerAwareInterface.phpnu�[���<?php
namespace Psr\Log;
/**
* Describes a logger-aware instance.
*/
interface LoggerAwareInterface
{
/**
* Sets a logger instance on the object.
*
* @param LoggerInterface $logger
*
* @return void
*/
public function setLogger(LoggerInterface $logger);
}
PKe�[z%���LoggerAwareTrait.phpnu�[���<?php
namespace Psr\Log;
/**
* Basic Implementation of LoggerAwareInterface.
*/
trait LoggerAwareTrait
{
/**
* The logger instance.
*
* @var LoggerInterface
*/
protected $logger;
/**
* Sets a logger.
*
* @param LoggerInterface $logger
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
}
}
PKe�[1b!q**LoggerInterface.phpnu�[���<?php
namespace Psr\Log;
/**
* Describes a logger instance.
*
* The message MUST be a string or object implementing __toString().
*
* The message MAY contain placeholders in the form: {foo} where foo
* will be replaced by the context data in key "foo".
*
* The context array can contain arbitrary data. The only assumption that
* can be made by implementors is that if an Exception instance is given
* to produce a stack trace, it MUST be in a key named
"exception".
*
* See
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
* for the full interface specification.
*/
interface LoggerInterface
{
/**
* System is unusable.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function emergency($message, array $context = array());
/**
* Action must be taken immediately.
*
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function alert($message, array $context = array());
/**
* Critical conditions.
*
* Example: Application component unavailable, unexpected exception.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function critical($message, array $context = array());
/**
* Runtime errors that do not require immediate action but should
typically
* be logged and monitored.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function error($message, array $context = array());
/**
* Exceptional occurrences that are not errors.
*
* Example: Use of deprecated APIs, poor use of an API, undesirable
things
* that are not necessarily wrong.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function warning($message, array $context = array());
/**
* Normal but significant events.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function notice($message, array $context = array());
/**
* Interesting events.
*
* Example: User logs in, SQL logs.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function info($message, array $context = array());
/**
* Detailed debug information.
*
* @param string $message
* @param mixed[] $context
*
* @return void
*/
public function debug($message, array $context = array());
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string $message
* @param mixed[] $context
*
* @return void
*
* @throws \Psr\Log\InvalidArgumentException
*/
public function log($level, $message, array $context = array());
}
PKe�[�W�jW
W
LoggerTrait.phpnu�[���<?php
namespace Psr\Log;
/**
* This is a simple Logger trait that classes unable to extend
AbstractLogger
* (because they extend another class, etc) can include.
*
* It simply delegates all log-level-specific methods to the `log` method
to
* reduce boilerplate code that a simple Logger that does the same thing
with
* messages regardless of the error level has to implement.
*/
trait LoggerTrait
{
/**
* System is unusable.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function emergency($message, array $context = array())
{
$this->log(LogLevel::EMERGENCY, $message, $context);
}
/**
* Action must be taken immediately.
*
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function alert($message, array $context = array())
{
$this->log(LogLevel::ALERT, $message, $context);
}
/**
* Critical conditions.
*
* Example: Application component unavailable, unexpected exception.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function critical($message, array $context = array())
{
$this->log(LogLevel::CRITICAL, $message, $context);
}
/**
* Runtime errors that do not require immediate action but should
typically
* be logged and monitored.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function error($message, array $context = array())
{
$this->log(LogLevel::ERROR, $message, $context);
}
/**
* Exceptional occurrences that are not errors.
*
* Example: Use of deprecated APIs, poor use of an API, undesirable
things
* that are not necessarily wrong.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function warning($message, array $context = array())
{
$this->log(LogLevel::WARNING, $message, $context);
}
/**
* Normal but significant events.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function notice($message, array $context = array())
{
$this->log(LogLevel::NOTICE, $message, $context);
}
/**
* Interesting events.
*
* Example: User logs in, SQL logs.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function info($message, array $context = array())
{
$this->log(LogLevel::INFO, $message, $context);
}
/**
* Detailed debug information.
*
* @param string $message
* @param array $context
*
* @return void
*/
public function debug($message, array $context = array())
{
$this->log(LogLevel::DEBUG, $message, $context);
}
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string $message
* @param array $context
*
* @return void
*
* @throws \Psr\Log\InvalidArgumentException
*/
abstract public function log($level, $message, array $context =
array());
}
PKe�[��PPLogLevel.phpnu�[���<?php
namespace Psr\Log;
/**
* Describes log levels.
*/
class LogLevel
{
const EMERGENCY = 'emergency';
const ALERT = 'alert';
const CRITICAL = 'critical';
const ERROR = 'error';
const WARNING = 'warning';
const NOTICE = 'notice';
const INFO = 'info';
const DEBUG = 'debug';
}
PKe�[���I��NullLogger.phpnu�[���<?php
namespace Psr\Log;
/**
* This Logger can be used to avoid conditional log calls.
*
* Logging should always be optional, and if no logger is provided to your
* library creating a NullLogger instance to have something to throw logs
at
* is a good way to avoid littering your code with `if ($this->logger) {
}`
* blocks.
*/
class NullLogger extends AbstractLogger
{
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string $message
* @param array $context
*
* @return void
*
* @throws \Psr\Log\InvalidArgumentException
*/
public function log($level, $message, array $context = array())
{
// noop
}
}
PK�T�[����
�
DelegatingPsrLogger.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log;
defined('JPATH_PLATFORM') or die;
use Psr\Log\AbstractLogger;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel;
/**
* Delegating logger which delegates log messages received from the PSR-3
interface to the Joomla! Log object.
*
* @since 3.8.0
*/
class DelegatingPsrLogger extends AbstractLogger
{
/**
* The Log instance to delegate messages to.
*
* @var Log
* @since 3.8.0
*/
protected $logger;
/**
* Mapping array to map a PSR-3 level to a Joomla priority.
*
* @var array
* @since 3.8.0
*/
protected $priorityMap = array(
LogLevel::EMERGENCY => Log::EMERGENCY,
LogLevel::ALERT => Log::ALERT,
LogLevel::CRITICAL => Log::CRITICAL,
LogLevel::ERROR => Log::ERROR,
LogLevel::WARNING => Log::WARNING,
LogLevel::NOTICE => Log::NOTICE,
LogLevel::INFO => Log::INFO,
LogLevel::DEBUG => Log::DEBUG
);
/**
* Constructor.
*
* @param Log $logger The Log instance to delegate messages to.
*
* @since 3.8.0
*/
public function __construct(Log $logger)
{
$this->logger = $logger;
}
/**
* Logs with an arbitrary level.
*
* @param mixed $level The log level.
* @param string $message The log message.
* @param array $context Additional message context.
*
* @return void
*
* @since 3.8.0
* @throws InvalidArgumentException
*/
public function log($level, $message, array $context = array())
{
// Make sure the log level is valid
if (!array_key_exists($level, $this->priorityMap))
{
throw new \InvalidArgumentException('An invalid log level has been
given.');
}
// Map the level to Joomla's priority
$priority = $this->priorityMap[$level];
$category = null;
$date = null;
// If a message category is given, map it
if (!empty($context['category']))
{
$category = $context['category'];
}
// If a message timestamp is given, map it
if (!empty($context['date']))
{
$date = $context['date'];
}
// Joomla's logging API will only process a string or a LogEntry
object, if $message is an object without __toString() we can't use it
if (!is_string($message) && !($message instanceof LogEntry))
{
if (!is_object($message) || !method_exists($message,
'__toString'))
{
throw new \InvalidArgumentException(
'The message must be a string, a LogEntry object, or an object
implementing the __toString() method.'
);
}
$message = (string) $message;
}
$this->logger->add($message, $priority, $category, $date,
$context);
}
}
PK�T�[F�`?�$�$Log.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log;
defined('JPATH_PLATFORM') or die;
/**
* Joomla! Log Class
*
* This class hooks into the global log configuration settings to allow for
user configured
* logging events to be sent to where the user wishes them to be sent. On
high load sites
* Syslog is probably the best (pure PHP function), then the text file
based loggers (CSV, W3c
* or plain Formattedtext) and finally MySQL offers the most features (e.g.
rapid searching)
* but will incur a performance hit due to INSERT being issued.
*
* @since 1.7.0
*/
class Log
{
/**
* All log priorities.
*
* @var integer
* @since 1.7.0
*/
const ALL = 30719;
/**
* The system is unusable.
*
* @var integer
* @since 1.7.0
*/
const EMERGENCY = 1;
/**
* Action must be taken immediately.
*
* @var integer
* @since 1.7.0
*/
const ALERT = 2;
/**
* Critical conditions.
*
* @var integer
* @since 1.7.0
*/
const CRITICAL = 4;
/**
* Error conditions.
*
* @var integer
* @since 1.7.0
*/
const ERROR = 8;
/**
* Warning conditions.
*
* @var integer
* @since 1.7.0
*/
const WARNING = 16;
/**
* Normal, but significant condition.
*
* @var integer
* @since 1.7.0
*/
const NOTICE = 32;
/**
* Informational message.
*
* @var integer
* @since 1.7.0
*/
const INFO = 64;
/**
* Debugging message.
*
* @var integer
* @since 1.7.0
*/
const DEBUG = 128;
/**
* The global Log instance.
*
* @var Log
* @since 1.7.0
*/
protected static $instance;
/**
* Container for Logger configurations.
*
* @var array
* @since 1.7.0
*/
protected $configurations = array();
/**
* Container for Logger objects.
*
* @var Logger[]
* @since 1.7.0
*/
protected $loggers = array();
/**
* Lookup array for loggers.
*
* @var array
* @since 1.7.0
*/
protected $lookup = array();
/**
* Constructor.
*
* @since 1.7.0
*/
protected function __construct()
{
}
/**
* Method to add an entry to the log.
*
* @param mixed $entry The LogEntry object to add to the log or
the message for a new LogEntry object.
* @param integer $priority Message priority.
* @param string $category Type of entry
* @param string $date Date of entry (defaults to now if not
specified or blank)
* @param array $context An optional array with additional message
context.
*
* @return void
*
* @since 1.7.0
*/
public static function add($entry, $priority = self::INFO, $category =
'', $date = null, array $context = array())
{
// Automatically instantiate the singleton object if not already done.
if (empty(static::$instance))
{
static::setInstance(new Log);
}
// If the entry object isn't a LogEntry object let's make one.
if (!($entry instanceof LogEntry))
{
$entry = new LogEntry((string) $entry, $priority, $category, $date,
$context);
}
static::$instance->addLogEntry($entry);
}
/**
* Add a logger to the Log instance. Loggers route log entries to the
correct files/systems to be logged.
*
* @param array $options The object configuration array.
* @param integer $priorities Message priority
* @param array $categories Types of entry
* @param boolean $exclude If true, all categories will be logged
except those in the $categories array
*
* @return void
*
* @since 1.7.0
*/
public static function addLogger(array $options, $priorities = self::ALL,
$categories = array(), $exclude = false)
{
// Automatically instantiate the singleton object if not already done.
if (empty(static::$instance))
{
static::setInstance(new Log);
}
static::$instance->addLoggerInternal($options, $priorities,
$categories, $exclude);
}
/**
* Add a logger to the Log instance. Loggers route log entries to the
correct files/systems to be logged.
* This method allows you to extend Log completely.
*
* @param array $options The object configuration array.
* @param integer $priorities Message priority
* @param array $categories Types of entry
* @param boolean $exclude If true, all categories will be logged
except those in the $categories array
*
* @return void
*
* @since 1.7.0
*/
protected function addLoggerInternal(array $options, $priorities =
self::ALL, $categories = array(), $exclude = false)
{
// The default logger is the formatted text log file.
if (empty($options['logger']))
{
$options['logger'] = 'formattedtext';
}
$options['logger'] = strtolower($options['logger']);
// Special case - if a Closure object is sent as the callback (in case of
CallbackLogger)
// Closure objects are not serializable so swap it out for a unique id
first then back again later
if (isset($options['callback']))
{
if (is_a($options['callback'], 'closure'))
{
$callback = $options['callback'];
$options['callback'] =
spl_object_hash($options['callback']);
}
elseif (is_array($options['callback']) &&
count($options['callback']) == 2 &&
is_object($options['callback'][0]))
{
$callback = $options['callback'];
$options['callback'] =
spl_object_hash($options['callback'][0]) . '::' .
$options['callback'][1];
}
}
// Generate a unique signature for the Log instance based on its options.
$signature = md5(serialize($options));
// Now that the options array has been serialized, swap the callback back
in
if (isset($callback))
{
$options['callback'] = $callback;
}
// Register the configuration if it doesn't exist.
if (empty($this->configurations[$signature]))
{
$this->configurations[$signature] = $options;
}
$this->lookup[$signature] = (object) array(
'priorities' => $priorities,
'categories' => array_map('strtolower', (array)
$categories),
'exclude' => (bool) $exclude,
);
}
/**
* Creates a delegated PSR-3 compatible logger from the current singleton
instance. This method always returns a new delegated logger.
*
* @return DelegatingPsrLogger
*
* @since 3.8.0
*/
public static function createDelegatedLogger()
{
// Ensure a singleton instance has been created first
if (empty(static::$instance))
{
static::setInstance(new static);
}
return new DelegatingPsrLogger(static::$instance);
}
/**
* Returns a reference to the a Log object, only creating it if it
doesn't already exist.
* Note: This is principally made available for testing and internal
purposes.
*
* @param Log $instance The logging object instance to be used by the
static methods.
*
* @return void
*
* @since 1.7.0
*/
public static function setInstance($instance)
{
if (($instance instanceof Log) || $instance === null)
{
static::$instance = & $instance;
}
}
/**
* Method to add an entry to the appropriate loggers.
*
* @param LogEntry $entry The LogEntry object to send to the loggers.
*
* @return void
*
* @since 1.7.0
* @throws \RuntimeException
*/
protected function addLogEntry(LogEntry $entry)
{
// Find all the appropriate loggers based on priority and category for
the entry.
$loggers = $this->findLoggers($entry->priority,
$entry->category);
foreach ((array) $loggers as $signature)
{
// Attempt to instantiate the logger object if it doesn't already
exist.
if (empty($this->loggers[$signature]))
{
$class = __NAMESPACE__ . '\\Logger\\' .
ucfirst($this->configurations[$signature]['logger']) .
'Logger';
if (!class_exists($class))
{
throw new \RuntimeException('Unable to create a Logger instance:
' . $class);
}
$this->loggers[$signature] = new
$class($this->configurations[$signature]);
}
// Add the entry to the logger.
$this->loggers[$signature]->addEntry(clone $entry);
}
}
/**
* Method to find the loggers to use based on priority and category
values.
*
* @param integer $priority Message priority.
* @param string $category Type of entry
*
* @return array The array of loggers to use for the given priority and
category values.
*
* @since 1.7.0
*/
protected function findLoggers($priority, $category)
{
$loggers = array();
// Sanitize inputs.
$priority = (int) $priority;
$category = strtolower($category);
// Let's go iterate over the loggers and get all the ones we need.
foreach ((array) $this->lookup as $signature => $rules)
{
// Check to make sure the priority matches the logger.
if ($priority & $rules->priorities)
{
if ($rules->exclude)
{
// If either there are no set categories or the category (including
the empty case) is not in the list of excluded categories, add this logger.
if (empty($rules->categories) || !in_array($category,
$rules->categories))
{
$loggers[] = $signature;
}
}
else
{
// If either there are no set categories (meaning all) or the specific
category is set, add this logger.
if (empty($rules->categories) || in_array($category,
$rules->categories))
{
$loggers[] = $signature;
}
}
}
}
return $loggers;
}
}
PK�T�[�*v>k
k
LogEntry.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Date\Date;
/**
* Joomla! Log Entry class
*
* This class is designed to hold log entries for either writing to an
engine, or for
* supported engines, retrieving lists and building in memory (PHP based)
search operations.
*
* @since 1.7.0
*/
class LogEntry
{
/**
* Application responsible for log entry.
* @var string
* @since 1.7.0
*/
public $category;
/**
* The message context.
*
* @var array
* @since 3.8.0
*/
public $context;
/**
* The date the message was logged.
* @var Date
* @since 1.7.0
*/
public $date;
/**
* Message to be logged.
* @var string
* @since 1.7.0
*/
public $message;
/**
* The priority of the message to be logged.
* @var string
* @since 1.7.0
* @see LogEntry::$priorities
*/
public $priority = Log::INFO;
/**
* List of available log priority levels [Based on the Syslog default
levels].
* @var array
* @since 1.7.0
*/
protected $priorities = array(
Log::EMERGENCY,
Log::ALERT,
Log::CRITICAL,
Log::ERROR,
Log::WARNING,
Log::NOTICE,
Log::INFO,
Log::DEBUG,
);
/**
* Call stack and back trace of the logged call.
* @var array
* @since 3.1.4
*/
public $callStack = array();
/**
* Constructor
*
* @param string $message The message to log.
* @param int $priority Message priority based on
{$this->priorities}.
* @param string $category Type of entry
* @param string $date Date of entry (defaults to now if not
specified or blank)
* @param array $context An optional array with additional message
context.
*
* @since 1.7.0
*/
public function __construct($message, $priority = Log::INFO, $category =
'', $date = null, array $context = array())
{
$this->message = (string) $message;
// Sanitize the priority.
if (!in_array($priority, $this->priorities, true))
{
$priority = Log::INFO;
}
$this->priority = $priority;
$this->context = $context;
// Sanitize category if it exists.
if (!empty($category))
{
$this->category = (string)
strtolower(preg_replace('/[^A-Z0-9_\.-]/i', '',
$category));
}
// Get the current call stack and back trace (without args to save
memory).
$this->callStack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
// Get the date as a Date object.
$this->date = new Date($date ? $date : 'now');
}
}
PK�T�[�v�SSLogger/CallbackLogger.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log\Logger;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Log\LogEntry;
use Joomla\CMS\Log\Logger;
/**
* Joomla! Callback Log class
*
* This class allows logging to be handled by a callback function.
* This allows unprecedented flexibility in the way logging can be handled.
*
* @since 3.0.1
*/
class CallbackLogger extends Logger
{
/**
* The function to call when an entry is added
*
* @var callable
* @since 3.0.1
*/
protected $callback;
/**
* Constructor.
*
* @param array &$options Log object options.
*
* @since 3.0.1
* @throws \RuntimeException
*/
public function __construct(array &$options)
{
// Call the parent constructor.
parent::__construct($options);
// Throw an exception if there is not a valid callback
if (!isset($this->options['callback']) ||
!is_callable($this->options['callback']))
{
throw new \RuntimeException(sprintf('%s created without valid
callback function.', get_class($this)));
}
$this->callback = $this->options['callback'];
}
/**
* Method to add an entry to the log.
*
* @param LogEntry $entry The log entry object to add to the log.
*
* @return void
*
* @since 3.0.1
* @throws \RuntimeException
*/
public function addEntry(LogEntry $entry)
{
// Pass the log entry to the callback function
call_user_func($this->callback, $entry);
}
}
PK�T�[.W����Logger/DatabaseLogger.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log\Logger;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Log\LogEntry;
use Joomla\CMS\Log\Logger;
/**
* Joomla! MySQL Database Log class
*
* This class is designed to output logs to a specific MySQL database
table. Fields in this
* table are based on the Syslog style of log output. This is designed to
allow quick and
* easy searching.
*
* @since 1.7.0
*/
class DatabaseLogger extends Logger
{
/**
* The name of the database driver to use for connecting to the database.
*
* @var string
* @since 1.7.0
*/
protected $driver = 'mysqli';
/**
* The host name (or IP) of the server with which to connect for the
logger.
*
* @var string
* @since 1.7.0
*/
protected $host = '127.0.0.1';
/**
* The database server user to connect as for the logger.
*
* @var string
* @since 1.7.0
*/
protected $user = 'root';
/**
* The password to use for connecting to the database server.
*
* @var string
* @since 1.7.0
*/
protected $password = '';
/**
* The name of the database table to use for the logger.
*
* @var string
* @since 1.7.0
*/
protected $database = 'logging';
/**
* The database table to use for logging entries.
*
* @var string
* @since 1.7.0
*/
protected $table = 'jos_';
/**
* The database driver object for the logger.
*
* @var \JDatabaseDriver
* @since 1.7.0
*/
protected $db;
/**
* Constructor.
*
* @param array &$options Log object options.
*
* @since 1.7.0
*/
public function __construct(array &$options)
{
// Call the parent constructor.
parent::__construct($options);
// If both the database object and driver options are empty we want to
use the system database connection.
if (empty($this->options['db_driver']))
{
$this->db = \JFactory::getDbo();
$this->driver = null;
$this->host = null;
$this->user = null;
$this->password = null;
$this->database = null;
$this->prefix = null;
}
else
{
$this->db = null;
$this->driver = (empty($this->options['db_driver'])) ?
'mysqli' : $this->options['db_driver'];
$this->host = (empty($this->options['db_host'])) ?
'127.0.0.1' : $this->options['db_host'];
$this->user = (empty($this->options['db_user'])) ?
'root' : $this->options['db_user'];
$this->password = (empty($this->options['db_pass'])) ?
'' : $this->options['db_pass'];
$this->database = (empty($this->options['db_database']))
? 'logging' : $this->options['db_database'];
$this->prefix = (empty($this->options['db_prefix'])) ?
'jos_' : $this->options['db_prefix'];
}
// The table name is independent of how we arrived at the connection
object.
$this->table = (empty($this->options['db_table'])) ?
'#__log_entries' : $this->options['db_table'];
}
/**
* Method to add an entry to the log.
*
* @param LogEntry $entry The log entry object to add to the log.
*
* @return void
*
* @since 1.7.0
* @throws \RuntimeException
*/
public function addEntry(LogEntry $entry)
{
// Connect to the database if not connected.
if (empty($this->db))
{
$this->connect();
}
// Convert the date.
$entry->date = $entry->date->toSql(false, $this->db);
$this->db->insertObject($this->table, $entry);
}
/**
* Method to connect to the database server based on object properties.
*
* @return void
*
* @since 1.7.0
* @throws \RuntimeException
*/
protected function connect()
{
// Build the configuration object to use for JDatabaseDriver.
$options = array(
'driver' => $this->driver,
'host' => $this->host,
'user' => $this->user,
'password' => $this->password,
'database' => $this->database,
'prefix' => $this->prefix,
);
$this->db = \JDatabaseDriver::getInstance($options);
}
}
PK�T�[pU5�Logger/EchoLogger.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log\Logger;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Log\LogEntry;
use Joomla\CMS\Log\Logger;
/**
* Joomla Echo logger class.
*
* @since 1.7.0
*/
class EchoLogger extends Logger
{
/**
* Value to use at the end of an echoed log entry to separate lines.
*
* @var string
* @since 1.7.0
*/
protected $line_separator = "\n";
/**
* Constructor.
*
* @param array &$options Log object options.
*
* @since 3.0.0
*/
public function __construct(array &$options)
{
parent::__construct($options);
if (!empty($this->options['line_separator']))
{
$this->line_separator =
$this->options['line_separator'];
}
}
/**
* Method to add an entry to the log.
*
* @param LogEntry $entry The log entry object to add to the log.
*
* @return void
*
* @since 1.7.0
*/
public function addEntry(LogEntry $entry)
{
echo $this->priorities[$entry->priority] . ': '
. $entry->message . (empty($entry->category) ? '' :
' [' . $entry->category . ']')
. $this->line_separator;
}
}
PK�T�[�7��]]Logger/FormattedtextLogger.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log\Logger;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Log\LogEntry;
use Joomla\CMS\Log\Logger;
use Joomla\Utilities\IpHelper;
\JLoader::import('joomla.filesystem.file');
\JLoader::import('joomla.filesystem.folder');
/**
* Joomla! Formatted Text File Log class
*
* This class is designed to use as a base for building formatted text
files for output. By
* default it emulates the Syslog style format output. This is a disk based
output format.
*
* @since 1.7.0
*/
class FormattedtextLogger extends Logger
{
/**
* The format which each entry follows in the log file.
*
* All fields must be named in all caps and be within curly brackets eg.
{FOOBAR}.
*
* @var string
* @since 1.7.0
*/
protected $format = '{DATETIME} {PRIORITY}
{CLIENTIP} {CATEGORY} {MESSAGE}';
/**
* The parsed fields from the format string.
*
* @var array
* @since 1.7.0
*/
protected $fields = array();
/**
* The full filesystem path for the log file.
*
* @var string
* @since 1.7.0
*/
protected $path;
/**
* If true, all writes will be deferred as long as possible.
* NOTE: Deferred logs may never be written if the application encounters
a fatal error.
*
* @var boolean
* @since 3.9.0
*/
protected $defer = false;
/**
* If deferring, entries will be stored here prior to writing.
*
* @var array
* @since 3.9.0
*/
protected $deferredEntries = array();
/**
* Constructor.
*
* @param array &$options Log object options.
*
* @since 1.7.0
*/
public function __construct(array &$options)
{
// Call the parent constructor.
parent::__construct($options);
// The name of the text file defaults to 'error.php' if not
explicitly given.
if (empty($this->options['text_file']))
{
$this->options['text_file'] = 'error.php';
}
// The name of the text file path defaults to that which is set in
configuration if not explicitly given.
if (empty($this->options['text_file_path']))
{
$this->options['text_file_path'] =
\JFactory::getConfig()->get('log_path');
}
// False to treat the log file as a php file.
if (empty($this->options['text_file_no_php']))
{
$this->options['text_file_no_php'] = false;
}
// Build the full path to the log file.
$this->path = $this->options['text_file_path'] .
'/' . $this->options['text_file'];
// Use the default entry format unless explicitly set otherwise.
if (!empty($this->options['text_entry_format']))
{
$this->format = (string)
$this->options['text_entry_format'];
}
// Wait as long as possible before writing logs
if (!empty($this->options['defer']))
{
$this->defer = (boolean) $this->options['defer'];
}
// Build the fields array based on the format string.
$this->parseFields();
}
/**
* If deferred, write all pending logs.
*
* @since 3.9.0
*/
public function __destruct()
{
// Nothing to do
if (!$this->defer || empty($this->deferredEntries))
{
return;
}
// Initialise the file if not already done.
$this->initFile();
// Format all lines and write to file.
$lines = array_map(array($this, 'formatLine'),
$this->deferredEntries);
if (!\JFile::append($this->path, implode("\n", $lines) .
"\n"))
{
throw new \RuntimeException('Cannot write to log file.');
}
}
/**
* Method to add an entry to the log.
*
* @param LogEntry $entry The log entry object to add to the log.
*
* @return void
*
* @since 1.7.0
* @throws \RuntimeException
*/
public function addEntry(LogEntry $entry)
{
// Store the entry to be written later.
if ($this->defer)
{
$this->deferredEntries[] = $entry;
}
// Write it immediately.
else
{
// Initialise the file if not already done.
$this->initFile();
// Write the new entry to the file.
$line = $this->formatLine($entry);
$line .= "\n";
if (!\JFile::append($this->path, $line))
{
throw new \RuntimeException('Cannot write to log file.');
}
}
}
/**
* Format a line for the log file.
*
* @param JLogEntry $entry The log entry to format as a string.
*
* @return String
*
* @since 3.9.0
*/
protected function formatLine(LogEntry $entry)
{
// Set some default field values if not already set.
if (!isset($entry->clientIP))
{
$ip = IpHelper::getIp();
if ($ip !== '')
{
$entry->clientIP = $ip;
}
}
// If the time field is missing or the date field isn't only the
date we need to rework it.
if ((strlen($entry->date) != 10) || !isset($entry->time))
{
// Get the date and time strings in GMT.
$entry->datetime = $entry->date->toISO8601();
$entry->time = $entry->date->format('H:i:s', false);
$entry->date = $entry->date->format('Y-m-d', false);
}
// Get a list of all the entry keys and make sure they are upper case.
$tmp = array_change_key_case(get_object_vars($entry), CASE_UPPER);
// Decode the entry priority into an English string.
$tmp['PRIORITY'] = $this->priorities[$entry->priority];
// Fill in field data for the line.
$line = $this->format;
foreach ($this->fields as $field)
{
$line = str_replace('{' . $field . '}',
(isset($tmp[$field])) ? $tmp[$field] : '-', $line);
}
return $line;
}
/**
* Method to generate the log file header.
*
* @return string The log file header
*
* @since 1.7.0
*/
protected function generateFileHeader()
{
$head = array();
// Build the log file header.
// If the no php flag is not set add the php die statement.
if (empty($this->options['text_file_no_php']))
{
// Blank line to prevent information disclose:
https://bugs.php.net/bug.php?id=60677
$head[] = '#';
$head[] = '#<?php die(\'Forbidden.\'); ?>';
}
$head[] = '#Date: ' . gmdate('Y-m-d H:i:s') . '
UTC';
$head[] = '#Software: ' . \JPlatform::getLongVersion();
$head[] = '';
// Prepare the fields string
$head[] = '#Fields: ' . strtolower(str_replace('}',
'', str_replace('{', '', $this->format)));
$head[] = '';
return implode("\n", $head);
}
/**
* Method to initialise the log file. This will create the folder path to
the file if it doesn't already
* exist and also get a new file header if the file doesn't already
exist. If the file already exists it
* will simply open it for writing.
*
* @return void
*
* @since 1.7.0
* @throws \RuntimeException
*/
protected function initFile()
{
// We only need to make sure the file exists
if (\JFile::exists($this->path))
{
return;
}
// Make sure the folder exists in which to create the log file.
\JFolder::create(dirname($this->path));
// Build the log file header.
$head = $this->generateFileHeader();
if (!\JFile::write($this->path, $head))
{
throw new \RuntimeException('Cannot write to log file.');
}
}
/**
* Method to parse the format string into an array of fields.
*
* @return void
*
* @since 1.7.0
*/
protected function parseFields()
{
$this->fields = array();
$matches = array();
// Get all of the available fields in the format string.
preg_match_all('/{(.*?)}/i', $this->format, $matches);
// Build the parsed fields list based on the found fields.
foreach ($matches[1] as $match)
{
$this->fields[] = strtoupper($match);
}
}
}
PK�T�[��T��Logger/MessagequeueLogger.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log\Logger;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Log\LogEntry;
use Joomla\CMS\Log\Logger;
/**
* Joomla MessageQueue logger class.
*
* This class is designed to output logs to a specific MySQL database
table. Fields in this
* table are based on the Syslog style of log output. This is designed to
allow quick and
* easy searching.
*
* @since 1.7.0
*/
class MessagequeueLogger extends Logger
{
/**
* Method to add an entry to the log.
*
* @param LogEntry $entry The log entry object to add to the log.
*
* @return void
*
* @since 1.7.0
*/
public function addEntry(LogEntry $entry)
{
switch ($entry->priority)
{
case Log::EMERGENCY:
case Log::ALERT:
case Log::CRITICAL:
case Log::ERROR:
\JFactory::getApplication()->enqueueMessage($entry->message,
'error');
break;
case Log::WARNING:
\JFactory::getApplication()->enqueueMessage($entry->message,
'warning');
break;
case Log::NOTICE:
\JFactory::getApplication()->enqueueMessage($entry->message,
'notice');
break;
case Log::INFO:
\JFactory::getApplication()->enqueueMessage($entry->message,
'message');
break;
default:
// Ignore other priorities.
break;
}
}
}
PK�T�[
�D�&
&
Logger/SyslogLogger.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log\Logger;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Log\LogEntry;
use Joomla\CMS\Log\Logger;
/**
* Joomla! Syslog Log class
*
* This class is designed to call the PHP Syslog function call which is
then sent to the
* system wide log system. For Linux/Unix based systems this is the syslog
subsystem, for
* the Windows based implementations this can be found in the Event Log.
For Windows,
* permissions may prevent PHP from properly outputting messages.
*
* @since 1.7.0
*/
class SyslogLogger extends Logger
{
/**
* Translation array for LogEntry priorities to SysLog priority names.
*
* @var array
* @since 1.7.0
*/
protected $priorities = array(
Log::EMERGENCY => 'EMERG',
Log::ALERT => 'ALERT',
Log::CRITICAL => 'CRIT',
Log::ERROR => 'ERR',
Log::WARNING => 'WARNING',
Log::NOTICE => 'NOTICE',
Log::INFO => 'INFO',
Log::DEBUG => 'DEBUG',
);
/**
* Constructor.
*
* @param array &$options Log object options.
*
* @since 1.7.0
*/
public function __construct(array &$options)
{
// Call the parent constructor.
parent::__construct($options);
// Ensure that we have an identity string for the Syslog entries.
if (empty($this->options['sys_ident']))
{
$this->options['sys_ident'] = 'Joomla Platform';
}
// If the option to add the process id to Syslog entries is set use it,
otherwise default to true.
if (isset($this->options['sys_add_pid']))
{
$this->options['sys_add_pid'] = (bool)
$this->options['sys_add_pid'];
}
else
{
$this->options['sys_add_pid'] = true;
}
// If the option to also send Syslog entries to STDERR is set use it,
otherwise default to false.
if (isset($this->options['sys_use_stderr']))
{
$this->options['sys_use_stderr'] = (bool)
$this->options['sys_use_stderr'];
}
else
{
$this->options['sys_use_stderr'] = false;
}
// Build the Syslog options from our log object options.
$sysOptions = 0;
if ($this->options['sys_add_pid'])
{
$sysOptions = $sysOptions | LOG_PID;
}
if ($this->options['sys_use_stderr'])
{
$sysOptions = $sysOptions | LOG_PERROR;
}
// Default logging facility is LOG_USER for Windows compatibility.
$sysFacility = LOG_USER;
// If we have a facility passed in and we're not on Windows, reset
it.
if (isset($this->options['sys_facility']) &&
!IS_WIN)
{
$sysFacility = $this->options['sys_facility'];
}
// Open the Syslog connection.
openlog((string) $this->options['sys_ident'], $sysOptions,
$sysFacility);
}
/**
* Destructor.
*
* @since 1.7.0
*/
public function __destruct()
{
closelog();
}
/**
* Method to add an entry to the log.
*
* @param LogEntry $entry The log entry object to add to the log.
*
* @return void
*
* @since 1.7.0
*/
public function addEntry(LogEntry $entry)
{
// Generate the value for the priority based on predefined constants.
$priority = constant(strtoupper('LOG_' .
$this->priorities[$entry->priority]));
// Send the entry to Syslog.
syslog($priority, '[' . $entry->category . '] ' .
$entry->message);
}
}
PK�T�[��6��Logger/W3cLogger.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log\Logger;
defined('JPATH_PLATFORM') or die;
/**
* Joomla! W3C Logging class
*
* This class is designed to build log files based on the W3C
specification.
*
* @link https://www.w3.org/TR/WD-logfile.html
* @since 1.7.0
*/
class W3cLogger extends FormattedtextLogger
{
/**
* The format which each entry follows in the log file.
*
* All fields must be named in all caps and be within curly brackets eg.
{FOOBAR}.
*
* @var string
* @since 1.7.0
*/
protected $format =
'{DATE} {TIME} {PRIORITY} {CLIENTIP} {CATEGORY} {MESSAGE}';
/**
* Constructor.
*
* @param array &$options Log object options.
*
* @since 1.7.0
*/
public function __construct(array &$options)
{
// The name of the text file defaults to 'error.w3c.php' if not
explicitly given.
if (empty($options['text_file']))
{
$options['text_file'] = 'error.w3c.php';
}
// Call the parent constructor.
parent::__construct($options);
}
}
PK�T�[tǥ��
Logger.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Log;
defined('JPATH_PLATFORM') or die;
/**
* Joomla! Logger Base Class
*
* This class is used to be the basis of logger classes to allow for
defined functions
* to exist regardless of the child class.
*
* @since 3.0.1
*/
abstract class Logger
{
/**
* Options array for the JLog instance.
*
* @var array
* @since 3.0.1
*/
protected $options = array();
/**
* Translation array for LogEntry priorities to text strings.
*
* @var array
* @since 3.0.1
*/
protected $priorities = array(
Log::EMERGENCY => 'EMERGENCY',
Log::ALERT => 'ALERT',
Log::CRITICAL => 'CRITICAL',
Log::ERROR => 'ERROR',
Log::WARNING => 'WARNING',
Log::NOTICE => 'NOTICE',
Log::INFO => 'INFO',
Log::DEBUG => 'DEBUG',
);
/**
* Constructor.
*
* @param array &$options Log object options.
*
* @since 3.0.1
*/
public function __construct(array &$options)
{
// Set the options for the class.
$this->options = & $options;
}
/**
* Method to add an entry to the log.
*
* @param LogEntry $entry The log entry object to add to the log.
*
* @return void
*
* @since 3.0.1
* @throws \RuntimeException
*/
abstract public function addEntry(LogEntry $entry);
}
PK��[HTg��Test/DummyTest.phpnu�[���<?php
namespace Psr\Log\Test;
/**
* This class is internal and does not follow the BC promise.
*
* Do NOT use this class in any way.
*
* @internal
*/
class DummyTest
{
public function __toString()
{
return 'DummyTest';
}
}
PK��[I\�))Test/LoggerInterfaceTest.phpnu�[���<?php
namespace Psr\Log\Test;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use PHPUnit\Framework\TestCase;
/**
* Provides a base test class for ensuring compliance with the
LoggerInterface.
*
* Implementors can extend the class and implement abstract methods to run
this
* as part of their test suite.
*/
abstract class LoggerInterfaceTest extends TestCase
{
/**
* @return LoggerInterface
*/
abstract public function getLogger();
/**
* This must return the log messages in order.
*
* The simple formatting of the messages is: "<LOG LEVEL>
<MESSAGE>".
*
* Example ->error('Foo') would yield "error
Foo".
*
* @return string[]
*/
abstract public function getLogs();
public function testImplements()
{
$this->assertInstanceOf('Psr\Log\LoggerInterface',
$this->getLogger());
}
/**
* @dataProvider provideLevelsAndMessages
*/
public function testLogsAtAllLevels($level, $message)
{
$logger = $this->getLogger();
$logger->{$level}($message, array('user' =>
'Bob'));
$logger->log($level, $message, array('user' =>
'Bob'));
$expected = array(
$level.' message of level '.$level.' with
context: Bob',
$level.' message of level '.$level.' with
context: Bob',
);
$this->assertEquals($expected, $this->getLogs());
}
public function provideLevelsAndMessages()
{
return array(
LogLevel::EMERGENCY => array(LogLevel::EMERGENCY,
'message of level emergency with context: {user}'),
LogLevel::ALERT => array(LogLevel::ALERT, 'message of
level alert with context: {user}'),
LogLevel::CRITICAL => array(LogLevel::CRITICAL,
'message of level critical with context: {user}'),
LogLevel::ERROR => array(LogLevel::ERROR, 'message of
level error with context: {user}'),
LogLevel::WARNING => array(LogLevel::WARNING, 'message
of level warning with context: {user}'),
LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of
level notice with context: {user}'),
LogLevel::INFO => array(LogLevel::INFO, 'message of
level info with context: {user}'),
LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of
level debug with context: {user}'),
);
}
/**
* @expectedException \Psr\Log\InvalidArgumentException
*/
public function testThrowsOnInvalidLevel()
{
$logger = $this->getLogger();
$logger->log('invalid level', 'Foo');
}
public function testContextReplacement()
{
$logger = $this->getLogger();
$logger->info('{Message {nothing} {user} {foo.bar}
a}', array('user' => 'Bob', 'foo.bar'
=> 'Bar'));
$expected = array('info {Message {nothing} Bob Bar a}');
$this->assertEquals($expected, $this->getLogs());
}
public function testObjectCastToString()
{
if (method_exists($this, 'createPartialMock')) {
$dummy =
$this->createPartialMock('Psr\Log\Test\DummyTest',
array('__toString'));
} else {
$dummy = $this->getMock('Psr\Log\Test\DummyTest',
array('__toString'));
}
$dummy->expects($this->once())
->method('__toString')
->will($this->returnValue('DUMMY'));
$this->getLogger()->warning($dummy);
$expected = array('warning DUMMY');
$this->assertEquals($expected, $this->getLogs());
}
public function testContextCanContainAnything()
{
$closed = fopen('php://memory', 'r');
fclose($closed);
$context = array(
'bool' => true,
'null' => null,
'string' => 'Foo',
'int' => 0,
'float' => 0.5,
'nested' => array('with object' =>
new DummyTest),
'object' => new \DateTime,
'resource' => fopen('php://memory',
'r'),
'closed' => $closed,
);
$this->getLogger()->warning('Crazy context data',
$context);
$expected = array('warning Crazy context data');
$this->assertEquals($expected, $this->getLogs());
}
public function testContextExceptionKeyCanBeExceptionOrOtherValues()
{
$logger = $this->getLogger();
$logger->warning('Random message',
array('exception' => 'oops'));
$logger->critical('Uncaught Exception!',
array('exception' => new \LogicException('Fail')));
$expected = array(
'warning Random message',
'critical Uncaught Exception!'
);
$this->assertEquals($expected, $this->getLogs());
}
}
PK��[� ���Test/TestLogger.phpnu�[���<?php
namespace Psr\Log\Test;
use Psr\Log\AbstractLogger;
/**
* Used for testing purposes.
*
* It records all records and gives you access to them for verification.
*
* @method bool hasEmergency($record)
* @method bool hasAlert($record)
* @method bool hasCritical($record)
* @method bool hasError($record)
* @method bool hasWarning($record)
* @method bool hasNotice($record)
* @method bool hasInfo($record)
* @method bool hasDebug($record)
*
* @method bool hasEmergencyRecords()
* @method bool hasAlertRecords()
* @method bool hasCriticalRecords()
* @method bool hasErrorRecords()
* @method bool hasWarningRecords()
* @method bool hasNoticeRecords()
* @method bool hasInfoRecords()
* @method bool hasDebugRecords()
*
* @method bool hasEmergencyThatContains($message)
* @method bool hasAlertThatContains($message)
* @method bool hasCriticalThatContains($message)
* @method bool hasErrorThatContains($message)
* @method bool hasWarningThatContains($message)
* @method bool hasNoticeThatContains($message)
* @method bool hasInfoThatContains($message)
* @method bool hasDebugThatContains($message)
*
* @method bool hasEmergencyThatMatches($message)
* @method bool hasAlertThatMatches($message)
* @method bool hasCriticalThatMatches($message)
* @method bool hasErrorThatMatches($message)
* @method bool hasWarningThatMatches($message)
* @method bool hasNoticeThatMatches($message)
* @method bool hasInfoThatMatches($message)
* @method bool hasDebugThatMatches($message)
*
* @method bool hasEmergencyThatPasses($message)
* @method bool hasAlertThatPasses($message)
* @method bool hasCriticalThatPasses($message)
* @method bool hasErrorThatPasses($message)
* @method bool hasWarningThatPasses($message)
* @method bool hasNoticeThatPasses($message)
* @method bool hasInfoThatPasses($message)
* @method bool hasDebugThatPasses($message)
*/
class TestLogger extends AbstractLogger
{
/**
* @var array
*/
public $records = [];
public $recordsByLevel = [];
/**
* @inheritdoc
*/
public function log($level, $message, array $context = [])
{
$record = [
'level' => $level,
'message' => $message,
'context' => $context,
];
$this->recordsByLevel[$record['level']][] = $record;
$this->records[] = $record;
}
public function hasRecords($level)
{
return isset($this->recordsByLevel[$level]);
}
public function hasRecord($record, $level)
{
if (is_string($record)) {
$record = ['message' => $record];
}
return $this->hasRecordThatPasses(function ($rec) use ($record)
{
if ($rec['message'] !== $record['message'])
{
return false;
}
if (isset($record['context']) &&
$rec['context'] !== $record['context']) {
return false;
}
return true;
}, $level);
}
public function hasRecordThatContains($message, $level)
{
return $this->hasRecordThatPasses(function ($rec) use ($message)
{
return strpos($rec['message'], $message) !== false;
}, $level);
}
public function hasRecordThatMatches($regex, $level)
{
return $this->hasRecordThatPasses(function ($rec) use ($regex) {
return preg_match($regex, $rec['message']) > 0;
}, $level);
}
public function hasRecordThatPasses(callable $predicate, $level)
{
if (!isset($this->recordsByLevel[$level])) {
return false;
}
foreach ($this->recordsByLevel[$level] as $i => $rec) {
if (call_user_func($predicate, $rec, $i)) {
return true;
}
}
return false;
}
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 = strtolower($matches[2]);
if (method_exists($this, $genericMethod)) {
$args[] = $level;
return call_user_func_array([$this, $genericMethod],
$args);
}
}
throw new \BadMethodCallException('Call to undefined method
' . get_class($this) . '::' . $method . '()');
}
public function reset()
{
$this->records = [];
$this->recordsByLevel = [];
}
}
PKe�[�GlAbstractLogger.phpnu�[���PKe�[
�X1``RInvalidArgumentException.phpnu�[���PKe�[�j�))�LoggerAwareInterface.phpnu�[���PKe�[z%���oLoggerAwareTrait.phpnu�[���PKe�[1b!q**@LoggerInterface.phpnu�[���PKe�[�W�jW
W
�LoggerTrait.phpnu�[���PKe�[��PPC*LogLevel.phpnu�[���PKe�[���I���+NullLogger.phpnu�[���PK�T�[����
�
�.DelegatingPsrLogger.phpnu�[���PK�T�[F�`?�$�$�9Log.phpnu�[���PK�T�[�*v>k
k
�^LogEntry.phpnu�[���PK�T�[�v�SSxiLogger/CallbackLogger.phpnu�[���PK�T�[.W����pLogger/DatabaseLogger.phpnu�[���PK�T�[pU5��Logger/EchoLogger.phpnu�[���PK�T�[�7��]]\�Logger/FormattedtextLogger.phpnu�[���PK�T�[��T���Logger/MessagequeueLogger.phpnu�[���PK�T�[
�D�&
&
'�Logger/SyslogLogger.phpnu�[���PK�T�[��6����Logger/W3cLogger.phpnu�[���PK�T�[tǥ��
��Logger.phpnu�[���PK��[HTg����Test/DummyTest.phpnu�[���PK��[I\�))��Test/LoggerInterfaceTest.phpnu�[���PK��[�
���F�Test/TestLogger.phpnu�[���PK88�