Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa5c3b9dcc | ||
|
|
24f7a903ef | ||
|
|
72993925f0 | ||
|
|
29d5ef92d4 | ||
|
|
f66f8f282e | ||
|
|
c010673705 | ||
|
|
b16ff4c613 |
@@ -109,7 +109,10 @@ return [
|
||||
'PhanWriteOnlyPublicProperty',
|
||||
'PhanUnreferencedConstant',
|
||||
'PhanWriteOnlyPublicProperty',
|
||||
'PhanReadOnlyPublicProperty'
|
||||
'PhanReadOnlyPublicProperty',
|
||||
// start ignore annotations
|
||||
'PhanUnextractableAnnotationElementName',
|
||||
'PhanUnextractableAnnotationSuffix',
|
||||
],
|
||||
|
||||
// Override to hardcode existence and types of (non-builtin) globals in the global scope.
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
],
|
||||
"minimum-stability": "dev",
|
||||
"require": {
|
||||
"php": ">=8.1"
|
||||
"php": ">=8.1",
|
||||
"psr/log": "^3.0@dev"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.10",
|
||||
|
||||
@@ -1 +1 @@
|
||||
8.3.1
|
||||
8.5.0
|
||||
|
||||
@@ -68,70 +68,70 @@ declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\ACL;
|
||||
|
||||
use CoreLibs\Check\Password;
|
||||
use CoreLibs\Security\Password;
|
||||
use CoreLibs\Convert\Json;
|
||||
|
||||
class Login
|
||||
{
|
||||
/** @var string the user id var*/
|
||||
private $euid;
|
||||
/** @var ?int the user id var*/
|
||||
private ?int $euid;
|
||||
/** @var string _GET/_POST loginUserId parameter for non password login */
|
||||
private $login_user_id = '';
|
||||
private string $login_user_id = '';
|
||||
/** @var string source, either _GET or _POST or empty */
|
||||
private $login_user_id_source = '';
|
||||
private string $login_user_id_source = '';
|
||||
/** @var bool set to true if illegal characters where found in the login user id string */
|
||||
private $login_user_id_unclear = false;
|
||||
private bool $login_user_id_unclear = false;
|
||||
// is set to one if login okay, or EUID is set and user is okay to access this page
|
||||
/** @var bool */
|
||||
private $permission_okay = false;
|
||||
private bool $permission_okay = false;
|
||||
/** @var string pressed login */
|
||||
private $login = '';
|
||||
private string $login = '';
|
||||
/** @var string master action command */
|
||||
private $action;
|
||||
private string $action;
|
||||
/** @var string login name */
|
||||
private $username;
|
||||
private string $username;
|
||||
/** @var string login password */
|
||||
private $password;
|
||||
private string $password;
|
||||
/** @var string logout button */
|
||||
private $logout;
|
||||
private string $logout;
|
||||
/** @var bool if this is set to true, the user can change passwords */
|
||||
private $password_change = false;
|
||||
private bool $password_change = false;
|
||||
/** @var bool password change was successful */
|
||||
private $password_change_ok = false;
|
||||
private bool $password_change_ok = false;
|
||||
// can we reset password and mail to user with new password set screen
|
||||
/** @var bool */
|
||||
private $password_forgot = false;
|
||||
private bool $password_forgot = false;
|
||||
/** @var bool password forgot mail send ok */
|
||||
// private $password_forgot_ok = false;
|
||||
/** @var string */
|
||||
private $change_password;
|
||||
private string $change_password;
|
||||
/** @var string */
|
||||
private $pw_username;
|
||||
private string $pw_username;
|
||||
/** @var string */
|
||||
private $pw_old_password;
|
||||
private string $pw_old_password;
|
||||
/** @var string */
|
||||
private $pw_new_password;
|
||||
private string $pw_new_password;
|
||||
/** @var string */
|
||||
private $pw_new_password_confirm;
|
||||
private string $pw_new_password_confirm;
|
||||
/** @var array<string> array of users for which the password change is forbidden */
|
||||
private $pw_change_deny_users = [];
|
||||
private array $pw_change_deny_users = [];
|
||||
/** @var string */
|
||||
private $logout_target = '';
|
||||
private string $logout_target = '';
|
||||
/** @var int */
|
||||
private $max_login_error_count = -1;
|
||||
private int $max_login_error_count = -1;
|
||||
/** @var array<string> */
|
||||
private $lock_deny_users = [];
|
||||
private array $lock_deny_users = [];
|
||||
/** @var string */
|
||||
private $page_name = '';
|
||||
private string $page_name = '';
|
||||
|
||||
/** @var int if we have password change we need to define some rules */
|
||||
private $password_min_length = 9;
|
||||
private int $password_min_length = 9;
|
||||
/** @var int an true maxium min, can never be set below this */
|
||||
private $password_min_length_max = 9;
|
||||
private int $password_min_length_max = 9;
|
||||
// max length is fixed as 255 (for input type max), if set highter
|
||||
// it will be set back to 255
|
||||
/** @var int */
|
||||
private $password_max_length = 255;
|
||||
private int $password_max_length = 255;
|
||||
|
||||
/** @var int minum password length */
|
||||
public const PASSWORD_MIN_LENGTH = 9;
|
||||
@@ -158,7 +158,7 @@ class Login
|
||||
. "$/";
|
||||
|
||||
/** @var array<string> can have several regexes, if nothing set, all is ok */
|
||||
private $password_valid_chars = [
|
||||
private array $password_valid_chars = [
|
||||
// '^(?=.*\d)(?=.*[A-Za-z])[0-9A-Za-z!@#$%]{8,}$',
|
||||
// '^(?.*(\pL)u)(?=.*(\pN)u)(?=.*([^\pL\pN])u).{8,}',
|
||||
];
|
||||
@@ -166,13 +166,13 @@ class Login
|
||||
// login error code, can be matched to the array login_error_msg,
|
||||
// which holds the string
|
||||
/** @var int */
|
||||
private $login_error = 0;
|
||||
private int $login_error = 0;
|
||||
/** @var array<mixed> all possible login error conditions */
|
||||
private $login_error_msg = [];
|
||||
private array $login_error_msg = [];
|
||||
// this is an array holding all strings & templates passed
|
||||
// rom the outside (translation)
|
||||
/** @var array<mixed> */
|
||||
private $login_template = [
|
||||
private array $login_template = [
|
||||
'strings' => [],
|
||||
'password_change' => '',
|
||||
'template' => ''
|
||||
@@ -180,59 +180,59 @@ class Login
|
||||
|
||||
// acl vars
|
||||
/** @var array<mixed> */
|
||||
private $acl = [];
|
||||
private array $acl = [];
|
||||
/** @var array<mixed> */
|
||||
private $default_acl_list = [];
|
||||
private array $default_acl_list = [];
|
||||
/** @var array<string,int> Reverse list to lookup level from type */
|
||||
private $default_acl_list_type = [];
|
||||
private array $default_acl_list_type = [];
|
||||
/** @var int default ACL level to be based on if nothing set */
|
||||
private $default_acl_level = 0;
|
||||
private int $default_acl_level = 0;
|
||||
// login html, if we are on an ajax page
|
||||
/** @var string|null */
|
||||
private $login_html = '';
|
||||
private ?string $login_html = '';
|
||||
/** @var bool */
|
||||
private $login_is_ajax_page = false;
|
||||
private bool $login_is_ajax_page = false;
|
||||
|
||||
// settings
|
||||
/** @var array<string,mixed> options */
|
||||
private $options = [];
|
||||
private array $options = [];
|
||||
/** @var array<string,string> locale options: locale, domain, encoding (opt), path */
|
||||
private $locale = [
|
||||
private array $locale = [
|
||||
'locale' => '',
|
||||
'domain' => '',
|
||||
'encoding' => '',
|
||||
'path' => '',
|
||||
];
|
||||
|
||||
/** @var \CoreLibs\Debug\Logging logger */
|
||||
public $log;
|
||||
/** @var \CoreLibs\Logging\Logging logger */
|
||||
public \CoreLibs\Logging\Logging $log;
|
||||
/** @var \CoreLibs\DB\IO database */
|
||||
public $db;
|
||||
public \CoreLibs\DB\IO $db;
|
||||
/** @var \CoreLibs\Language\L10n language */
|
||||
public $l;
|
||||
public \CoreLibs\Language\L10n $l;
|
||||
/** @var \CoreLibs\Create\Session session class */
|
||||
public $session;
|
||||
public \CoreLibs\Create\Session $session;
|
||||
|
||||
/**
|
||||
* constructor, does ALL, opens db, works through connection checks,
|
||||
* 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
|
||||
@@ -883,7 +883,7 @@ class Login
|
||||
}
|
||||
// normal user processing
|
||||
// set class var and session var
|
||||
$_SESSION['EUID'] = $this->euid = $res['edit_user_id'];
|
||||
$_SESSION['EUID'] = $this->euid = (int)$res['edit_user_id'];
|
||||
// check if user is okay
|
||||
$this->loginCheckPermissions();
|
||||
if ($this->login_error == 0) {
|
||||
@@ -1048,7 +1048,7 @@ class Login
|
||||
}
|
||||
// build master unit array
|
||||
$unit_access[$res['edit_access_id']] = [
|
||||
'id' => $res['edit_access_id'],
|
||||
'id' => (int)$res['edit_access_id'],
|
||||
'acl_level' => $res['level'],
|
||||
'acl_type' => $res['type'],
|
||||
'name' => $res['name'],
|
||||
@@ -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
|
||||
@@ -1849,13 +1855,13 @@ HTML;
|
||||
if ($login_user_id_changed > 0) {
|
||||
$this->login_user_id_unclear = true;
|
||||
// error for invalid user id?
|
||||
$this->log->debug('LOGIN USER ID', 'Invalid characters: '
|
||||
$this->log->error('LOGIN USER ID: Invalid characters: '
|
||||
. $login_user_id_changed . ' in loginUserId: '
|
||||
. $this->login_user_id . ' (' . $this->login_user_id_source . ')');
|
||||
}
|
||||
}
|
||||
// if there is none, there is none, saves me POST/GET check
|
||||
$this->euid = array_key_exists('EUID', $_SESSION) ? $_SESSION['EUID'] : 0;
|
||||
$this->euid = array_key_exists('EUID', $_SESSION) ? (int)$_SESSION['EUID'] : 0;
|
||||
// get login vars, are so, can't be changed
|
||||
// prepare
|
||||
// pass on vars to Object vars
|
||||
@@ -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 {
|
||||
@@ -2119,7 +2110,7 @@ HTML;
|
||||
// unset session vars set/used in this login
|
||||
$this->session->sessionDestroy();
|
||||
// unset euid
|
||||
$this->euid = '';
|
||||
$this->euid = null;
|
||||
// then prints the login screen again
|
||||
$this->permission_okay = false;
|
||||
}
|
||||
@@ -2507,7 +2498,7 @@ HTML;
|
||||
*/
|
||||
public function loginGetEuid(): string
|
||||
{
|
||||
return $this->euid;
|
||||
return (string)$this->euid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,97 +35,97 @@ class Backend
|
||||
{
|
||||
// page name
|
||||
/** @var array<mixed> */
|
||||
public $menu = [];
|
||||
public array $menu = [];
|
||||
/** @var int|string */
|
||||
public $menu_show_flag = 0; // top menu flag (mostly string)
|
||||
public int|string $menu_show_flag = 0; // top menu flag (mostly string)
|
||||
// action ids
|
||||
/** @var array<string> */
|
||||
public $action_list = [
|
||||
public array $action_list = [
|
||||
'action', 'action_id', 'action_sub_id', 'action_yes', 'action_flag',
|
||||
'action_menu', 'action_value', 'action_error', 'action_loaded'
|
||||
];
|
||||
/** @var string */
|
||||
public $action;
|
||||
public string $action;
|
||||
/** @var string|int */
|
||||
public $action_id;
|
||||
public string|int $action_id;
|
||||
/** @var string|int */
|
||||
public $action_sub_id;
|
||||
public string|int $action_sub_id;
|
||||
/** @var string|int|bool */
|
||||
public $action_yes;
|
||||
public string|int|bool $action_yes;
|
||||
/** @var string */
|
||||
public $action_flag;
|
||||
public string $action_flag;
|
||||
/** @var string */
|
||||
public $action_menu;
|
||||
public string $action_menu;
|
||||
/** @var string */
|
||||
public $action_loaded;
|
||||
public string $action_loaded;
|
||||
/** @var string */
|
||||
public $action_value;
|
||||
public string $action_value;
|
||||
/** @var string */
|
||||
public $action_error;
|
||||
public string $action_error;
|
||||
// ACL array variable if we want to set acl data from outisde
|
||||
/** @var array<mixed> */
|
||||
public $acl = [];
|
||||
public array $acl = [];
|
||||
/** @var int */
|
||||
public $default_acl;
|
||||
public int $default_acl;
|
||||
// queue key
|
||||
/** @var string */
|
||||
public $queue_key;
|
||||
public string $queue_key;
|
||||
// the current active edit access id
|
||||
/** @var int */
|
||||
public $edit_access_id;
|
||||
/** @var int|null */
|
||||
public int|null $edit_access_id;
|
||||
/** @var string */
|
||||
public $page_name;
|
||||
public string $page_name;
|
||||
// error/warning/info messages
|
||||
/** @var array<mixed> */
|
||||
public $messages = [];
|
||||
public array $messages = [];
|
||||
/** @var bool */
|
||||
public $error = false;
|
||||
public bool $error = false;
|
||||
/** @var bool */
|
||||
public $warning = false;
|
||||
public bool $warning = false;
|
||||
/** @var bool */
|
||||
public $info = false;
|
||||
public bool $info = false;
|
||||
// internal lang & encoding vars
|
||||
/** @var string */
|
||||
public $lang_dir = '';
|
||||
public string $lang_dir = '';
|
||||
/** @var string */
|
||||
public $lang;
|
||||
public string $lang;
|
||||
/** @var string */
|
||||
public $lang_short;
|
||||
public string $lang_short;
|
||||
/** @var string */
|
||||
public $domain;
|
||||
public string $domain;
|
||||
/** @var string */
|
||||
public $encoding;
|
||||
/** @var \CoreLibs\Debug\Logging logger */
|
||||
public $log;
|
||||
public string $encoding;
|
||||
/** @var \CoreLibs\Logging\Logging logger */
|
||||
public \CoreLibs\Logging\Logging $log;
|
||||
/** @var \CoreLibs\DB\IO database */
|
||||
public $db;
|
||||
public \CoreLibs\DB\IO $db;
|
||||
/** @var \CoreLibs\Language\L10n language */
|
||||
public $l;
|
||||
public \CoreLibs\Language\L10n $l;
|
||||
/** @var \CoreLibs\Create\Session session class */
|
||||
public $session;
|
||||
public \CoreLibs\Create\Session $session;
|
||||
// smarty publics [end processing in smarty class]
|
||||
/** @var array<mixed> */
|
||||
public $DATA;
|
||||
public array $DATA = [];
|
||||
/** @var array<mixed> */
|
||||
public $HEADER;
|
||||
public array $HEADER = [];
|
||||
/** @var array<mixed> */
|
||||
public $DEBUG_DATA;
|
||||
public array $DEBUG_DATA = [];
|
||||
/** @var array<mixed> */
|
||||
public $CONTENT_DATA;
|
||||
public array $CONTENT_DATA = [];
|
||||
|
||||
// CONSTRUCTOR / DECONSTRUCTOR |====================================>
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -20,36 +20,36 @@ use SmartyException;
|
||||
class EditBase
|
||||
{
|
||||
/** @var array<mixed> */
|
||||
private $HEADER = [];
|
||||
private array $HEADER = [];
|
||||
/** @var array<mixed> */
|
||||
private $DATA = [];
|
||||
private array $DATA = [];
|
||||
/** @var array<mixed> */
|
||||
private $DEBUG_DATA = [];
|
||||
private array $DEBUG_DATA = [];
|
||||
|
||||
/** @var string the template name */
|
||||
private $EDIT_TEMPLATE = '';
|
||||
private string $EDIT_TEMPLATE = '';
|
||||
|
||||
/** @var \CoreLibs\Template\SmartyExtend smarty system */
|
||||
private $smarty;
|
||||
private \CoreLibs\Template\SmartyExtend $smarty;
|
||||
/** @var \CoreLibs\Output\Form\Generate form generate system */
|
||||
private $form;
|
||||
/** @var \CoreLibs\Debug\Logging */
|
||||
public $log;
|
||||
private \CoreLibs\Output\Form\Generate $form;
|
||||
/** @var \CoreLibs\Logging\Logging */
|
||||
public \CoreLibs\Logging\Logging $log;
|
||||
/** @var \CoreLibs\ACL\Login */
|
||||
public $login;
|
||||
public \CoreLibs\ACL\Login $login;
|
||||
|
||||
/**
|
||||
* 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(
|
||||
|
||||
121
src/Basic.php
121
src/Basic.php
@@ -58,39 +58,39 @@ class Basic
|
||||
{
|
||||
// page and host name
|
||||
/** @var string */
|
||||
public $page_name;
|
||||
public string $page_name;
|
||||
/** @var string */
|
||||
public $host_name;
|
||||
public string $host_name;
|
||||
/** @var int */
|
||||
public $host_port;
|
||||
public int $host_port;
|
||||
// logging interface, Debug\Logging class
|
||||
/** @var \CoreLibs\Debug\Logging */
|
||||
public $log;
|
||||
/** @var \CoreLibs\Logging\Logging */
|
||||
public \CoreLibs\Logging\Logging $log;
|
||||
/** @var \CoreLibs\Create\Session */
|
||||
public $session;
|
||||
public \CoreLibs\Create\Session $session;
|
||||
|
||||
// email valid checks
|
||||
/** @var array<mixed> */
|
||||
public $email_regex_check = [];
|
||||
public array $email_regex_check = [];
|
||||
/** @var string */
|
||||
public $email_regex; // regex var for email check
|
||||
public string $email_regex; // regex var for email check
|
||||
|
||||
// data path for files
|
||||
/** @var array<mixed> */
|
||||
public $data_path = [];
|
||||
public array $data_path = [];
|
||||
|
||||
// ajax flag
|
||||
/** @var bool */
|
||||
protected $ajax_page_flag = false;
|
||||
protected bool $ajax_page_flag = false;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1164,7 +1109,7 @@ class Basic
|
||||
public function passwordSet(string $password): string
|
||||
{
|
||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Check\Password::passwordSet()', E_USER_DEPRECATED);
|
||||
return \CoreLibs\Check\Password::passwordSet($password);
|
||||
return \CoreLibs\Security\Password::passwordSet($password);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1177,7 +1122,7 @@ class Basic
|
||||
public function passwordVerify(string $password, string $hash): bool
|
||||
{
|
||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Check\Password::passwordVerify()', E_USER_DEPRECATED);
|
||||
return \CoreLibs\Check\Password::passwordVerify($password, $hash);
|
||||
return \CoreLibs\Security\Password::passwordVerify($password, $hash);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1189,7 +1134,7 @@ class Basic
|
||||
public function passwordRehashCheck(string $hash): bool
|
||||
{
|
||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Check\Password::passwordRehashCheck()', E_USER_DEPRECATED);
|
||||
return \CoreLibs\Check\Password::passwordRehashCheck($hash);
|
||||
return \CoreLibs\Security\Password::passwordRehashCheck($hash);
|
||||
}
|
||||
|
||||
// *** BETTER PASSWORD OPTIONS END ***
|
||||
|
||||
@@ -8,7 +8,7 @@ class Email
|
||||
{
|
||||
// this is for error check parts in where the email regex failed
|
||||
/** @var array<int,string> */
|
||||
private static $email_regex_check = [
|
||||
private static array $email_regex_check = [
|
||||
0 => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@"
|
||||
. "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$", // MASTER
|
||||
1 => "@(.*)@(.*)", // double @
|
||||
@@ -21,7 +21,7 @@ class Email
|
||||
];
|
||||
// for above position, description string below
|
||||
/** @var array<int,string> */
|
||||
private static $email_regex_check_message = [
|
||||
private static array $email_regex_check_message = [
|
||||
0 => 'Invalid email address',
|
||||
1 => 'Double @ mark in email address',
|
||||
2 => 'Invalid email part before @ sign',
|
||||
@@ -33,7 +33,7 @@ class Email
|
||||
];
|
||||
// the array with the mobile types that are valid
|
||||
/** @var array<string,string> */
|
||||
private static $mobile_email_type = [
|
||||
private static array $mobile_email_type = [
|
||||
'.*@docomo\.ne\.jp$' => 'keitai_docomo',
|
||||
// correct are a[2-4], b2, c[1-9], e[2-9], h[2-4], t[1-9]
|
||||
'.*@([a-z0-9]{2}\.)?ezweb\.ne\.jp$' => 'keitai_kddi_ezweb',
|
||||
@@ -72,7 +72,7 @@ class Email
|
||||
];
|
||||
// short list for mobile email types
|
||||
/** @var array<string,string> */
|
||||
private static $mobile_email_type_short = [
|
||||
private static array $mobile_email_type_short = [
|
||||
'keitai_docomo' => 'docomo',
|
||||
'keitai_kddi_ezweb' => 'kddi',
|
||||
'keitai_kddi' => 'kddi',
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace CoreLibs\Check;
|
||||
class Encoding
|
||||
{
|
||||
/** @var int<min, -1>|int<1, max>|string */
|
||||
private static $mb_error_char = '';
|
||||
private static int|string $mb_error_char = '';
|
||||
|
||||
/**
|
||||
* set error char
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* NOTE: this is deprecated and all moved \CoreLibs\Security\Password
|
||||
*
|
||||
* core password set, check and rehash check wrapper functions
|
||||
*/
|
||||
|
||||
@@ -8,6 +10,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Check;
|
||||
|
||||
use CoreLibs\Security\Password as PasswordNew;
|
||||
|
||||
class Password
|
||||
{
|
||||
/**
|
||||
@@ -15,13 +19,16 @@ class Password
|
||||
*
|
||||
* @param string $password password
|
||||
* @return string hashed password
|
||||
* @deprecated v9.0 Moved to \CoreLibs\Security\Password::passwordSet
|
||||
*/
|
||||
public static function passwordSet(string $password): string
|
||||
{
|
||||
// always use the PHP default for the password
|
||||
// password options ca be set in the password init,
|
||||
// but should be kept as default
|
||||
return password_hash($password, PASSWORD_DEFAULT);
|
||||
trigger_error(
|
||||
'Method ' . __METHOD__ . ' is deprecated, use '
|
||||
. '\CoreLibs\Security\Password::passwordSet',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
return PasswordNew::passwordSet($password);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,14 +37,16 @@ class Password
|
||||
* @param string $password password
|
||||
* @param string $hash password hash
|
||||
* @return bool true or false
|
||||
* @deprecated v9.0 Moved to \CoreLibs\Security\Password::passwordVerify
|
||||
*/
|
||||
public static function passwordVerify(string $password, string $hash): bool
|
||||
{
|
||||
if (password_verify($password, $hash)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
trigger_error(
|
||||
'Method ' . __METHOD__ . ' is deprecated, use '
|
||||
. '\CoreLibs\Security\Password::passwordVerify',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
return PasswordNew::passwordVerify($password, $hash);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,14 +54,16 @@ class Password
|
||||
*
|
||||
* @param string $hash password hash
|
||||
* @return bool true or false
|
||||
* @deprecated v9.0 Moved to \CoreLibs\Security\Password::passwordRehashCheck
|
||||
*/
|
||||
public static function passwordRehashCheck(string $hash): bool
|
||||
{
|
||||
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
trigger_error(
|
||||
'Method ' . __METHOD__ . ' is deprecated, use '
|
||||
. '\CoreLibs\Security\Password::passwordRehashCheck',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
return PasswordNew::passwordRehashCheck($hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace CoreLibs\Convert;
|
||||
class MimeAppName
|
||||
{
|
||||
/** @var array<string,string> */
|
||||
private static $mime_apps = [];
|
||||
private static array $mime_apps = [];
|
||||
|
||||
/**
|
||||
* constructor: init mime list
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace CoreLibs\Create;
|
||||
class Email
|
||||
{
|
||||
/** @var array<string> allowed list for encodings that can do KV folding */
|
||||
private static $encoding_kv_allowed = [
|
||||
private static array $encoding_kv_allowed = [
|
||||
'UTF-8',
|
||||
'EUC-JP',
|
||||
'SJIS',
|
||||
@@ -25,7 +25,7 @@ class Email
|
||||
'JIS-ms',
|
||||
];
|
||||
/** @var string normaly this does not need to be changed */
|
||||
private static $mb_convert_kana_mode = 'KV';
|
||||
private static string $mb_convert_kana_mode = 'KV';
|
||||
|
||||
/**
|
||||
* create mime encoded email part for to/from emails.
|
||||
@@ -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' ?
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace CoreLibs\Create;
|
||||
|
||||
class Hash
|
||||
{
|
||||
public const DEFAULT_HASH = 'adler32';
|
||||
public const STANDARD_HASH_LONG = 'ripemd160';
|
||||
public const STANDARD_HASH_SHORT = 'adler32';
|
||||
|
||||
@@ -58,7 +59,7 @@ class Hash
|
||||
/**
|
||||
* replacemend for __crc32b call (alternate)
|
||||
* defaults to adler 32
|
||||
* allowed crc32b, adler32, fnv132, fnv1a32, joaat
|
||||
* allowed: any in hash algos list, default to adler 32
|
||||
* all that create 8 char long hashes
|
||||
*
|
||||
* @param string $string string to hash
|
||||
@@ -67,15 +68,15 @@ class Hash
|
||||
*/
|
||||
public static function __hash(
|
||||
string $string,
|
||||
string $hash_type = self::STANDARD_HASH_SHORT
|
||||
string $hash_type = self::DEFAULT_HASH
|
||||
): string {
|
||||
// if not empty, check if in valid list
|
||||
if (
|
||||
!in_array(
|
||||
$hash_type,
|
||||
['crc32b', 'adler32', 'fnv132', 'fnv1a32', 'joaat']
|
||||
)
|
||||
empty($hash_type) ||
|
||||
!in_array($hash_type, hash_algos())
|
||||
) {
|
||||
$hash_type = 'adler32';
|
||||
// fallback to default hash type if none set or invalid
|
||||
$hash_type = self::DEFAULT_HASH;
|
||||
}
|
||||
return hash($hash_type, $string);
|
||||
}
|
||||
|
||||
@@ -12,13 +12,13 @@ class RandomKey
|
||||
{
|
||||
// key generation
|
||||
/** @var string */
|
||||
private static $key_range = '';
|
||||
private static string $key_range = '';
|
||||
/** @var int */
|
||||
private static $one_key_length;
|
||||
private static int $one_key_length;
|
||||
/** @var int */
|
||||
private static $key_length = 4; // default key length
|
||||
private static int $key_length = 4; // default key length
|
||||
/** @var int */
|
||||
private static $max_key_length = 256; // max allowed length
|
||||
private static int $max_key_length = 256; // max allowed length
|
||||
|
||||
/**
|
||||
* if launched as class, init random key data first
|
||||
@@ -100,7 +100,9 @@ class RandomKey
|
||||
public static function randomKeyGen(int $key_length = -1): string
|
||||
{
|
||||
// init random key strings if not set
|
||||
if (!is_numeric(self::$one_key_length)) {
|
||||
if (
|
||||
!isset(self::$one_key_length)
|
||||
) {
|
||||
self::initRandomKeyData();
|
||||
}
|
||||
$use_key_length = 0;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace CoreLibs\Create;
|
||||
class Session
|
||||
{
|
||||
/** @var string list for errors */
|
||||
private $session_intern_error_str = '';
|
||||
private string $session_intern_error_str = '';
|
||||
|
||||
/**
|
||||
* init a session, if array is empty or array does not have session_name set
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Create uniqIds
|
||||
*
|
||||
* If convert ID to hash:
|
||||
* https://github.com/vinkla/hashids
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Create;
|
||||
@@ -7,10 +14,39 @@ namespace CoreLibs\Create;
|
||||
class Uids
|
||||
{
|
||||
// what to use as a default hash if non ise set and no DEFAULT_HASH is defined
|
||||
public const DEFAULT_HASH = 'sha256';
|
||||
|
||||
/** @var int */
|
||||
public const DEFAULT_UNNIQ_ID_LENGTH = 64;
|
||||
/** @var string */
|
||||
public const STANDARD_HASH_LONG = 'ripemd160';
|
||||
/** @var string */
|
||||
public const STANDARD_HASH_SHORT = 'adler32';
|
||||
|
||||
/**
|
||||
* Create unique id, lower length is for
|
||||
*
|
||||
* @param int $length Length for uniq id, min is 4 characters
|
||||
* Uneven lengths will return lower bound (9 -> 8)
|
||||
* @param bool $force_length [default=false] if set to true and we have
|
||||
* uneven length, then we shorten to this length
|
||||
* @return string Uniq id
|
||||
*/
|
||||
private static function uniqIdL(int $length = 64, bool $force_length = false): string
|
||||
{
|
||||
$uniqid_length = ($length < 4) ? 4 : $length;
|
||||
if ($force_length) {
|
||||
$uniqid_length++;
|
||||
}
|
||||
/** @var int<1,max> make sure that internal this is correct */
|
||||
$random_bytes_length = ($uniqid_length - ($uniqid_length % 2)) / 2;
|
||||
$uniqid = bin2hex(random_bytes($random_bytes_length));
|
||||
// if not forced shorten return next lower length
|
||||
if (!$force_length) {
|
||||
return $uniqid;
|
||||
}
|
||||
return substr($uniqid, 0, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* creates psuedo random uuid v4
|
||||
* Code take from class here:
|
||||
@@ -20,7 +56,7 @@ class Uids
|
||||
*/
|
||||
public static function uuidv4(): string
|
||||
{
|
||||
return sprintf(
|
||||
/* return sprintf(
|
||||
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
// 32 bits for "time_low"
|
||||
mt_rand(0, 0xffff),
|
||||
@@ -38,49 +74,62 @@ class Uids
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0xffff)
|
||||
);
|
||||
); */
|
||||
|
||||
$data = random_bytes(16);
|
||||
assert(strlen($data) == 16);
|
||||
|
||||
// 0-1: 32 bits for "time_low"
|
||||
// 2: 16 bits for "time_mid"
|
||||
// 3: 16 bits for "time_hi_and_version",
|
||||
// four most significant bits holds version number 4
|
||||
$data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
|
||||
// 4: 16 bits, 8 bits for "clk_seq_hi_res",
|
||||
// 8 bits for "clk_seq_low",
|
||||
// two most significant bits holds zero and one for variant DCE1.1
|
||||
$data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
|
||||
// 5-7: 48 bits for "node"
|
||||
|
||||
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: make this a proper uniq ID creation
|
||||
* add uuidv4 subcall to the uuid function too
|
||||
* creates a uniq id
|
||||
* creates a uniq id based on lengths
|
||||
*
|
||||
* @param string $type uniq id type, currently md5 or sha256 allowed
|
||||
* if not set will use DEFAULT_HASH if set
|
||||
* @return string uniq id
|
||||
* @param int|string $length Either length in int, or fallback type for length
|
||||
* for string type md5 (32), sha256 (64)
|
||||
* STANDARD_HASH_LONG: ripemd160 (40)
|
||||
* STANDARD_HASH_SHORT: adler32 (8)
|
||||
* It is recommended to use the integer
|
||||
* @param bool $force_length [default=false] if set to true and we have
|
||||
* uneven length, then we shorten to this length
|
||||
* @return string Uniq id
|
||||
*/
|
||||
public static function uniqId(string $type = ''): string
|
||||
{
|
||||
$uniq_id = '';
|
||||
switch ($type) {
|
||||
public static function uniqId(
|
||||
int|string $length = self::DEFAULT_UNNIQ_ID_LENGTH,
|
||||
bool $force_length = false
|
||||
): string {
|
||||
if (is_int($length)) {
|
||||
return self::uniqIdL($length, $force_length);
|
||||
}
|
||||
switch ($length) {
|
||||
case 'md5':
|
||||
$uniq_id = md5(uniqid((string)rand(), true));
|
||||
$length = 32;
|
||||
break;
|
||||
case self::DEFAULT_HASH:
|
||||
$uniq_id = hash(self::DEFAULT_HASH, uniqid((string)rand(), true));
|
||||
case 'sha256':
|
||||
$length = 64;
|
||||
break;
|
||||
case self::STANDARD_HASH_LONG:
|
||||
$uniq_id = hash(self::STANDARD_HASH_LONG, uniqid((string)rand(), true));
|
||||
$length = 40;
|
||||
break;
|
||||
case self::STANDARD_HASH_SHORT:
|
||||
$uniq_id = hash(self::STANDARD_HASH_SHORT, uniqid((string)rand(), true));
|
||||
$length = 8;
|
||||
break;
|
||||
default:
|
||||
// if not empty, check if in valid list
|
||||
if (
|
||||
!empty($type) &&
|
||||
in_array($type, hash_algos())
|
||||
) {
|
||||
$hash = $type;
|
||||
} else {
|
||||
// fallback to default hash type if none set or invalid
|
||||
$hash = self::DEFAULT_HASH;
|
||||
}
|
||||
$uniq_id = hash($hash, uniqid((string)rand(), true));
|
||||
$length = 64;
|
||||
break;
|
||||
}
|
||||
return $uniq_id;
|
||||
return self::uniqIdL($length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,16 +39,16 @@ class ArrayIO extends \CoreLibs\DB\IO
|
||||
{
|
||||
// main calss variables
|
||||
/** @var array<mixed> */
|
||||
public $table_array; // the array from the table to work on
|
||||
public array $table_array; // the array from the table to work on
|
||||
/** @var string */
|
||||
public $table_name; // the table_name
|
||||
public string $table_name; // the table_name
|
||||
/** @var string */
|
||||
public $pk_name = ''; // the primary key from this table
|
||||
public string $pk_name = ''; // the primary key from this table
|
||||
/** @var int|string|null */
|
||||
public $pk_id; // the PK id
|
||||
public int|string|null $pk_id; // the PK id
|
||||
// security values
|
||||
/** @var int base acl for current page */
|
||||
private $base_acl_level = 0;
|
||||
private int $base_acl_level = 0;
|
||||
|
||||
/**
|
||||
* constructor for the array io class, set the
|
||||
@@ -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
|
||||
) {
|
||||
@@ -243,7 +243,7 @@ class ArrayIO extends \CoreLibs\DB\IO
|
||||
return $this->table_array;
|
||||
}
|
||||
if ($acl_limit === true && $this->base_acl_level < 100) {
|
||||
$this->log->debug('DB DELETE ERROR', 'ACL Limit on, Delete, '
|
||||
$this->log->error('DB DELETE ERROR: ACL Limit on, Delete, '
|
||||
. 'but base ACL level of 100 not met: ' . $this->base_acl_level);
|
||||
return $this->table_array;
|
||||
}
|
||||
@@ -406,7 +406,7 @@ class ArrayIO extends \CoreLibs\DB\IO
|
||||
}
|
||||
// early abort for new write with not enough ACL level
|
||||
if ($insert && $acl_limit === true && $this->base_acl_level < 100) {
|
||||
$this->log->debug('DB WRITE ERROR', 'ACL Limit on, Insert, '
|
||||
$this->log->error('DB WRITE ERROR: ACL Limit on, Insert, '
|
||||
. 'but base ACL level of 100 not met: ' . $this->base_acl_level);
|
||||
return $this->table_array;
|
||||
}
|
||||
@@ -579,7 +579,7 @@ class ArrayIO extends \CoreLibs\DB\IO
|
||||
} // while ...
|
||||
|
||||
if (empty($q_data)) {
|
||||
$this->log->debug('DB WRITE ERROR', 'No data to write, possible through ACL');
|
||||
$this->log->error('DB WRITE ERROR: No data to write, possible through ACL');
|
||||
return $this->table_array;
|
||||
}
|
||||
|
||||
|
||||
168
src/DB/IO.php
168
src/DB/IO.php
@@ -298,111 +298,108 @@ class IO
|
||||
// can bet set from outside
|
||||
// encoding to
|
||||
/** @var string */
|
||||
private $to_encoding = '';
|
||||
/** @var string */
|
||||
private $query; // the query string at the moment
|
||||
/** @var array<mixed> */
|
||||
private $params; // current params for query
|
||||
private string $to_encoding = '';
|
||||
/** @var string the query string at the moment */
|
||||
private string $query;
|
||||
/** @var array<mixed> current params for query */
|
||||
private array $params;
|
||||
// only inside
|
||||
// basic vars
|
||||
/** @var \PgSql\Connection|false|null */ // replace object with PgSql\Connection|
|
||||
private $dbh; // the dbh handler, if disconnected by command is null, bool:false on error,
|
||||
/** @var bool */
|
||||
private $db_debug = false; // DB_DEBUG ... (if set prints out debug msgs)
|
||||
/** @var string */
|
||||
private $db_name; // the DB connected to
|
||||
/** @var string */
|
||||
private $db_user; // the username used
|
||||
/** @var string */
|
||||
private $db_pwd; // the password used
|
||||
/** @var string */
|
||||
private $db_host; // the hostname
|
||||
/** @var int */
|
||||
private $db_port; // default db port
|
||||
/** @var string */
|
||||
private $db_schema; // optional DB schema, if not set uses public
|
||||
/** @var string */
|
||||
private $db_encoding; // optional auto encoding convert, not used if not set
|
||||
/** @var string */
|
||||
private $db_type; // type of db (mysql,postgres,...)
|
||||
/** @var string */
|
||||
private $db_ssl; // ssl flag (for postgres only), disable, allow, prefer, require
|
||||
// the dbh handler, if disconnected by command is null, bool:false on error,
|
||||
/** @var \PgSql\Connection|false|null */
|
||||
private \PgSql\Connection|false|null $dbh;
|
||||
/** @var bool DB_DEBUG ... (if set prints out debug msgs) */
|
||||
private bool $db_debug = false;
|
||||
/** @var string the DB connected to */
|
||||
private string $db_name;
|
||||
/** @var string the username used */
|
||||
private string $db_user;
|
||||
/** @var string the password used*/
|
||||
private string $db_pwd;
|
||||
/** @var string the hostname */
|
||||
private string $db_host;
|
||||
/** @var int default db port */
|
||||
private int $db_port;
|
||||
/** @var string optional DB schema, if not set uses public*/
|
||||
private string $db_schema;
|
||||
/** @var string optional auto encoding convert, not used if not set */
|
||||
private string $db_encoding;
|
||||
/** @var string type of db (mysql,postgres,...) */
|
||||
private string $db_type;
|
||||
/** @var string ssl flag (for postgres only), disable, allow, prefer, require */
|
||||
private string $db_ssl;
|
||||
// FOR BELOW: (This should be private and only readable through some method)
|
||||
// cursor array for cached readings
|
||||
/** @var array<mixed,mixed> */
|
||||
private $cursor_ext; // hash of hashes
|
||||
/** @var array<string,mixed> extended cursoers string index with content */
|
||||
private array $cursor_ext;
|
||||
// per query vars
|
||||
/** @var \PgSql\Result|false */ // replace object with PgSql\Result
|
||||
private $cursor; // actual cursor (DBH)
|
||||
/** @var int */
|
||||
private $num_rows; // how many rows have been found
|
||||
/** @var int */
|
||||
private $num_fields; // how many fields has the query
|
||||
/** @var \PgSql\Result|false actual cursor (DBH) */
|
||||
private \PgSql\Result|false $cursor;
|
||||
/** @var int how many rows have been found */
|
||||
private int $num_rows;
|
||||
/** @var int how many fields has the query */
|
||||
private int $num_fields;
|
||||
/** @var array<string> array with the field names of the current query */
|
||||
private $field_names = [];
|
||||
private array $field_names = [];
|
||||
/** @var array<string> field type names */
|
||||
private $field_types = [];
|
||||
/** @var array<mixed> */
|
||||
private $insert_id_arr = []; // always return as array, even if only one
|
||||
/** @var string */
|
||||
private $insert_id_pk_name; // primary key name for insert recovery from insert_id_arr
|
||||
private array $field_types = [];
|
||||
/** @var array<mixed> always return as array, even if only one */
|
||||
private array $insert_id_arr = [];
|
||||
/** @var string primary key name for insert recovery from insert_id_arr */
|
||||
private string $insert_id_pk_name;
|
||||
// other vars
|
||||
/** @var string */
|
||||
private $nbsp = ''; // used by print_array recursion function
|
||||
/** @var string used by print_array recursion function */
|
||||
private string $nbsp = '';
|
||||
// error & warning id
|
||||
/** @var string */
|
||||
private $error_id;
|
||||
private string $error_id;
|
||||
/** @var string */
|
||||
private $warning_id;
|
||||
private string $warning_id;
|
||||
/** @var string */
|
||||
private $error_history_id;
|
||||
private string $error_history_id;
|
||||
/** @var array<mixed> Stores warning and errors combinded with detail info */
|
||||
private $error_history_long = [];
|
||||
// error thrown on class init if we cannot connect to db
|
||||
/** @var bool */
|
||||
protected $db_connection_closed = false;
|
||||
private array $error_history_long = [];
|
||||
/** @var bool error thrown on class init if we cannot connect to db */
|
||||
protected bool $db_connection_closed = false;
|
||||
// sub include with the database functions
|
||||
/** @var \CoreLibs\DB\SQL\PgSQL if we have other DB types we need to add them here */
|
||||
private $db_functions;
|
||||
private \CoreLibs\DB\SQL\PgSQL $db_functions;
|
||||
// endless loop protection
|
||||
/** @var int */
|
||||
private $MAX_QUERY_CALL;
|
||||
/** @var int */
|
||||
public const DEFAULT_MAX_QUERY_CALL = 20; // default
|
||||
private int $MAX_QUERY_CALL;
|
||||
/** @var int maxium query calls allowed in a dbReturnRow loop before we error out */
|
||||
public const DEFAULT_MAX_QUERY_CALL = 20;
|
||||
/** @var array<mixed> */
|
||||
private $query_called = [];
|
||||
private array $query_called = [];
|
||||
// error string
|
||||
/** @var array<mixed> */
|
||||
protected $error_string = [];
|
||||
protected array $error_string = [];
|
||||
// prepared list
|
||||
/** @var array<mixed> */
|
||||
private $prepare_cursor = [];
|
||||
private array $prepare_cursor = [];
|
||||
// primary key per table list
|
||||
// format is 'table' => 'pk_name'
|
||||
/** @var array<mixed> */
|
||||
private $pk_name_table = [];
|
||||
// internal primary key name, for cross calls in async
|
||||
/** @var string */
|
||||
private $pk_name;
|
||||
// if we use RETURNING in the INSERT call
|
||||
/** @var bool */
|
||||
private $returning_id = false;
|
||||
// if a sync is running holds the hash key of the query
|
||||
/** @var string */
|
||||
private $async_running;
|
||||
private array $pk_name_table = [];
|
||||
/** @var string internal primary key name, for cross calls in async */
|
||||
private string $pk_name;
|
||||
/** @var bool if we use RETURNING in the INSERT call */
|
||||
private bool $returning_id = false;
|
||||
/** @var string if a sync is running holds the hash key of the query */
|
||||
private string $async_running;
|
||||
// logging class, must be public so settings can be changed
|
||||
/** @var \CoreLibs\Debug\Logging */
|
||||
public $log;
|
||||
/** @var \CoreLibs\Logging\Logging */
|
||||
public \CoreLibs\Logging\Logging $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 +700,20 @@ 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);
|
||||
switch ($id) {
|
||||
case 'DB_ERROR':
|
||||
$this->log->error($debug_id . ' :' . $prefix . $error_string);
|
||||
break;
|
||||
case 'DB_WARNING':
|
||||
$this->log->warning($debug_id . ' :' . $prefix . $error_string);
|
||||
break;
|
||||
default:
|
||||
$this->log->debug($debug_id, $error_string, $prefix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1366,7 +1373,10 @@ class IO
|
||||
*/
|
||||
public function dbClose(): void
|
||||
{
|
||||
if ($this->dbh) {
|
||||
if (
|
||||
!empty($this->dbh) &&
|
||||
$this->dbh instanceof \PgSql\Connection
|
||||
) {
|
||||
// reset any client encodings set
|
||||
$this->dbResetEncoding();
|
||||
// calls db close
|
||||
@@ -2735,9 +2745,9 @@ class IO
|
||||
}
|
||||
$result = $this->db_functions->__dbExecute($stm_name, $data);
|
||||
if ($result === false) {
|
||||
$this->log->debug('ExecuteData', 'ERROR in STM[' . $stm_name . '|'
|
||||
$this->log->error('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'],
|
||||
@@ -3398,6 +3408,9 @@ class IO
|
||||
*/
|
||||
public function dbGetInsertPKName(): string
|
||||
{
|
||||
if (!isset($this->insert_id_pk_name)) {
|
||||
return '';
|
||||
}
|
||||
return (string)$this->insert_id_pk_name;
|
||||
}
|
||||
|
||||
@@ -3506,6 +3519,9 @@ class IO
|
||||
*/
|
||||
public function dbGetNumFields(): ?int
|
||||
{
|
||||
if (!isset($this->num_fields)) {
|
||||
return null;
|
||||
}
|
||||
return $this->num_fields;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,9 +59,9 @@ namespace CoreLibs\DB\SQL;
|
||||
class PgSQL implements Interface\SqlFunctions
|
||||
{
|
||||
/** @var string */
|
||||
private $last_error_query;
|
||||
private string $last_error_query;
|
||||
/** @var \PgSql\Connection|false */
|
||||
private $dbh = false;
|
||||
private \PgSql\Connection|false $dbh = false;
|
||||
|
||||
/**
|
||||
* queries last error query and returns true or false if error was set
|
||||
|
||||
@@ -12,9 +12,9 @@ namespace CoreLibs\Debug;
|
||||
class FileWriter
|
||||
{
|
||||
/** @var string */
|
||||
private static $debug_filename = 'debug_file.log'; // where to write output
|
||||
private static string $debug_filename = 'debug_file.log'; // where to write output
|
||||
/** @var string */
|
||||
private static $debug_folder;
|
||||
private static string $debug_folder;
|
||||
|
||||
/**
|
||||
* Set a debug log folder, if not set BASE+LOG folders are set
|
||||
@@ -77,7 +77,7 @@ class FileWriter
|
||||
) {
|
||||
/** @deprecated Do not use this anymore, define path with fsetFolder */
|
||||
trigger_error(
|
||||
'fsetFolder must be set first. Setting via LOG_FILE_ID and LOg constants is deprecated',
|
||||
'fsetFolder must be set first. Setting via LOG_FILE_ID and LOG constants is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
self::$debug_folder = BASE . LOG;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
911
src/Debug/LoggingLegacy.php
Normal file
911
src/Debug/LoggingLegacy.php
Normal 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__
|
||||
@@ -13,13 +13,13 @@ use CoreLibs\Convert\Byte;
|
||||
class MemoryUsage
|
||||
{
|
||||
/** @var int */
|
||||
private static $start_memory = 0;
|
||||
private static int $start_memory = 0;
|
||||
/** @var int */
|
||||
private static $set_memory = 0;
|
||||
private static int $set_memory = 0;
|
||||
/** @var int */
|
||||
private static $previous_memory = 0;
|
||||
private static int $previous_memory = 0;
|
||||
/** @var bool */
|
||||
private static $debug_memory = false;
|
||||
private static bool $debug_memory = false;
|
||||
|
||||
/**
|
||||
* set memory flag, or return set memory flag
|
||||
|
||||
@@ -12,18 +12,18 @@ class RunningTime
|
||||
{
|
||||
// hr
|
||||
/** @var float */
|
||||
private static $hr_start_time;
|
||||
private static float $hr_start_time;
|
||||
/** @var float */
|
||||
private static $hr_end_time;
|
||||
private static float $hr_end_time;
|
||||
/** @var float */
|
||||
private static $hr_last_time;
|
||||
private static float $hr_last_time;
|
||||
// normal
|
||||
/** @var float */
|
||||
private static $start_time;
|
||||
private static float $start_time;
|
||||
/** @var float */
|
||||
private static $end_time;
|
||||
private static float $end_time;
|
||||
/** @var string */
|
||||
private static $running_time_string;
|
||||
private static string $running_time_string;
|
||||
|
||||
/**
|
||||
* sub calculation for running time based on out time.
|
||||
@@ -79,7 +79,7 @@ class RunningTime
|
||||
public static function hrRunningTime(string $out_time = 'ms'): float
|
||||
{
|
||||
// if start time not set, set start time
|
||||
if (!self::$hr_start_time) {
|
||||
if (empty(self::$hr_start_time)) {
|
||||
self::$hr_start_time = hrtime(true);
|
||||
self::$hr_last_time = self::$hr_start_time;
|
||||
$run_time = 0;
|
||||
@@ -137,7 +137,7 @@ class RunningTime
|
||||
list($micro, $timestamp) = explode(' ', microtime());
|
||||
$running_time = 0;
|
||||
// set start & end time
|
||||
if (!self::$start_time) {
|
||||
if (empty(self::$start_time)) {
|
||||
// always reset running time string on first call
|
||||
self::$running_time_string = '';
|
||||
self::$start_time = ((float)$micro + (float)$timestamp);
|
||||
@@ -149,7 +149,7 @@ class RunningTime
|
||||
self::$running_time_string .= date('Y-m-d H:i:s', (int)$timestamp);
|
||||
self::$running_time_string .= ' ' . $micro . ($simple ? ', ' : '<br>');
|
||||
// if both are set
|
||||
if (self::$start_time && self::$end_time) {
|
||||
if (!empty(self::$start_time) && !empty(self::$end_time)) {
|
||||
$running_time = self::$end_time - self::$start_time;
|
||||
self::$running_time_string .= ($simple ? 'Run: ' : "<b>Script running time</b>: ") . $running_time . " s";
|
||||
// reset start & end time after run
|
||||
|
||||
@@ -21,7 +21,7 @@ class Support
|
||||
*/
|
||||
public static function printTime(int $set_microtime = -1): string
|
||||
{
|
||||
list($microtime, $timestamp) = explode(' ', microtime());
|
||||
[$microtime, $timestamp] = explode(' ', microtime());
|
||||
$string = date("Y-m-d H:i:s", (int)$timestamp);
|
||||
// if microtime flag is -1 no round, if 0, no microtime, if >= 1, round that size
|
||||
if ($set_microtime == -1) {
|
||||
@@ -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,93 @@ class Support
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps var data and returns it as string
|
||||
* var_dump based
|
||||
* Recommended debug output
|
||||
*
|
||||
* @param mixed $data Anything
|
||||
* @param bool $no_html [default=false] 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 {
|
||||
// dump data
|
||||
ob_start();
|
||||
var_dump($data);
|
||||
$debug_dump = ob_get_clean() ?: '[FAILED TO GET var_dump() data]';
|
||||
// check if the original caller is dV, if yes, up the caller level for
|
||||
// the file line get by 1, so we get file + pos from the dV call and
|
||||
// not this call
|
||||
$caller_level = 1;
|
||||
$caller_list = self::getCallerMethodList();
|
||||
if ($caller_list[0] == 'dV') {
|
||||
echo "Raise caller level<br>: " . $caller_list[0] . "<br>";
|
||||
$caller_level = 2;
|
||||
}
|
||||
// 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($caller_level);
|
||||
$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
|
||||
['>', '<', ' ', ' '],
|
||||
['>', '<', "\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
|
||||
*/
|
||||
|
||||
@@ -54,14 +54,15 @@ class System
|
||||
|
||||
/**
|
||||
* get the host name without the port as given by the SELF var
|
||||
* if no host name found will set to NOHOST:0
|
||||
*
|
||||
* @return array<mixed> host name/port name
|
||||
* @return array{string,int} host name/port number
|
||||
*/
|
||||
public static function getHostName(): array
|
||||
{
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'NOHOST:NOPORT';
|
||||
list($host_name, $port) = array_pad(explode(':', $host), 2, self::DEFAULT_PORT);
|
||||
return [$host_name, $port];
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'NOHOST:0';
|
||||
[$host_name, $port] = array_pad(explode(':', $host), 2, self::DEFAULT_PORT);
|
||||
return [$host_name, (int)$port];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,9 +29,9 @@ namespace CoreLibs\Language\Core;
|
||||
class CachedFileReader extends \CoreLibs\Language\Core\StringReader
|
||||
{
|
||||
/** @var int */
|
||||
public $error = 0;
|
||||
public int $error = 0;
|
||||
/** @var string */
|
||||
public $fd_str = '';
|
||||
public string $fd_str = '';
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
|
||||
@@ -27,13 +27,13 @@ namespace CoreLibs\Language\Core;
|
||||
class FileReader
|
||||
{
|
||||
/** @var int */
|
||||
public $fr_pos;
|
||||
public int $fr_pos;
|
||||
/** @var resource|bool */
|
||||
public $fr_fd;
|
||||
public mixed $fr_fd; // no resource type yet
|
||||
/** @var int */
|
||||
public $fr_length;
|
||||
public int $fr_length;
|
||||
/** @var int */
|
||||
public $error = 0;
|
||||
public int $error = 0;
|
||||
|
||||
/**
|
||||
* file read constructor
|
||||
|
||||
@@ -41,31 +41,31 @@ class GetTextReader
|
||||
{
|
||||
// public:
|
||||
/** @var int */
|
||||
public $error = 0; // public variable that holds error code (0 if no error)
|
||||
public int $error = 0; // public variable that holds error code (0 if no error)
|
||||
|
||||
// private:
|
||||
/** @var int */
|
||||
private $BYTEORDER = 0; // 0: low endian, 1: big endian
|
||||
private int $BYTEORDER = 0; // 0: low endian, 1: big endian
|
||||
/** @var FileReader */
|
||||
private $STREAM;
|
||||
private FileReader $STREAM;
|
||||
/** @var bool */
|
||||
private $short_circuit = false;
|
||||
private bool $short_circuit = false;
|
||||
/** @var bool */
|
||||
private $enable_cache = false;
|
||||
private bool $enable_cache = false;
|
||||
/** @var int */
|
||||
private $originals = 0; // offset of original table
|
||||
private int $originals = 0; // offset of original table
|
||||
/** @var int */
|
||||
private $translations = 0; // offset of translation table
|
||||
private int $translations = 0; // offset of translation table
|
||||
/** @var string */
|
||||
private $pluralheader = ''; // cache header field for plural forms
|
||||
private string $pluralheader = ''; // cache header field for plural forms
|
||||
/** @var int */
|
||||
private $total = 0; // total string count
|
||||
private int $total = 0; // total string count
|
||||
/** @var array<mixed>|null */
|
||||
private $table_originals = null; // table for original strings (offsets)
|
||||
private array|null $table_originals = null; // table for original strings (offsets)
|
||||
/** @var array<mixed>|null */
|
||||
private $table_translations = null; // table for translated strings (offsets)
|
||||
private array|null $table_translations = null; // table for translated strings (offsets)
|
||||
/** @var array<mixed> */
|
||||
private $cache_translations = []; // original -> translation mapping
|
||||
private array $cache_translations = []; // original -> translation mapping
|
||||
|
||||
/* Methods */
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ namespace CoreLibs\Language\Core;
|
||||
class StringReader
|
||||
{
|
||||
/** @var int */
|
||||
public $sr_pos;
|
||||
public int $sr_pos;
|
||||
/** @var string */
|
||||
public $sr_str;
|
||||
public string $sr_str;
|
||||
|
||||
/**
|
||||
* constructor for string reader
|
||||
|
||||
@@ -35,42 +35,42 @@ class L10n
|
||||
/** @var string the default fallback encoding if nothing is set */
|
||||
public const DEFAULT_CHARSET = 'UTF-8';
|
||||
/** @var string the current locale */
|
||||
private $locale = '';
|
||||
private string $locale = '';
|
||||
/** @var string the SET locale as WHERE the domain file is */
|
||||
private $locale_set = '';
|
||||
private string $locale_set = '';
|
||||
/** @var string the default selected/active domain */
|
||||
private $domain = '';
|
||||
private string $domain = '';
|
||||
/** @var string encoding, as from locale or set from outside */
|
||||
private $override_encoding = self::DEFAULT_CHARSET;
|
||||
private string $override_encoding = self::DEFAULT_CHARSET;
|
||||
/** @var string encoding set during the parse Locale */
|
||||
private $encoding = '';
|
||||
private string $encoding = '';
|
||||
/** @var array<string,array<string,GetTextReader>> locale > domain = translator */
|
||||
private $domains = [];
|
||||
private array $domains = [];
|
||||
/** @var array<string,string> bound paths for domains */
|
||||
private $paths = ['' => './'];
|
||||
private array $paths = ['' => './'];
|
||||
|
||||
// files
|
||||
/** @var string the full path to the mo file to loaded */
|
||||
private $mofile = '';
|
||||
private string $mofile = '';
|
||||
/** @var string base path to search level */
|
||||
private $base_locale_path = '';
|
||||
private string $base_locale_path = '';
|
||||
/** @var string dynamic set path to where the mo file is actually */
|
||||
private $base_content_path = '';
|
||||
private string $base_content_path = '';
|
||||
|
||||
// errors
|
||||
/** @var bool if load of mo file was unsuccessful */
|
||||
private $load_failure = false;
|
||||
private bool $load_failure = false;
|
||||
|
||||
// object holders
|
||||
/** @var FileReader|bool reader class for file reading, false for short circuit */
|
||||
private $input = false;
|
||||
private FileReader|bool $input = false;
|
||||
/** @var GetTextReader reader class for MO data */
|
||||
private $l10n;
|
||||
private GetTextReader|null $l10n = null;
|
||||
/**
|
||||
* @static
|
||||
* @var L10n self class
|
||||
*/
|
||||
private static $instance;
|
||||
private static L10n $instance;
|
||||
|
||||
/**
|
||||
* class constructor call for language getstring
|
||||
@@ -124,7 +124,6 @@ class L10n
|
||||
*/
|
||||
public static function getInstance(): L10n
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (empty(self::$instance)) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
@@ -253,6 +252,13 @@ class L10n
|
||||
// dummy
|
||||
$this->l10n = new GetTextReader($this->input);
|
||||
}
|
||||
// if this is still null here, we abort
|
||||
if ($this->l10n === null) {
|
||||
throw new \Exception(
|
||||
"Could not create CoreLibs\Language\Core\GetTextReader object",
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
return $this->l10n;
|
||||
}
|
||||
|
||||
@@ -673,6 +679,7 @@ class L10n
|
||||
// fallback passthrough
|
||||
if ($this->l10n === null) {
|
||||
echo $text;
|
||||
return;
|
||||
}
|
||||
echo $this->l10n->translate($text);
|
||||
}
|
||||
|
||||
107
src/Logging/Logger/Flag.php
Normal file
107
src/Logging/Logger/Flag.php
Normal 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__
|
||||
216
src/Logging/Logger/Level.php
Normal file
216
src/Logging/Logger/Level.php
Normal 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__
|
||||
1334
src/Logging/Logging.php
Normal file
1334
src/Logging/Logging.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -219,96 +219,97 @@ declare(strict_types=1);
|
||||
namespace CoreLibs\Output\Form;
|
||||
|
||||
use CoreLibs\Get\System;
|
||||
use CoreLibs\Debug\Support;
|
||||
|
||||
class Generate extends \CoreLibs\DB\Extended\ArrayIO
|
||||
{
|
||||
// for the load statetment describes which elements from
|
||||
// the load query should be shown and i which format
|
||||
/** @var array<mixed> */
|
||||
public $field_array = [];
|
||||
public array $field_array = [];
|
||||
/** @var string */
|
||||
public $load_query; // the query needed for loading a data set (one row in the table)
|
||||
public string $load_query; // the query needed for loading a data set (one row in the table)
|
||||
/** @var string */
|
||||
public $col_name; // the name of the columen (before _<type>) [used for order button]
|
||||
public string $col_name; // the name of the columen (before _<type>) [used for order button]
|
||||
/** @var int */
|
||||
public $yes; // the yes flag that triggers the template to show ALL and not only new/load
|
||||
public int $yes; // the yes flag that triggers the template to show ALL and not only new/load
|
||||
/** @var string */
|
||||
public $msg; // the error msg
|
||||
public string $msg; // the error msg
|
||||
/** @var int */
|
||||
public $error; // the error flag set for printing red error msg
|
||||
public int $error; // the error flag set for printing red error msg
|
||||
/** @var int */
|
||||
public $warning; // warning flag, for information (saved, loaded, etc)
|
||||
public int $warning; // warning flag, for information (saved, loaded, etc)
|
||||
/** @var string */
|
||||
public $archive_pk_name; // the pk name for the load select form
|
||||
public string $archive_pk_name; // the pk name for the load select form
|
||||
/** @var string */
|
||||
private $int_pk_name; // primary key, only internal usage
|
||||
private string $int_pk_name; // primary key, only internal usage
|
||||
/** @var array<mixed> */
|
||||
public $reference_array = []; // reference arrays -> stored in $this->reference_array[$table_name] => [];
|
||||
public array $reference_array = []; // reference arrays -> stored in $this->reference_array[$table_name] => [];
|
||||
// NOTE: should be changed to this @var mixed[]
|
||||
/** @var array<mixed> */
|
||||
public $element_list; // element list for elements next to each other as a special sub group
|
||||
public array $element_list; // element list for elements next to each other as a special sub group
|
||||
/** @var array<mixed> */
|
||||
public $table_array = [];
|
||||
public array $table_array = [];
|
||||
/** @var string */
|
||||
public $my_page_name; // the name of the page without .php extension
|
||||
public string $my_page_name; // the name of the page without .php extension
|
||||
/** @var bool */
|
||||
public $mobile_phone = false;
|
||||
public bool $mobile_phone = false;
|
||||
/** @var string */
|
||||
public $email_regex;
|
||||
public string $email_regex;
|
||||
// buttons and checkboxes
|
||||
/** @var string */
|
||||
public $archive;
|
||||
public string $archive;
|
||||
/** @var string */
|
||||
public $new;
|
||||
public string $new;
|
||||
/** @var string */
|
||||
public $really_new;
|
||||
public string $really_new;
|
||||
/** @var string */
|
||||
public $delete;
|
||||
public string $delete;
|
||||
/** @var string */
|
||||
public $really_delete;
|
||||
public string $really_delete;
|
||||
/** @var string */
|
||||
public $save;
|
||||
public string $save;
|
||||
/** @var string */
|
||||
public $remove_button;
|
||||
public string $remove_button;
|
||||
// security values
|
||||
/** @var int base acl for current page */
|
||||
private $base_acl_level = 0;
|
||||
private int $base_acl_level = 0;
|
||||
/** @var int admin master flag (1/0) */
|
||||
private $acl_admin = 0;
|
||||
private int $acl_admin = 0;
|
||||
/** @var array<mixed> */
|
||||
public $security_level;
|
||||
public array $security_level;
|
||||
/** @var array<string,mixed> Login ACL */
|
||||
public $login_acl = [];
|
||||
public array $login_acl = [];
|
||||
// layout publics
|
||||
/** @var int */
|
||||
public $table_width;
|
||||
public int $table_width;
|
||||
// internal lang & encoding vars
|
||||
/** @var string */
|
||||
public $lang_dir = '';
|
||||
public string $lang_dir = '';
|
||||
/** @var string */
|
||||
public $lang;
|
||||
public string $lang;
|
||||
/** @var string */
|
||||
public $lang_short;
|
||||
public string $lang_short;
|
||||
/** @var string */
|
||||
public $domain;
|
||||
public string $domain;
|
||||
/** @var string */
|
||||
public $encoding;
|
||||
public string $encoding;
|
||||
// language
|
||||
/** @var \CoreLibs\Language\L10n */
|
||||
public $l;
|
||||
public \CoreLibs\Language\L10n $l;
|
||||
// log
|
||||
/** @var \CoreLibs\Debug\Logging */
|
||||
public $log;
|
||||
/** @var \CoreLibs\Logging\Logging */
|
||||
public \CoreLibs\Logging\Logging $log;
|
||||
|
||||
// now some default error msgs (english)
|
||||
/** @var array<mixed> */
|
||||
public $language_array = [];
|
||||
public array $language_array = [];
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -388,7 +389,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
|
||||
$this->load_query = $config_array['load_query'];
|
||||
}
|
||||
if (empty($this->load_query)) {
|
||||
$this->log->debug('INIT ERROR', 'Missing Load Query for: ' . $this->my_page_name);
|
||||
$this->log->error('Missing Load Query for: ' . $this->my_page_name);
|
||||
}
|
||||
$this->archive_pk_name = 'a_' . $this->pk_name;
|
||||
$this->col_name = str_replace('_id', '', $this->pk_name);
|
||||
@@ -485,7 +486,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
|
||||
/** @var TableArrays\Interface\TableArraysInterface|false $class */
|
||||
$class = new $class_string($this);
|
||||
} catch (\Throwable $t) {
|
||||
$this->log->debug('CLASS LOAD', 'Failed loading: ' . $class_string . ' => ' . $t->getMessage());
|
||||
$this->log->critical('CLASS LOADING: Failed loading: ' . $class_string . ' => ' . $t->getMessage());
|
||||
return false;
|
||||
}
|
||||
if (is_object($class)) {
|
||||
@@ -827,7 +828,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
|
||||
return $return_array;
|
||||
}
|
||||
if (empty($this->load_query)) {
|
||||
$this->log->debug('LOAD LIST ERROR', 'Missing load list query');
|
||||
$this->log->error('Missing load list query');
|
||||
return $return_array;
|
||||
}
|
||||
|
||||
@@ -1954,7 +1955,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
|
||||
if ($this->table_array[$key]['value']) {
|
||||
// use the better new passwordSet instead of crypt based
|
||||
$this->table_array[$key]['value'] =
|
||||
\CoreLibs\Check\Password::passwordSet($this->table_array[$key]['value']);
|
||||
\CoreLibs\Security\Password::passwordSet($this->table_array[$key]['value']);
|
||||
$this->table_array[$key]['HIDDEN_value'] = $this->table_array[$key]['value'];
|
||||
} else {
|
||||
// $this->table_array[$key]['HIDDEN_value'] =
|
||||
@@ -2617,8 +2618,8 @@ 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']] ?? []));
|
||||
$this->log->error('P: ' . $data['prefix'] . ', '
|
||||
. Support::prAr($_POST['ERROR'][$data['prefix']] ?? []));
|
||||
if ($this->error && !empty($_POST['ERROR'][$data['prefix']])) {
|
||||
$prfx = $data['prefix']; // short
|
||||
$_post_data = [];
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace CoreLibs\Output\Form\TableArrays;
|
||||
class EditAccess implements Interface\TableArraysInterface
|
||||
{
|
||||
/** @var \CoreLibs\Output\Form\Generate */
|
||||
private $form;
|
||||
private \CoreLibs\Output\Form\Generate $form;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace CoreLibs\Output\Form\TableArrays;
|
||||
class EditGroups implements Interface\TableArraysInterface
|
||||
{
|
||||
/** @var \CoreLibs\Output\Form\Generate */
|
||||
private $form;
|
||||
private \CoreLibs\Output\Form\Generate $form;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace CoreLibs\Output\Form\TableArrays;
|
||||
class EditLanguages implements Interface\TableArraysInterface
|
||||
{
|
||||
/** @var \CoreLibs\Output\Form\Generate */
|
||||
private $form;
|
||||
private \CoreLibs\Output\Form\Generate $form;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace CoreLibs\Output\Form\TableArrays;
|
||||
class EditMenuGroup implements Interface\TableArraysInterface
|
||||
{
|
||||
/** @var \CoreLibs\Output\Form\Generate */
|
||||
private $form;
|
||||
private \CoreLibs\Output\Form\Generate $form;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace CoreLibs\Output\Form\TableArrays;
|
||||
class EditPages implements Interface\TableArraysInterface
|
||||
{
|
||||
/** @var \CoreLibs\Output\Form\Generate */
|
||||
private $form;
|
||||
private \CoreLibs\Output\Form\Generate $form;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace CoreLibs\Output\Form\TableArrays;
|
||||
class EditSchemas implements Interface\TableArraysInterface
|
||||
{
|
||||
/** @var \CoreLibs\Output\Form\Generate */
|
||||
private $form;
|
||||
private \CoreLibs\Output\Form\Generate $form;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace CoreLibs\Output\Form\TableArrays;
|
||||
class EditUsers implements Interface\TableArraysInterface
|
||||
{
|
||||
/** @var \CoreLibs\Output\Form\Generate */
|
||||
private $form;
|
||||
private \CoreLibs\Output\Form\Generate $form;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace CoreLibs\Output\Form\TableArrays;
|
||||
class EditVisibleGroup implements Interface\TableArraysInterface
|
||||
{
|
||||
/** @var \CoreLibs\Output\Form\Generate */
|
||||
private $form;
|
||||
private \CoreLibs\Output\Form\Generate $form;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
|
||||
@@ -23,13 +23,13 @@ class ProgressBar
|
||||
// private vars
|
||||
|
||||
/** @var string */
|
||||
public $code; // unique code
|
||||
public string $code; // unique code
|
||||
/** @var string */
|
||||
public $status = 'new'; // current status (new,show,hide)
|
||||
public string $status = 'new'; // current status (new,show,hide)
|
||||
/** @var float|int */
|
||||
public $step = 0; // current step
|
||||
public float|int $step = 0; // current step
|
||||
/** @var array<string,null|int|float> */
|
||||
public $position = [ // current bar position
|
||||
public array $position = [ // current bar position
|
||||
'left' => null,
|
||||
'top' => null,
|
||||
'width' => null,
|
||||
@@ -37,43 +37,43 @@ class ProgressBar
|
||||
];
|
||||
|
||||
/** @var int */
|
||||
public $clear_buffer_size = 1; // we need to send this before the lfush to get browser output
|
||||
public int $clear_buffer_size = 1; // we need to send this before the lfush to get browser output
|
||||
/** @var int */
|
||||
public $clear_buffer_size_init = 1024 * 1024; // if I don't send that junk, it won't send anything
|
||||
public int $clear_buffer_size_init = 1024 * 1024; // if I don't send that junk, it won't send anything
|
||||
|
||||
// public vars
|
||||
|
||||
/** @var int */
|
||||
public $min = 0; // minimal steps
|
||||
public int $min = 0; // minimal steps
|
||||
/** @var int */
|
||||
public $max = 100; // maximal steps
|
||||
public int $max = 100; // maximal steps
|
||||
|
||||
/** @var int */
|
||||
public $left = 5; // bar position from left
|
||||
public int $left = 5; // bar position from left
|
||||
/** @var int */
|
||||
public $top = 5; // bar position from top
|
||||
public int $top = 5; // bar position from top
|
||||
/** @var int */
|
||||
public $width = 300; // bar width
|
||||
public int $width = 300; // bar width
|
||||
/** @var int */
|
||||
public $height = 25; // bar height
|
||||
public int $height = 25; // bar height
|
||||
/** @var int */
|
||||
public $pedding = 0; // bar pedding
|
||||
public int $pedding = 0; // bar pedding
|
||||
/** @var string */
|
||||
public $color = '#0033ff'; // bar color
|
||||
public string $color = '#0033ff'; // bar color
|
||||
/** @var string */
|
||||
public $bgr_color = '#c0c0c0'; // bar background color
|
||||
public string $bgr_color = '#c0c0c0'; // bar background color
|
||||
/** @var string */
|
||||
public $bgr_color_master = '#ffffff'; // master div background color
|
||||
public string $bgr_color_master = '#ffffff'; // master div background color
|
||||
/** @var int */
|
||||
public $border = 1; // bar border width
|
||||
public int $border = 1; // bar border width
|
||||
/** @var string */
|
||||
public $brd_color = '#000000'; // bar border color
|
||||
public string $brd_color = '#000000'; // bar border color
|
||||
|
||||
/** @var string */
|
||||
public $direction = 'right'; // direction of motion (right,left,up,down)
|
||||
public string $direction = 'right'; // direction of motion (right,left,up,down)
|
||||
|
||||
/** @var array<string,string|bool|int> */
|
||||
public $frame = ['show' => false]; // ProgressBar Frame
|
||||
public array $frame = ['show' => false]; // ProgressBar Frame
|
||||
/* 'show' => false, # frame show (true/false)
|
||||
'left' => 200, # frame position from left
|
||||
'top' => 100, # frame position from top
|
||||
@@ -86,7 +86,7 @@ class ProgressBar
|
||||
|
||||
/** @#var array{string}{string: string|int} */
|
||||
/** @var mixed[][] */
|
||||
public $label = []; // ProgressBar Labels
|
||||
public array $label = []; // ProgressBar Labels
|
||||
/* 'name' => [ # label name
|
||||
'type' => 'text', # label type (text,button,step,percent,crossbar)
|
||||
'value' => 'Please wait ...', # label value
|
||||
@@ -105,7 +105,7 @@ class ProgressBar
|
||||
|
||||
/** @var string */
|
||||
// output strings
|
||||
public $prefix_message = '';
|
||||
public string $prefix_message = '';
|
||||
|
||||
/**
|
||||
* progress bar constructor
|
||||
|
||||
61
src/Security/CreateKey.php
Normal file
61
src/Security/CreateKey.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* very simple symmetric encryption
|
||||
* better use: https://paragonie.com/project/halite
|
||||
*
|
||||
* this is for creating secret keys for
|
||||
* Security\SymmetricEncryption
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Security;
|
||||
|
||||
class CreateKey
|
||||
{
|
||||
/**
|
||||
* Create a random key that is a hex string
|
||||
*
|
||||
* @return string Hex string key for encrypting
|
||||
*/
|
||||
public static function generateRandomKey(): string
|
||||
{
|
||||
return self::bin2hex(self::randomKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* create a random string as binary to encrypt data
|
||||
* to store it in clear text in some .env file use bin2hex
|
||||
*
|
||||
* @return string Binary string for encryption
|
||||
*/
|
||||
public static function randomKey(): string
|
||||
{
|
||||
return random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert binary key to hex string
|
||||
*
|
||||
* @param string $hex_key Convert binary key string to hex
|
||||
* @return string
|
||||
*/
|
||||
public static function bin2hex(string $hex_key): string
|
||||
{
|
||||
return sodium_bin2hex($hex_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert hex string to binary key
|
||||
*
|
||||
* @param string $string_key Convery hex key string to binary
|
||||
* @return string
|
||||
*/
|
||||
public static function hex2bin(string $string_key): string
|
||||
{
|
||||
return sodium_hex2bin($string_key);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
59
src/Security/Password.php
Normal file
59
src/Security/Password.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* core password set, check and rehash check wrapper functions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Security;
|
||||
|
||||
class Password
|
||||
{
|
||||
/**
|
||||
* creates the password hash
|
||||
*
|
||||
* @param string $password password
|
||||
* @return string hashed password
|
||||
*/
|
||||
public static function passwordSet(string $password): string
|
||||
{
|
||||
// always use the PHP default for the password
|
||||
// password options ca be set in the password init,
|
||||
// but should be kept as default
|
||||
return password_hash($password, PASSWORD_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if the entered password matches the hash
|
||||
*
|
||||
* @param string $password password
|
||||
* @param string $hash password hash
|
||||
* @return bool true or false
|
||||
*/
|
||||
public static function passwordVerify(string $password, string $hash): bool
|
||||
{
|
||||
if (password_verify($password, $hash)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if the password needs to be rehashed
|
||||
*
|
||||
* @param string $hash password hash
|
||||
* @return bool true or false
|
||||
*/
|
||||
public static function passwordRehashCheck(string $hash): bool
|
||||
{
|
||||
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
98
src/Security/SymmetricEncryption.php
Normal file
98
src/Security/SymmetricEncryption.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* very simple symmetric encryption
|
||||
* Better use:
|
||||
* https://paragonie.com/project/halite
|
||||
* https://github.com/paragonie/halite
|
||||
*
|
||||
* current code is just to encrypt and decrypt
|
||||
*
|
||||
* must use a valid encryption key created with
|
||||
* Secruty\CreateKey class
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Security;
|
||||
|
||||
use CoreLibs\Security\CreateKey;
|
||||
use SodiumException;
|
||||
|
||||
class SymmetricEncryption
|
||||
{
|
||||
/**
|
||||
* Encrypt a message
|
||||
*
|
||||
* @param string $message Message to encrypt
|
||||
* @param string $key Encryption key (as hex string)
|
||||
* @return string
|
||||
* @throws \RangeException
|
||||
*/
|
||||
public static function encrypt(string $message, string $key): string
|
||||
{
|
||||
try {
|
||||
$key = CreateKey::hex2bin($key);
|
||||
} catch (SodiumException $e) {
|
||||
throw new \Exception('Invalid hex key');
|
||||
}
|
||||
if (mb_strlen($key, '8bit') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
|
||||
throw new \RangeException(
|
||||
'Key is not the correct size (must be '
|
||||
. 'SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long).'
|
||||
);
|
||||
}
|
||||
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
|
||||
|
||||
$cipher = base64_encode(
|
||||
$nonce
|
||||
. sodium_crypto_secretbox(
|
||||
$message,
|
||||
$nonce,
|
||||
$key
|
||||
)
|
||||
);
|
||||
sodium_memzero($message);
|
||||
sodium_memzero($key);
|
||||
return $cipher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a message
|
||||
*
|
||||
* @param string $encrypted Message encrypted with safeEncrypt()
|
||||
* @param string $key Encryption key (as hex string)
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function decrypt(string $encrypted, string $key): string
|
||||
{
|
||||
try {
|
||||
$key = CreateKey::hex2bin($key);
|
||||
} catch (SodiumException $e) {
|
||||
throw new \Exception('Invalid hex key');
|
||||
}
|
||||
$decoded = base64_decode($encrypted);
|
||||
$nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
|
||||
$ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
|
||||
|
||||
$plain = false;
|
||||
try {
|
||||
$plain = sodium_crypto_secretbox_open(
|
||||
$ciphertext,
|
||||
$nonce,
|
||||
$key
|
||||
);
|
||||
} catch (SodiumException $e) {
|
||||
throw new \Exception('Invalid ciphertext (too short)');
|
||||
}
|
||||
if (!is_string($plain)) {
|
||||
throw new \Exception('Invalid Key');
|
||||
}
|
||||
sodium_memzero($ciphertext);
|
||||
sodium_memzero($key);
|
||||
return $plain;
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -24,134 +24,132 @@ class SmartyExtend extends \Smarty
|
||||
{
|
||||
// internal translation engine
|
||||
/** @var \CoreLibs\Language\L10n */
|
||||
public $l10n;
|
||||
public \CoreLibs\Language\L10n $l10n;
|
||||
|
||||
// lang & encoding
|
||||
/** @var string */
|
||||
public $lang_dir = '';
|
||||
public string $lang_dir = '';
|
||||
/** @var string */
|
||||
public $lang;
|
||||
public string $lang;
|
||||
/** @var string */
|
||||
public $locale_set;
|
||||
public string $lang_short;
|
||||
/** @var string */
|
||||
public $lang_short;
|
||||
public string $domain;
|
||||
/** @var string */
|
||||
public $domain;
|
||||
/** @var string */
|
||||
public $encoding;
|
||||
public string $encoding;
|
||||
// page name
|
||||
/** @var string */
|
||||
public $page_name;
|
||||
public string $page_name;
|
||||
|
||||
// array for data parsing
|
||||
/** @var array<mixed> */
|
||||
public $HEADER = [];
|
||||
public array $HEADER = [];
|
||||
/** @var array<mixed> */
|
||||
public $DATA = [];
|
||||
public array $DATA = [];
|
||||
/** @var array<mixed> */
|
||||
public $DEBUG_DATA = [];
|
||||
public array $DEBUG_DATA = [];
|
||||
/** @var array<mixed> */
|
||||
private $CONTENT_DATA = [];
|
||||
private array $CONTENT_DATA = [];
|
||||
// control vars
|
||||
/** @var bool */
|
||||
public $USE_PROTOTYPE = USE_PROTOTYPE;
|
||||
public bool $USE_PROTOTYPE = USE_PROTOTYPE;
|
||||
/** @var bool */
|
||||
public $USE_JQUERY = USE_JQUERY;
|
||||
public bool $USE_JQUERY = USE_JQUERY;
|
||||
/** @var bool */
|
||||
public $USE_SCRIPTACULOUS = USE_SCRIPTACULOUS;
|
||||
public bool $USE_SCRIPTACULOUS = USE_SCRIPTACULOUS;
|
||||
// sub content input vars
|
||||
/** @var bool */
|
||||
public $USE_TINY_MCE = false;
|
||||
public bool $USE_TINY_MCE = false;
|
||||
/** @var bool */
|
||||
public $JS_DATEPICKR = false;
|
||||
public bool $JS_DATEPICKR = false;
|
||||
/** @var bool */
|
||||
public $JS_FLATPICKR = false;
|
||||
public bool $JS_FLATPICKR = false;
|
||||
/** @var bool */
|
||||
public $JS_FILE_UPLOADER = false;
|
||||
public bool $JS_FILE_UPLOADER = false;
|
||||
/** @var bool */
|
||||
public $DEBUG_TMPL = false;
|
||||
public bool $DEBUG_TMPL = false;
|
||||
/** @var bool */
|
||||
public $USE_INCLUDE_TEMPLATE = false;
|
||||
public bool $USE_INCLUDE_TEMPLATE = false;
|
||||
// cache & compile
|
||||
/** @var string */
|
||||
public $CACHE_ID = '';
|
||||
public string $CACHE_ID = '';
|
||||
/** @var string */
|
||||
public $COMPILE_ID = '';
|
||||
public string $COMPILE_ID = '';
|
||||
// template vars
|
||||
/** @var string */
|
||||
public $MASTER_TEMPLATE_NAME;
|
||||
public string $MASTER_TEMPLATE_NAME;
|
||||
/** @var string */
|
||||
public $PAGE_FILE_NAME;
|
||||
public string $PAGE_FILE_NAME;
|
||||
/** @var string */
|
||||
public $CONTENT_INCLUDE;
|
||||
public string $CONTENT_INCLUDE;
|
||||
/** @var string */
|
||||
public $FORM_NAME;
|
||||
public string $FORM_NAME;
|
||||
/** @var string */
|
||||
public $FORM_ACTION;
|
||||
public string $FORM_ACTION;
|
||||
/** @var string */
|
||||
public $L_TITLE;
|
||||
public string $L_TITLE;
|
||||
/** @var string|int */
|
||||
public $PAGE_WIDTH;
|
||||
public string|int $PAGE_WIDTH;
|
||||
// smarty include/set var
|
||||
/** @var string */
|
||||
public $TEMPLATE_PATH;
|
||||
public string $TEMPLATE_PATH;
|
||||
/** @var string */
|
||||
public $TEMPLATE_NAME;
|
||||
public string $TEMPLATE_NAME;
|
||||
/** @var string */
|
||||
public $INC_TEMPLATE_NAME;
|
||||
public string $INC_TEMPLATE_NAME;
|
||||
/** @var string */
|
||||
public $JS_TEMPLATE_NAME;
|
||||
public string $JS_TEMPLATE_NAME;
|
||||
/** @var string */
|
||||
public $CSS_TEMPLATE_NAME;
|
||||
public string $CSS_TEMPLATE_NAME;
|
||||
/** @var string|null */
|
||||
public $TEMPLATE_TRANSLATE;
|
||||
public string|null $TEMPLATE_TRANSLATE;
|
||||
/** @var string|null */
|
||||
public $JS_TRANSLATE;
|
||||
public string|null $JS_TRANSLATE;
|
||||
// core group
|
||||
/** @var string */
|
||||
public $JS_CORE_TEMPLATE_NAME;
|
||||
public string $JS_CORE_TEMPLATE_NAME;
|
||||
/** @var string */
|
||||
public $CSS_CORE_TEMPLATE_NAME;
|
||||
public string $CSS_CORE_TEMPLATE_NAME;
|
||||
/** @var string */
|
||||
public $JS_CORE_INCLUDE;
|
||||
public string $JS_CORE_INCLUDE;
|
||||
/** @var string */
|
||||
public $CSS_CORE_INCLUDE;
|
||||
public string $CSS_CORE_INCLUDE;
|
||||
// local names
|
||||
/** @var string */
|
||||
public $JS_SPECIAL_TEMPLATE_NAME = '';
|
||||
public string $JS_SPECIAL_TEMPLATE_NAME = '';
|
||||
/** @var string */
|
||||
public $CSS_SPECIAL_TEMPLATE_NAME = '';
|
||||
public string $CSS_SPECIAL_TEMPLATE_NAME = '';
|
||||
/** @var string */
|
||||
public $JS_INCLUDE;
|
||||
public string $JS_INCLUDE;
|
||||
/** @var string */
|
||||
public $CSS_INCLUDE;
|
||||
public string $CSS_INCLUDE;
|
||||
/** @var string */
|
||||
public $JS_SPECIAL_INCLUDE;
|
||||
public string $JS_SPECIAL_INCLUDE;
|
||||
/** @var string */
|
||||
public $CSS_SPECIAL_INCLUDE;
|
||||
public string $CSS_SPECIAL_INCLUDE;
|
||||
/** @var string */
|
||||
public $ADMIN_JAVASCRIPT;
|
||||
public string $ADMIN_JAVASCRIPT;
|
||||
/** @var string */
|
||||
public $ADMIN_STYLESHEET;
|
||||
public string $ADMIN_STYLESHEET;
|
||||
/** @var string */
|
||||
public $FRONTEND_JAVASCRIPT;
|
||||
public string $FRONTEND_JAVASCRIPT;
|
||||
/** @var string */
|
||||
public $FRONTEND_STYLESHEET;
|
||||
public string $FRONTEND_STYLESHEET;
|
||||
// other smarty folder vars
|
||||
/** @var string */
|
||||
public $INCLUDES;
|
||||
public string $INCLUDES;
|
||||
/** @var string */
|
||||
public $JAVASCRIPT;
|
||||
public string $JAVASCRIPT;
|
||||
/** @var string */
|
||||
public $CSS;
|
||||
public string $CSS;
|
||||
/** @var string */
|
||||
public $FONT;
|
||||
public string $FONT;
|
||||
/** @var string */
|
||||
public $PICTURES;
|
||||
public string $PICTURES;
|
||||
/** @var string */
|
||||
public $CACHE_PICTURES;
|
||||
public string $CACHE_PICTURES;
|
||||
/** @var string */
|
||||
public $CACHE_PICTURES_ROOT;
|
||||
public string $CACHE_PICTURES_ROOT;
|
||||
|
||||
// constructor class, just sets the language stuff
|
||||
/**
|
||||
@@ -222,6 +220,7 @@ class SmartyExtend extends \Smarty
|
||||
// core CS
|
||||
$this->CSS_CORE_INCLUDE = '';
|
||||
if (
|
||||
!empty($this->CSS_CORE_TEMPLATE_NAME) &&
|
||||
file_exists($this->CSS . $this->CSS_CORE_TEMPLATE_NAME) &&
|
||||
is_file($this->CSS . $this->CSS_CORE_TEMPLATE_NAME)
|
||||
) {
|
||||
@@ -230,6 +229,7 @@ class SmartyExtend extends \Smarty
|
||||
// core JS
|
||||
$this->JS_CORE_INCLUDE = '';
|
||||
if (
|
||||
!empty($this->JS_CORE_TEMPLATE_NAME) &&
|
||||
file_exists($this->JAVASCRIPT . $this->JS_CORE_TEMPLATE_NAME) &&
|
||||
is_file($this->JAVASCRIPT . $this->JS_CORE_TEMPLATE_NAME)
|
||||
) {
|
||||
@@ -398,7 +398,7 @@ class SmartyExtend extends \Smarty
|
||||
// javascript translate data as template for auto translate
|
||||
if (empty($this->TEMPLATE_TRANSLATE)) {
|
||||
$this->TEMPLATE_TRANSLATE = 'jsTranslate-'
|
||||
. $this->locale_set . '.' . $this->encoding
|
||||
. $this->l10n->getLocaleSet() . '.' . $this->encoding
|
||||
. '.tpl';
|
||||
} else {
|
||||
// we assume we have some fixed set
|
||||
@@ -408,12 +408,12 @@ class SmartyExtend extends \Smarty
|
||||
if (strpos($this->TEMPLATE_TRANSLATE, '.tpl')) {
|
||||
$this->TEMPLATE_TRANSLATE = str_replace(
|
||||
'.tpl',
|
||||
'-' . $this->locale_set . '.' . $this->encoding . '.tpl',
|
||||
'-' . $this->l10n->getLocaleSet() . '.' . $this->encoding . '.tpl',
|
||||
$this->TEMPLATE_TRANSLATE
|
||||
);
|
||||
} else {
|
||||
$this->TEMPLATE_TRANSLATE .= '-'
|
||||
. $this->locale_set . '.' . $this->encoding
|
||||
. $this->l10n->getLocaleSet() . '.' . $this->encoding
|
||||
. '.tpl';
|
||||
}
|
||||
}
|
||||
@@ -423,7 +423,7 @@ class SmartyExtend extends \Smarty
|
||||
}
|
||||
if (empty($this->JS_TRANSLATE)) {
|
||||
$this->JS_TRANSLATE = 'translate-'
|
||||
. $this->locale_set . '.' . $this->encoding . '.js';
|
||||
. $this->l10n->getLocaleSet() . '.' . $this->encoding . '.js';
|
||||
} else {
|
||||
// we assume we have some fixed set
|
||||
// we must add _<locale>.<encoding>
|
||||
@@ -432,12 +432,12 @@ class SmartyExtend extends \Smarty
|
||||
if (strpos($this->JS_TRANSLATE, '.js')) {
|
||||
$this->JS_TRANSLATE = str_replace(
|
||||
'.js',
|
||||
'-' . $this->locale_set . '.' . $this->encoding . '.js',
|
||||
'-' . $this->l10n->getLocaleSet() . '.' . $this->encoding . '.js',
|
||||
$this->JS_TRANSLATE
|
||||
);
|
||||
} else {
|
||||
$this->JS_TRANSLATE .= '-'
|
||||
. $this->locale_set . '.' . $this->encoding
|
||||
. $this->l10n->getLocaleSet() . '.' . $this->encoding
|
||||
. '.js';
|
||||
}
|
||||
}
|
||||
@@ -675,10 +675,12 @@ class SmartyExtend extends \Smarty
|
||||
$this->HEADER['DEFAULT_ENCODING'] = $set_default_encoding;
|
||||
|
||||
// form name
|
||||
$this->DATA['FORM_NAME'] = !$this->FORM_NAME ?
|
||||
$this->DATA['FORM_NAME'] = empty($this->FORM_NAME) ?
|
||||
str_replace('.php', '', $this->page_name) :
|
||||
$this->FORM_NAME;
|
||||
$this->DATA['FORM_ACTION'] = $this->FORM_ACTION;
|
||||
$this->DATA['FORM_ACTION'] = empty($this->FORM_ACTION) ?
|
||||
'' :
|
||||
$this->FORM_ACTION;
|
||||
// special for admin
|
||||
if ($admin_call === true) {
|
||||
// depreacte call globals cms on null 4mcs
|
||||
@@ -735,7 +737,7 @@ class SmartyExtend extends \Smarty
|
||||
}
|
||||
// html title
|
||||
// set local page title
|
||||
$this->HEADER['HTML_TITLE'] = !$this->L_TITLE ?
|
||||
$this->HEADER['HTML_TITLE'] = empty($this->L_TITLE) ?
|
||||
ucfirst(str_replace('_', ' ', \CoreLibs\Get\System::getPageName(1)))
|
||||
. (!empty($set_g_title) ? '-' . $this->l10n->__($set_g_title) : '') :
|
||||
$this->l10n->__($this->L_TITLE);
|
||||
|
||||
@@ -68,13 +68,10 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
|
||||
// logger is always needed
|
||||
// define basic connection set valid and one invalid
|
||||
self::$log = new \CoreLibs\Debug\Logging([
|
||||
self::$log = new \CoreLibs\Logging\Logging([
|
||||
// 'log_folder' => __DIR__ . DIRECTORY_SEPARATOR . 'log',
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
|
||||
'file_id' => 'CoreLibs-ACL-Login-Test',
|
||||
'debug_all' => true,
|
||||
'echo_all' => false,
|
||||
'print_all' => true,
|
||||
'log_file_id' => 'CoreLibs-ACL-Login-Test',
|
||||
]);
|
||||
// test database we need to connect do, if not possible this test is skipped
|
||||
self::$db = new \CoreLibs\DB\IO(
|
||||
|
||||
@@ -22,12 +22,9 @@ final class CoreLibsCreateEmailTest extends TestCase
|
||||
*/
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
self::$log = new \CoreLibs\Debug\Logging([
|
||||
self::$log = new \CoreLibs\Logging\Logging([
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
|
||||
'file_id' => 'CoreLibs-Create-Email-Test',
|
||||
'debug_all' => true,
|
||||
'echo_all' => false,
|
||||
'print_all' => true,
|
||||
'log_file_id' => 'CoreLibs-Create-Email-Test',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -624,7 +621,7 @@ final class CoreLibsCreateEmailTest extends TestCase
|
||||
// force new set for each run
|
||||
self::$log->setLogUniqueId(true);
|
||||
// set on of unique log id
|
||||
self::$log->setLogPer('run', true);
|
||||
self::$log->setLogFlag(\CoreLibs\Logging\Logger\Flag::per_run);
|
||||
// init logger
|
||||
$status = \CoreLibs\Create\Email::sendEmail(
|
||||
$subject,
|
||||
@@ -646,7 +643,9 @@ final class CoreLibsCreateEmailTest extends TestCase
|
||||
// assert content: must load JSON from log file
|
||||
if ($status == 2) {
|
||||
// open file, get last entry with 'SEND EMAIL JSON' key
|
||||
$file = file_get_contents(self::$log->getLogFileName());
|
||||
$file = file_get_contents(
|
||||
self::$log->getLogFolder() . self::$log->getLogFile()
|
||||
);
|
||||
if ($file !== false) {
|
||||
// extract SEND EMAIL JSON line
|
||||
$found = preg_match_all("/^.* <SEND EMAIL JSON> - (.*)$/m", $file, $matches);
|
||||
|
||||
@@ -21,45 +21,83 @@ final class CoreLibsCreateUidsTest extends TestCase
|
||||
public function uniqIdProvider(): array
|
||||
{
|
||||
return [
|
||||
// number length
|
||||
'too short' => [
|
||||
0 => 1,
|
||||
1 => 4,
|
||||
2 => null
|
||||
],
|
||||
'valid length: 10' => [
|
||||
0 => 10,
|
||||
1 => 10,
|
||||
2 => null
|
||||
],
|
||||
'valid length: 9, auto length' => [
|
||||
0 => 9,
|
||||
1 => 8,
|
||||
2 => null
|
||||
],
|
||||
'valid length: 9, force length' => [
|
||||
0 => 9,
|
||||
1 => 9,
|
||||
2 => true,
|
||||
],
|
||||
'very long: 512' => [
|
||||
0 => 512,
|
||||
1 => 512,
|
||||
2 => null
|
||||
],
|
||||
// below is all legacy
|
||||
'md5 hash' => [
|
||||
0 => 'md5',
|
||||
1 => 32,
|
||||
2 => null
|
||||
],
|
||||
'sha256 hash' => [
|
||||
0 => 'sha256',
|
||||
1 => 64
|
||||
1 => 64,
|
||||
2 => null
|
||||
],
|
||||
'ripemd160 hash' => [
|
||||
0 => 'ripemd160',
|
||||
1 => 40
|
||||
1 => 40,
|
||||
2 => null
|
||||
],
|
||||
'adler32 hash' => [
|
||||
0 => 'adler32',
|
||||
1 => 8
|
||||
1 => 8,
|
||||
2 => null
|
||||
],
|
||||
'not in list hash but valid' => [
|
||||
'not in list, set default length' => [
|
||||
0 => 'sha3-512',
|
||||
1 => strlen(hash('sha3-512', 'A'))
|
||||
1 => 64,
|
||||
2 => null
|
||||
],
|
||||
'default hash not set' => [
|
||||
0 => null,
|
||||
1 => 64,
|
||||
2 => null
|
||||
],
|
||||
'invalid name' => [
|
||||
0 => 'iamnotavalidhash',
|
||||
1 => 64,
|
||||
2 => null
|
||||
],
|
||||
'auto: ' . \CoreLibs\Create\Uids::DEFAULT_HASH => [
|
||||
0 => \CoreLibs\Create\Uids::DEFAULT_HASH,
|
||||
1 => strlen(hash(\CoreLibs\Create\Uids::DEFAULT_HASH, 'A'))
|
||||
// auto calls
|
||||
'auto: ' . \CoreLibs\Create\Uids::DEFAULT_UNNIQ_ID_LENGTH => [
|
||||
0 => \CoreLibs\Create\Uids::DEFAULT_UNNIQ_ID_LENGTH,
|
||||
1 => 64,
|
||||
2 => null
|
||||
],
|
||||
'auto: ' . \CoreLibs\Create\Uids::STANDARD_HASH_LONG => [
|
||||
0 => \CoreLibs\Create\Uids::STANDARD_HASH_LONG,
|
||||
1 => strlen(hash(\CoreLibs\Create\Uids::STANDARD_HASH_LONG, 'A'))
|
||||
1 => strlen(hash(\CoreLibs\Create\Uids::STANDARD_HASH_LONG, 'A')),
|
||||
2 => null
|
||||
],
|
||||
'auto: ' . \CoreLibs\Create\Uids::STANDARD_HASH_SHORT => [
|
||||
0 => \CoreLibs\Create\Uids::STANDARD_HASH_SHORT,
|
||||
1 => strlen(hash(\CoreLibs\Create\Uids::STANDARD_HASH_SHORT, 'A'))
|
||||
1 => strlen(hash(\CoreLibs\Create\Uids::STANDARD_HASH_SHORT, 'A')),
|
||||
2 => null
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -105,25 +143,26 @@ final class CoreLibsCreateUidsTest extends TestCase
|
||||
*
|
||||
* @covers ::uniqId
|
||||
* @dataProvider uniqIdProvider
|
||||
* @testdox uniqId $input will be length $expected [$_dataName]
|
||||
* @testdox uniqId $input will be length $expected (Force $flag) [$_dataName]
|
||||
*
|
||||
* @param string|null $input
|
||||
* @param int|string|null $input
|
||||
* @param string $expected
|
||||
* @param bool|null $flag
|
||||
* @return void
|
||||
*/
|
||||
public function testUniqId(?string $input, int $expected): void
|
||||
public function testUniqId(int|string|null $input, int $expected, ?bool $flag): void
|
||||
{
|
||||
if ($input === null) {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
strlen(\CoreLibs\Create\Uids::uniqId())
|
||||
);
|
||||
$uniq_id_length = strlen(\CoreLibs\Create\Uids::uniqId());
|
||||
} elseif ($flag === null) {
|
||||
$uniq_id_length = strlen(\CoreLibs\Create\Uids::uniqId($input));
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
strlen(\CoreLibs\Create\Uids::uniqId($input))
|
||||
);
|
||||
$uniq_id_length = strlen(\CoreLibs\Create\Uids::uniqId($input, $flag));
|
||||
}
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$uniq_id_length
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -132,13 +132,10 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
);
|
||||
}
|
||||
// define basic connection set valid and one invalid
|
||||
self::$log = new \CoreLibs\Debug\Logging([
|
||||
self::$log = new \CoreLibs\Logging\Logging([
|
||||
// 'log_folder' => __DIR__ . DIRECTORY_SEPARATOR . 'log',
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
|
||||
'file_id' => 'CoreLibs-DB-IO-Test',
|
||||
'debug_all' => false,
|
||||
'echo_all' => false,
|
||||
'print_all' => false,
|
||||
'log_file_id' => 'CoreLibs-DB-IO-Test',
|
||||
]);
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config['valid'],
|
||||
|
||||
@@ -10,12 +10,13 @@ use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Test class for Debug\Logging
|
||||
* @coversDefaultClass \CoreLibs\Debug\Logging
|
||||
* @testdox \CoreLibs\Debug\Logging method tests
|
||||
* @coversDefaultClass \CoreLibs\Debug\LoggingLegacy
|
||||
* @testdox \CoreLibs\Debug\LoggingLegacy method tests
|
||||
*/
|
||||
final class CoreLibsDebugLoggingTest extends TestCase
|
||||
final class CoreLibsDebugLoggingLegacyTest extends TestCase
|
||||
{
|
||||
private const LOG_FOLDER = __DIR__ . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR;
|
||||
|
||||
/**
|
||||
* test set for options BASIC
|
||||
*
|
||||
@@ -24,7 +25,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
* 1: expected
|
||||
* 2: override
|
||||
* override:
|
||||
* - constant for COSNTANTS
|
||||
* - constant for CONSTANTS
|
||||
* - global for _GLOBALS
|
||||
*
|
||||
* @return array
|
||||
@@ -138,7 +139,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
// catch this with the message
|
||||
$this->expectExceptionMessage($deprecation_message);
|
||||
}
|
||||
$log = new \CoreLibs\Debug\Logging($options);
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy($options);
|
||||
// reset error handler
|
||||
restore_error_handler();
|
||||
// check that settings match
|
||||
@@ -308,7 +309,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
// catch this with the message
|
||||
$this->expectExceptionMessage($deprecation_message);
|
||||
}
|
||||
$log = new \CoreLibs\Debug\Logging($options);
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy($options);
|
||||
// reset error handler
|
||||
restore_error_handler();
|
||||
// check current
|
||||
@@ -385,7 +386,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
bool $expected_get
|
||||
): void {
|
||||
// neutral start with default
|
||||
$log = new \CoreLibs\Debug\Logging([
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy([
|
||||
'file_id' => 'testSetGetLogLevelAll',
|
||||
'log_folder' => self::LOG_FOLDER
|
||||
]);
|
||||
@@ -510,7 +511,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
$expected_get
|
||||
): void {
|
||||
// neutral start with default
|
||||
$log = new \CoreLibs\Debug\Logging([
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy([
|
||||
'file_id' => 'testSetGetLogLevel',
|
||||
'log_folder' => self::LOG_FOLDER
|
||||
]);
|
||||
@@ -592,7 +593,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
bool $expected_get
|
||||
): void {
|
||||
// neutral start with default
|
||||
$log = new \CoreLibs\Debug\Logging([
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy([
|
||||
'file_id' => 'testSetGetLogPer',
|
||||
'log_folder' => self::LOG_FOLDER
|
||||
]);
|
||||
@@ -624,7 +625,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
public function testSetGetLogPrintFileDate(bool $input, bool $expected_set, bool $expected_get): void
|
||||
{
|
||||
// neutral start with default
|
||||
$log = new \CoreLibs\Debug\Logging([
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy([
|
||||
'file_id' => 'testSetGetLogPrintFileDate',
|
||||
'log_folder' => self::LOG_FOLDER
|
||||
]);
|
||||
@@ -693,7 +694,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
*/
|
||||
public function testPrAr(array $input, string $expected): void
|
||||
{
|
||||
$log = new \CoreLibs\Debug\Logging([
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy([
|
||||
'file_id' => 'testPrAr',
|
||||
'log_folder' => self::LOG_FOLDER
|
||||
]);
|
||||
@@ -757,7 +758,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
*/
|
||||
public function testPrBl(bool $input, ?string $true, ?string $false, string $expected): void
|
||||
{
|
||||
$log = new \CoreLibs\Debug\Logging([
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy([
|
||||
'file_id' => 'testPrBl',
|
||||
'log_folder' => self::LOG_FOLDER
|
||||
]);
|
||||
@@ -932,7 +933,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
// remove any files named /tmp/error_log_TestDebug*.log
|
||||
array_map('unlink', glob($options['log_folder'] . 'error_msg_' . $options['file_id'] . '*.log'));
|
||||
// init logger
|
||||
$log = new \CoreLibs\Debug\Logging($options);
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy($options);
|
||||
// * debug (A/B)
|
||||
// NULL check for strip/prefix
|
||||
$this->assertEquals(
|
||||
@@ -1046,13 +1047,13 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
public function testLogUniqueId(bool $option, bool $override): void
|
||||
{
|
||||
if ($option === true) {
|
||||
$log = new \CoreLibs\Debug\Logging([
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy([
|
||||
'file_id' => 'testLogUniqueId',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
'per_run' => $option
|
||||
]);
|
||||
} else {
|
||||
$log = new \CoreLibs\Debug\Logging([
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy([
|
||||
'file_id' => 'testLogUniqueId',
|
||||
'log_folder' => self::LOG_FOLDER
|
||||
]);
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CoreLibs\Debug\Support;
|
||||
|
||||
/**
|
||||
* Test class for Debug\Support
|
||||
@@ -40,6 +41,32 @@ final class CoreLibsDebugSupportTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::printTime
|
||||
* @dataProvider printTimeProvider
|
||||
* @testdox printTime test with $microtime and match to regex [$_dataName]
|
||||
*
|
||||
* @param int|null $mircrotime
|
||||
* @param string $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testPrintTime(?int $microtime, string $regex): void
|
||||
{
|
||||
if ($microtime === null) {
|
||||
$this->assertMatchesRegularExpression(
|
||||
$regex,
|
||||
Support::printTime()
|
||||
);
|
||||
} else {
|
||||
$this->assertMatchesRegularExpression(
|
||||
$regex,
|
||||
Support::printTime($microtime)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
@@ -50,18 +77,55 @@ final class CoreLibsDebugSupportTest extends TestCase
|
||||
return [
|
||||
'empty array' => [
|
||||
0 => [],
|
||||
1 => "<pre>Array\n(\n)\n</pre>"
|
||||
1 => "<pre>Array\n(\n)\n</pre>",
|
||||
2 => "Array\n(\n)\n",
|
||||
],
|
||||
'simple array' => [
|
||||
0 => ['a', 'b'],
|
||||
1 => "<pre>Array\n(\n"
|
||||
. " [0] => a\n"
|
||||
. " [1] => b\n"
|
||||
. ")\n</pre>"
|
||||
. ")\n</pre>",
|
||||
2 => "Array\n(\n"
|
||||
. " [0] => a\n"
|
||||
. " [1] => b\n"
|
||||
. ")\n",
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::printAr
|
||||
* @cover ::printArray
|
||||
* @dataProvider printArrayProvider
|
||||
* @testdox printAr/printArray $input will be $expected [$_dataName]
|
||||
*
|
||||
* @param array $input
|
||||
* @param string $expected
|
||||
* @param string $expected_strip
|
||||
* @return void
|
||||
*/
|
||||
public function testPrintAr(array $input, string $expected, string $expected_strip): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
Support::printAr($input),
|
||||
'assert printAr'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
Support::printArray($input),
|
||||
'assert printArray'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected_strip,
|
||||
Support::prAr($input),
|
||||
'assert prAr'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
@@ -73,27 +137,31 @@ final class CoreLibsDebugSupportTest extends TestCase
|
||||
'true input default' => [
|
||||
0 => true,
|
||||
1 => [],
|
||||
2 => 'true'
|
||||
2 => 'true',
|
||||
3 => 'true',
|
||||
],
|
||||
'false input default' => [
|
||||
0 => false,
|
||||
1 => [],
|
||||
2 => 'false'
|
||||
2 => 'false',
|
||||
3 => 'false'
|
||||
],
|
||||
'false input param name' => [
|
||||
0 => false,
|
||||
1 => [
|
||||
'name' => 'param test'
|
||||
],
|
||||
2 => '<b>param test</b>: false'
|
||||
2 => '<b>param test</b>: false',
|
||||
3 => 'false'
|
||||
],
|
||||
'true input param name, true override' => [
|
||||
0 => true,
|
||||
1 => [
|
||||
'name' => 'param test',
|
||||
'true' => 'ok'
|
||||
'true' => 'ok',
|
||||
],
|
||||
2 => '<b>param test</b>: ok'
|
||||
2 => '<b>param test</b>: ok',
|
||||
3 => 'ok',
|
||||
],
|
||||
'false input param name, true override, false override' => [
|
||||
0 => false,
|
||||
@@ -102,11 +170,77 @@ final class CoreLibsDebugSupportTest extends TestCase
|
||||
'true' => 'ok',
|
||||
'false' => 'not',
|
||||
],
|
||||
2 => '<b>param test</b>: not'
|
||||
2 => '<b>param test</b>: not',
|
||||
3 => 'not'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::printBool
|
||||
* @dataProvider printBoolProvider
|
||||
* @testdox printBool $input will be $expected [$_dataName]
|
||||
*
|
||||
* @param bool $input
|
||||
* @param array $params
|
||||
* @param string $expected
|
||||
* @param string $expected_strip
|
||||
* @return void
|
||||
*/
|
||||
public function testPrintBool(bool $input, array $params, string $expected, string $expected_strip): void
|
||||
{
|
||||
if (
|
||||
isset($params['name']) &&
|
||||
isset($params['true']) &&
|
||||
isset($params['false'])
|
||||
) {
|
||||
$string = Support::printBool(
|
||||
$input,
|
||||
$params['name'],
|
||||
$params['true'],
|
||||
$params['false']
|
||||
);
|
||||
$string_strip = Support::prBl(
|
||||
$input,
|
||||
$params['true'],
|
||||
$params['false']
|
||||
);
|
||||
} elseif (isset($params['name']) && isset($params['true'])) {
|
||||
$string = Support::printBool(
|
||||
$input,
|
||||
$params['name'],
|
||||
$params['true']
|
||||
);
|
||||
$string_strip = Support::prBl(
|
||||
$input,
|
||||
$params['true'],
|
||||
);
|
||||
} elseif (isset($params['name'])) {
|
||||
$string = Support::printBool(
|
||||
$input,
|
||||
$params['name']
|
||||
);
|
||||
$string_strip = Support::prBl(
|
||||
$input
|
||||
);
|
||||
} else {
|
||||
$string = Support::printBool($input);
|
||||
$string_strip = Support::prBl($input);
|
||||
}
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$string,
|
||||
'assert printBool'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected_strip,
|
||||
$string_strip,
|
||||
'assert prBl'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
@@ -169,12 +303,10 @@ final class CoreLibsDebugSupportTest extends TestCase
|
||||
'an array, no html' => [
|
||||
['a', 'b'],
|
||||
true,
|
||||
"##HTMLPRE##"
|
||||
. "Array\n(\n"
|
||||
"Array\n(\n"
|
||||
. " [0] => a\n"
|
||||
. " [1] => b\n"
|
||||
. ")\n"
|
||||
. "##/HTMLPRE##",
|
||||
. ")\n",
|
||||
],
|
||||
// resource
|
||||
'a resource' => [
|
||||
@@ -191,6 +323,253 @@ final class CoreLibsDebugSupportTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::printToString
|
||||
* @dataProvider printToStringProvider
|
||||
* @testdox printToString $input with $flag will be $expected [$_dataName]
|
||||
*
|
||||
* @param mixed $input anything
|
||||
* @param boolean|null $flag html flag, only for string and array
|
||||
* @param string $expected always string
|
||||
* @return void
|
||||
*/
|
||||
public function testPrintToString(mixed $input, ?bool $flag, string $expected): void
|
||||
{
|
||||
if ($flag === null) {
|
||||
// if expected starts with / and ends with / then this is a regex compare
|
||||
if (
|
||||
substr($expected, 0, 1) == '/' &&
|
||||
substr($expected, -1, 1) == '/'
|
||||
) {
|
||||
$this->assertMatchesRegularExpression(
|
||||
$expected,
|
||||
Support::printToString($input)
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
Support::printToString($input)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
Support::printToString($input, $flag)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerDumpExportVar(): array
|
||||
{
|
||||
return [
|
||||
'string' => [
|
||||
'input' => 'string',
|
||||
'flag' => null,
|
||||
'expected_dump' => 'string(6) "string"' . "\n",
|
||||
'expected_export' => "<pre>'string'</pre>",
|
||||
],
|
||||
'string, no html' => [
|
||||
'input' => 'string',
|
||||
'flag' => true,
|
||||
'expected_dump' => 'string(6) "string"' . "\n",
|
||||
'expected_export' => "'string'",
|
||||
],
|
||||
// int
|
||||
'int' => [
|
||||
'input' => 6,
|
||||
'flag' => null,
|
||||
'expected_dump' => 'int(6)' . "\n",
|
||||
'expected_export' => "<pre>6</pre>",
|
||||
],
|
||||
// float
|
||||
'float' => [
|
||||
'input' => 1.6,
|
||||
'flag' => null,
|
||||
'expected_dump' => 'float(1.6)' . "\n",
|
||||
'expected_export' => "<pre>1.6</pre>",
|
||||
],
|
||||
// bool
|
||||
'bool' => [
|
||||
'input' => true,
|
||||
'flag' => null,
|
||||
'expected_dump' => 'bool(true)' . "\n",
|
||||
'expected_export' => "<pre>true</pre>",
|
||||
],
|
||||
// array
|
||||
'array' => [
|
||||
'input' => ['string', true],
|
||||
'flag' => null,
|
||||
'expected_dump' => "array(2) {\n"
|
||||
. " [0]=>\n"
|
||||
. " string(6) \"string\"\n"
|
||||
. " [1]=>\n"
|
||||
. " bool(true)\n"
|
||||
. "}\n",
|
||||
'expected_export' => "<pre>array (\n"
|
||||
. " 0 => 'string',\n"
|
||||
. " 1 => true,\n"
|
||||
. ")</pre>",
|
||||
],
|
||||
// more
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::dumpVar
|
||||
* @cover ::exportVar
|
||||
* @dataProvider providerDumpExportVar
|
||||
* @testdox dump/exportVar $input with $flag will be $expected_dump / $expected_export [$_dataName]
|
||||
*
|
||||
* @param mixed $input
|
||||
* @param bool|null $flag
|
||||
* @param string $expected_dump
|
||||
* @param string $expected_export
|
||||
* @return void
|
||||
*/
|
||||
public function testDumpExportVar(mixed $input, ?bool $flag, string $expected_dump, string $expected_export): void
|
||||
{
|
||||
if ($flag === null) {
|
||||
$dump = Support::dumpVar($input);
|
||||
$export = Support::exportVar($input);
|
||||
} else {
|
||||
$dump = Support::dumpVar($input, $flag);
|
||||
$export = Support::exportVar($input, $flag);
|
||||
}
|
||||
$this->assertEquals(
|
||||
$expected_dump,
|
||||
$dump,
|
||||
'assert dumpVar'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected_export,
|
||||
$export,
|
||||
'assert dumpVar'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::getCallerFileLine
|
||||
* @testWith ["/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/www/vendor/phpunit/phpunit/src/Framework/TestCase.php:1608"]
|
||||
* @testdox getCallerFileLine check if it returns $expected [$_dataName]
|
||||
*
|
||||
* @param string $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testGetCallerFileLine(string $expected): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
Support::getCallerFileLine()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::getCallerMethod
|
||||
* @testWith ["testGetCallerMethod"]
|
||||
* @testdox getCallerMethod check if it returns $expected [$_dataName]
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetCallerMethod(string $expected): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
Support::getCallerMethod()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::getCallerMethodList
|
||||
* @testWith [["main", "run", "run", "run", "run", "run", "run", "runBare", "runTest", "testGetCallerMethodList"]]
|
||||
* @testdox getCallerMethodList check if it returns $expected [$_dataName]
|
||||
*
|
||||
* @param array $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testGetCallerMethodList(array $expected): void
|
||||
{
|
||||
$compare = Support::getCallerMethodList();
|
||||
// 10: legact
|
||||
// 11: direct
|
||||
// 12: full call
|
||||
switch (count($compare)) {
|
||||
case 10:
|
||||
// add nothing
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
Support::getCallerMethodList(),
|
||||
'assert expected 10'
|
||||
);
|
||||
break;
|
||||
case 11:
|
||||
// add one "run" before "runBare"
|
||||
array_splice(
|
||||
$expected,
|
||||
7,
|
||||
0,
|
||||
['run']
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
Support::getCallerMethodList(),
|
||||
'assert expected 11'
|
||||
);
|
||||
break;
|
||||
case 12:
|
||||
// add two "run" before "runBare"
|
||||
array_splice(
|
||||
$expected,
|
||||
7,
|
||||
0,
|
||||
['run']
|
||||
);
|
||||
array_splice(
|
||||
$expected,
|
||||
0,
|
||||
0,
|
||||
['include']
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
Support::getCallerMethodList(),
|
||||
'assert expected 12'
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::getCallerClass
|
||||
* @testWith ["PHPUnit\\TextUI\\Command"]
|
||||
* @testdox getCallerClass check if it returns $expected [$_dataName]
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetCallerClass(string $expected): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
Support::getCallerClass()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
@@ -236,205 +615,6 @@ final class CoreLibsDebugSupportTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::printTime
|
||||
* @dataProvider printTimeProvider
|
||||
* @testdox printTime test with $microtime and match to regex [$_dataName]
|
||||
*
|
||||
* @param int|null $mircrotime
|
||||
* @param string $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testPrintTime(?int $microtime, string $regex): void
|
||||
{
|
||||
if ($microtime === null) {
|
||||
$this->assertMatchesRegularExpression(
|
||||
$regex,
|
||||
\CoreLibs\Debug\Support::printTime()
|
||||
);
|
||||
} else {
|
||||
$this->assertMatchesRegularExpression(
|
||||
$regex,
|
||||
\CoreLibs\Debug\Support::printTime($microtime)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::printAr
|
||||
* @cover ::printArray
|
||||
* @dataProvider printArrayProvider
|
||||
* @testdox printAr/printArray $input will be $expected [$_dataName]
|
||||
*
|
||||
* @param array $input
|
||||
* @param string $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testPrintAr(array $input, string $expected): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::printAr($input),
|
||||
'assert printAr'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::printArray($input),
|
||||
'assert printArray'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::printBool
|
||||
* @dataProvider printBoolProvider
|
||||
* @testdox printBool $input will be $expected [$_dataName]
|
||||
*
|
||||
* @param bool $input
|
||||
* @param array $params
|
||||
* @param string $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testPrintBool(bool $input, array $params, string $expected): void
|
||||
{
|
||||
if (
|
||||
isset($params['name']) &&
|
||||
isset($params['true']) &&
|
||||
isset($params['false'])
|
||||
) {
|
||||
$string = \CoreLibs\Debug\Support::printBool(
|
||||
$input,
|
||||
$params['name'],
|
||||
$params['true'],
|
||||
$params['false']
|
||||
);
|
||||
} elseif (isset($params['name']) && isset($params['true'])) {
|
||||
$string = \CoreLibs\Debug\Support::printBool(
|
||||
$input,
|
||||
$params['name'],
|
||||
$params['true']
|
||||
);
|
||||
} elseif (isset($params['name'])) {
|
||||
$string = \CoreLibs\Debug\Support::printBool(
|
||||
$input,
|
||||
$params['name']
|
||||
);
|
||||
} else {
|
||||
$string = \CoreLibs\Debug\Support::printBool($input);
|
||||
}
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$string,
|
||||
'assert printBool'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::printToString
|
||||
* @dataProvider printToStringProvider
|
||||
* @testdox printToString $input with $flag will be $expected [$_dataName]
|
||||
*
|
||||
* @param mixed $input anything
|
||||
* @param boolean|null $flag html flag, only for string and array
|
||||
* @param string $expected always string
|
||||
* @return void
|
||||
*/
|
||||
public function testPrintToString(mixed $input, ?bool $flag, string $expected): void
|
||||
{
|
||||
if ($flag === null) {
|
||||
// if expected starts with / and ends with / then this is a regex compare
|
||||
if (
|
||||
substr($expected, 0, 1) == '/' &&
|
||||
substr($expected, -1, 1) == '/'
|
||||
) {
|
||||
$this->assertMatchesRegularExpression(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::printToString($input)
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::printToString($input)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::printToString($input, $flag)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::getCallerMethod
|
||||
* @testWith ["testGetCallerMethod"]
|
||||
* @testdox getCallerMethod check if it returns $expected [$_dataName]
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetCallerMethod(string $expected): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::getCallerMethod()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::getCallerMethodList
|
||||
* @testWith [["main", "run", "run", "run", "run", "run", "run", "runBare", "runTest", "testGetCallerMethodList"],["include", "main", "run", "run", "run", "run", "run", "run", "run", "runBare", "runTest", "testGetCallerMethodList"]]
|
||||
* @testdox getCallerMethodList check if it returns $expected [$_dataName]
|
||||
*
|
||||
* @param array $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testGetCallerMethodList(array $expected, array $expected_group): void
|
||||
{
|
||||
$compare = \CoreLibs\Debug\Support::getCallerMethodList();
|
||||
// if we direct call we have 10, if we call as folder we get 11
|
||||
if (count($compare) == 10) {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::getCallerMethodList(),
|
||||
'assert expected 10'
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected_group,
|
||||
\CoreLibs\Debug\Support::getCallerMethodList(),
|
||||
'assert expected group'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @cover ::getCallerClass
|
||||
* @testWith ["PHPUnit\\TextUI\\Command"]
|
||||
* @testdox getCallerClass check if it returns $expected [$_dataName]
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetCallerClass(string $expected): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::getCallerClass()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
@@ -453,19 +633,19 @@ final class CoreLibsDebugSupportTest extends TestCase
|
||||
if ($replace === null && $flag === null) {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::debugString($input),
|
||||
Support::debugString($input),
|
||||
'assert all default'
|
||||
);
|
||||
} elseif ($flag === null) {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::debugString($input, $replace),
|
||||
Support::debugString($input, $replace),
|
||||
'assert flag default'
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Debug\Support::debugString($input, $replace, $flag),
|
||||
Support::debugString($input, $replace, $flag),
|
||||
'assert all set'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,17 +67,17 @@ final class CoreLibsGetSystemTest extends TestCase
|
||||
'original set' => [
|
||||
0 => null,
|
||||
1 => 'NOHOST',
|
||||
2 => 'NOPORT',
|
||||
2 => 0,
|
||||
],
|
||||
'override set no port' => [
|
||||
0 => 'foo.org',
|
||||
1 => 'foo.org',
|
||||
2 => '80'
|
||||
2 => 80
|
||||
],
|
||||
'override set with port' => [
|
||||
0 => 'foo.org:443',
|
||||
1 => 'foo.org',
|
||||
2 => '443'
|
||||
2 => 443
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -138,10 +138,10 @@ final class CoreLibsGetSystemTest extends TestCase
|
||||
*
|
||||
* @param string|null $input
|
||||
* @param string $expected_host
|
||||
* @param string $expected_port
|
||||
* @param int $expected_port
|
||||
* @return void
|
||||
*/
|
||||
public function testGetHostNanme(?string $input, string $expected_host, string $expected_port): void
|
||||
public function testGetHostNanme(?string $input, string $expected_host, int $expected_port): void
|
||||
{
|
||||
// print "HOSTNAME: " . $_SERVER['HTTP_HOST'] . "<br>";
|
||||
// print "SERVER: " . print_r($_SERVER, true) . "\n";
|
||||
|
||||
797
test/phpunit/Logging/CoreLibsLoggingLoggingTest.php
Normal file
797
test/phpunit/Logging/CoreLibsLoggingLoggingTest.php
Normal file
@@ -0,0 +1,797 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CoreLibs\Logging\Logger\Level;
|
||||
use CoreLibs\Logging\Logger\Flag;
|
||||
|
||||
// TODO: setLogPer test log file written matches pattern
|
||||
|
||||
/**
|
||||
* Test class for Logging
|
||||
* @coversDefaultClass \CoreLibs\Logging\Logging
|
||||
* @testdox \CoreLibs\Logging\Logging method tests
|
||||
*/
|
||||
final class CoreLibsLoggingLoggingTest extends TestCase
|
||||
{
|
||||
private const LOG_FOLDER = __DIR__ . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR;
|
||||
private const REGEX_BASE = "\[[\d\-\s\.:]+\]\s{1}" // date
|
||||
. "\[[\w\.]+(:\d+)?\]\s{1}" // host:port
|
||||
. "\[[\w+\.\/]+:\d+\]\s{1}" // folder/file
|
||||
. "\[\w+\]\s{1}" // run id
|
||||
. "{[\w\\\\]+(::\w+)?}\s{1}"; // class
|
||||
|
||||
/**
|
||||
* test set for options BASIC
|
||||
*
|
||||
* 0: options
|
||||
* - null for NOT set
|
||||
* 1: expected
|
||||
* 2: override
|
||||
* override:
|
||||
* - constant for COSNTANTS
|
||||
* - global for _GLOBALS
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function optionsProvider(): array
|
||||
{
|
||||
return [
|
||||
'log folder set' => [
|
||||
'options' => [
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
|
||||
'log_file_id' => 'testClassInit',
|
||||
],
|
||||
'expected' => [
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
|
||||
'log_level' => Level::Debug,
|
||||
'log_file_id' => 'testClassInit',
|
||||
],
|
||||
'override' => [],
|
||||
],
|
||||
// -> deprecation warning, log_folder must be set
|
||||
'no log folder set' => [
|
||||
'options' => [
|
||||
'log_file_id' => 'testClassInit'
|
||||
],
|
||||
'expected' => [
|
||||
'log_folder' => getcwd() . DIRECTORY_SEPARATOR,
|
||||
'log_level' => Level::Debug,
|
||||
'log_file_id' => 'testClassInit',
|
||||
],
|
||||
'override' => []
|
||||
],
|
||||
// -> upcoming deprecated
|
||||
'file_id set but not log_file_id' => [
|
||||
'options' => [
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
|
||||
'file_id' => 'testClassInit',
|
||||
],
|
||||
'expected' => [
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
|
||||
'log_level' => Level::Debug,
|
||||
'log_file_id' => 'testClassInit',
|
||||
],
|
||||
'override' => [],
|
||||
],
|
||||
// both file_id and log_file_id set -> WARNING
|
||||
'file_id and log_file_id set' => [
|
||||
'options' => [
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
|
||||
'file_id' => 'testClassInit',
|
||||
'log_file_id' => 'testClassInit',
|
||||
],
|
||||
'expected' => [
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
|
||||
'log_level' => Level::Debug,
|
||||
'log_file_id' => 'testClassInit',
|
||||
],
|
||||
'override' => [],
|
||||
],
|
||||
// no log file id set -> error,
|
||||
'nothing set' => [
|
||||
'options' => [],
|
||||
'expected' => [
|
||||
'log_folder' => getcwd() . DIRECTORY_SEPARATOR,
|
||||
'log_level' => Level::Debug,
|
||||
'log_file_id' => 'NOHOST-0_PHPUnit-TextUI-Command',
|
||||
],
|
||||
'override' => []
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* init logging class
|
||||
*
|
||||
* @dataProvider optionsProvider
|
||||
* @testdox init test [$_dataName]
|
||||
*
|
||||
* @param array $options
|
||||
* @param array $expected
|
||||
* @param array $override
|
||||
* @return void
|
||||
*/
|
||||
public function testClassInit(array $options, array $expected, array $override): void
|
||||
{
|
||||
if (!empty($override['constant'])) {
|
||||
foreach ($override['constant'] as $var => $value) {
|
||||
if (!defined($var)) {
|
||||
define($var, $value);
|
||||
}
|
||||
}
|
||||
// for deprecated no log_folder set
|
||||
// if base is defined and it does have AAASetupData set
|
||||
// change the log_folder "Debug" to "AAASetupData"
|
||||
if (
|
||||
defined('BASE') &&
|
||||
strpos(BASE, DIRECTORY_SEPARATOR . 'AAASetupData') !== false
|
||||
) {
|
||||
$expected['log_folder'] = str_replace(
|
||||
DIRECTORY_SEPARATOR . 'Debug',
|
||||
DIRECTORY_SEPARATOR . 'AAASetupData',
|
||||
$expected['log_folder']
|
||||
);
|
||||
}
|
||||
}
|
||||
// if not log folder and constant set -> expect E_USER_DEPRECATION
|
||||
if (!empty($override['constant']) && empty($options['log_folder'])) {
|
||||
// the deprecation message
|
||||
$deprecation_message = 'options: log_folder must be set. '
|
||||
. 'Setting via BASE and LOG constants is deprecated';
|
||||
// convert E_USER_DEPRECATED to a exception
|
||||
set_error_handler(
|
||||
static function (int $errno, string $errstr): never {
|
||||
throw new \Exception($errstr, $errno);
|
||||
},
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// catch this with the message
|
||||
$this->expectExceptionMessage($deprecation_message);
|
||||
}
|
||||
// alert for log file id with globals
|
||||
if (!empty($override['constant']) && empty($options['log_file_id'])) {
|
||||
//
|
||||
}
|
||||
// alert for log file id and file id set
|
||||
if (
|
||||
!empty($options['log_file_id']) &&
|
||||
!empty($options['file_id'])
|
||||
) {
|
||||
set_error_handler(
|
||||
static function (int $errno, string $errstr): never {
|
||||
throw new \InvalidArgumentException($errstr, $errno);
|
||||
},
|
||||
E_USER_WARNING
|
||||
);
|
||||
$error_message = 'options: "file_id" is deprecated use: "log_file_id".';
|
||||
$this->expectExceptionMessage($error_message);
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
set_error_handler(
|
||||
static function (int $errno, string $errstr): never {
|
||||
throw new \Exception($errstr, $errno);
|
||||
},
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$this->expectException(\Exception::class);
|
||||
// $error_message = 'options: both log_file_id and log_id are set at the same time, will use log_file_id';
|
||||
// $this->expectExceptionMessage($error_message);
|
||||
}
|
||||
// empty log folder
|
||||
if (empty($override['constant']) && empty($options['log_folder'])) {
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessageMatches("/^Missing mandatory option: \"/");
|
||||
} elseif (empty($options['log_file_id']) && !empty($options['file_id'])) {
|
||||
// the deprecation message
|
||||
$deprecation_message = 'options: "file_id" is deprecated use: "log_file_id".';
|
||||
// convert E_USER_DEPRECATED to a exception
|
||||
set_error_handler(
|
||||
static function (int $errno, string $errstr): never {
|
||||
throw new \Exception($errstr, $errno);
|
||||
},
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// catch this with the message
|
||||
$this->expectExceptionMessage($deprecation_message);
|
||||
}
|
||||
$log = new \CoreLibs\Logging\Logging($options);
|
||||
// reset error handler
|
||||
restore_error_handler();
|
||||
// check that settings match
|
||||
$this->assertEquals(
|
||||
$expected['log_folder'],
|
||||
$log->getLogFolder(),
|
||||
'log folder not matching'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected['log_file_id'],
|
||||
$log->getLogFileId(),
|
||||
'log file id not matching'
|
||||
);
|
||||
}
|
||||
|
||||
// test all setters/getters
|
||||
|
||||
// setLoggingLevel
|
||||
// getLoggingLevel
|
||||
// getJsDebug
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::setLoggingLevel
|
||||
* @covers ::getLoggingLevel
|
||||
* @covers ::getJsDebug
|
||||
* @testdox setLoggingLevel set/get checks
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetLoggingLevel(): void
|
||||
{
|
||||
// valid that is not Debug
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testSetLoggingLevel',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
'log_level' => Level::Info
|
||||
]);
|
||||
$this->assertEquals(
|
||||
Level::Info,
|
||||
$log->getLoggingLevel()
|
||||
);
|
||||
$this->assertFalse(
|
||||
$log->getJsDebug()
|
||||
);
|
||||
// not set, should be debug]
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testSetLoggingLevel',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
]);
|
||||
$this->assertEquals(
|
||||
Level::Debug,
|
||||
$log->getLoggingLevel()
|
||||
);
|
||||
$this->assertTrue(
|
||||
$log->getJsDebug()
|
||||
);
|
||||
// invalid, should be debug, will throw excpetion too
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Option: "log_level" is not of instance \CoreLibs\Logging\Logger\Level');
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testSetLoggingLevel',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
'log_level' => 'I'
|
||||
]);
|
||||
$this->assertEquals(
|
||||
Level::Debug,
|
||||
$log->getLoggingLevel()
|
||||
);
|
||||
$this->assertTrue(
|
||||
$log->getJsDebug()
|
||||
);
|
||||
// set valid, then change
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testSetLoggingLevel',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
'log_level' => Level::Info
|
||||
]);
|
||||
$this->assertEquals(
|
||||
Level::Info,
|
||||
$log->getLoggingLevel()
|
||||
);
|
||||
$log->setLoggingLevel(Level::Notice);
|
||||
$this->assertEquals(
|
||||
Level::Notice,
|
||||
$log->getLoggingLevel()
|
||||
);
|
||||
// illegal logging level
|
||||
$this->expectException(\Psr\Log\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessageMatches("/^Level \"NotGood\" is not defined, use one of: /");
|
||||
$log->setLoggingLevel('NotGood');
|
||||
}
|
||||
|
||||
// setLogFileId
|
||||
// getLogFileId
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::setLogFileId
|
||||
* @covers ::getLogFileId
|
||||
* @testdox setLogFileId set/get checks
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLogFileId(): void
|
||||
{
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testLogFileId',
|
||||
'log_folder' => self::LOG_FOLDER
|
||||
]);
|
||||
// bad, keep same
|
||||
$log->setLogFileId('$$##$%#$%&');
|
||||
$this->assertEquals(
|
||||
'testLogFileId',
|
||||
$log->getLogFileId()
|
||||
);
|
||||
// good, change
|
||||
$log->setLogFileId('validID');
|
||||
$this->assertEquals(
|
||||
'validID',
|
||||
$log->getLogFileId()
|
||||
);
|
||||
// invalid on init
|
||||
$this->expectException(\Psr\Log\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('LogFileId: no log file id set');
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => '$$$"#"#$"#$',
|
||||
'log_folder' => self::LOG_FOLDER
|
||||
]);
|
||||
}
|
||||
|
||||
// setLogUniqueId
|
||||
// getLogUniqueId
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function logUniqueIdProvider(): array
|
||||
{
|
||||
return [
|
||||
'option set' => [
|
||||
'option' => true,
|
||||
'override' => false,
|
||||
],
|
||||
'direct set' => [
|
||||
'option' => false,
|
||||
'override' => false,
|
||||
],
|
||||
'override set' => [
|
||||
'option' => false,
|
||||
'override' => true,
|
||||
],
|
||||
'option and override set' => [
|
||||
'option' => false,
|
||||
'override' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::setLogUniqueId
|
||||
* @covers ::getLogUniqueId
|
||||
* @dataProvider logUniqueIdProvider
|
||||
* @testdox per run log id set test: option: $option, override: $override [$_dataName]
|
||||
*
|
||||
* @param bool $option
|
||||
* @param bool $override
|
||||
* @return void
|
||||
*/
|
||||
public function testLogUniqueId(bool $option, bool $override): void
|
||||
{
|
||||
if ($option === true) {
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testLogUniqueId',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
'log_per_run' => $option
|
||||
]);
|
||||
} else {
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testLogUniqueId',
|
||||
'log_folder' => self::LOG_FOLDER
|
||||
]);
|
||||
$log->setLogUniqueId();
|
||||
}
|
||||
$per_run_id = $log->getLogUniqueId();
|
||||
$this->assertMatchesRegularExpression(
|
||||
"/^\d{4}-\d{2}-\d{2}_\d{6}_U_[a-z0-9]{8}$/",
|
||||
$per_run_id,
|
||||
'assert per log run id 1st'
|
||||
);
|
||||
if ($override === true) {
|
||||
$log->setLogUniqueId(true);
|
||||
$per_run_id_2nd = $log->getLogUniqueId();
|
||||
$this->assertMatchesRegularExpression(
|
||||
"/^\d{4}-\d{2}-\d{2}_\d{6}_U_[a-z0-9]{8}$/",
|
||||
$per_run_id_2nd,
|
||||
'assert per log run id 2nd'
|
||||
);
|
||||
$this->assertNotEquals(
|
||||
$per_run_id,
|
||||
$per_run_id_2nd,
|
||||
'1st and 2nd don\'t match'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// setLogDate
|
||||
// getLogDate
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::setLogDate
|
||||
* @covers ::getLogDate
|
||||
* @testdox setLogDate set/get checks
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetLogDate(): void
|
||||
{
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testLogFileId',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
'log_per_date' => true,
|
||||
]);
|
||||
$this->assertEquals(
|
||||
date('Y-m-d'),
|
||||
$log->getLogDate()
|
||||
);
|
||||
}
|
||||
|
||||
// setLogFlag
|
||||
// getLogFlag
|
||||
// unsetLogFlag
|
||||
// getLogFlags
|
||||
// Logger\Flag
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers Logger\Flag
|
||||
* @testdox Logger\Flag enum test
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLoggerFlag(): void
|
||||
{
|
||||
// logger flags to check that they exist
|
||||
$flags = [
|
||||
'all_off' => 0,
|
||||
'per_run' => 1,
|
||||
'per_date' => 2,
|
||||
'per_group' => 4,
|
||||
'per_page' => 8,
|
||||
'per_class' => 16,
|
||||
'per_level' => 32,
|
||||
];
|
||||
// from int -> return value
|
||||
foreach ($flags as $name => $value) {
|
||||
$this->assertEquals(
|
||||
Flag::fromName($name),
|
||||
Flag::fromValue($value)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::setLogFlag
|
||||
* @covers ::getLogFlag
|
||||
* @covers ::unsetLogFlag
|
||||
* @covers ::getLogFlags
|
||||
* @testdox setLogDate set/get checks
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetLogFlag(): void
|
||||
{
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testSetLogFlag',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
]);
|
||||
// set valid log flag
|
||||
$log->setLogFlag(Flag::per_run);
|
||||
$this->assertTrue(
|
||||
$log->getLogFlag(Flag::per_run)
|
||||
);
|
||||
// flags seum
|
||||
$this->assertEquals(
|
||||
Flag::per_run->value,
|
||||
$log->getLogFlags(),
|
||||
);
|
||||
// unset valid log flag
|
||||
$log->unsetLogFlag(Flag::per_run);
|
||||
$this->assertFalse(
|
||||
$log->getLogFlag(Flag::per_run)
|
||||
);
|
||||
// illegal Flags cannot be set, they will throw eerros onrun
|
||||
|
||||
// test multi set and sum is equals set
|
||||
$log->setLogFlag(Flag::per_date);
|
||||
$log->setLogFlag(Flag::per_group);
|
||||
$this->assertEquals(
|
||||
Flag::per_date->value + Flag::per_group->value,
|
||||
$log->getLogFlags()
|
||||
);
|
||||
}
|
||||
|
||||
// setLogFolder
|
||||
// getLogFolder
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::setLogFolder
|
||||
* @covers ::getLogFolder
|
||||
* @testdox setLogFolder set/get checks, init check
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetLogFolder(): void
|
||||
{
|
||||
// set to good folder
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testSetLogFolder',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
]);
|
||||
$this->assertEquals(
|
||||
self::LOG_FOLDER,
|
||||
$log->getLogFolder()
|
||||
);
|
||||
// set to a good other folder
|
||||
$log->setLogFolder(DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR);
|
||||
$this->assertEquals(
|
||||
DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
|
||||
$log->getLogFolder()
|
||||
);
|
||||
// good other folder with missing trailing slash
|
||||
$log->setLogFolder(DIRECTORY_SEPARATOR . 'tmp');
|
||||
$this->assertEquals(
|
||||
DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
|
||||
$log->getLogFolder()
|
||||
);
|
||||
// a bad folder -> last good folder
|
||||
$log->setLogFolder('I-am-not existing');
|
||||
$this->assertEquals(
|
||||
DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
|
||||
$log->getLogFolder()
|
||||
);
|
||||
// init with a bad folder
|
||||
$this->expectException(\Psr\Log\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Folder: "I-am-bad" is not writeable for logging');
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testSetLogFolderInvalid',
|
||||
'log_folder' => 'I-am-bad',
|
||||
]);
|
||||
}
|
||||
|
||||
// getLogFile (no set, only correct after log run)
|
||||
|
||||
// setLogMaxFileSize
|
||||
// getLogMaxFileSize
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::setLogMaxFileSize
|
||||
* @covers ::getLogMaxFileSize
|
||||
* @testdox setLogMaxFileSize set/get checks, init check
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetLogMaxFileSize(): void
|
||||
{
|
||||
// init set to 0
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testSetLogMaxFileSize',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
]);
|
||||
$this->assertEquals(
|
||||
0,
|
||||
$log->getLogMaxFileSize()
|
||||
);
|
||||
// set to new, valid size
|
||||
$file_size = 200 * 1024;
|
||||
$valid = $log->setLogMaxFileSize($file_size);
|
||||
$this->assertTrue($valid);
|
||||
$this->assertEquals(
|
||||
$file_size,
|
||||
$log->getLogMaxFileSize()
|
||||
);
|
||||
// invalid size, < 0, will be last and return false
|
||||
$valid = $log->setLogMaxFileSize(-1);
|
||||
$this->assertFalse($valid);
|
||||
$this->assertEquals(
|
||||
$file_size,
|
||||
$log->getLogMaxFileSize()
|
||||
);
|
||||
// too small (< MIN_LOG_MAX_FILESIZE)
|
||||
$valid = $log->setLogMaxFileSize($log::MIN_LOG_MAX_FILESIZE - 1);
|
||||
$this->assertFalse($valid);
|
||||
$this->assertEquals(
|
||||
$file_size,
|
||||
$log->getLogMaxFileSize()
|
||||
);
|
||||
}
|
||||
|
||||
// getOption (option params)
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::getOption
|
||||
* @testdox getOption checks
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetOption(): void
|
||||
{
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testGetOption',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
]);
|
||||
$this->assertEquals(
|
||||
self::LOG_FOLDER,
|
||||
$log->getOption('log_folder')
|
||||
);
|
||||
// not found
|
||||
$this->assertNull(
|
||||
$log->getOption('I_do not exist')
|
||||
);
|
||||
}
|
||||
|
||||
// test all logger functions
|
||||
// debug (special)
|
||||
// info
|
||||
// notice
|
||||
// warning
|
||||
// error
|
||||
// critical
|
||||
// alert
|
||||
// emergency
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::debug
|
||||
* @testdox debug checks
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDebug(): void
|
||||
{
|
||||
// init logger
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testDebug',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
]);
|
||||
// clean all data in folder first
|
||||
array_map('unlink', glob($log->getLogFolder() . $log->getLogFileId() . '*.log'));
|
||||
|
||||
$group_id = 'G';
|
||||
$message = 'D';
|
||||
$log_status = $log->debug($group_id, $message);
|
||||
$this->assertTrue($log_status, 'debug write successful');
|
||||
$file_content = file_get_contents(
|
||||
$log->getLogFolder() . $log->getLogFile()
|
||||
) ?: '';
|
||||
$log_level = $log->getLoggingLevel()->getName();
|
||||
// [2023-05-30 15:51:39.36128800] [NOHOST:0]
|
||||
// [www/vendor/bin/phpunit] [7b9d0747] {PHPUnit\TextUI\Command}
|
||||
// <DEBUG:G> D
|
||||
$this->assertMatchesRegularExpression(
|
||||
"/" . self::REGEX_BASE
|
||||
. "<$log_level:$group_id>\s{1}" // log level / group id
|
||||
. "$message" // message
|
||||
. "/",
|
||||
$file_content
|
||||
);
|
||||
}
|
||||
|
||||
public function providerLoggingLevelWrite(): array
|
||||
{
|
||||
return [
|
||||
'info' => [
|
||||
'message' => 'I',
|
||||
'file_id' => Level::Info->name,
|
||||
'level' => Level::Info
|
||||
],
|
||||
'notice' => [
|
||||
'message' => 'N',
|
||||
'file_id' => Level::Notice->name,
|
||||
'level' => Level::Notice
|
||||
],
|
||||
'warning' => [
|
||||
'message' => 'W',
|
||||
'file_id' => Level::Warning->name,
|
||||
'level' => Level::Warning
|
||||
],
|
||||
'error' => [
|
||||
'message' => 'E',
|
||||
'file_id' => Level::Error->name,
|
||||
'level' => Level::Error
|
||||
],
|
||||
'crticial' => [
|
||||
'message' => 'C',
|
||||
'file_id' => Level::Critical->name,
|
||||
'level' => Level::Critical
|
||||
],
|
||||
'alert' => [
|
||||
'message' => 'A',
|
||||
'file_id' => Level::Alert->name,
|
||||
'level' => Level::Alert
|
||||
],
|
||||
'emergency' => [
|
||||
'message' => 'Em',
|
||||
'file_id' => Level::Emergency->name,
|
||||
'level' => Level::Emergency
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::info
|
||||
* @covers ::notice
|
||||
* @covers ::warning
|
||||
* @covers ::error
|
||||
* @covers ::critical
|
||||
* @covers ::alert
|
||||
* @covers ::emergency
|
||||
* @dataProvider providerLoggingLevelWrite
|
||||
* @testdox logging level write checks for $level [$_dataName]
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLoggingLevelWrite(string $message, string $file_id, Level $level): void
|
||||
{
|
||||
// init logger
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'test' . $file_id,
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
'log_level' => $level,
|
||||
]);
|
||||
// clean all data in folder first
|
||||
array_map('unlink', glob($log->getLogFolder() . $log->getLogFileId() . '*.log'));
|
||||
|
||||
switch ($level->value) {
|
||||
case 200:
|
||||
$log_status = $log->info($message);
|
||||
break;
|
||||
case 250:
|
||||
$log_status = $log->notice($message);
|
||||
break;
|
||||
case 300:
|
||||
$log_status = $log->warning($message);
|
||||
break;
|
||||
case 400:
|
||||
$log_status = $log->error($message);
|
||||
break;
|
||||
case 500:
|
||||
$log_status = $log->critical($message);
|
||||
break;
|
||||
case 550:
|
||||
$log_status = $log->alert($message);
|
||||
break;
|
||||
case 600:
|
||||
$log_status = $log->emergency($message);
|
||||
break;
|
||||
}
|
||||
$this->assertTrue($log_status, 'log write successful');
|
||||
$file_content = file_get_contents(
|
||||
$log->getLogFolder() . $log->getLogFile()
|
||||
) ?: '';
|
||||
$log_level = $log->getLoggingLevel()->getName();
|
||||
$this->assertMatchesRegularExpression(
|
||||
"/" . self::REGEX_BASE
|
||||
. "<$log_level>\s{1}" // log level / group id
|
||||
. "$message" // message
|
||||
. "/",
|
||||
$file_content,
|
||||
'log message regex'
|
||||
);
|
||||
}
|
||||
|
||||
// deprecated calls check?
|
||||
}
|
||||
|
||||
// __END__
|
||||
3
test/phpunit/Logging/log/.gitignore
vendored
Normal file
3
test/phpunit/Logging/log/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*log
|
||||
*LOG
|
||||
!.gitignore
|
||||
@@ -7,11 +7,11 @@ namespace tests;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Test class for Check\Password
|
||||
* @coversDefaultClass \CoreLibs\Check\Password
|
||||
* @testdox \CoreLibs\Check\Password method tests
|
||||
* Test class for Security\Password
|
||||
* @coversDefaultClass \CoreLibs\Security\Password
|
||||
* @testdox \CoreLibs\Security\Password method tests
|
||||
*/
|
||||
final class CoreLibsCheckPasswordTest extends TestCase
|
||||
final class CoreLibsSecurityPasswordTest extends TestCase
|
||||
{
|
||||
public function passwordProvider(): array
|
||||
{
|
||||
@@ -46,7 +46,7 @@ final class CoreLibsCheckPasswordTest extends TestCase
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Check\Password::passwordVerify($input, \CoreLibs\Check\Password::passwordSet($input_hash))
|
||||
\CoreLibs\Security\Password::passwordVerify($input, \CoreLibs\Security\Password::passwordSet($input_hash))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ final class CoreLibsCheckPasswordTest extends TestCase
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Check\Password::passwordRehashCheck($input)
|
||||
\CoreLibs\Security\Password::passwordRehashCheck($input)
|
||||
);
|
||||
}
|
||||
}
|
||||
172
test/phpunit/Security/CoreLibsSecuritySymmetricEncryption.php
Normal file
172
test/phpunit/Security/CoreLibsSecuritySymmetricEncryption.php
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CoreLibs\Security\CreateKey;
|
||||
use CoreLibs\Security\SymmetricEncryption;
|
||||
|
||||
/**
|
||||
* Test class for Security\SymmetricEncryption and Security\CreateKey
|
||||
* @coversDefaultClass \CoreLibs\Security\SymmetricEncryption
|
||||
* @testdox \CoreLibs\Security\SymmetricEncryption method tests
|
||||
*/
|
||||
final class CoreLibsSecuritySymmetricEncryption extends TestCase
|
||||
{
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerEncryptDecryptSuccess(): array
|
||||
{
|
||||
return [
|
||||
'valid string' => [
|
||||
'input' => 'I am a secret',
|
||||
'expected' => 'I am a secret',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* test encrypt/decrypt produce correct output
|
||||
*
|
||||
* @covers ::generateRandomKey
|
||||
* @covers ::encrypt
|
||||
* @covers ::decrypt
|
||||
* @dataProvider providerEncryptDecryptSuccess
|
||||
* @testdox encrypt/decrypt $input must be $expected [$_dataName]
|
||||
*
|
||||
* @param string $input
|
||||
* @param string $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testEncryptDecryptSuccess(string $input, string $expected): void
|
||||
{
|
||||
$key = CreateKey::generateRandomKey();
|
||||
$encrypted = SymmetricEncryption::encrypt($input, $key);
|
||||
$decrypted = SymmetricEncryption::decrypt($encrypted, $key);
|
||||
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$decrypted
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerEncryptFailed(): array
|
||||
{
|
||||
return [
|
||||
'wrong decryption key' => [
|
||||
'input' => 'I am a secret',
|
||||
'excpetion_message' => 'Invalid Key'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test decryption with wrong key
|
||||
*
|
||||
* @covers ::generateRandomKey
|
||||
* @covers ::encrypt
|
||||
* @covers ::decrypt
|
||||
* @dataProvider providerEncryptFailed
|
||||
* @testdox decrypt with wrong key $input throws $exception_message [$_dataName]
|
||||
*
|
||||
* @param string $input
|
||||
* @param string $exception_message
|
||||
* @return void
|
||||
*/
|
||||
public function testEncryptFailed(string $input, string $exception_message): void
|
||||
{
|
||||
$key = CreateKey::generateRandomKey();
|
||||
$encrypted = SymmetricEncryption::encrypt($input, $key);
|
||||
$wrong_key = CreateKey::generateRandomKey();
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::decrypt($encrypted, $wrong_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerWrongKey(): array
|
||||
{
|
||||
return [
|
||||
'not hex key' => [
|
||||
'key' => 'not_a_hex_key',
|
||||
'exception_message' => 'Invalid hex key'
|
||||
],
|
||||
'too short hex key' => [
|
||||
'key' => '1cabd5cba9e042f12522f4ff2de5c31d233b',
|
||||
'excpetion_message' => 'Key is not the correct size (must be '
|
||||
. 'SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long).'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* test invalid key provided to decrypt or encrypt
|
||||
*
|
||||
* @covers ::encrypt
|
||||
* @covers ::decrypt
|
||||
* @dataProvider providerWrongKey
|
||||
* @testdox wrong key $key throws $exception_message [$_dataName]
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $exception_message
|
||||
* @return void
|
||||
*/
|
||||
public function testWrongKey(string $key, string $exception_message): void
|
||||
{
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::encrypt('test', $key);
|
||||
// we must encrypt valid thing first so we can fail with the wrong kjey
|
||||
$enc_key = CreateKey::generateRandomKey();
|
||||
$encrypted = SymmetricEncryption::encrypt('test', $enc_key);
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::decrypt($encrypted, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerWrongCiphertext(): array
|
||||
{
|
||||
return [
|
||||
'too short ciphertext' => [
|
||||
'input' => 'short',
|
||||
'exception_message' => 'Invalid ciphertext (too short)'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::decrypt
|
||||
* @dataProvider providerWrongCiphertext
|
||||
* @testdox too short ciphertext $input throws $exception_message [$_dataName]
|
||||
*
|
||||
* @param string $input
|
||||
* @param string $exception_message
|
||||
* @return void
|
||||
*/
|
||||
public function testWrongCiphertext(string $input, string $exception_message): void
|
||||
{
|
||||
$key = CreateKey::generateRandomKey();
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::decrypt($input, $key);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
Reference in New Issue
Block a user