This commit is contained in:
Markus
2022-04-28 09:40:10 +02:00
commit 795794f992
9586 changed files with 1146991 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Log\Handlers;
/**
* Base class for logging
*/
abstract class BaseHandler implements HandlerInterface
{
/**
* Handles
*
* @var array
*/
protected $handles;
/**
* Date format for logging
*
* @var string
*/
protected $dateFormat = 'Y-m-d H:i:s';
/**
* Constructor
*/
public function __construct(array $config)
{
$this->handles = $config['handles'] ?? [];
}
/**
* Checks whether the Handler will handle logging items of this
* log Level.
*/
public function canHandle(string $level): bool
{
return in_array($level, $this->handles, true);
}
/**
* Handles logging the message.
* If the handler returns false, then execution of handlers
* will stop. Any handlers that have not run, yet, will not
* be run.
*
* @param string $level
* @param string $message
*/
abstract public function handle($level, $message): bool;
/**
* Stores the date format to use while logging messages.
*/
public function setDateFormat(string $format): HandlerInterface
{
$this->dateFormat = $format;
return $this;
}
}

View File

@@ -0,0 +1,164 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Log\Handlers;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
/**
* Class ChromeLoggerHandler
*
* Allows for logging items to the Chrome console for debugging.
* Requires the ChromeLogger extension installed in your browser.
*
* @see https://craig.is/writing/chrome-logger
*/
class ChromeLoggerHandler extends BaseHandler
{
/**
* Version of this library - for ChromeLogger use.
*/
public const VERSION = 1.0;
/**
* The number of track frames returned from the backtrace.
*
* @var int
*/
protected $backtraceLevel = 0;
/**
* The final data that is sent to the browser.
*
* @var array
*/
protected $json = [
'version' => self::VERSION,
'columns' => [
'log',
'backtrace',
'type',
],
'rows' => [],
];
/**
* The header used to pass the data.
*
* @var string
*/
protected $header = 'X-ChromeLogger-Data';
/**
* Maps the log levels to the ChromeLogger types.
*
* @var array
*/
protected $levels = [
'emergency' => 'error',
'alert' => 'error',
'critical' => 'error',
'error' => 'error',
'warning' => 'warn',
'notice' => 'warn',
'info' => 'info',
'debug' => 'info',
];
/**
* Constructor
*/
public function __construct(array $config = [])
{
parent::__construct($config);
$this->json['request_uri'] = current_url();
}
/**
* Handles logging the message.
* If the handler returns false, then execution of handlers
* will stop. Any handlers that have not run, yet, will not
* be run.
*
* @param string $level
* @param string $message
*/
public function handle($level, $message): bool
{
// Format our message
$message = $this->format($message);
// Generate Backtrace info
$backtrace = debug_backtrace(0, $this->backtraceLevel);
$backtrace = end($backtrace);
$backtraceMessage = 'unknown';
if (isset($backtrace['file'], $backtrace['line'])) {
$backtraceMessage = $backtrace['file'] . ':' . $backtrace['line'];
}
// Default to 'log' type.
$type = '';
if (array_key_exists($level, $this->levels)) {
$type = $this->levels[$level];
}
$this->json['rows'][] = [
[$message],
$backtraceMessage,
$type,
];
$this->sendLogs();
return true;
}
/**
* Converts the object to display nicely in the Chrome Logger UI.
*
* @param mixed $object
*
* @return array
*/
protected function format($object)
{
if (! is_object($object)) {
return $object;
}
// @todo Modify formatting of objects once we can view them in browser.
$objectArray = (array) $object;
$objectArray['___class_name'] = get_class($object);
return $objectArray;
}
/**
* Attaches the header and the content to the passed in request object.
*
* @param ResponseInterface $response
*/
public function sendLogs(?ResponseInterface &$response = null)
{
if ($response === null) {
$response = Services::response(null, true);
}
$data = base64_encode(utf8_encode(json_encode($this->json)));
$response->setHeader($this->header, $data);
}
}

View File

