Logging class major change, Debug\Support update

old Debug\Logging is in Debug\LoggingLegacy and Debug\Logging extends
Logging\Logging

Logging\Logging is a new class with most of the functionality except
there is no more print/outout to screen, but we use the default log
levels (RFC5424)
The plan is to be a frontend between the old type class and
Monolog\Monolog

Updated all other classes to use new class interface
This commit is contained in:
Clemens Schwaighofer
2023-05-30 18:12:24 +09:00
parent 7b5ad92e66
commit b0a8783276
75 changed files with 4292 additions and 2019 deletions

View File

@@ -204,7 +204,7 @@ class Login
'path' => '',
];
/** @var \CoreLibs\Debug\Logging logger */
/** @var \CoreLibs\Logging\Logging logger */
public $log;
/** @var \CoreLibs\DB\IO database */
public $db;
@@ -218,21 +218,21 @@ class Login
* finishes itself
*
* @param \CoreLibs\DB\IO $db Database connection class
* @param \CoreLibs\Debug\Logging $log Logging class
* @param \CoreLibs\Logging\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class
* @param array<string,mixed> $options Login ACL settings
* $auto_login [default true] DEPRECATED, moved into options
*/
public function __construct(
\CoreLibs\DB\IO $db,
\CoreLibs\Debug\Logging $log,
\CoreLibs\Logging\Logging $log,
\CoreLibs\Create\Session $session,
array $options = []
) {
// attach db class
$this->db = $db;
// log login data for this class only
$log->setLogPer('class', true);
$log->setLogFlag(\CoreLibs\Logging\Logger\Flag::per_class);
// attach logger
$this->log = $log;
// attach session class
@@ -1179,6 +1179,12 @@ class Login
$this->acl['page'] = $_SESSION['PAGES_ACL_LEVEL'][$this->page_name];
}
$this->acl['unit_id'] = null;
$this->acl['unit_name'] = null;
$this->acl['unit_uid'] = null;
$this->acl['unit'] = [];
$this->acl['unit_detail'] = [];
// PER ACCOUNT (UNIT/edit access)->
foreach ($_SESSION['UNIT'] as $ea_id => $unit) {
// if admin flag is set, all units are set to 100
@@ -1911,21 +1917,6 @@ HTML;
// echo $this->login_html;
$this->loginPrintLogin();
}
// do not go anywhere, quit processing here
// do something with possible debug data?
if (
in_array($this->options['target'], ['live', 'remove'])
) {
// login
$this->log->setLogLevelAll('debug', $this->options['debug']);
$this->log->setLogLevelAll('echo', false);
$this->log->setLogLevelAll('print', $this->options['debug']);
}
$status_msg = $this->log->printErrorMsg();
// if ($this->echo_output_all) {
if ($this->log->getLogLevelAll('echo')) {
echo $status_msg;
}
// exit so we don't process anything further, at all
$this->loginTerminate(3000);
} else {

View File

@@ -95,7 +95,7 @@ class Backend
public $domain;
/** @var string */
public $encoding;
/** @var \CoreLibs\Debug\Logging logger */
/** @var \CoreLibs\Logging\Logging logger */
public $log;
/** @var \CoreLibs\DB\IO database */
public $db;
@@ -118,14 +118,14 @@ class Backend
* main class constructor
*
* @param \CoreLibs\DB\IO $db Database connection class
* @param \CoreLibs\Debug\Logging $log Logging class
* @param \CoreLibs\Logging\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class
* @param \CoreLibs\Language\L10n $l10n l10n language class
* @param int|null $set_default_acl_level Default ACL level
*/
public function __construct(
\CoreLibs\DB\IO $db,
\CoreLibs\Debug\Logging $log,
\CoreLibs\Logging\Logging $log,
\CoreLibs\Create\Session $session,
\CoreLibs\Language\L10n $l10n,
?int $set_default_acl_level = null
@@ -133,7 +133,7 @@ class Backend
// attach db class
$this->db = $db;
// set to log not per class
$log->setLogPer('class', false);
$log->unsetLogFlag(\CoreLibs\Logging\Logger\Flag::per_class);
// attach logger
$this->log = $log;
// attach session class

View File

@@ -33,7 +33,7 @@ class EditBase
private $smarty;
/** @var \CoreLibs\Output\Form\Generate form generate system */
private $form;
/** @var \CoreLibs\Debug\Logging */
/** @var \CoreLibs\Logging\Logging */
public $log;
/** @var \CoreLibs\ACL\Login */
public $login;
@@ -42,14 +42,14 @@ class EditBase
* construct form generator
*
* @param array<mixed> $db_config db config array, mandatory
* @param \CoreLibs\Debug\Logging $log Logging class, null auto set
* @param \CoreLibs\Logging\Logging $log Logging class, null auto set
* @param \CoreLibs\Language\L10n $l10n l10n language class, null auto set
* @param \CoreLibs\ACL\Login $login login class for ACL settings
* @param array<string,mixed> $options Various settings options
*/
public function __construct(
array $db_config,
\CoreLibs\Debug\Logging $log,
\CoreLibs\Logging\Logging $log,
\CoreLibs\Language\L10n $l10n,
\CoreLibs\ACL\Login $login,
array $options
@@ -63,7 +63,7 @@ class EditBase
$options['compile_id'] ?? '',
);
// turn off set log per class
$log->setLogPer('class', false);
$log->unsetLogFlag(\CoreLibs\Logging\Logger\Flag::per_class);
// create form class
$this->form = new \CoreLibs\Output\Form\Generate(

View File

@@ -64,7 +64,7 @@ class Basic
/** @var int */
public $host_port;
// logging interface, Debug\Logging class
/** @var \CoreLibs\Debug\Logging */
/** @var \CoreLibs\Logging\Logging */
public $log;
/** @var \CoreLibs\Create\Session */
public $session;
@@ -85,12 +85,12 @@ class Basic
/**
* main Basic constructor to init and check base settings
* @param \CoreLibs\Debug\Logging|null $log Logging class
* @param \CoreLibs\Logging\Logging|null $log Logging class
* @param string|null $session_name Set session name
* @deprecated DO NOT USE Class\Basic anymore. Use dedicated logger and sub classes
*/
public function __construct(
\CoreLibs\Debug\Logging $log = null,
\CoreLibs\Logging\Logging $log = null,
?string $session_name = null
) {
trigger_error('Class \CoreLibs\Basic is deprected', E_USER_DEPRECATED);
@@ -120,7 +120,10 @@ class Basic
}
// logging interface moved here (->debug is now ->log->debug)
$this->log = $log ?? new \CoreLibs\Debug\Logging();
$this->log = $log ?? new \CoreLibs\Logging\Logging([
'log_folder' => BASE . LOG,
'log_file_id' => 'ClassBasic-DEPRECATED',
]);
// set ajax page flag based on the AJAX_PAGE varaibles
// convert to true/false so if AJAX_PAGE is 0 or false it is
@@ -176,8 +179,9 @@ class Basic
*/
public function basicSetLogId(string $string): string
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use $basic->log->basicSetLogId() or use \CoreLibs\Debug\Logging() class', E_USER_DEPRECATED);
return $this->log->setLogId($string);
trigger_error('Method ' . __METHOD__ . ' is deprecated, use log->setLogId() or use \CoreLibs\Logging\Logging() class', E_USER_DEPRECATED);
$this->log->setLogFileId($string);
return $this->log->getLogFileId();
}
// ****** DEBUG/ERROR FUNCTIONS ******
@@ -252,7 +256,7 @@ class Basic
}
// ****** DEBUG LOGGING FUNCTIONS ******
// Moved to \CoreLibs\Debug\Logging
// Moved to \CoreLibs\Logging\Logging
/**
* passes list of level names, to turn on debug
@@ -265,68 +269,9 @@ class Basic
*/
public function debugFor(string $type, string $flag): void
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use $basic->log->debugFor() or use \CoreLibs\Debug\Logging() class', E_USER_DEPRECATED);
/** @phan-suppress-next-line PhanTypeMismatchArgumentReal, PhanParamTooFew @phpstan-ignore-next-line */
$this->log->setLogLevel(...[func_get_args()]);
trigger_error('Method ' . __METHOD__ . ' functionaility is fully deprecated', E_USER_DEPRECATED);
}
/**
* checks if we have a need to work on certain debug output
* Needs debug/echo/print ad target for which of the debug flag groups we check
* also needs level string to check in the per level output flag check.
* In case we have invalid target it will return false
* @param string $target target group to check debug/echo/print
* @param string $level level to check in detailed level flag
* @return bool true on access allowed or false on no access
*/
/* private function doDebugTrigger(string $target, string $level): bool
{
$access = false;
// check if we do debug, echo or print
switch ($target) {
case 'debug':
if ((
(isset($this->debug_output[$level]) && $this->debug_output[$level]) ||
$this->debug_output_all
) &&
(!isset($this->debug_output_not[$level]) ||
(isset($this->debug_output_not[$level]) && !$this->debug_output_not[$level])
)
) {
$access = true;
}
break;
case 'echo':
if ((
(isset($this->echo_output[$level]) && $this->echo_output[$level]) ||
$this->echo_output_all
) &&
(!isset($this->echo_output_not[$level]) ||
(isset($this->echo_output_not[$level]) && !$this->echo_output_not[$level])
)
) {
$access = true;
}
break;
case 'print':
if ((
(isset($this->print_output[$level]) && $this->print_output[$level]) ||
$this->print_output_all
) &&
(!isset($this->print_output_not[$level]) ||
(isset($this->print_output_not[$level]) && !$this->print_output_not[$level])
)
) {
$access = true;
}
break;
default:
// fall through with access false
break;
}
return $access;
} */
/**
* write debug data to error_msg array
* @param string $level id for error message, groups messages together
@@ -335,11 +280,12 @@ class Basic
* all html tags will be stripped and <br> changed to \n
* this is only used for debug output
* @return void has no return
* @deprecated Use $basic->log->debug() instead
* @deprecated Use Logger\Logger->debug() instead
*/
public function debug(string $level, string $string, bool $strip = false): void
{
$this->log->debug($level, $string, $strip);
trigger_error('Method ' . __METHOD__ . ' has moved to Logger\Logger->debug()', E_USER_DEPRECATED);
$this->log->debug($level, $string);
}
/**
@@ -351,8 +297,7 @@ class Basic
*/
public function mergeErrors(array $error_msg = []): void
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use $basic->log->mergeErrors() or use \CoreLibs\Debug\Logging() class', E_USER_DEPRECATED);
$this->log->mergeErrors($error_msg);
trigger_error('Method ' . __METHOD__ . ' is fully deprecated', E_USER_DEPRECATED);
}
/**
@@ -363,7 +308,8 @@ class Basic
*/
public function printErrorMsg(string $string = ''): string
{
return $this->log->printErrorMsg($string);
trigger_error('Method ' . __METHOD__ . ' is fully deprecated', E_USER_DEPRECATED);
return '';
}
/**
@@ -376,8 +322,7 @@ class Basic
*/
public function resetErrorMsg(string $level = ''): void
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use $basic->log->resetErrorMsg() or use \CoreLibs\Debug\Logging() class', E_USER_DEPRECATED);
$this->log->resetErrorMsg($level);
trigger_error('Method ' . __METHOD__ . ' is fully deprecated', E_USER_DEPRECATED);
}
// ****** DEBUG SUPPORT FUNCTIONS ******
@@ -388,11 +333,11 @@ class Basic
* prints a html formatted (pre) array
* @param array<mixed> $array any array
* @return string formatted array for output with <pre> tag added
* @deprecated Use $this->log->prAr() instead
* @deprecated Use \CoreLibs\Debug\Support::prAr() instead
*/
public function printAr(array $array): string
{
return $this->log->prAr($array);
return \CoreLibs\Debug\Support::prAr($array);
}
/**

View File

@@ -137,7 +137,7 @@ class Email
* @param bool $kv_folding If set to true and a valid encoding,
* do KV folding
* @param bool $test test flag, default off
* @param \CoreLibs\Debug\Logging|null $log Logging class,
* @param \CoreLibs\Logging\Logging|null $log Logging class,
* only used if test flag is true
* @return int 2 test only, no sent
* 1 for ok,
@@ -156,7 +156,7 @@ class Email
string $encoding = 'UTF-8',
bool $kv_folding = false,
bool $test = false,
?\CoreLibs\Debug\Logging $log = null
?\CoreLibs\Logging\Logging $log = null
): int {
/** @var array<string> */
$to_emails = [];
@@ -259,11 +259,11 @@ class Email
$mail_delivery_status = 2;
}
// log if an log instance exists
if ($log instanceof \CoreLibs\Debug\Logging) {
if ($log instanceof \CoreLibs\Logging\Logging) {
// build debug strings: convert to UTF-8 if not utf-8
$log->debug('SEND EMAIL', 'HEADERS: ' . $log->prAr($headers) . ', '
$log->debug('SEND EMAIL', 'HEADERS: ' . \CoreLibs\Debug\Support::prAr($headers) . ', '
. 'ENCODING: ' . $encoding . ', '
. 'KV FOLDING: ' . $log->prBl($kv_folding) . ', '
. 'KV FOLDING: ' . \CoreLibs\Debug\Support::prBl($kv_folding) . ', '
. 'TO: ' . $to_email . ', '
. 'SUBJECT: ' . $out_subject . ', '
. 'BODY: ' . ($encoding == 'UTF-8' ?

View File

@@ -57,7 +57,7 @@ class ArrayIO extends \CoreLibs\DB\IO
* @param array<mixed> $db_config db connection config
* @param array<mixed> $table_array table array config
* @param string $table_name table name string
* @param \CoreLibs\Debug\Logging $log Logging class
* @param \CoreLibs\Logging\Logging $log Logging class
* @param int $base_acl_level Set base acl level, if needed
* @param int $acl_admin Flag if this is an admin ACL access level
*/
@@ -65,7 +65,7 @@ class ArrayIO extends \CoreLibs\DB\IO
array $db_config,
array $table_array,
string $table_name,
\CoreLibs\Debug\Logging $log,
\CoreLibs\Logging\Logging $log,
int $base_acl_level = 0,
int $acl_admin = 0
) {

View File

@@ -391,18 +391,18 @@ class IO
/** @var string */
private $async_running;
// logging class, must be public so settings can be changed
/** @var \CoreLibs\Debug\Logging */
/** @var \CoreLibs\Logging\Logging */
public $log;
/**
* main DB concstructor with auto connection to DB and failure set on failed connection
* @param array<mixed> $db_config DB configuration array
* @param \CoreLibs\Debug\Logging $log Logging class
* @param \CoreLibs\Logging\Logging $log Logging class
* @param bool|null $db_debug_override Overrides debug settings in db_config
*/
public function __construct(
array $db_config,
\CoreLibs\Debug\Logging $log,
\CoreLibs\Logging\Logging $log,
?bool $db_debug_override = null
) {
// attach logger
@@ -703,10 +703,10 @@ class IO
}
if ($error_data !== []) {
$error_string .= '<br>['
. $this->log->prAr($error_data)
. \CoreLibs\Debug\Support::prAr($error_data)
. ']';
}
$this->log->debug($debug_id, $error_string, true, $prefix);
$this->log->debug($debug_id, $error_string, $prefix);
}
/**
@@ -2737,7 +2737,7 @@ class IO
if ($result === false) {
$this->log->debug('ExecuteData', 'ERROR in STM[' . $stm_name . '|'
. $this->prepare_cursor[$stm_name]['result'] . ']: '
. $this->log->prAr($data));
. \CoreLibs\Debug\Support::prAr($data));
$this->__dbError(
22,
$this->prepare_cursor[$stm_name]['result'],

View File

@@ -1,895 +1,26 @@
<?php
/*
* Debug support functions
*
* These are if there is any debug to print out at all at the end
 * debug_output_all - general yes no
 * It's recommended to use the method "debug_for" to turn on of the array vars
 * debug_output - turn on for one level (Array)
 * debug_output_not - turn off for one level (array)
 *
 * Print out the debug at thend of the html
 * echo_output_all
 * echo_output
 * echo_output_not
 *
 * Write debug to file
 * print_output_all
 * print_output
 * print_output_not
* This is a wrapper placeholder for
* \CoreLibs\Logging\Logger
*/
declare(strict_types=1);
namespace CoreLibs\Debug;
use CoreLibs\Debug\Support;
use CoreLibs\Create\Uids;
use CoreLibs\Get\System;
use CoreLibs\Convert\Html;
class Logging
/**
* @deprecated Use \CoreLibs\Logger\Logging
*/
class Logging extends \CoreLibs\Logging\Logging
{
// options
/** @var array<mixed> */
private $options = [];
// page and host name
/** @var string */
private $page_name;
/** @var string */
private $host_name;
/** @var int */
private $host_port;
// internal error reporting vars
/** @var array<mixed> */
private $error_msg = []; // the "connection" to the outside errors
// debug output prefix
/** @var string */
private $error_msg_prefix = ''; // prefix to the error string (the class name)
// debug flags
/** @var array<mixed> */
private $debug_output = []; // if this is true, show debug on desconstructor
/** @var array<mixed> */
private $debug_output_not = [];
/** @var bool */
private $debug_output_all = false;
/** @var array<mixed> */
private $echo_output = []; // errors: echo out, default is 1
/** @var array<mixed> */
private $echo_output_not = [];
/** @var bool */
private $echo_output_all = false;
/** @var array<mixed> */
private $print_output = []; // errors: print to file, default is 0
/** @var array<mixed> */
private $print_output_not = [];
/** @var bool */
private $print_output_all = false;
// debug flags/settings
/** @var string */
private $running_uid = ''; // unique ID set on class init and used in logging as prefix
// log file name
/** @var string */
private $log_folder = '';
/** @var string */
private $log_file_name_ext = 'log'; // use this for date rotate
/** @var string */
private $log_file_name = '';
/** @var int */
private $log_max_filesize = 0; // set in kilobytes
/** @var string */
private $log_print_file = 'error_msg##LOGID####LEVEL####CLASS####PAGENAME####DATE##';
/** @var string */
private $log_file_unique_id; // a unique ID set only once for call derived from this class
/** @var string */
private $log_file_date = ''; // Y-m-d file in file name
/** @var bool */
private $log_print_file_date = true; // if set add Y-m-d and do automatic daily rotation
/** @var string */
private $log_file_id = ''; // a alphanumeric name that has to be set as global definition
/** @var bool */
private $log_per_level = false; // set, it will split per level (first parameter in debug call)
/** @var bool */
private $log_per_class = false; // set, will split log per class
/** @var bool */
private $log_per_page = false; // set, will split log per called file
/** @var bool */
private $log_per_run = false; // create a new log file per run (time stamp + unique ID)
// script running time
/** @var float */
private $script_starttime;
/**
* Init logger
*
* global vars that can be used
* - BASE
* - LOG
* - LOG_FILE_ID
* options array layout
* - log_folder:
* - print_file_date:
* - file_id:
* - unique_id:
* - log_per_level:
* - log_per_class:
* - log_per_page:
* - log_per_run:
* - debug_all:
* - echo_all:
* - print_all:
* - debug (array):
* - echo (array):
* - print (array):
* - debug_not (array):
* - echo_not (array):
* - print_not (array):
*
* @param array<mixed> $options Array with settings options
*/
public function __construct(array $options = [])
{
// copy the options over
$this->options = $options;
// set log folder from options
$this->log_folder = $this->options['log_folder'] ?? '';
// legacy flow, check must set constants
if (empty($this->log_folder) && defined('BASE') && defined('LOG')) {
/** @deprecated Do not use this anymore, define path on class load */
trigger_error(
'options: log_folder must be set. Setting via BASE and LOG constants is deprecated',
E_USER_DEPRECATED
);
// make sure this is writeable, else skip
$this->log_folder = BASE . LOG;
}
// fallback + notice
if (empty($this->log_folder)) {
/* trigger_error(
'options or constant not set or folder not writable. fallback to: ' . getcwd(),
E_USER_NOTICE
); */
$this->log_folder = getcwd() . DIRECTORY_SEPARATOR;
}
// if folder is not writeable, abort
if (!is_writeable($this->log_folder)) {
trigger_error(
'Folder: ' . $this->log_folder . ' is not writeable for logging',
E_USER_ERROR
);
}
// check if log_folder has a trailing /
if (substr($this->log_folder, -1, 1) != DIRECTORY_SEPARATOR) {
$this->log_folder .= DIRECTORY_SEPARATOR;
}
// running time start for script
$this->script_starttime = microtime(true);
// set per run UID for logging
$this->running_uid = Uids::uniqIdShort();
// set the page name
$this->page_name = System::getPageName();
// set host name
list($this->host_name , $this->host_port) = System::getHostName();
// add port to host name if not port 80
if ($this->host_port != 80) {
$this->host_name .= ':' . $this->host_port;
}
// can be overridden with basicSetLogFileId later
if (!empty($this->options['file_id'])) {
$this->setLogId($this->options['file_id']);
} elseif (!empty($GLOBALS['LOG_FILE_ID'])) {
/** @deprecated Do not use this anymore, define file_id on class load */
trigger_error(
'options: file_id must be set. Setting via LOG_FILE_ID global variable is deprecated',
E_USER_DEPRECATED
);
// legacy flow, should be removed and only set via options
$this->setLogId($GLOBALS['LOG_FILE_ID']);
// TODO trigger deprecation error
// trigger_error(
// 'Debug\Logging: Do not use globals LOG_FILE_ID to set log id for Logging',
// E_USER_DEPRECATED
// );
} elseif (defined('LOG_FILE_ID')) {
/** @deprecated Do not use this anymore, define file_id on class load */
trigger_error(
'options: file_id must be set. Setting via LOG_FILE_ID constant is deprecated',
E_USER_DEPRECATED
);
// legacy flow, should be removed and only set via options
$this->setLogId(LOG_FILE_ID);
// trigger deprecation error
// trigger_error(
// 'Debug\Logging: Do not use constant LOG_FILE_ID to set log id for Logging',
// E_USER_DEPRECATED
// );
}
// init the log levels
$this->initLogLevels();
}
// *** PRIVATE ***
/**
* init the basic log levels based on global set variables
*
* @return void
*/
private function initLogLevels(): void
{
// if given via parameters, only for all
// globals overrule given settings, for one (array), eg $ECHO['db'] = 1;
foreach (['debug', 'echo', 'print'] as $type) {
// include or exclude (off) from output
foreach (['on', 'off'] as $flag) {
$in_type = $type;
if ($flag == 'off') {
$in_type .= '_not';
}
$up_type = strtoupper($in_type);
if (
isset($this->options[$in_type]) &&
is_array($this->options[$in_type])
) {
$this->setLogLevel($type, $flag, $this->options[$in_type]);
} elseif (
isset($GLOBALS[$up_type]) &&
is_array($GLOBALS[$up_type])
) {
// TODO trigger deprecation error
$this->setLogLevel($type, $flag, $GLOBALS[$up_type]);
}
}
}
// TODO remove all $GLOBALS call and only use options
// all overrule
$this->setLogLevelAll(
'debug',
$this->options['debug_all'] ??
// for user login, should be handled outside like globals
$_SESSION['DEBUG_ALL'] ?? // DEPRECATED
$GLOBALS['DEBUG_ALL'] ?? // DEPRECATED
false
);
$this->setLogLevelAll(
'print',
$this->options['print_all'] ??
// for user login, should be handled outside like globals
$_SESSION['DEBUG_ALL'] ?? // DEPRECATED
$GLOBALS['PRINT_ALL'] ?? // DEPRECATED
false
);
$this->setLogLevelAll(
'echo',
$this->options['echo_all'] ??
$GLOBALS['ECHO_ALL'] ?? // DEPRECATED
false
);
// GLOBAL rules for log writing
// add file date is default on
$this->setGetLogPrintFileDate(
$this->options['print_file_date'] ??
$GLOBALS['LOG_PRINT_FILE_DATE'] ?? // DEPRECATED
true
);
// all other logging file name flags are off
$this->setLogPer(
'level',
$this->options['per_level'] ??
$GLOBALS['LOG_PER_LEVEL'] ?? // DEPRECATED
false
);
$this->setLogPer(
'class',
$this->options['per_class'] ??
$GLOBALS['LOG_PER_CLASS'] ?? // DEPRECATED
false
);
$this->setLogPer(
'page',
$this->options['per_page'] ??
$GLOBALS['LOG_PER_PAGE'] ?? // DEPRECATED
false
);
$this->setLogPer(
'run',
$this->options['per_run'] ??
$GLOBALS['LOG_PER_RUN'] ?? // DEPRECATED
false
);
// set log per date
if ($this->setGetLogPrintFileDate()) {
$this->log_file_date = date('Y-m-d');
}
// set per run ID
if ($this->log_per_run) {
$this->setLogUniqueId();
}
}
/**
* checks if we have a need to work on certain debug output
* Needs debug/echo/print ad target for which of the debug flag groups we check
* also needs level string to check in the per level output flag check.
* In case we have invalid target it will return false
*
* @param string $target target group to check debug/echo/print
* @param string $level level to check in detailed level flag
* @return bool true on access allowed or false on no access
*/
private function doDebugTrigger(string $target, string $level): bool
{
$access = false;
// check if we do debug, echo or print
if (
(
$this->getLogLevel($target, 'on', $level) ||
$this->getLogLevelAll($target)
) &&
!$this->getLogLevel($target, 'off', $level)
) {
$access = true;
}
return $access;
}
/**
* writes error msg data to file for current level
*
* @param string $level the level to write
* @param string $error_string error string to write
* @return bool True if message written, FAlse if not
*/
private function writeErrorMsg(string $level, string $error_string): bool
{
// only write if write is requested
if (
!($this->doDebugTrigger('debug', $level) &&
$this->doDebugTrigger('print', $level))
) {
return false;
}
// init base file path
$fn = $this->log_folder . $this->log_print_file . '.' . $this->log_file_name_ext;
// log ID prefix settings, if not valid, replace with empty
if (!empty($this->log_file_id)) {
$rpl_string = '_' . $this->log_file_id;
} else {
$rpl_string = '';
}
$fn = str_replace('##LOGID##', $rpl_string, $fn); // log id (like a log file prefix)
if ($this->log_per_run) {
$rpl_string = '_' . $this->log_file_unique_id; // add 8 char unique string
} elseif ($this->setGetLogPrintFileDate()) {
$rpl_string = '_' . $this->log_file_date; // add date to file
} else {
$rpl_string = '';
}
$fn = str_replace('##DATE##', $rpl_string, $fn); // create output filename
// write per level
$rpl_string = !$this->log_per_level ? '' :
// normalize level, replace all non alphanumeric characters with -
'_' . (
// if return is only - then set error string
preg_match(
"/^-+$/",
$level_string = preg_replace("/[^A-Za-z0-9-_]/", '-', $level) ?? ''
) ?
'INVALID-LEVEL-STRING' :
$level_string
);
$fn = str_replace('##LEVEL##', $rpl_string, $fn); // create output filename
// set per class, but don't use get_class as we will only get self
$rpl_string = !$this->log_per_class ? '' : '_'
// set sub class settings
. str_replace('\\', '-', Support::getCallerClass());
$fn = str_replace('##CLASS##', $rpl_string, $fn); // create output filename
// if request to write to one file
$rpl_string = !$this->log_per_page ?
'' :
'_' . System::getPageName(System::NO_EXTENSION);
$fn = str_replace('##PAGENAME##', $rpl_string, $fn); // create output filename
// write to file
// first check if max file size is is set and file is bigger
if (
$this->log_max_filesize > 0 &&
((filesize($fn) / 1024) > $this->log_max_filesize)
) {
// for easy purpose, rename file only to attach timestamp, nur sequence numbering
rename($fn, $fn . '.' . date("YmdHis"));
}
$this->log_file_name = $fn;
$fp = fopen($this->log_file_name, 'a');
if ($fp !== false) {
fwrite($fp, $error_string);
fclose($fp);
return true;
} else {
echo "<!-- could not open file: " . $this->log_file_name . " //-->";
return false;
}
}
// *** PUBLIC ***
/**
* Temporary method to read all class variables for testing purpose
*
* @param string $name what variable to return
* @return mixed can be anything, bool, string, int, array
*/
public function getSetting(string $name): mixed
{
// for debug purpose only
return $this->{$name};
}
/**
* sets the internal log file prefix id
* string must be a alphanumeric string
* if non valid string is given it returns the previous set one only
*
* @param string $string log file id string value
* @return string returns the set log file id string
* @deprecated Use $log->setLogId()
*/
public function basicSetLogId(string $string): string
{
return $this->setLogId($string);
}
/**
* sets the internal log file prefix id
* string must be a alphanumeric string
* if non valid string is given it returns the previous set one only
*
* @param string $string log file id string value
* @return string returns the set log file id string
*/
public function setLogId(string $string): string
{
if (preg_match("/^[\w\-]+$/", $string)) {
$this->log_file_id = $string;
}
return $this->log_file_id;
}
/**
* return current set log file id
* @return string
*/
public function getLogId(): string
{
return $this->log_file_id;
}
/**
* old name for setLogLevel
*
* @param string $type debug, echo, print
* @param string $flag on/off
* array $array of levels to turn on/off debug
* @return bool Return false if type or flag is invalid
* @deprecated Use setLogLevel
*/
public function debugFor(string $type, string $flag): bool
{
/** @phan-suppress-next-line PhanTypeMismatchArgumentReal, PhanParamTooFew @phpstan-ignore-next-line */
return $this->setLogLevel(...[func_get_args()]);
}
/**
* set log level settings for All types
* if invalid type, skip
*
* @param string $type Type to get: debug, echo, print
* @param bool $set True or False
* @return bool Return false if type invalid
*/
public function setLogLevelAll(string $type, bool $set): bool
{
// skip set if not valid
if (!in_array($type, ['debug', 'echo', 'print'])) {
return false;
}
$this->{$type . '_output_all'} = $set;
return true;
}
/**
* get the current log level setting for All level blocks
*
* @param string $type Type to get: debug, echo, print
* @return bool False on failure, or the boolean flag from the all var
*/
public function getLogLevelAll(string $type): bool
{
// type check for debug/echo/print
if (!in_array($type, ['debug', 'echo', 'print'])) {
return false;
}
return $this->{$type . '_output_all'};
}
/**
* passes list of level names, to turn on debug
* eg $foo->debugFor('print', 'on', ['LOG', 'DEBUG', 'INFO']);
*
* @param string $type debug, echo, print
* @param string $flag on/off
* @param array<mixed> $debug_on Array of levels to turn on/off debug
* To turn off a level set 'Level' => false,
* If not set, switches to on
* @return bool Return false if type or flag invalid
* also false if debug array is empty
*/
public function setLogLevel(string $type, string $flag, array $debug_on): bool
{
// abort if not valid type
if (!in_array($type, ['debug', 'echo', 'print'])) {
return false;
}
// invalid flag type
if (!in_array($flag, ['on', 'off'])) {
return false;
}
if (count($debug_on) >= 1) {
foreach ($debug_on as $level => $set) {
$switch = $type . '_output' . ($flag == 'off' ? '_not' : '');
if (!is_bool($set)) {
$level = $set;
$set = true;
}
$this->{$switch}[$level] = $set;
}
} else {
return false;
}
return true;
}
/**
* return the log level for the array type normal and not (disable)
*
* @param string $type debug, echo, print
* @param string $flag on/off
* @param string|null $level if not null then check if this array entry is set
* else return false
* @return array<mixed>|bool if $level is null, return array, else boolean true/false
*/
public function getLogLevel(string $type, string $flag, ?string $level = null): array|bool
{
// abort if not valid type
if (!in_array($type, ['debug', 'echo', 'print'])) {
return false;
}
// invalid flag type
if (!in_array($flag, ['on', 'off'])) {
return false;
}
$switch = $type . '_output' . ($flag == 'off' ? '_not' : '');
// log level direct check must be not null or not empty string
if (!empty($level)) {
return $this->{$switch}[$level] ?? false;
}
// array
return $this->{$switch};
}
/**
* set flags for per log level type
* - level: set per sub group level
* - class: split by class
* - page: split per page called
* - run: for each run
*
* @param string $type Type to get: level, class, page, run
* @param bool $set True or False
* @return bool Return false if type invalid
*/
public function setLogPer(string $type, bool $set): bool
{
if (!in_array($type, ['level', 'class', 'page', 'run'])) {
return false;
}
$this->{'log_per_' . $type} = $set;
// if per run set unique id
if ($type == 'run' && $set == true) {
$this->setLogUniqueId();
}
return true;
}
/**
* return current set log per flag in bool
*
* @param string $type Type to get: level, class, page, run
* @return bool True of false for turned on or off
*/
public function getLogPer(string $type): bool
{
if (!in_array($type, ['level', 'class', 'page', 'run'])) {
return false;
}
return $this->{'log_per_' . $type};
}
/**
* Sets a unique id based on current date (y/m/d, h:i:s) and a unique id (8 chars)
* if override is set to true it will be newly set, else if already set nothing changes
*
* @param bool $override True to force new set
* @return void
*/
public function setLogUniqueId(bool $override = false): void
{
if (!$this->log_file_unique_id || $override == true) {
$this->log_file_unique_id =
date('Y-m-d_His') . '_U_'
. substr(hash('sha1', uniqid((string)mt_rand(), true)), 0, 8);
}
}
/**
* Return current set log file unique id,
* empty string for not set
*
* @return string
*/
public function getLogUniqueId(): string
{
return $this->log_file_unique_id;
}
/**
* Set or get the log file date extension flag
* if null or empty parameter gets current flag
*
* @param boolean|null $set Set the date suffix for log files
* If set to null return current set
* @return boolean Current set flag
*/
public function setGetLogPrintFileDate(?bool $set = null): bool
{
if ($set !== null) {
$this->log_print_file_date = $set;
}
return $this->log_print_file_date;
}
/**
* Return current set log file name
*
* @return string Filename set set after the last time debug was called
*/
public function getLogFileName(): string
{
return $this->log_file_name;
}
/**
* A replacement for the \CoreLibs\Debug\Support::printAr
* But this does not wrap it in <pre></pre>
* It uses some special code sets so we can convert that to pre flags
* for echo output {##HTMLPRE##} ... {##/HTMLPRE##}
* Do not use this without using it in a string in debug function
*
* @param array<mixed> $a Array to format
* @return string print_r formated
*/
public function prAr(array $a): string
{
return '##HTMLPRE##' . print_r($a, true) . '##/HTMLPRE##';
}
/**
* Convert bool value to string value
*
* @param bool $bool Bool value to be transformed
* @param string $true Override default string 'true'
* @param string $false Override default string 'false'
* @return string $true or $false string for true/false bool
*/
public function prBl(
bool $bool,
string $true = 'true',
string $false = 'false'
): string {
return $bool ? $true : $false;
}
/**
* write debug data to error_msg array
*
* @param string $level id for error message, groups messages together
* @param string $string the actual error message
* @param bool $strip default on false, if set to true,
* all html tags will be stripped and <br> changed to \n
* this is only used for debug output
* @param string $prefix Attach some block before $string.
* Will not be stripped even
* when strip is true
* if strip is false, recommended to add that to $string
* @return bool True if logged, false if not logged
*/
public function debug(
string $level,
string $string,
bool $strip = false,
string $prefix = ''
): bool {
$status = false;
// must be debug on and either echo or print on
if (
!$this->doDebugTrigger('debug', $level) ||
(
// if debug is on, either print or echo must be set to on
!$this->doDebugTrigger('print', $level) &&
!$this->doDebugTrigger('echo', $level)
)
) {
return $status;
}
// get the last class entry and wrie that
$class = Support::getCallerClass();
// get timestamp
$timestamp = Support::printTime();
// same string put for print (no html data inside)
// write to file if set
$status = $this->writeErrorMsg(
$level,
'[' . $timestamp . '] '
. '[' . $this->host_name . '] '
. '[' . System::getPageName(System::FULL_PATH) . '] '
. '[' . $this->running_uid . '] '
. '{' . $class . '} '
. '<' . $level . '> - '
// strip the htmlpre special tags if exist
. str_replace(
['##HTMLPRE##', '##/HTMLPRE##'],
'',
// if stripping all html, etc is requested, only for write error msg
($strip ?
// find any <br> and replace them with \n
// strip rest of html elements (base only)
preg_replace(
"/(<\/?)(\w+)([^>]*>)/",
'',
str_replace('<br>', "\n", $prefix . $string)
) :
$prefix . $string
) ?: ''
)
. "\n"
);
// write to error level msg array if there is an echo request
if ($this->doDebugTrigger('echo', $level)) {
// init if not set
if (!isset($this->error_msg[$level])) {
$this->error_msg[$level] = [];
}
// HTML string
$this->error_msg[$level][] = '<div>'
. '[<span style="font-weight: bold; color: #5e8600;">' . $timestamp . '</span>] '
. '[<span style="font-weight: bold; color: #c56c00;">' . $level . '</span>] '
. '[<span style="color: #b000ab;">' . $this->host_name . '</span>] '
. '[<span style="color: #08b369;">' . $this->page_name . '</span>] '
. '[<span style="color: #0062A2;">' . $this->running_uid . '</span>] '
. '{<span style="font-style: italic; color: #928100;">' . $class . '</span>} - '
// as is prefix, allow HTML
. $prefix
// we replace special HTMLPRE with <pre> entries
. str_replace(
['##HTMLPRE##', '##/HTMLPRE##'],
['<pre>', '</pre>'],
Html::htmlent($string)
)
. "</div><!--#BR#-->";
$status = true;
}
return $status;
}
/**
* for ECHO ON only
* returns error data as string so it can be echoed out
*
* @param string $header_prefix prefix string for header
* @return string error msg for all levels
*/
public function printErrorMsg(string $header_prefix = ''): string
{
$string_output = '';
// if not debug && echo on, do not return anything
if (
!$this->getLogLevelAll('debug') ||
!$this->getLogLevelAll('echo')
) {
return $string_output;
}
if ($this->error_msg_prefix) {
$header_prefix = $this->error_msg_prefix;
}
$script_end = microtime(true) - $this->script_starttime;
foreach ($this->error_msg as $level => $temp_debug_output) {
if ($this->doDebugTrigger('debug', $level)) {
if ($this->doDebugTrigger('echo', $level)) {
$string_output .= '<div style="font-size: 12px;">'
. '[<span style="font-style: italic; color: #c56c00;">' . $level . '</span>] '
. ($header_prefix ? "<b>**** " . Html::htmlent($header_prefix) . " ****</br>\n" : '')
. '</div>'
. join('', $temp_debug_output);
} // echo it out
} // do printout
} // for each level
// create the output wrapper around
// so we have a nice formated output per class
if ($string_output) {
$string_prefix = '<div style="text-align: left; padding: 5px; font-size: 10px; '
. 'font-family: sans-serif; border-top: 1px solid black; '
. 'border-bottom: 1px solid black; margin: 10px 0 10px 0; '
. 'background-color: white; color: black;">'
. '<div style="font-size: 12px;">{<span style="font-style: italic; color: #928100;">'
. Support::getCallerClass() . '</span>}</div>';
$string_output = $string_prefix . $string_output
. '<div><span style="font-style: italic; color: #108db3;">Script Run Time:</span> '
. $script_end . '</div>'
. '</div>';
}
// }
return $string_output;
}
/**
* for ECHO ON only
* unsests the error message array
* can be used if writing is primary to file
* if no level given resets all
*
* @param string $level optional level
* @return void has no return
*/
public function resetErrorMsg(string $level = ''): void
{
if (!$level) {
$this->error_msg = [];
} elseif (isset($this->error_msg[$level])) {
unset($this->error_msg[$level]);
}
}
/**
* for ECHO ON only
* Get current error message array
*
* @return array<mixed> error messages collected
*/
public function getErrorMsg(): array
{
return $this->error_msg;
}
/**
* for ECHO ON only
* merges the given error array with the one from this class
* only merges visible ones
*
* @param array<mixed> $error_msg error array
* @return void has no return
*/
public function mergeErrors(array $error_msg = []): void
{
array_push($this->error_msg, ...$error_msg);
parent::__construct($options);
}
}

View File

@@ -0,0 +1,911 @@
<?php
/**
* THIS IS LEGACY LOGGING AND WILL BE FULLY REMOVED IN FUTURE VERSION.
* use \CoreLibs\Logger\Logging instead
* for the need to reference old:
* use CoreLibs\Debug\LoggingLegacy as Logging;
*/
/*
* Debug support functions
*
* These are if there is any debug to print out at all at the end
 * debug_output_all - general yes no
 * It's recommended to use the method "debug_for" to turn on of the array vars
 * debug_output - turn on for one level (Array)
 * debug_output_not - turn off for one level (array)
 *
 * Print out the debug at thend of the html
 * echo_output_all
 * echo_output
 * echo_output_not
 *
 * Write debug to file
 * print_output_all
 * print_output
 * print_output_not
*/
declare(strict_types=1);
namespace CoreLibs\Debug;
use CoreLibs\Debug\Support;
use CoreLibs\Create\Uids;
use CoreLibs\Get\System;
use CoreLibs\Convert\Html;
class LoggingLegacy
{
// options
/** @var array<mixed> */
private $options = [];
// page and host name
/** @var string */
private $page_name;
/** @var string */
private $host_name;
/** @var int */
private $host_port;
// internal error reporting vars
/** @var array<mixed> */
private $error_msg = []; // the "connection" to the outside errors
// debug output prefix
/** @var string */
private $error_msg_prefix = ''; // prefix to the error string (the class name)
// debug flags/settings
/** @var string */
private $running_uid = ''; // unique ID set on class init and used in logging as prefix
// log file name
/** @var string */
private $log_folder = '';
/** @var string */
private $log_file_name_ext = 'log'; // use this for date rotate
/** @var string */
private $log_file_name = '';
/** @var int */
private $log_max_filesize = 0; // set in kilobytes
/** @var string */
private $log_print_file = 'error_msg{LOGID}{LEVEL}{CLASS}{PAGENAME}{DATE_RUNID}';
/** @var string */
private $log_file_unique_id; // a unique ID set only once for call derived from this class
/** @var string */
private $log_file_date = ''; // Y-m-d file in file name
/** @var bool */
private $log_print_file_date = true; // if set add Y-m-d and do automatic daily rotation
/** @var string */
private $log_file_id = ''; // a alphanumeric name that has to be set as global definition
/** @var bool */
private $log_per_level = false; // set, it will split per level (first parameter in debug call)
/** @var bool */
private $log_per_class = false; // set, will split log per class
/** @var bool */
private $log_per_page = false; // set, will split log per called file
/** @var bool */
private $log_per_run = false; // create a new log file per run (time stamp + unique ID)
// script running time
/** @var float */
private $script_starttime;
/** @var string[] current log levels */
private $log_levels = ['debug', 'echo', 'print'];
/** @var string[] log group per what for writing to file */
private $log_grouping = ['level', 'class', 'page', 'run'];
// debug flags [they must exist or we get a warning]
/** @var array<mixed> */
private $debug_output = []; // if this is true, show debug on desconstructor
/** @var array<mixed> */
private $debug_output_not = [];
/** @var bool */
private $debug_output_all = false;
/** @var array<mixed> */
private $echo_output = []; // errors: echo out, default is 1
/** @var array<mixed> */
private $echo_output_not = [];
/** @var bool */
private $echo_output_all = false;
/** @var array<mixed> */
private $print_output = []; // errors: print to file, default is 0
/** @var array<mixed> */
private $print_output_not = [];
/** @var bool */
private $print_output_all = false;
/**
* Init logger
*
* global vars that can be used
* - BASE
* - LOG
* - LOG_FILE_ID
* options array layout
* - log_folder:
* - file_id:
* - unique_id:
* - print_file_date:
* - log_per_level:
* - log_per_class:
* - log_per_page:
* - log_per_run:
* - debug_all:
* - echo_all:
* - print_all:
* - debug (array):
* - echo (array):
* - print (array):
* - debug_not (array):
* - echo_not (array):
* - print_not (array):
*
* @param array<mixed> $options Array with settings options
*/
public function __construct(array $options = [])
{
// copy the options over
$this->options = $options;
// set log folder from options
$this->log_folder = $this->options['log_folder'] ?? '';
// legacy flow, check must set constants
if (empty($this->log_folder) && defined('BASE') && defined('LOG')) {
/** @deprecated Do not use this anymore, define path on class load */
trigger_error(
'options: log_folder must be set. Setting via BASE and LOG constants is deprecated',
E_USER_DEPRECATED
);
// make sure this is writeable, else skip
$this->log_folder = BASE . LOG;
}
// fallback + notice
if (empty($this->log_folder)) {
/* trigger_error(
'options or constant not set or folder not writable. fallback to: ' . getcwd(),
E_USER_NOTICE
); */
$this->log_folder = getcwd() . DIRECTORY_SEPARATOR;
}
// if folder is not writeable, abort
if (!is_writeable($this->log_folder)) {
trigger_error(
'Folder: ' . $this->log_folder . ' is not writeable for logging',
E_USER_ERROR
);
}
// check if log_folder has a trailing /
if (substr($this->log_folder, -1, 1) != DIRECTORY_SEPARATOR) {
$this->log_folder .= DIRECTORY_SEPARATOR;
}
// running time start for script
$this->script_starttime = microtime(true);
// set per run UID for logging
$this->running_uid = Uids::uniqIdShort();
// set the page name
$this->page_name = System::getPageName();
// set host name
list($this->host_name , $this->host_port) = System::getHostName();
// add port to host name if not port 80
if ($this->host_port != 80) {
$this->host_name .= ':' . $this->host_port;
}
// can be overridden with basicSetLogFileId later
if (!empty($this->options['file_id'])) {
$this->setLogId($this->options['file_id']);
} elseif (!empty($GLOBALS['LOG_FILE_ID'])) {
/** @deprecated Do not use this anymore, define file_id on class load */
trigger_error(
'options: file_id must be set. Setting via LOG_FILE_ID global variable is deprecated',
E_USER_DEPRECATED
);
// legacy flow, should be removed and only set via options
$this->setLogId($GLOBALS['LOG_FILE_ID']);
// TODO trigger deprecation error
// trigger_error(
// 'Debug\Logging: Do not use globals LOG_FILE_ID to set log id for Logging',
// E_USER_DEPRECATED
// );
} elseif (defined('LOG_FILE_ID')) {
/** @deprecated Do not use this anymore, define file_id on class load */
trigger_error(
'options: file_id must be set. Setting via LOG_FILE_ID constant is deprecated',
E_USER_DEPRECATED
);
// legacy flow, should be removed and only set via options
$this->setLogId((string)LOG_FILE_ID);
// trigger deprecation error
// trigger_error(
// 'Debug\Logging: Do not use constant LOG_FILE_ID to set log id for Logging',
// E_USER_DEPRECATED
// );
}
// init the log levels
$this->initLogLevels();
}
// *** PRIVATE ***
/**
* init the basic log levels based on global set variables
*
* @return void
*/
private function initLogLevels(): void
{
// if given via parameters, only for all
// globals overrule given settings, for one (array), eg $ECHO['db'] = 1;
foreach ($this->log_levels as $type) {
// include or exclude (off) from output
foreach (['on', 'off'] as $flag) {
$in_type = $type;
if ($flag == 'off') {
$in_type .= '_not';
}
$up_type = strtoupper($in_type);
if (
isset($this->options[$in_type]) &&
is_array($this->options[$in_type])
) {
$this->setLogLevel($type, $flag, $this->options[$in_type]);
} elseif (
isset($GLOBALS[$up_type]) &&
is_array($GLOBALS[$up_type])
) {
// TODO trigger deprecation error
$this->setLogLevel($type, $flag, $GLOBALS[$up_type]);
}
}
}
// TODO remove all $GLOBALS call and only use options
// all overrule
$this->setLogLevelAll(
'debug',
$this->options['debug_all'] ??
// for user login, should be handled outside like globals
$_SESSION['DEBUG_ALL'] ?? // DEPRECATED
$GLOBALS['DEBUG_ALL'] ?? // DEPRECATED
false
);
$this->setLogLevelAll(
'print',
$this->options['print_all'] ??
// for user login, should be handled outside like globals
$_SESSION['DEBUG_ALL'] ?? // DEPRECATED
$GLOBALS['PRINT_ALL'] ?? // DEPRECATED
false
);
$this->setLogLevelAll(
'echo',
$this->options['echo_all'] ??
$GLOBALS['ECHO_ALL'] ?? // DEPRECATED
false
);
// GLOBAL rules for log writing
// add file date is default on
$this->setGetLogPrintFileDate(
$this->options['print_file_date'] ??
$GLOBALS['LOG_PRINT_FILE_DATE'] ?? // DEPRECATED
true
);
// all other logging file name flags are off
$this->setLogPer(
'level',
$this->options['per_level'] ??
$GLOBALS['LOG_PER_LEVEL'] ?? // DEPRECATED
false
);
$this->setLogPer(
'class',
$this->options['per_class'] ??
$GLOBALS['LOG_PER_CLASS'] ?? // DEPRECATED
false
);
$this->setLogPer(
'page',
$this->options['per_page'] ??
$GLOBALS['LOG_PER_PAGE'] ?? // DEPRECATED
false
);
$this->setLogPer(
'run',
$this->options['per_run'] ??
$GLOBALS['LOG_PER_RUN'] ?? // DEPRECATED
false
);
// set log per date
if ($this->setGetLogPrintFileDate()) {
$this->log_file_date = date('Y-m-d');
}
// set per run ID
if ($this->log_per_run) {
$this->setLogUniqueId();
}
}
/**
* checks if we have a need to work on certain debug output
* Needs debug/echo/print ad target for which of the debug flag groups we check
* also needs level string to check in the per level output flag check.
* In case we have invalid target it will return false
*
* @param string $target target group to check debug/echo/print
* @param string $level level to check in detailed level flag
* @return bool true on access allowed or false on no access
*/
private function doDebugTrigger(string $target, string $level): bool
{
$access = false;
// check if we do debug, echo or print
if (
(
$this->getLogLevel($target, 'on', $level) ||
$this->getLogLevelAll($target)
) &&
!$this->getLogLevel($target, 'off', $level)
) {
$access = true;
}
return $access;
}
/**
* writes error msg data to file for current level
*
* @param string $level the level to write
* @param string $error_string error string to write
* @return bool True if message written, False if not
*/
private function writeErrorMsg(string $level, string $error_string): bool
{
// only write if write is requested
if (
!($this->doDebugTrigger('debug', $level) &&
$this->doDebugTrigger('print', $level))
) {
return false;
}
// init base file path
$fn = $this->log_folder . $this->log_print_file . '.' . $this->log_file_name_ext;
// log ID prefix settings, if not valid, replace with empty
if (!empty($this->log_file_id)) {
$rpl_string = '_' . $this->log_file_id;
} else {
$rpl_string = '';
}
$fn = str_replace('{LOGID}', $rpl_string, $fn); // log id (like a log file prefix)
// if run id, we auto add ymd, so we ignore the log file date
if ($this->log_per_run) {
$rpl_string = '_' . $this->log_file_unique_id; // add 8 char unique string
} elseif ($this->setGetLogPrintFileDate()) {
$rpl_string = '_' . $this->log_file_date; // add date to file
} else {
$rpl_string = '';
}
$fn = str_replace('{DATE_RUNID}', $rpl_string, $fn); // create output filename
// write per level
$rpl_string = !$this->log_per_level ? '' :
// normalize level, replace all non alphanumeric characters with -
'_' . (
// if return is only - then set error string
preg_match(
"/^-+$/",
$level_string = preg_replace("/[^A-Za-z0-9-_]/", '-', $level) ?? ''
) ?
'INVALID-LEVEL-STRING' :
$level_string
);
$fn = str_replace('{LEVEL}', $rpl_string, $fn); // create output filename
// set per class, but don't use get_class as we will only get self
$rpl_string = !$this->log_per_class ? '' : '_'
// set sub class settings
. str_replace('\\', '-', Support::getCallerClass());
$fn = str_replace('{CLASS}', $rpl_string, $fn); // create output filename
// if request to write to one file
$rpl_string = !$this->log_per_page ?
'' :
'_' . System::getPageName(System::NO_EXTENSION);
$fn = str_replace('{PAGENAME}', $rpl_string, $fn); // create output filename
// write to file
// first check if max file size is is set and file is bigger
if (
$this->log_max_filesize > 0 &&
((filesize($fn) / 1024) > $this->log_max_filesize)
) {
// for easy purpose, rename file only to attach timestamp, nur sequence numbering
rename($fn, $fn . '.' . date("YmdHis"));
}
$this->log_file_name = $fn;
$fp = fopen($this->log_file_name, 'a');
if ($fp !== false) {
fwrite($fp, $error_string);
fclose($fp);
return true;
} else {
echo "<!-- could not open file: " . $this->log_file_name . " //-->";
return false;
}
}
// *** PUBLIC ***
/**
* Temporary method to read all class variables for testing purpose
*
* @param string $name what variable to return
* @return mixed can be anything, bool, string, int, array
*/
public function getSetting(string $name): mixed
{
// for debug purpose only
return $this->{$name};
}
/**
* sets the internal log file prefix id
* string must be a alphanumeric string
* if non valid string is given it returns the previous set one only
*
* @param string $string log file id string value
* @return string returns the set log file id string
* @deprecated Use $log->setLogId()
*/
public function basicSetLogId(string $string): string
{
return $this->setLogId($string);
}
/**
* sets the internal log file prefix id
* string must be a alphanumeric string
* if non valid string is given it returns the previous set one only
*
* @param string $string log file id string value
* @return string returns the set log file id string
*/
public function setLogId(string $string): string
{
if (preg_match("/^[\w\-]+$/", $string)) {
$this->log_file_id = $string;
}
return $this->log_file_id;
}
/**
* return current set log file id
* @return string
*/
public function getLogId(): string
{
return $this->log_file_id;
}
/**
* old name for setLogLevel
*
* @param string $type debug, echo, print
* @param string $flag on/off
* array $array of levels to turn on/off debug
* @return bool Return false if type or flag is invalid
* @deprecated Use setLogLevel
*/
public function debugFor(string $type, string $flag): bool
{
/** @phan-suppress-next-line PhanTypeMismatchArgumentReal, PhanParamTooFew @phpstan-ignore-next-line */
return $this->setLogLevel(...[func_get_args()]);
}
/**
* set log level settings for All types
* if invalid type, skip
*
* @param string $type Type to get: debug, echo, print
* @param bool $set True or False
* @return bool Return false if type invalid
*/
public function setLogLevelAll(string $type, bool $set): bool
{
// skip set if not valid
if (!in_array($type, $this->log_levels)) {
return false;
}
$this->{$type . '_output_all'} = $set;
return true;
}
/**
* get the current log level setting for All level blocks
*
* @param string $type Type to get: debug, echo, print
* @return bool False on failure, or the boolean flag from the all var
*/
public function getLogLevelAll(string $type): bool
{
// type check for debug/echo/print
if (!in_array($type, $this->log_levels)) {
return false;
}
return $this->{$type . '_output_all'};
}
/**
* passes list of level names, to turn on debug
* eg $foo->debugFor('print', 'on', ['LOG', 'DEBUG', 'INFO']);
*
* @param string $type debug, echo, print
* @param string $flag on/off
* @param array<mixed> $debug_on Array of levels to turn on/off debug
* To turn off a level set 'Level' => false,
* If not set, switches to on
* @return bool Return false if type or flag invalid
* also false if debug array is empty
*/
public function setLogLevel(string $type, string $flag, array $debug_on): bool
{
// abort if not valid type
if (!in_array($type, $this->log_levels)) {
return false;
}
// invalid flag type
if (!in_array($flag, ['on', 'off'])) {
return false;
}
if (count($debug_on) >= 1) {
foreach ($debug_on as $level => $set) {
$switch = $type . '_output' . ($flag == 'off' ? '_not' : '');
if (!is_bool($set)) {
$level = $set;
$set = true;
}
$this->{$switch}[$level] = $set;
}
} else {
return false;
}
return true;
}
/**
* return the log level for the array type normal and not (disable)
*
* @param string $type debug, echo, print
* @param string $flag on/off
* @param string|null $level if not null then check if this array entry is set
* else return false
* @return array<mixed>|bool if $level is null, return array, else boolean true/false
*/
public function getLogLevel(string $type, string $flag, ?string $level = null): array|bool
{
// abort if not valid type
if (!in_array($type, $this->log_levels)) {
return false;
}
// invalid flag type
if (!in_array($flag, ['on', 'off'])) {
return false;
}
$switch = $type . '_output' . ($flag == 'off' ? '_not' : '');
// log level direct check must be not null or not empty string
if (!empty($level)) {
return $this->{$switch}[$level] ?? false;
}
// array
return $this->{$switch};
}
/**
* set flags for per log level type
* - level: set per sub group level
* - class: split by class
* - page: split per page called
* - run: for each run
*
* @param string $type Type to get: level, class, page, run
* @param bool $set True or False
* @return bool Return false if type invalid
*/
public function setLogPer(string $type, bool $set): bool
{
if (!in_array($type, $this->log_grouping)) {
return false;
}
$this->{'log_per_' . $type} = $set;
// if per run set unique id
if ($type == 'run' && $set == true) {
$this->setLogUniqueId();
}
return true;
}
/**
* return current set log per flag in bool
*
* @param string $type Type to get: level, class, page, run
* @return bool True of false for turned on or off
*/
public function getLogPer(string $type): bool
{
if (!in_array($type, $this->log_grouping)) {
return false;
}
return $this->{'log_per_' . $type};
}
/**
* Sets a unique id based on current date (y/m/d, h:i:s) and a unique id (8 chars)
* if override is set to true it will be newly set, else if already set nothing changes
*
* @param bool $override True to force new set
* @return void
*/
public function setLogUniqueId(bool $override = false): void
{
if (!$this->log_file_unique_id || $override == true) {
$this->log_file_unique_id =
date('Y-m-d_His') . '_U_'
. substr(hash('sha1', uniqid((string)mt_rand(), true)), 0, 8);
}
}
/**
* Return current set log file unique id,
* empty string for not set
*
* @return string
*/
public function getLogUniqueId(): string
{
return $this->log_file_unique_id;
}
/**
* Set or get the log file date extension flag
* if null or empty parameter gets current flag
*
* @param boolean|null $set Set the date suffix for log files
* If set to null return current set
* @return boolean Current set flag
*/
public function setGetLogPrintFileDate(?bool $set = null): bool
{
if ($set !== null) {
$this->log_print_file_date = $set;
}
return $this->log_print_file_date;
}
/**
* Return current set log file name
*
* @return string Filename set set after the last time debug was called
*/
public function getLogFileName(): string
{
return $this->log_file_name;
}
/**
* A replacement for the \CoreLibs\Debug\Support::printAr
* But this does not wrap it in <pre></pre>
* It uses some special code sets so we can convert that to pre flags
* for echo output {##HTMLPRE##} ... {##/HTMLPRE##}
* Do not use this without using it in a string in debug function
*
* @param array<mixed> $a Array to format
* @return string print_r formated
*/
public function prAr(array $a): string
{
return '##HTMLPRE##' . print_r($a, true) . '##/HTMLPRE##';
}
/**
* Convert bool value to string value
*
* @param bool $bool Bool value to be transformed
* @param string $true Override default string 'true'
* @param string $false Override default string 'false'
* @return string $true or $false string for true/false bool
*/
public function prBl(
bool $bool,
string $true = 'true',
string $false = 'false'
): string {
return $bool ? $true : $false;
}
/**
* write debug data to error_msg array
*
* @param string $level id for error message, groups messages together
* @param string $string the actual error message
* @param bool $strip default on false, if set to true,
* all html tags will be stripped and <br> changed to \n
* this is only used for debug output
* @param string $prefix Attach some block before $string.
* Will not be stripped even
* when strip is true
* if strip is false, recommended to add that to $string
* @return bool True if logged, false if not logged
*/
public function debug(
string $level,
string $string,
bool $strip = false,
string $prefix = ''
): bool {
$status = false;
// must be debug on and either echo or print on
if (
!$this->doDebugTrigger('debug', $level) ||
(
// if debug is on, either print or echo must be set to on
!$this->doDebugTrigger('print', $level) &&
!$this->doDebugTrigger('echo', $level)
)
) {
return $status;
}
// get the last class entry and wrie that
$class = Support::getCallerClass();
// get timestamp
$timestamp = Support::printTime();
// same string put for print (no html data inside)
// write to file if set
$status = $this->writeErrorMsg(
$level,
'[' . $timestamp . '] '
. '[' . $this->host_name . '] '
. '[' . System::getPageName(System::FULL_PATH) . '] '
. '[' . $this->running_uid . '] '
. '{' . $class . '} '
. '<' . $level . '> - '
// strip the htmlpre special tags if exist
. str_replace(
['##HTMLPRE##', '##/HTMLPRE##'],
'',
// if stripping all html, etc is requested, only for write error msg
($strip ?
// find any <br> and replace them with \n
// strip rest of html elements (base only)
preg_replace(
"/(<\/?)(\w+)([^>]*>)/",
'',
str_replace('<br>', "\n", $prefix . $string)
) :
$prefix . $string
) ?: ''
)
. "\n"
);
// write to error level msg array if there is an echo request
if ($this->doDebugTrigger('echo', $level)) {
// init if not set
if (!isset($this->error_msg[$level])) {
$this->error_msg[$level] = [];
}
// HTML string
$this->error_msg[$level][] = '<div>'
. '[<span style="font-weight: bold; color: #5e8600;">' . $timestamp . '</span>] '
. '[<span style="font-weight: bold; color: #c56c00;">' . $level . '</span>] '
. '[<span style="color: #b000ab;">' . $this->host_name . '</span>] '
. '[<span style="color: #08b369;">' . $this->page_name . '</span>] '
. '[<span style="color: #0062A2;">' . $this->running_uid . '</span>] '
. '{<span style="font-style: italic; color: #928100;">' . $class . '</span>} - '
// as is prefix, allow HTML
. $prefix
// we replace special HTMLPRE with <pre> entries
. str_replace(
['##HTMLPRE##', '##/HTMLPRE##'],
['<pre>', '</pre>'],
Html::htmlent($string)
)
. "</div><!--#BR#-->";
$status = true;
}
return $status;
}
/**
* for ECHO ON only
* returns error data as string so it can be echoed out
*
* @param string $header_prefix prefix string for header
* @return string error msg for all levels
*/
public function printErrorMsg(string $header_prefix = ''): string
{
$string_output = '';
// if not debug && echo on, do not return anything
if (
!$this->getLogLevelAll('debug') ||
!$this->getLogLevelAll('echo')
) {
return $string_output;
}
if ($this->error_msg_prefix) {
$header_prefix = $this->error_msg_prefix;
}
$script_end = microtime(true) - $this->script_starttime;
foreach ($this->error_msg as $level => $temp_debug_output) {
if ($this->doDebugTrigger('debug', $level)) {
if ($this->doDebugTrigger('echo', $level)) {
$string_output .= '<div style="font-size: 12px;">'
. '[<span style="font-style: italic; color: #c56c00;">' . $level . '</span>] '
. ($header_prefix ? "<b>**** " . Html::htmlent($header_prefix) . " ****</br>\n" : '')
. '</div>'
. join('', $temp_debug_output);
} // echo it out
} // do printout
} // for each level
// create the output wrapper around
// so we have a nice formated output per class
if ($string_output) {
$string_prefix = '<div style="text-align: left; padding: 5px; font-size: 10px; '
. 'font-family: sans-serif; border-top: 1px solid black; '
. 'border-bottom: 1px solid black; margin: 10px 0 10px 0; '
. 'background-color: white; color: black;">'
. '<div style="font-size: 12px;">{<span style="font-style: italic; color: #928100;">'
. Support::getCallerClass() . '</span>}</div>';
$string_output = $string_prefix . $string_output
. '<div><span style="font-style: italic; color: #108db3;">Script Run Time:</span> '
. $script_end . '</div>'
. '</div>';
}
// }
return $string_output;
}
/**
* for ECHO ON only
* unsests the error message array
* can be used if writing is primary to file
* if no level given resets all
*
* @param string $level optional level
* @return void has no return
*/
public function resetErrorMsg(string $level = ''): void
{
if (!$level) {
$this->error_msg = [];
} elseif (isset($this->error_msg[$level])) {
unset($this->error_msg[$level]);
}
}
/**
* for ECHO ON only
* Get current error message array
*
* @return array<mixed> error messages collected
*/
public function getErrorMsg(): array
{
return $this->error_msg;
}
/**
* for ECHO ON only
* merges the given error array with the one from this class
* only merges visible ones
*
* @param array<mixed> $error_msg error array
* @return void has no return
*/
public function mergeErrors(array $error_msg = []): void
{
array_push($this->error_msg, ...$error_msg);
}
}
// __END__

View File

@@ -37,23 +37,21 @@ class Support
* prints a html formatted (pre) array
*
* @param array<mixed> $array any array
* @param bool $no_html set to true to use ##HTMLPRE##
* @param bool $no_html default add <pre>
* @return string formatted array for output with <pre> tag added
*/
public static function printAr(array $array, bool $no_html = false): string
{
if ($no_html === false) {
return "<pre>" . print_r($array, true) . "</pre>";
} else {
return '##HTMLPRE##' . print_r($array, true) . '##/HTMLPRE##';
}
return $no_html ?
print_r($array, true) :
'<pre>' . print_r($array, true) . '</pre>';
}
/**
* alternate name for printAr function
*
* @param array<mixed> $array any array
* @param bool $no_html set to true to use ##HTMLPRE##
* @param bool $no_html default add <pre>
* @return string formatted array for output with <pre> tag added
*/
public static function printArray(array $array, bool $no_html = false): string
@@ -61,26 +59,61 @@ class Support
return self::printAr($array, $no_html);
}
/**
* A replacement for the \CoreLibs\Debug\Support::printAr
* But this does not wrap it in <pre></pre>
* Do not use this without using it in a string in debug function
* Note: for full data debug dumps use Support::dumpVar()
*
* @param array<mixed> $a Array to format
* @return string print_r formated
*/
public static function prAr(array $a): string
{
return self::printAr($a, true);
}
/**
* convert bool value to string
* if $name is set prefix with nae
* default true: true, false: false
*
* @param bool $bool Variable to convert
* @param string $name [default: ''] Prefix name
* @param string $true [default: true] True string
* @param string $false [default: false] False string
* @return string String with converted bool text for debug
* @param bool $bool Variable to convert
* @param string $name [default: ''] Prefix name
* @param string $true [default: 'true'] True string
* @param string $false [default: 'false'] False string
* @param bool $no_html [default: false] if true do not print html
* @return string String with converted bool text for debug
*/
public static function printBool(
bool $bool,
string $name = '',
string $true = 'true',
string $false = 'false',
bool $no_html = false,
): string {
return
(!empty($name) ?
($no_html ?
$name : '<b>' . $name . '</b>') . ': '
: '')
. ($bool ? $true : $false);
}
/**
* Convert bool value to string value. Short name alias for printBool
*
* @param bool $bool Bool value to be transformed
* @param string $true [default: 'true'] Override default string 'true'
* @param string $false [default: 'false'] Override default string 'false'
* @return string $true or $false string for true/false bool
*/
public static function prBl(
bool $bool,
string $true = 'true',
string $false = 'false'
): string {
$string = (!empty($name) ? '<b>' . $name . '</b>: ' : '')
. ($bool ? $true : $false);
return $string;
return self::printBool($bool, '', $true, $false, true);
}
/**
@@ -89,9 +122,10 @@ class Support
* if object return get_class
* for array use printAr function, can be controlled with no_html for
* Debug\Logging compatible output
* Recommended to use Support::dumpVar()
*
* @param mixed $mixed
* @param bool $no_html set to true to use ##HTMLPRE##or html escape
* @param bool $no_html set to true to strip <pre> tags
* @return string
*/
public static function printToString(mixed $mixed, bool $no_html = false): string
@@ -119,12 +153,80 @@ class Support
}
}
/**
* Dumps var data and returns it as string
* var_dump based
* Recommended debug output
*
* @param mixed $data Anything
* @param bool $no_html If true strip all html tags (for text print)
* @return string A text string
*/
public static function dumpVar(mixed $data, bool $no_html = false): string
{
ob_start();
var_dump($data);
$debug_dump = ob_get_clean() ?: '[FAILED TO GET var_dump() data]';
// we need to strip the string in <small></small that is
// "path ... CoreLibs/Debug/Support.php:<number>:
// and replace it with the caller methods and location
$caller_file_number = self::getCallerFileLine();
$debug_dump = preg_replace(
'|<small>(/.*:\d+:)</small>|',
'<small>' . $caller_file_number . ':</small>',
$debug_dump
) ?? $debug_dump; // in case of failure keep original
// if strip is ture, remove all HTML tags and convert any html entities back
return $no_html ?
str_replace(
// things to replace in the string if set
['&gt;', '&lt;', '&#13;', '&#10;'],
['>', '<', "\r", "\n"],
strip_tags($debug_dump)
) :
$debug_dump;
}
/**
* exports (dumps) var, in more printable design, but without detail info
*
* @param mixed $data Anything
* @param bool $no_html If true true do not add <pre> tags
* @return string A text string
*/
public static function exportVar(mixed $data, bool $no_html = false): string
{
return $no_html ?
var_export($data, true) :
'<pre>' . var_export($data, true) . '</pre>';
}
/**
* Return file name and line number where this was called
* One level up
*
* @param int $level trace level, default 1
* @return string|null null or file name:line number
*/
public static function getCallerFileLine(int $level = 1): ?string
{
$traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
// print \CoreLibs\Debug\Support::printAr($traces);
// We should check from top down if unset?
// sets the start point here, and in level two (the sub call) we find this
if (isset($traces[$level])) {
return ($traces[$level]['file'] ?? $traces[$level]['function'])
. ':' . ($traces[$level]['line'] ?? '-');
}
return null;
}
/**
* if there is a need to find out which parent method called a child method,
* eg for debugging, this function does this
*
* call this method in the child method and you get the parent function that called
* @param int $level debug level, default 1
* @param int $level trace level, default 1
* @return ?string null or the function that called the function
* where this method is called
*/

View File

@@ -0,0 +1,107 @@
<?php
/**
* AUTOR: Clemens Schwaighofer
* CREATED: 2023/5/29
* DESCRIPTION:
* Logging options flags for output file name building
*
* per_run: and timestamp + uid will be added
* per_date: ymd will be added (per_run > per_date, cannot be used at the same time)
* per_group: for debug level, group per group id (old level)
* per_page: per file name logging
* per_class: log per class
* per_level: per logging level file split
*/
declare(strict_types=1);
namespace CoreLibs\Logging\Logger;
enum Flag: int
{
/** all off flag */
case all_off = 0;
/** write per run */
case per_run = 1;
/** write per date */
case per_date = 2;
/** was PER_LEVEL, write per group id (debug) */
case per_group = 4;
/** write per page (filename) */
case per_page = 8;
/** write per class */
case per_class = 16;
/** write per log level name */
case per_level = 32;
/**
* get internal name from string value
*
* @param non-empty-string $name
* @return self
*/
public static function fromName(string $name): self
{
return match ($name) {
'Run', 'run', 'per_run', 'PER_RUN' => self::per_run,
'Date', 'date', 'per_date', 'PER_DATE' => self::per_date,
'Group', 'group', 'per_group', 'PER_GROUP' => self::per_group,
'Page', 'page', 'per_page', 'PER_PAGE' => self::per_page,
'Class', 'class', 'per_class', 'PER_CLASS' => self::per_class,
'Level', 'level', 'per_level', 'PER_LEVEL' => self::per_level,
default => self::all_off,
};
}
/**
* Get internal name from int value
*
* @param int $value
* @return self
*/
public static function fromValue(int $value): self
{
return self::from($value);
}
/**
* convert current set level to name (upper case)
*
* @return string
*/
public function getName(): string
{
return strtoupper($this->name);
}
/** @var int[] */
public const VALUES = [
0,
1,
2,
4,
8,
16,
32,
];
/** @var string[] */
public const NAMES = [
'ALL_OFF',
'PER_RUN',
'PER_DATE',
'PER_GROUP',
'PER_PAGE',
'PER_CLASS',
'PER_LEVEL',
];
}
// __END__

View File

@@ -0,0 +1,216 @@
<?php // phpcs:disable Generic.Files.LineLength
/**
* AUTOR: Clemens Schwaighofer
* CREATED: 2023-05-25
* DESCRIPTION:
* Debug levels
*
* They are based on the Mono log ones
* FC 5424 {@see https://datatracker.ietf.org/doc/html/rfc5424}
*/
declare(strict_types=1);
namespace CoreLibs\Logging\Logger;
use Psr\Log\LogLevel;
/**
* Represents the log levels
*
* Monolog supports the logging levels described by RFC 5424 {@see https://datatracker.ietf.org/doc/html/rfc5424}
* but due to BC the severity values used internally are not 0-7.
*
* To get the level name/value out of a Level there are several options:
*
* - Use ->getName() to get the standard Monolog name which is full uppercased (e.g. "DEBUG")
* - Use ->toPsrLogLevel() to get the standard PSR-3 name which is full lowercased (e.g. "debug")
* - Use ->toRFC5424Level() to get the standard RFC 5424 value (e.g. 7 for debug, 0 for emergency)
* - Use ->name to get the enum case's name which is capitalized (e.g. "Debug")
*
* To get the internal value for filtering, if the includes/isLowerThan/isHigherThan methods are
* not enough, you can use ->value to get the enum case's integer value.
*/
enum Level: int
{
/**
* Detailed debug information
*/
case Debug = 100;
/**
* Interesting events
*
* Examples: User logs in, SQL logs.
*/
case Info = 200;
/**
* Uncommon events
*/
case 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.
*/
case Warning = 300;
/**
* Runtime errors
*/
case Error = 400;
/**
* Critical conditions
*
* Example: Application component unavailable, unexpected exception.
*/
case Critical = 500;
/**
* Action must be taken immediately
*
* Example: Entire website down, database unavailable, etc.
* This should trigger the SMS alerts and wake you up.
*/
case Alert = 550;
/**
* Urgent alert.
*/
case Emergency = 600;
/**
* @param value-of<self::NAMES>|LogLevel::*|'Debug'|'Info'|'Notice'|'Warning'|'Error'|'Critical'|'Alert'|'Emergency' $name
* @return static
*/
public static function fromName(string $name): self
{
return match ($name) {
'debug', 'Debug', 'DEBUG' => self::Debug,
'info', 'Info', 'INFO' => self::Info,
'notice', 'Notice', 'NOTICE' => self::Notice,
'warning', 'Warning', 'WARNING' => self::Warning,
'error', 'Error', 'ERROR' => self::Error,
'critical', 'Critical', 'CRITICAL' => self::Critical,
'alert', 'Alert', 'ALERT' => self::Alert,
'emergency', 'Emergency', 'EMERGENCY' => self::Emergency,
};
}
/**
* @param value-of<self::VALUES> $value
* @return static
*/
public static function fromValue(int $value): self
{
return self::from($value);
}
/**
* Returns true if the passed $level is higher or equal to $this
*/
public function includes(Level $level): bool
{
return $this->value <= $level->value;
}
public function isHigherThan(Level $level): bool
{
return $this->value > $level->value;
}
public function isLowerThan(Level $level): bool
{
return $this->value < $level->value;
}
/**
* Returns the monolog standardized all-capitals name of the level
*
* Use this instead of $level->name which returns the enum case name (e.g. Debug vs DEBUG if you use getName())
*
* @phan-suppress-next-line PhanTypeMismatchDeclaredReturn
* @return value-of<self::NAMES>
*/
public function getName(): string
{
return match ($this) {
self::Debug => 'DEBUG',
self::Info => 'INFO',
self::Notice => 'NOTICE',
self::Warning => 'WARNING',
self::Error => 'ERROR',
self::Critical => 'CRITICAL',
self::Alert => 'ALERT',
self::Emergency => 'EMERGENCY',
};
}
/**
* Returns the PSR-3 level matching this instance
*
* @phpstan-return \Psr\Log\LogLevel::*
*/
public function toPsrLogLevel(): string
{
return match ($this) {
self::Debug => LogLevel::DEBUG,
self::Info => LogLevel::INFO,
self::Notice => LogLevel::NOTICE,
self::Warning => LogLevel::WARNING,
self::Error => LogLevel::ERROR,
self::Critical => LogLevel::CRITICAL,
self::Alert => LogLevel::ALERT,
self::Emergency => LogLevel::EMERGENCY,
};
}
/**
* Returns the RFC 5424 level matching this instance
*
* @phpstan-return int<0, 7>
*/
public function toRFC5424Level(): int
{
return match ($this) {
self::Debug => 7,
self::Info => 6,
self::Notice => 5,
self::Warning => 4,
self::Error => 3,
self::Critical => 2,
self::Alert => 1,
self::Emergency => 0,
};
}
public const VALUES = [
100,
200,
250,
300,
400,
500,
550,
600,
];
public const NAMES = [
'DEBUG',
'INFO',
'NOTICE',
'WARNING',
'ERROR',
'CRITICAL',
'ALERT',
'EMERGENCY',
];
}
// __END__

File diff suppressed because it is too large Load Diff

View File

@@ -219,6 +219,7 @@ declare(strict_types=1);
namespace CoreLibs\Output\Form;
use CoreLibs\Get\System;
use CoreLibs\Debug\Support;
class Generate extends \CoreLibs\DB\Extended\ArrayIO
{
@@ -297,7 +298,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
/** @var \CoreLibs\Language\L10n */
public $l;
// log
/** @var \CoreLibs\Debug\Logging */
/** @var \CoreLibs\Logging\Logging */
public $log;
// now some default error msgs (english)
@@ -308,7 +309,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
* construct form generator
*
* @param array<mixed> $db_config db config array, mandatory
* @param \CoreLibs\Debug\Logging $log Logging class
* @param \CoreLibs\Logging\Logging $log Logging class
* @param \CoreLibs\Language\L10n $l10n l10n language class
* @param array<string,mixed> $login_acl Login ACL array,
* at least base/admin should be set
@@ -319,7 +320,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
*/
public function __construct(
array $db_config,
\CoreLibs\Debug\Logging $log,
\CoreLibs\Logging\Logging $log,
\CoreLibs\Language\L10n $l10n,
array $login_acl,
?array $table_arrays = null,
@@ -327,7 +328,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
// init logger if not set
$this->log = $log;
// don't log per class
$this->log->setLogPer('class', false);
$this->log->unsetLogFlag(\CoreLibs\Logging\Logger\Flag::per_class);
// init the language class
$this->l = $l10n;
// parse and read, legacy stuff
@@ -2618,7 +2619,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
}
// add lost error ones
$this->log->debug('ERROR', 'P: ' . $data['prefix'] . ', '
. $this->log->prAr($_POST['ERROR'][$data['prefix']] ?? []));
. Support::prAr($_POST['ERROR'][$data['prefix']] ?? []));
if ($this->error && !empty($_POST['ERROR'][$data['prefix']])) {
$prfx = $data['prefix']; // short
$_post_data = [];

View File

@@ -32,8 +32,13 @@ function MyErrorHandler(
int $line,
array $context = []
): bool {
/** @phpstan-ignore-next-line cannot check show all errors constant */
if (!(error_reporting() & $type) && SHOW_ALL_ERRORS === false) {
if (!defined('SHOW_ALL_ERRORS')) {
return false;
}
if (
!(error_reporting() & $type) &&
SHOW_ALL_ERRORS === false
) {
// This error code is not included in error_reporting
return false;
}

View File

@@ -18,10 +18,10 @@ class TestDB
/**
* Undocumented function
*
* @param \CoreLibs\Debug\Logging $log
* @param \CoreLibs\Logging\Logging $log
*/
public function __construct(
\CoreLibs\Debug\Logging $log
\CoreLibs\Logging\Logging $log
) {
$this->config = [
'db_name' => $_ENV['DB_NAME_TEST'] ?? '',

View File

@@ -24,7 +24,7 @@ class Test
private $test_db;
public function __construct(
\CoreLibs\Debug\Logging $log
\CoreLibs\Logging\Logging $log
) {
// calls all tests
$this->testPrivate();