@@ -0,0 +1,84 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Log\Handlers;
use CodeIgniter\Log\Exceptions\LogException;
/**
* Log handler that writes to PHP's `error_log()`
*/
class ErrorlogHandler extends BaseHandler
{
/**
* Message is sent to PHP's system logger, using the Operating System's
* system logging mechanism or a file, depending on what the error_log
* configuration directive is set to.
*/
public const TYPE_OS = 0;
/**
* Message is sent directly to the SAPI logging handler.
*/
public const TYPE_SAPI = 4;
/**
* Says where the error should go. Currently supported are
* 0 (`TYPE_OS`) and 4 (`TYPE_SAPI`).
*
* @var int
*/
protected $messageType = 0;
/**
* Constructor.
*
* @param mixed[] $config
*/
public function __construct(array $config = [])
{
parent::__construct($config);
$messageType = $config['messageType'] ?? self::TYPE_OS;
if (! is_int($messageType) || ! in_array($messageType, [self::TYPE_OS, self::TYPE_SAPI], true)) {
throw LogException::forInvalidMessageType(print_r($messageType, true));
}
$this->messageType = $messageType;
}
/**
* Handles logging the message.
* If the handler returns false, then execution of handlers
* will stop. Any handlers that have not run, yet, will not
* be run.
*
* @param string $level
* @param string $message
*/
public function handle($level, $message): bool
{
$message = strtoupper($level) . ' --> ' . $message . "\n";
return $this->errorLog($message, $this->messageType);
}
/**
* Extracted call to `error_log()` in order to be tested.
*
* @codeCoverageIgnore
*/
protected function errorLog(string $message, int $messageType): bool
{
return error_log($message, $messageType);
}
}

View File

@@ -0,0 +1,122 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Log\Handlers;
use DateTime;
use Exception;
/**
* Log error messages to file system
*/
class FileHandler extends BaseHandler
{
/**
* Folder to hold logs
*
* @var string
*/
protected $path;
/**
* Extension to use for log files
*
* @var string
*/
protected $fileExtension;
/**
* Permissions for new log files
*
* @var int
*/
protected $filePermissions;
/**
* Constructor
*/
public function __construct(array $config = [])
{
parent::__construct($config);
$this->path = empty($config['path']) ? WRITEPATH . 'logs/' : $config['path'];
$this->fileExtension = empty($config['fileExtension']) ? 'log' : $config['fileExtension'];
$this->fileExtension = ltrim($this->fileExtension, '.');
$this->filePermissions = $config['filePermissions'] ?? 0644;
}
/**
* Handles logging the message.
* If the handler returns false, then execution of handlers
* will stop. Any handlers that have not run, yet, will not
* be run.
*
* @param string $level
* @param string $message
*
* @throws Exception
*/
public function handle($level, $message): bool
{
$filepath = $this->path . 'log-' . date('Y-m-d') . '.' . $this->fileExtension;
$msg = '';
if (! is_file($filepath)) {
$newfile = true;
// Only add protection to php files
if ($this->fileExtension === 'php') {
$msg .= "<?php defined('SYSTEMPATH') || exit('No direct script access allowed'); ?>\n\n";
}
}
if (! $fp = @fopen($filepath, 'ab')) {
return false;
}
// Instantiating DateTime with microseconds appended to initial date is needed for proper support of this format
if (strpos($this->dateFormat, 'u') !== false) {
$microtimeFull = microtime(true);
$microtimeShort = sprintf('%06d', ($microtimeFull - floor($microtimeFull)) * 1000000);
$date = new DateTime(date('Y-m-d H:i:s.' . $microtimeShort, (int) $microtimeFull));
$date = $date->format($this->dateFormat);
} else {
$date = date($this->dateFormat);
}
$msg .= strtoupper($level) . ' - ' . $date . ' --> ' . $message . "\n";
flock($fp, LOCK_EX);
$result = null;
for ($written = 0, $length = strlen($msg); $written < $length; $written += $result) {
if (($result = fwrite($fp, substr($msg, $written))) === false) {
// if we get this far, we'll never see this during travis-ci
// @codeCoverageIgnoreStart
break;
// @codeCoverageIgnoreEnd
}
}
flock($fp, LOCK_UN);
fclose($fp);
if (isset($newfile) && $newfile === true) {
chmod($filepath, $this->filePermissions);
}
return is_int($result);
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Log\Handlers;
/**
* Expected behavior for a Log handler
*/
interface HandlerInterface
{
/**
* Handles logging the message.
* If the handler returns false, then execution of handlers
* will stop. Any handlers that have not run, yet, will not
* be run.
*
* @param string $level
* @param string $message
*/
public function handle($level, $message): bool;
/**
* Checks whether the Handler will handle logging items of this
* log Level.
*/
public function canHandle(string $level): bool;
/**
* Sets the preferred date format to use when logging.
*
* @return HandlerInterface
*/
public function setDateFormat(string $format);
}