Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa5c3b9dcc | ||
|
|
24f7a903ef | ||
|
|
72993925f0 | ||
|
|
29d5ef92d4 | ||
|
|
f66f8f282e | ||
|
|
c010673705 | ||
|
|
b16ff4c613 | ||
|
|
e9c791c164 | ||
|
|
c7ec1300b7 | ||
|
|
064710324e | ||
|
|
e0356dcadf | ||
|
|
62a5992e3a | ||
|
|
6bb957fcb3 | ||
|
|
0c1f060759 | ||
|
|
aad46ec80a | ||
|
|
f5e9f0610d | ||
|
|
14a5250cd7 | ||
|
|
6e6edef57d | ||
|
|
d3810db965 | ||
|
|
187a012284 | ||
|
|
b3d2662fd2 | ||
|
|
1189aecae9 | ||
|
|
024d6d2d7a | ||
|
|
f2d5377347 | ||
|
|
af11bd8199 | ||
|
|
0e6a43a2c2 | ||
|
|
94eeaaaa51 | ||
|
|
4a246bec5f | ||
|
|
46b2b60718 | ||
|
|
9616d956cb | ||
|
|
df401b9add | ||
|
|
4b9e393971 | ||
|
|
6cda319ed0 | ||
|
|
583edbfe0a | ||
|
|
67a8e1a533 | ||
|
|
38788dddce | ||
|
|
cf196d56dd | ||
|
|
0cb76c8db2 | ||
|
|
db02bdd102 | ||
|
|
d9b71a64b3 | ||
|
|
f410d761ba | ||
|
|
fb4b9f3f81 | ||
|
|
1e94cd7b57 |
@@ -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,13 +16,15 @@
|
||||
],
|
||||
"minimum-stability": "dev",
|
||||
"require": {
|
||||
"php": ">=8.1"
|
||||
"php": ">=8.1",
|
||||
"psr/log": "^3.0@dev"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.10.x-dev",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"phan/phan": "v5.x-dev",
|
||||
"phpunit/phpunit": "^9",
|
||||
"egrajp/smarty-extended": "^4.3"
|
||||
"egrajp/smarty-extended": "^4.3",
|
||||
"vimeo/psalm": "^5.0@dev"
|
||||
},
|
||||
"repositories": {
|
||||
"git.egplusww.jp.Composer": {
|
||||
|
||||
@@ -1 +1 @@
|
||||
8.0.0
|
||||
8.5.0
|
||||
|
||||
@@ -20,7 +20,11 @@ fi;
|
||||
# read in the .env.deploy file and we must have
|
||||
# GITLAB_USER
|
||||
# GITLAB_TOKEN
|
||||
# GITLAB_URL
|
||||
# GITEA_USER
|
||||
# GITEA_DEPLOY_TOKEN
|
||||
# GITEA_URL_DL
|
||||
# GITEA_URL_PUSH
|
||||
if [ ! -f "${BASE_FOLDER}.env.deploy" ]; then
|
||||
echo "Deploy enviroment file .env.deploy is missing";
|
||||
exit;
|
||||
@@ -31,30 +35,34 @@ source .env.deploy;
|
||||
cd -;
|
||||
set +o allexport;
|
||||
|
||||
echo "[START]";
|
||||
# gitea
|
||||
if [ ! -z "${GITEA_USER}" ] && [ ! -z "${GITEA_TOKEN}" ]; then
|
||||
if [ ! -z "${GITEA_URL_DL}" ] && [ ! -z "${GITEA_URL_PUSH}" ] &&
|
||||
[ ! -z "${GITEA_USER}" ] && [ ! -z "${GITEA_TOKEN}" ]; then
|
||||
curl -LJO \
|
||||
--output-dir "${BASE_FOLDER}" \
|
||||
https://git.egplusww.jp/Composer/CoreLibs-Composer-All/archive/v${VERSION}.zip;
|
||||
${GITEA_URL_DL}/v${VERSION}.zip;
|
||||
curl --user ${GITEA_USER}:${GITEA_TOKEN} \
|
||||
--upload-file "${BASE_FOLDER}/CoreLibs-Composer-All-v${VERSION}.zip" \
|
||||
https://git.egplusww.jp/api/packages/Composer/composer?version=${VERSION};
|
||||
${GITEA_URL_PUSH}?version=${VERSION};
|
||||
echo "${VERSION}" > "${file_last_published}";
|
||||
else
|
||||
echo "Missing either GITEA_USER or GITEA_TOKEN environment variable";
|
||||
fi;
|
||||
|
||||
# gitlab
|
||||
if [ ! -z "${GITLAB_DEPLOY_TOKEN}" ]; then
|
||||
if [ ! -z "${GITLAB_URL}" ] && [ ! -z "${GITLAB_DEPLOY_TOKEN}" ]; then
|
||||
curl --data tag=v${VERSION} \
|
||||
--header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
|
||||
"https://gitlab-na.factory.tools/api/v4/projects/950/packages/composer";
|
||||
"${GITLAB_URL}";
|
||||
curl --data branch=master \
|
||||
--header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
|
||||
"https://gitlab-na.factory.tools/api/v4/projects/950/packages/composer";
|
||||
"${GITLAB_URL}";
|
||||
echo "${VERSION}" > "${file_last_published}";
|
||||
else
|
||||
echo "Missing GITLAB_DEPLOY_TOKEN environment variable";
|
||||
fi;
|
||||
echo "";
|
||||
echo "[DONE]";
|
||||
|
||||
# __END__
|
||||
|
||||
@@ -68,71 +68,97 @@ 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;
|
||||
/** @var int maxium password lenght */
|
||||
public const PASSWORD_MAX_LENGTH = 255;
|
||||
/** @var string special characters for regex */
|
||||
public const PASSWORD_SPECIAL_RANGE = '@$!%*?&';
|
||||
/** @var string regex for lower case alphabet */
|
||||
public const PASSWORD_LOWER = '(?=.*[a-z])';
|
||||
/** @var string regex for upper case alphabet */
|
||||
public const PASSWORD_UPPER = '(?=.*[A-Z])';
|
||||
/** @var string regex for numbers */
|
||||
public const PASSWORD_NUMBER = '(?=.*\d)';
|
||||
/** @var string regex for special chanagers */
|
||||
public const PASSWORD_SPECIAL = "(?=.*[" . self::PASSWORD_SPECIAL_RANGE . "])";
|
||||
/** @var string regex for fixed allowed characters password regex */
|
||||
public const PASSWORD_REGEX = "/^"
|
||||
. self::PASSWORD_LOWER
|
||||
. self::PASSWORD_UPPER
|
||||
. self::PASSWORD_NUMBER
|
||||
. self::PASSWORD_SPECIAL
|
||||
. "[A-Za-z\d" . self::PASSWORD_SPECIAL_RANGE . "]"
|
||||
. "{" . self::PASSWORD_MIN_LENGTH . "," . self::PASSWORD_MAX_LENGTH . "}"
|
||||
. "$/";
|
||||
|
||||
/** @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,}',
|
||||
];
|
||||
@@ -140,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' => ''
|
||||
@@ -154,54 +180,71 @@ 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;
|
||||
|
||||
/** @var \CoreLibs\Debug\Logging logger */
|
||||
public $log;
|
||||
// settings
|
||||
/** @var array<string,mixed> options */
|
||||
private array $options = [];
|
||||
/** @var array<string,string> locale options: locale, domain, encoding (opt), path */
|
||||
private array $locale = [
|
||||
'locale' => '',
|
||||
'domain' => '',
|
||||
'encoding' => '',
|
||||
'path' => '',
|
||||
];
|
||||
|
||||
/** @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 bool $auto_login [default true] Auto login flag, legacy
|
||||
* If set to true will run login
|
||||
* during construction
|
||||
* @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,
|
||||
bool $auto_login = true
|
||||
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
|
||||
$this->session = $session;
|
||||
|
||||
// set and check options
|
||||
if (false === $this->loginSetOptions($options)) {
|
||||
// on failure, exit
|
||||
echo "<b>Could not set options</b>";
|
||||
$this->loginTerminate(4000);
|
||||
}
|
||||
|
||||
// string key, msg: string, flag: e (error), o (ok)
|
||||
$this->login_error_msg = [
|
||||
'0' => [
|
||||
@@ -339,7 +382,7 @@ class Login
|
||||
$_SESSION['DEFAULT_ACL_LIST_TYPE'] = $this->default_acl_list_type;
|
||||
|
||||
// this will be deprecated
|
||||
if ($auto_login === true) {
|
||||
if ($this->options['auto_login'] === true) {
|
||||
$this->loginMainCall();
|
||||
}
|
||||
}
|
||||
@@ -384,6 +427,192 @@ class Login
|
||||
// **** PRIVATE INTERNAL
|
||||
// *************************************************************************
|
||||
|
||||
/**
|
||||
* Set options
|
||||
* Current allowed:
|
||||
* target <string>: site target
|
||||
* debug <bool>
|
||||
* auto_login <bool>: self start login process
|
||||
* db_schema <string>
|
||||
* password_min_length <int>
|
||||
* default_acl_level <int>
|
||||
* logout_target <string>: should default be '' or target path to where
|
||||
* can_change <bool>: can change password (NOT IMPLEMENTED)
|
||||
* forget_flow <boo>: reset password on forget (NOT IMPLEMENTED)
|
||||
* locale_path <string>: absolue path to the locale folder
|
||||
* site_locale <string>: what locale to load
|
||||
* site_domain <string>: what domain (locale file name) to use
|
||||
*
|
||||
* @param array<string,mixed> $options Options array from class load
|
||||
* @return bool True on ok, False on failure
|
||||
*/
|
||||
private function loginSetOptions(array $options): bool
|
||||
{
|
||||
// target and debug flag
|
||||
if (
|
||||
empty($options['target'])
|
||||
) {
|
||||
$options['target'] = 'test';
|
||||
}
|
||||
if (
|
||||
empty($options['debug']) ||
|
||||
!is_bool($options['debug'])
|
||||
) {
|
||||
$options['debug'] = false;
|
||||
}
|
||||
|
||||
// AUTO LOGIN
|
||||
if (
|
||||
!isset($options['auto_login']) ||
|
||||
!is_bool($options['auto_login'])
|
||||
) {
|
||||
// if set to true will run login call during class construction
|
||||
$options['auto_login'] = false;
|
||||
}
|
||||
|
||||
// DB SCHEMA
|
||||
if (
|
||||
empty($options['db_schema']) ||
|
||||
// TODO more strict check
|
||||
is_string($options['db_schema'])
|
||||
) {
|
||||
// get scham from db, else fallback to public
|
||||
if (!empty($this->db->dbGetSchema(true))) {
|
||||
$options['db_schema'] = $this->db->dbGetSchema(true);
|
||||
} else {
|
||||
$options['db_schema'] = 'public';
|
||||
}
|
||||
}
|
||||
if ($this->db->dbGetSchema() != $options['db_schema']) {
|
||||
$this->db->dbSetSchema($options['db_schema']);
|
||||
}
|
||||
|
||||
// MIN PASSWORD LENGTH
|
||||
// can only be in length of current defined min/max
|
||||
if (
|
||||
!empty($options['password_min_lenght']) &&
|
||||
!is_numeric($options['password_min_length']) &&
|
||||
$options['password_min_length'] >= self::PASSWORD_MIN_LENGTH &&
|
||||
$options['password_min_length'] <= self::PASSWORD_MAX_LENGTH
|
||||
) {
|
||||
if (
|
||||
false === $this->loginSetPasswordMinLength(
|
||||
(int)$options['password_min_length']
|
||||
)
|
||||
) {
|
||||
$options['password_min_length'] = self::PASSWORD_MIN_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
// DEFAULT ACL LEVEL
|
||||
if (
|
||||
!isset($options['default_acl_level']) ||
|
||||
!is_numeric($options['default_acl_level']) ||
|
||||
$options['default_acl_level'] < 0 || $options['default_acl_level'] > 100
|
||||
) {
|
||||
$options['default_acl_level'] = 0;
|
||||
if (defined('DEFAULT_ACL_LEVEL')) {
|
||||
trigger_error(
|
||||
'loginMainCall: DEFAULT_ACL_LEVEL should not be used',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$options['default_acl_level'] = DEFAULT_ACL_LEVEL;
|
||||
}
|
||||
}
|
||||
$this->default_acl_level = (int)$options['default_acl_level'];
|
||||
|
||||
// LOGOUT TARGET
|
||||
if (!isset($options['logout_target'])) {
|
||||
if (defined('LOGOUT_TARGET')) {
|
||||
trigger_error(
|
||||
'loginMainCall: LOGOUT_TARGET should not be used',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$options['logout_target'] = LOGOUT_TARGET;
|
||||
$this->logout_target = $options['logout_target'];
|
||||
}
|
||||
}
|
||||
|
||||
// *** PASSWORD SETTINGS
|
||||
// User can change password
|
||||
if (
|
||||
!isset($options['can_change']) ||
|
||||
!is_bool($options['can_change'])
|
||||
) {
|
||||
$options['can_change'] = false;
|
||||
}
|
||||
$this->password_change = $options['can_change'];
|
||||
// User can trigger a forgot password flow
|
||||
if (
|
||||
!isset($options['forgot_flow']) ||
|
||||
!is_bool($options['forgot_flow'])
|
||||
) {
|
||||
$options['forgot_flow'] = false;
|
||||
}
|
||||
$this->password_forgot = $options['forgot_flow'];
|
||||
|
||||
// *** LANGUAGE
|
||||
// LANG: LOCALE PATH
|
||||
if (empty($options['locale_path'])) {
|
||||
// trigger deprecation error
|
||||
trigger_error(
|
||||
'loginSetOptions: misssing locale_path entry is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// set path
|
||||
$options['locale_path'] = BASE . INCLUDES . LOCALE;
|
||||
}
|
||||
$_SESSION['LOCALE_PATH'] = $options['locale_path'];
|
||||
// LANG: LOCALE
|
||||
if (empty($options['site_locale'])) {
|
||||
trigger_error(
|
||||
'loginMainCall: SITE_LOCALE should not be used',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$options['site_locale'] = defined('SITE_LOCALE') && !empty(SITE_LOCALE) ?
|
||||
SITE_LOCALE : 'en.UTF-8';
|
||||
}
|
||||
// LANG: DOMAIN
|
||||
if (empty($options['site_domain'])) {
|
||||
// we need to get domain set from outside
|
||||
$options['site_domain'] = 'admin';
|
||||
if (
|
||||
defined('SITE_DOMAIN')
|
||||
) {
|
||||
// trigger deprecation error
|
||||
trigger_error(
|
||||
'loginSetOptions: misssing site_domain entry is deprecated (SITE_DOMAIN)',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// set domain
|
||||
$options['site_domain'] = SITE_DOMAIN;
|
||||
} elseif (
|
||||
defined('CONTENT_PATH')
|
||||
) {
|
||||
// trigger deprecation error
|
||||
trigger_error(
|
||||
'loginSetOptions: misssing site_domain entry is deprecated (CONTENT_PATH)',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$options['set_domain'] = str_replace(DIRECTORY_SEPARATOR, '', CONTENT_PATH);
|
||||
}
|
||||
}
|
||||
$_SESSION['DEFAULT_DOMAIN'] = $options['site_domain'];
|
||||
// LANG: ENCODING
|
||||
if (empty($options['site_encoding'])) {
|
||||
trigger_error(
|
||||
'loginMainCall: SITE_ENCODING should not be used',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$options['site_encoding'] = defined('SITE_ENCODING') && !empty(SITE_ENCODING) ?
|
||||
SITE_ENCODING : 'UTF-8';
|
||||
}
|
||||
|
||||
// write array to options
|
||||
$this->options = $options;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for all flags and sets error codes for each
|
||||
* In order:
|
||||
@@ -525,7 +754,10 @@ class Login
|
||||
// we have to get the themes in here too
|
||||
$q = "SELECT eu.edit_user_id, eu.username, eu.password, "
|
||||
. "eu.edit_group_id, "
|
||||
. "eg.name AS edit_group_name, admin, "
|
||||
. "eg.name AS edit_group_name, eu.admin, "
|
||||
// additinal acl lists
|
||||
. "eu.additional_acl AS user_additional_acl, "
|
||||
. "eg.additional_acl AS group_additional_acl, "
|
||||
// login error + locked
|
||||
. "eu.login_error_count, eu.login_error_date_last, "
|
||||
. "eu.login_error_date_first, eu.strict, eu.locked, "
|
||||
@@ -651,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) {
|
||||
@@ -673,8 +905,10 @@ class Login
|
||||
$_SESSION['GROUP_NAME'] = $res['edit_group_name'];
|
||||
$_SESSION['USER_ACL_LEVEL'] = $res['user_level'];
|
||||
$_SESSION['USER_ACL_TYPE'] = $res['user_type'];
|
||||
$_SESSION['USER_ADDITIONAL_ACL'] = Json::jsonConvertToArray($res['user_additional_acl']);
|
||||
$_SESSION['GROUP_ACL_LEVEL'] = $res['group_level'];
|
||||
$_SESSION['GROUP_ACL_TYPE'] = $res['group_type'];
|
||||
$_SESSION['GROUP_ADDITIONAL_ACL'] = Json::jsonConvertToArray($res['group_additional_acl']);
|
||||
// deprecated TEMPLATE setting
|
||||
$_SESSION['TEMPLATE'] = $res['template'] ? $res['template'] : '';
|
||||
$_SESSION['HEADER_COLOR'] = !empty($res['second_header_color']) ?
|
||||
@@ -691,6 +925,7 @@ class Login
|
||||
// rgb: nnn.n for each
|
||||
// hsl: nnn.n for first, nnn.n% for 2nd, 3rd
|
||||
// Check\Colors::validateColor()
|
||||
// LANGUAGE/LOCALE/ENCODING:
|
||||
$_SESSION['LANG'] = $res['locale'] ?? 'en';
|
||||
$_SESSION['DEFAULT_CHARSET'] = $res['encoding'] ?? 'UTF-8';
|
||||
$_SESSION['DEFAULT_LOCALE'] = $_SESSION['LANG']
|
||||
@@ -792,7 +1027,8 @@ class Login
|
||||
$_SESSION['PAGES'] = $pages;
|
||||
$_SESSION['PAGES_ACL_LEVEL'] = $pages_acl;
|
||||
// load the edit_access user rights
|
||||
$q = "SELECT ea.edit_access_id, level, type, ea.name, ea.color, ea.uid, edit_default "
|
||||
$q = "SELECT ea.edit_access_id, level, type, ea.name, "
|
||||
. "ea.color, ea.uid, edit_default, ea.additional_acl "
|
||||
. "FROM edit_access_user eau, edit_access_right ear, edit_access ea "
|
||||
. "WHERE eau.edit_access_id = ea.edit_access_id "
|
||||
. "AND eau.edit_access_right_id = ear.edit_access_right_id "
|
||||
@@ -812,13 +1048,14 @@ 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'],
|
||||
'uid' => $res['uid'],
|
||||
'color' => $res['color'],
|
||||
'default' => $res['edit_default'],
|
||||
'additional_acl' => Json::jsonConvertToArray($res['additional_acl']),
|
||||
'data' => $ea_data
|
||||
];
|
||||
// set the default unit
|
||||
@@ -893,6 +1130,11 @@ class Login
|
||||
// username (login), group name
|
||||
$this->acl['user_name'] = $_SESSION['USER_NAME'];
|
||||
$this->acl['group_name'] = $_SESSION['GROUP_NAME'];
|
||||
// set additional acl
|
||||
$this->acl['additional_acl'] = [
|
||||
'user' => $_SESSION['USER_ADDITIONAL_ACL'],
|
||||
'group' => $_SESSION['GROUP_ADDITIONAL_ACL'],
|
||||
];
|
||||
// we start with the default acl
|
||||
$this->acl['base'] = $this->default_acl_level;
|
||||
|
||||
@@ -937,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
|
||||
@@ -955,7 +1203,8 @@ class Login
|
||||
'uid' => $unit['uid'],
|
||||
'level' => $this->default_acl_list[$this->acl['unit'][$ea_id]]['name'] ?? -1,
|
||||
'default' => $unit['default'],
|
||||
'data' => $unit['data']
|
||||
'data' => $unit['data'],
|
||||
'additional_acl' => $unit['additional_acl']
|
||||
];
|
||||
// set default
|
||||
if (!empty($unit['default'])) {
|
||||
@@ -980,6 +1229,65 @@ class Login
|
||||
// $this->debug('ACL', $this->print_ar($this->acl));
|
||||
}
|
||||
|
||||
/**
|
||||
* set locale
|
||||
* if invalid, set to empty string
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function loginSetLocale(): void
|
||||
{
|
||||
// ** LANGUAGE SET AFTER LOGIN **
|
||||
// set the locale
|
||||
if (
|
||||
!empty($_SESSION['DEFAULT_LOCALE']) &&
|
||||
preg_match("/^[-A-Za-z0-9_.@]+$/", $_SESSION['DEFAULT_LOCALE'])
|
||||
) {
|
||||
$locale = $_SESSION['DEFAULT_LOCALE'];
|
||||
} elseif (
|
||||
!preg_match("/^[-A-Za-z0-9_.@]+$/", $this->options['site_locale'])
|
||||
) {
|
||||
$locale = $this->options['site_locale'];
|
||||
} else {
|
||||
$locale = '';
|
||||
}
|
||||
// set the charset
|
||||
preg_match('/(?:\\.(?P<charset>[-A-Za-z0-9_]+))/', $locale, $matches);
|
||||
$locale_encoding = $matches['charset'] ?? '';
|
||||
if (!empty($locale_encoding)) {
|
||||
$encoding = strtoupper($locale_encoding);
|
||||
} elseif (
|
||||
!empty($_SESSION['DEFAULT_CHARSET']) &&
|
||||
preg_match("/^[-A-Za-z0-9_]+$/", $_SESSION['DEFAULT_CHARSET'])
|
||||
) {
|
||||
$encoding = $_SESSION['DEFAULT_CHARSET'];
|
||||
} elseif (
|
||||
!preg_match("/^[-A-Za-z0-9_]+$/", $this->options['site_encoding'])
|
||||
) {
|
||||
$encoding = $this->options['site_encoding'];
|
||||
} else {
|
||||
$encoding = '';
|
||||
}
|
||||
// check domain
|
||||
$domain = $this->options['site_domain'];
|
||||
if (
|
||||
!preg_match("/^\w+$/", $this->options['site_domain'])
|
||||
) {
|
||||
$domain = '';
|
||||
}
|
||||
$path = $this->options['locale_path'];
|
||||
if (!is_dir($path)) {
|
||||
$path = '';
|
||||
}
|
||||
// domain and path are a must set from class options
|
||||
$this->locale = [
|
||||
'locale' => $locale,
|
||||
'domain' => $domain,
|
||||
'encoding' => $encoding,
|
||||
'path' => $path,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if the password is in a valid format
|
||||
*
|
||||
@@ -1306,7 +1614,7 @@ class Login
|
||||
// TODO: submit or JS to set target page as ajax call
|
||||
// NOTE: for the HTML block I ignore line lengths
|
||||
// phpcs:disable
|
||||
$this->login_template['password_change'] = <<<EOM
|
||||
$this->login_template['password_change'] = <<<HTML
|
||||
<div id="pw_change_div" class="hidden" style="position: absolute; top: 30px; left: 50px; width: 400px; height: 220px; background-color: white; border: 1px solid black; padding: 25px;">
|
||||
<table>
|
||||
<tr><td class="norm" align="center" colspan="2"><h3>{TITLE_PASSWORD_CHANGE}</h3></td></tr>
|
||||
@@ -1324,7 +1632,7 @@ class Login
|
||||
</table>
|
||||
</div>
|
||||
{PASSWORD_CHANGE_SHOW}
|
||||
EOM;
|
||||
HTML;
|
||||
// phpcs:enable
|
||||
}
|
||||
if ($this->password_forgot) {
|
||||
@@ -1348,7 +1656,7 @@ EOM;
|
||||
// now check templates
|
||||
// TODO: submit or JS to set target page as ajax call
|
||||
if (!$this->login_template['template']) {
|
||||
$this->login_template['template'] = <<<EOM
|
||||
$this->login_template['template'] = <<<HTML
|
||||
<!DOCTYPE html>
|
||||
<html lang="{LANGUAGE}">
|
||||
<head>
|
||||
@@ -1410,7 +1718,7 @@ h3 { font-size: 18px; }
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
EOM;
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1513,50 +1821,9 @@ EOM;
|
||||
echo '<b>No active session found</b>';
|
||||
$this->loginTerminate(2000);
|
||||
}
|
||||
|
||||
// if we have a search path we need to set it, to use the correct DB to login
|
||||
// check what schema to use. if there is a login schema use this, else check
|
||||
// if there is a schema set in the config, or fall back to DB_SCHEMA
|
||||
// if this exists, if this also does not exists use public schema
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (defined('LOGIN_DB_SCHEMA') && !empty(LOGIN_DB_SCHEMA)) {
|
||||
$SCHEMA = LOGIN_DB_SCHEMA;
|
||||
} elseif (!empty($this->db->dbGetSchema(true))) {
|
||||
$SCHEMA = $this->db->dbGetSchema(true);
|
||||
} elseif (defined('PUBLIC_SCHEMA')) {
|
||||
$SCHEMA = PUBLIC_SCHEMA;
|
||||
} else {
|
||||
$SCHEMA = 'public';
|
||||
}
|
||||
// set schema if schema differs to schema set in db conneciton
|
||||
if ($this->db->dbGetSchema() != $SCHEMA) {
|
||||
$this->db->dbExec("SET search_path TO " . $SCHEMA);
|
||||
}
|
||||
|
||||
// set internal page name
|
||||
$this->page_name = $this->loginReadPageName();
|
||||
|
||||
// set default ACL Level
|
||||
if (defined('DEFAULT_ACL_LEVEL')) {
|
||||
$this->default_acl_level = DEFAULT_ACL_LEVEL;
|
||||
}
|
||||
|
||||
if (defined('PASSWORD_MIN_LENGTH')) {
|
||||
$this->password_min_length = PASSWORD_MIN_LENGTH;
|
||||
$this->password_min_length_max = PASSWORD_MIN_LENGTH;
|
||||
}
|
||||
if (defined('PASSWORD_MIN_LENGTH')) {
|
||||
$this->password_max_length = PASSWORD_MAX_LENGTH;
|
||||
}
|
||||
|
||||
// pre-check that password min/max lengths are inbetween 1 and 255;
|
||||
if ($this->password_max_length > 255) {
|
||||
$this->password_max_length = 255;
|
||||
}
|
||||
if ($this->password_min_length < 1) {
|
||||
$this->password_min_length = 1;
|
||||
}
|
||||
|
||||
// set global is ajax page for if we show the data directly,
|
||||
// or need to pass it back
|
||||
// to the continue AJAX class for output back to the user
|
||||
@@ -1588,13 +1855,13 @@ EOM;
|
||||
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
|
||||
@@ -1608,20 +1875,8 @@ EOM;
|
||||
$this->pw_old_password = $_POST['pw_old_password'] ?? '';
|
||||
$this->pw_new_password = $_POST['pw_new_password'] ?? '';
|
||||
$this->pw_new_password_confirm = $_POST['pw_new_password_confirm'] ?? '';
|
||||
// logout target (from config)
|
||||
if (defined('LOGOUT_TARGET')) {
|
||||
$this->logout_target = LOGOUT_TARGET;
|
||||
}
|
||||
// disallow user list for password change
|
||||
$this->pw_change_deny_users = ['admin'];
|
||||
// set flag if password change is okay
|
||||
if (defined('PASSWORD_CHANGE')) {
|
||||
$this->password_change = PASSWORD_CHANGE;
|
||||
}
|
||||
// NOTE: forgot password flow with email
|
||||
if (defined('PASSWORD_FORGOT')) {
|
||||
$this->password_forgot = PASSWORD_FORGOT;
|
||||
}
|
||||
// max login counts before error reporting
|
||||
$this->max_login_error_count = 10;
|
||||
// users that never get locked, even if they are set strict
|
||||
@@ -1634,26 +1889,13 @@ EOM;
|
||||
// logsout user
|
||||
$this->loginLogoutUser();
|
||||
// ** LANGUAGE SET AFTER LOGIN **
|
||||
// set the locale
|
||||
if (
|
||||
$this->session->checkActiveSession() === true &&
|
||||
!empty($_SESSION['DEFAULT_LOCALE'])
|
||||
) {
|
||||
$locale = $_SESSION['DEFAULT_LOCALE'];
|
||||
} else {
|
||||
$locale = (defined('SITE_LOCALE') && !empty(SITE_LOCALE)) ?
|
||||
SITE_LOCALE :
|
||||
/** @phpstan-ignore-next-line DEFAULT_LOCALE could be empty */
|
||||
((defined('DEFAULT_LOCALE') && !empty(DEFAULT_LOCALE)) ?
|
||||
DEFAULT_LOCALE : 'en.UTF-8');
|
||||
}
|
||||
// set domain
|
||||
if (defined('CONTENT_PATH')) {
|
||||
$domain = str_replace('/', '', CONTENT_PATH);
|
||||
} else {
|
||||
$domain = 'admin';
|
||||
}
|
||||
$this->l = new \CoreLibs\Language\L10n($locale, $domain);
|
||||
$this->loginSetLocale();
|
||||
// load translator
|
||||
$this->l = new \CoreLibs\Language\L10n(
|
||||
$this->locale['locale'],
|
||||
$this->locale['domain'],
|
||||
$this->locale['path']
|
||||
);
|
||||
// if the password change flag is okay, run the password change method
|
||||
if ($this->password_change) {
|
||||
$this->loginPasswordChange();
|
||||
@@ -1669,24 +1911,12 @@ EOM;
|
||||
// if variable AJAX flag is not set, show output
|
||||
// else pass through for ajax work
|
||||
if ($this->login_is_ajax_page === false) {
|
||||
// the login screen if we hav no login permission & login screen html data
|
||||
// the login screen if we hav no login permission and
|
||||
// login screen html data
|
||||
if ($this->login_html !== null) {
|
||||
// echo $this->login_html;
|
||||
$this->loginPrintLogin();
|
||||
}
|
||||
// do not go anywhere, quit processing here
|
||||
// do something with possible debug data?
|
||||
if (TARGET == 'live' || TARGET == 'remote') {
|
||||
// login
|
||||
$this->log->setLogLevelAll('debug', DEBUG ? true : false);
|
||||
$this->log->setLogLevelAll('echo', false);
|
||||
$this->log->setLogLevelAll('print', DEBUG ? true : false);
|
||||
}
|
||||
$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 {
|
||||
@@ -1802,7 +2032,7 @@ EOM;
|
||||
if (
|
||||
$length >= $this->password_min_length_max &&
|
||||
$length <= $this->password_max_length &&
|
||||
$length <= 255
|
||||
$length <= self::PASSWORD_MAX_LENGTH
|
||||
) {
|
||||
$this->password_min_length = $length;
|
||||
return true;
|
||||
@@ -1880,7 +2110,7 @@ EOM;
|
||||
// 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;
|
||||
}
|
||||
@@ -2223,6 +2453,53 @@ EOM;
|
||||
): bool|string {
|
||||
return $this->loginGetEditAccessData($edit_access_id, $data_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return locale settings with
|
||||
* locale
|
||||
* domain
|
||||
* encoding
|
||||
* path
|
||||
*
|
||||
* empty string if not set
|
||||
*
|
||||
* @return array<string,string> Locale settings
|
||||
*/
|
||||
public function loginGetLocale(): array
|
||||
{
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* return header color or null for not set
|
||||
*
|
||||
* @return string|null Header color in RGB hex with leading sharp
|
||||
*/
|
||||
public function loginGetHeaderColor(): ?string
|
||||
{
|
||||
return $_SESSION['HEADER_COLOR'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current loaded list of pages the user can access
|
||||
*
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public function loginGetPages(): array
|
||||
{
|
||||
|
||||
return $_SESSION['PAGES'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current set EUID (edit user id)
|
||||
*
|
||||
* @return string EUID as string
|
||||
*/
|
||||
public function loginGetEuid(): string
|
||||
{
|
||||
return (string)$this->euid;
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -35,105 +35,105 @@ 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 array<string,string> $locale locale data read from setLocale
|
||||
* @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,
|
||||
array $locale
|
||||
?int $set_default_acl_level = null
|
||||
) {
|
||||
// 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
|
||||
@@ -141,12 +141,12 @@ class Backend
|
||||
// get the language sub class & init it
|
||||
$this->l = $l10n;
|
||||
// parse and read, legacy stuff
|
||||
$locale = $this->l->getLocaleAsArray();
|
||||
$this->encoding = $locale['encoding'];
|
||||
$this->lang = $locale['lang'];
|
||||
// get first part from lang
|
||||
$this->lang_short = explode('_', $locale['lang'])[0];
|
||||
$this->domain = $this->l->getDomain();
|
||||
$this->lang_dir = $this->l->getBaseLocalePath();
|
||||
$this->lang_short = $locale['lang_short'];
|
||||
$this->domain = $locale['domain'];
|
||||
$this->lang_dir = $locale['path'];
|
||||
|
||||
// set the page name
|
||||
$this->page_name = \CoreLibs\Get\System::getPageName();
|
||||
@@ -156,7 +156,14 @@ class Backend
|
||||
$this->$_action = $_POST[$_action] ?? '';
|
||||
}
|
||||
|
||||
$this->default_acl = DEFAULT_ACL_LEVEL;
|
||||
if ($set_default_acl_level === null) {
|
||||
/** @deprecated Admin::__construct missing default_acl_level parameter */
|
||||
trigger_error(
|
||||
'Calling Admin::__construct without default_acl_level parameter is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
$this->default_acl = $set_default_acl_level ?? DEFAULT_ACL_LEVEL;
|
||||
|
||||
// queue key
|
||||
if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action)) {
|
||||
@@ -190,35 +197,34 @@ class Backend
|
||||
* @param string $event any kind of event description,
|
||||
* @param string|array<mixed> $data any kind of data related to that event
|
||||
* @param string $write_type write type can bei STRING or BINARY
|
||||
* @param string|null $db_schema override target schema
|
||||
* @return void
|
||||
*/
|
||||
public function adbEditLog(
|
||||
string $event = '',
|
||||
string|array $data = '',
|
||||
string $write_type = 'STRING'
|
||||
string $write_type = 'STRING',
|
||||
?string $db_schema = null
|
||||
): void {
|
||||
$data_binary = '';
|
||||
$data_write = '';
|
||||
if ($write_type == 'BINARY') {
|
||||
$data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data)));
|
||||
$data = 'see bzip compressed data_binary field';
|
||||
$data_write = 'see bzip compressed data_binary field';
|
||||
}
|
||||
if ($write_type == 'STRING') {
|
||||
$data_binary = '';
|
||||
$data = $this->db->dbEscapeString(serialize($data));
|
||||
$data_write = $this->db->dbEscapeString(serialize($data));
|
||||
}
|
||||
|
||||
// check schema
|
||||
$SCHEMA = 'public';
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (defined('LOGIN_DB_SCHEMA') && !empty(LOGIN_DB_SCHEMA)) {
|
||||
$SCHEMA = LOGIN_DB_SCHEMA;
|
||||
} elseif ($this->db->dbGetSchema()) {
|
||||
$SCHEMA = $this->db->dbGetSchema();
|
||||
} elseif (defined('PUBLIC_SCHEMA')) {
|
||||
$SCHEMA = PUBLIC_SCHEMA;
|
||||
/** @var string $DB_SCHEMA check schema */
|
||||
$DB_SCHEMA = 'public';
|
||||
if ($db_schema !== null) {
|
||||
$DB_SCHEMA = $db_schema;
|
||||
} elseif (!empty($this->db->dbGetSchema())) {
|
||||
$DB_SCHEMA = $this->db->dbGetSchema();
|
||||
}
|
||||
/** @phpstan-ignore-next-line for whatever reason $SCHEMA is seen as possible array */
|
||||
$q = "INSERT INTO " . $SCHEMA . ".edit_log "
|
||||
$q = "INSERT INTO " . $DB_SCHEMA . ".edit_log "
|
||||
. "(euid, event_date, event, data, data_binary, page, "
|
||||
. "ip, user_agent, referer, script_name, query_string, server_name, http_host, "
|
||||
. "http_accept, http_accept_charset, http_accept_encoding, session_id, "
|
||||
@@ -229,10 +235,12 @@ class Backend
|
||||
'NULL')
|
||||
. ", "
|
||||
. "NOW(), "
|
||||
. "'" . $this->db->dbEscapeString((string)$event) . "', '" . $data . "', "
|
||||
. "'" . $data_binary . "', '" . $this->db->dbEscapeString((string)$this->page_name) . "', "
|
||||
. "'" . @$_SERVER["REMOTE_ADDR"] . "', "
|
||||
. "'" . $this->db->dbEscapeString(@$_SERVER['HTTP_USER_AGENT']) . "', "
|
||||
. "'" . $this->db->dbEscapeString((string)$event) . "', "
|
||||
. "'" . $data_write . "', "
|
||||
. "'" . $data_binary . "', "
|
||||
. "'" . $this->db->dbEscapeString((string)$this->page_name) . "', "
|
||||
. "'" . ($_SERVER["REMOTE_ADDR"] ?? '') . "', "
|
||||
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_USER_AGENT'] ?? '') . "', "
|
||||
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_REFERER'] ?? '') . "', "
|
||||
. "'" . $this->db->dbEscapeString($_SERVER['SCRIPT_FILENAME'] ?? '') . "', "
|
||||
. "'" . $this->db->dbEscapeString($_SERVER['QUERY_STRING'] ?? '') . "', "
|
||||
@@ -282,11 +290,25 @@ class Backend
|
||||
/**
|
||||
* menu creater (from login menu session pages)
|
||||
*
|
||||
* @param int $flag visible flag trigger
|
||||
* @param string|null $set_content_path
|
||||
* @param int $flag visible flag trigger
|
||||
* @return array<mixed> menu array for output on page (smarty)
|
||||
*/
|
||||
public function adbTopMenu(int $flag = 0): array
|
||||
{
|
||||
public function adbTopMenu(
|
||||
?string $set_content_path = null,
|
||||
int $flag = 0,
|
||||
): array {
|
||||
if (
|
||||
$set_content_path === null ||
|
||||
!is_string($set_content_path)
|
||||
) {
|
||||
/** @deprecated adbTopMenu missing set_content_path parameter */
|
||||
trigger_error(
|
||||
'Calling adbTopMenu without set_content_path parameter is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
$set_content_path = $set_content_path ?? CONTENT_PATH;
|
||||
if ($this->menu_show_flag) {
|
||||
$flag = $this->menu_show_flag;
|
||||
}
|
||||
@@ -377,7 +399,7 @@ class Backend
|
||||
\CoreLibs\Get\System::getPageName() == $data['filename'] &&
|
||||
(!isset($data['hostname']) || (
|
||||
isset($data['hostname']) &&
|
||||
(!$data['hostname'] || strstr($data['hostname'], CONTENT_PATH) !== false)
|
||||
(!$data['hostname'] || strstr($data['hostname'], $set_content_path) !== false)
|
||||
))
|
||||
) {
|
||||
$selected = 1;
|
||||
@@ -427,69 +449,6 @@ class Backend
|
||||
};
|
||||
return $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates out of a normal db_return array an assoc array
|
||||
*
|
||||
* @param array<mixed> $db_array input array
|
||||
* @param string|int|bool $key key
|
||||
* @param string|int|bool $value value
|
||||
* @return array<mixed> associative array
|
||||
* @deprecated \CoreLibs\Combined\ArrayHandler::genAssocArray()
|
||||
*/
|
||||
public function adbAssocArray(array $db_array, string|int|bool $key, string|int|bool $value): array
|
||||
{
|
||||
trigger_error(
|
||||
'Method ' . __METHOD__ . ' is deprecated: \CoreLibs\Combined\ArrayHandler::genAssocArray',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
return \CoreLibs\Combined\ArrayHandler::genAssocArray($db_array, $key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* converts bytes into formated string with KB, MB, etc
|
||||
*
|
||||
* @param string|int|float $number string or int or number
|
||||
* @return string formatted string
|
||||
* @deprecated \CoreLibs\Convert\Byte::humanReadableByteFormat()
|
||||
*/
|
||||
public function adbByteStringFormat(string|int|float $number): string
|
||||
{
|
||||
trigger_error(
|
||||
'Method ' . __METHOD__ . ' is deprecated: \CoreLibs\Convert\Byte::humanReadableByteFormat()',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
return \CoreLibs\Convert\Byte::humanReadableByteFormat($number);
|
||||
}
|
||||
|
||||
/**
|
||||
* converts picture to a thumbnail with max x and max y size
|
||||
*
|
||||
* @param string $pic source image file with or without path
|
||||
* @param int $size_x maximum size width
|
||||
* @param int $size_y maximum size height
|
||||
* @param string $dummy empty, or file_type to show an icon
|
||||
* instead of nothing if file is not found
|
||||
* @param string $path if source start is not ROOT path
|
||||
* if empty ROOT is choosen
|
||||
* @return string|bool thumbnail name, or false for error
|
||||
* @deprecated \CoreLibs\Output\Image::createThumbnail()
|
||||
*/
|
||||
public function adbCreateThumbnail(
|
||||
string $pic,
|
||||
int $size_x,
|
||||
int $size_y,
|
||||
string $dummy = '',
|
||||
string $path = '',
|
||||
string $cache = ''
|
||||
): string|bool {
|
||||
trigger_error(
|
||||
'Method ' . __METHOD__ . ' is deprecated: \CoreLibs\Output\Image::createThumbnail()',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
return \CoreLibs\Output\Image::createThumbnail($pic, $size_x, $size_y, $dummy, $path, $cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper function to fill up the mssages array
|
||||
*
|
||||
@@ -523,15 +482,16 @@ class Backend
|
||||
/**
|
||||
* writes live queue
|
||||
*
|
||||
* @param string $queue_key string to identfy the queue
|
||||
* @param string $type [description]
|
||||
* @param string $target [description]
|
||||
* @param string $data [description]
|
||||
* @param string $key_name [description]
|
||||
* @param string $key_value [description]
|
||||
* @param ?string $associate [description]
|
||||
* @param ?string $file [description]
|
||||
* @return void has no return
|
||||
* @param string $queue_key string to identfy the queue
|
||||
* @param string $type [description]
|
||||
* @param string $target [description]
|
||||
* @param string $data [description]
|
||||
* @param string $key_name [description]
|
||||
* @param string $key_value [description]
|
||||
* @param string|null $associate [description]
|
||||
* @param string|null $file [description]
|
||||
* @param string|null $db_schema override target schema
|
||||
* @return void
|
||||
*/
|
||||
public function adbLiveQueue(
|
||||
string $queue_key,
|
||||
@@ -541,19 +501,17 @@ class Backend
|
||||
string $key_name,
|
||||
string $key_value,
|
||||
string $associate = null,
|
||||
string $file = null
|
||||
string $file = null,
|
||||
string $db_schema = null,
|
||||
): void {
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (defined('GLOBAL_DB_SCHEMA') && !empty(GLOBAL_DB_SCHEMA)) {
|
||||
$SCHEMA = GLOBAL_DB_SCHEMA;
|
||||
} elseif ($this->db->dbGetSchema()) {
|
||||
$SCHEMA = $this->db->dbGetSchema();
|
||||
} elseif (defined('PUBLIC_SCHEMA')) {
|
||||
$SCHEMA = PUBLIC_SCHEMA;
|
||||
} else {
|
||||
$SCHEMA = 'public';
|
||||
/** @var string $DB_SCHEMA check schema */
|
||||
$DB_SCHEMA = 'public';
|
||||
if ($db_schema !== null) {
|
||||
$DB_SCHEMA = $db_schema;
|
||||
} elseif (!empty($this->db->dbGetSchema())) {
|
||||
$DB_SCHEMA = $this->db->dbGetSchema();
|
||||
}
|
||||
$q = "INSERT INTO " . $SCHEMA . ".live_queue ("
|
||||
$q = "INSERT INTO " . $DB_SCHEMA . ".live_queue ("
|
||||
. "queue_key, key_value, key_name, type, target, data, group_key, action, associate, file"
|
||||
. ") VALUES ("
|
||||
. "'" . $this->db->dbEscapeString($queue_key) . "', '" . $this->db->dbEscapeString($key_value) . "', "
|
||||
|
||||
@@ -20,49 +20,57 @@ 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 \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 array<string,string> $locale locale array from ::setLocale,
|
||||
* 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,
|
||||
array $locale
|
||||
\CoreLibs\ACL\Login $login,
|
||||
array $options
|
||||
) {
|
||||
$this->log = $log;
|
||||
$this->login = $login;
|
||||
// smarty template engine (extended Translation version)
|
||||
$this->smarty = new \CoreLibs\Template\SmartyExtend($l10n, $locale);
|
||||
$this->smarty = new \CoreLibs\Template\SmartyExtend(
|
||||
$l10n,
|
||||
$options['cache_id'] ?? '',
|
||||
$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(
|
||||
$db_config,
|
||||
$log,
|
||||
$l10n,
|
||||
$locale
|
||||
$this->login->loginGetAcl()
|
||||
);
|
||||
if ($this->form->mobile_phone) {
|
||||
echo "I am sorry, but this page cannot be viewed by a mobile phone";
|
||||
@@ -228,10 +236,14 @@ class EditBase
|
||||
/**
|
||||
* all edit pages
|
||||
*
|
||||
* @param string $set_root
|
||||
* @param string $set_content_path
|
||||
* @return void
|
||||
*/
|
||||
private function editPageFlow(): void
|
||||
{
|
||||
private function editPageFlow(
|
||||
string $set_root,
|
||||
string $set_content_path,
|
||||
): void {
|
||||
// set table width
|
||||
$table_width = '100%';
|
||||
// load call only if id is set
|
||||
@@ -268,23 +280,16 @@ class EditBase
|
||||
|
||||
// MENU START
|
||||
// request some session vars
|
||||
if (empty($_SESSION['HEADER_COLOR'])) {
|
||||
$this->DATA['HEADER_COLOR'] = '#E0E2FF';
|
||||
} else {
|
||||
$this->DATA['HEADER_COLOR'] = $_SESSION['HEADER_COLOR'];
|
||||
}
|
||||
$this->DATA['USER_NAME'] = $_SESSION['USER_NAME'];
|
||||
$this->DATA['EUID'] = $_SESSION['EUID'];
|
||||
$this->DATA['GROUP_NAME'] = $_SESSION['GROUP_NAME'];
|
||||
$this->DATA['GROUP_LEVEL'] = $_SESSION['GROUP_ACL_LEVEL'];
|
||||
$PAGES = $_SESSION['PAGES'];
|
||||
$this->DATA['HEADER_COLOR'] = $this->login->loginGetHeaderColor() ?? '#E0E2FF';
|
||||
$this->DATA['USER_NAME'] = $this->login->loginGetAcl()['user_name'] ?? '';
|
||||
$this->DATA['EUID'] = $this->login->loginGetEuid();
|
||||
$this->DATA['GROUP_NAME'] = $this->login->loginGetAcl()['group_name'] ?? '';
|
||||
$this->DATA['ACCESS_LEVEL'] = $this->login->loginGetAcl()['base'] ?? '';
|
||||
// below is old and to removed when edit_body.tpl is updates
|
||||
$this->DATA['GROUP_LEVEL'] = $this->DATA['ACCESS_LEVEL'];
|
||||
$PAGES = $this->login->loginGetPages();
|
||||
|
||||
//$this->form->log->debug('menu', $this->form->log->prAr($PAGES));
|
||||
|
||||
// build nav from $PAGES ...
|
||||
if (!isset($PAGES) || !is_array($PAGES)) {
|
||||
$PAGES = [];
|
||||
}
|
||||
$menuarray = [];
|
||||
foreach ($PAGES as $PAGE_CUID => $PAGE_DATA) {
|
||||
if ($PAGE_DATA['menu'] && $PAGE_DATA['online']) {
|
||||
@@ -334,7 +339,7 @@ class EditBase
|
||||
$menu_element['filename'] == \CoreLibs\Get\System::getPageName() &&
|
||||
(!isset($menu_element['hostname']) || (
|
||||
isset($menu_element['hostname']) &&
|
||||
(!$menu_element['hostname'] || strstr($menu_element['hostname'], CONTENT_PATH) !== false)
|
||||
(!$menu_element['hostname'] || strstr($menu_element['hostname'], $set_content_path) !== false)
|
||||
))
|
||||
) {
|
||||
$position = $i;
|
||||
@@ -431,7 +436,7 @@ class EditBase
|
||||
$search_glob = [];
|
||||
foreach ($folders as $folder) {
|
||||
// make sure this folder actually exists
|
||||
if (is_dir(ROOT . $folder)) {
|
||||
if (is_dir($set_root . $folder)) {
|
||||
foreach ($files as $file) {
|
||||
$search_glob[] = $folder . $file;
|
||||
}
|
||||
@@ -534,31 +539,74 @@ class EditBase
|
||||
* @throws Exception
|
||||
* @throws SmartyException
|
||||
*/
|
||||
public function editBaseRun(): void
|
||||
{
|
||||
public function editBaseRun(
|
||||
?string $template_dir = null,
|
||||
?string $compile_dir = null,
|
||||
?string $cache_dir = null,
|
||||
?string $set_admin_stylesheet = null,
|
||||
?string $set_default_encoding = null,
|
||||
?string $set_css = null,
|
||||
?string $set_js = null,
|
||||
?string $set_root = null,
|
||||
?string $set_content_path = null
|
||||
): void {
|
||||
// trigger deprecated warning
|
||||
if (
|
||||
$template_dir === null ||
|
||||
$compile_dir === null ||
|
||||
$cache_dir === null ||
|
||||
$set_admin_stylesheet === null ||
|
||||
$set_default_encoding === null ||
|
||||
$set_css === null ||
|
||||
$set_js === null ||
|
||||
$set_root === null ||
|
||||
$set_content_path === null
|
||||
) {
|
||||
/** @deprecated editBaseRun call without parameters */
|
||||
trigger_error(
|
||||
'Calling editBaseRun without paramters is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
// set vars (to be deprecated)
|
||||
$template_dir = $template_dir ?? BASE . INCLUDES . TEMPLATES . CONTENT_PATH;
|
||||
$compile_dir = $compile_dir ?? BASE . TEMPLATES_C;
|
||||
$cache_dir = $cache_dir ?? BASE . CACHE;
|
||||
$set_admin_stylesheet = $set_admin_stylesheet ?? ADMIN_STYLESHEET;
|
||||
$set_default_encoding = $set_default_encoding ?? DEFAULT_ENCODING;
|
||||
$set_css = $set_css ?? LAYOUT . CSS;
|
||||
$set_js = $set_js ?? LAYOUT . JS;
|
||||
$set_root = $set_root ?? ROOT;
|
||||
$set_content_path = $set_content_path ?? CONTENT_PATH;
|
||||
|
||||
// set the template dir
|
||||
// WARNING: this has a special check for the mailing tool layout (old layout)
|
||||
if (defined('LAYOUT')) {
|
||||
$this->smarty->setTemplateDir(BASE . INCLUDES . TEMPLATES . CONTENT_PATH);
|
||||
$this->DATA['css'] = LAYOUT . CSS;
|
||||
$this->DATA['js'] = LAYOUT . JS;
|
||||
} else {
|
||||
// WARNING: this has a special check for the mailing tool layout (old no layout folder)
|
||||
if (!defined('LAYOUT')) {
|
||||
trigger_error(
|
||||
'EditBase with unset LAYOUT is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$this->smarty->setTemplateDir(TEMPLATES);
|
||||
$this->DATA['css'] = CSS;
|
||||
$this->DATA['js'] = JS;
|
||||
} else {
|
||||
$this->smarty->setTemplateDir($template_dir);
|
||||
$this->DATA['css'] = $set_css;
|
||||
$this->DATA['js'] = $set_js;
|
||||
}
|
||||
$ADMIN_STYLESHEET = 'edit.css';
|
||||
// define all needed smarty stuff for the general HTML/page building
|
||||
$this->HEADER['CSS'] = CSS;
|
||||
$this->HEADER['DEFAULT_ENCODING'] = DEFAULT_ENCODING;
|
||||
/** @phpstan-ignore-next-line because ADMIN_STYLESHEET can be null */
|
||||
$this->HEADER['STYLESHEET'] = $ADMIN_STYLESHEET ?? ADMIN_STYLESHEET;
|
||||
$this->HEADER['CSS'] = $set_css;
|
||||
$this->HEADER['DEFAULT_ENCODING'] = $set_default_encoding;
|
||||
$this->HEADER['STYLESHEET'] = $set_admin_stylesheet;
|
||||
|
||||
// main run
|
||||
if ($this->form->my_page_name == 'edit_order') {
|
||||
$this->editOrderPage();
|
||||
} else {
|
||||
$this->editPageFlow();
|
||||
$this->editPageFlow(
|
||||
$set_root,
|
||||
$set_content_path
|
||||
);
|
||||
}
|
||||
|
||||
// debug data, if DEBUG flag is on, this data is print out
|
||||
@@ -571,11 +619,11 @@ class EditBase
|
||||
foreach ($CONTENT_DATA as $key => $value) {
|
||||
$this->smarty->assign($key, $value);
|
||||
}
|
||||
if (is_dir(BASE . TEMPLATES_C)) {
|
||||
$this->smarty->setCompileDir(BASE . TEMPLATES_C);
|
||||
if (is_dir($compile_dir)) {
|
||||
$this->smarty->setCompileDir($compile_dir);
|
||||
}
|
||||
if (is_dir(BASE . CACHE)) {
|
||||
$this->smarty->setCacheDir(BASE . CACHE);
|
||||
if (is_dir($cache_dir)) {
|
||||
$this->smarty->setCacheDir($cache_dir);
|
||||
}
|
||||
$this->smarty->display(
|
||||
$this->EDIT_TEMPLATE,
|
||||
|
||||
123
src/Basic.php
123
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -989,7 +934,7 @@ class Basic
|
||||
int $jpeg_quality = 80
|
||||
) {
|
||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Output\Image::createThumbnailSimple()', E_USER_DEPRECATED);
|
||||
return \CoreLibs\Output\Image::createThumbnailSimple($filename, $thumb_width, $thumb_height, $thumbnail_path, $create_dummy, $use_cache, $high_quality, $jpeg_quality);
|
||||
return \CoreLibs\Output\Image::createThumbnailSimple($filename, $thumb_width, $thumb_height, $thumbnail_path, null, $create_dummy, $use_cache, $high_quality, $jpeg_quality);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -177,6 +177,65 @@ class ArrayHandler
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* search for one or many keys in array and return matching values
|
||||
* If flat is set to true, return flat array with found values only
|
||||
* If prefix is turned on each found group will be prefixed with the
|
||||
* search key
|
||||
*
|
||||
* @param array<mixed> $array array to search in
|
||||
* @param array<mixed> $needles keys to find in array
|
||||
* @param bool $flat [false] Turn on flat output
|
||||
* @param bool $prefix [false] Prefix found with needle key
|
||||
* @return array<mixed> Found values
|
||||
*/
|
||||
public static function arraySearchKey(
|
||||
array $array,
|
||||
array $needles,
|
||||
bool $flat = false,
|
||||
bool $prefix = false
|
||||
): array {
|
||||
$iterator = new \RecursiveArrayIterator($array);
|
||||
$recursive = new \RecursiveIteratorIterator(
|
||||
$iterator,
|
||||
\RecursiveIteratorIterator::SELF_FIRST
|
||||
);
|
||||
$hit_list = [];
|
||||
if ($prefix === true) {
|
||||
$hit_list = array_fill_keys($needles, []);
|
||||
}
|
||||
$key_path = [];
|
||||
$prev_depth = 0;
|
||||
foreach ($recursive as $key => $value) {
|
||||
if ($prev_depth > $recursive->getDepth()) {
|
||||
// remove all trailing to ne depth
|
||||
$diff = $prev_depth - $recursive->getDepth();
|
||||
array_splice($key_path, -$diff, $diff);
|
||||
}
|
||||
$prev_depth = $recursive->getDepth();
|
||||
if ($flat === false) {
|
||||
$key_path[$recursive->getDepth()] = $key;
|
||||
}
|
||||
if (in_array($key, $needles, true)) {
|
||||
ksort($key_path);
|
||||
if ($flat === true) {
|
||||
$hit = $value;
|
||||
} else {
|
||||
$hit = [
|
||||
'value' => $value,
|
||||
'path' => $key_path
|
||||
];
|
||||
}
|
||||
if ($prefix === true) {
|
||||
$hit_list[$key][] = $hit;
|
||||
} else {
|
||||
$hit_list[] = $hit;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $hit_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* correctly recursive merges as an array as array_merge_recursive
|
||||
* just glues things together
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -90,33 +91,6 @@ class Hash
|
||||
{
|
||||
return hash(self::STANDARD_HASH_LONG, $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a unique id with the standard hash type defined in __hash
|
||||
*
|
||||
* @return string Unique ID with fixed length of 8 characters
|
||||
* @deprecated Use \CoreLibs\Create\Uids::uniqIdShort() instead
|
||||
*/
|
||||
public static function __uniqId(): string
|
||||
{
|
||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, '
|
||||
. '\CoreLibs\Create\Uids::uniqIdShort() class', E_USER_DEPRECATED);
|
||||
return \CoreLibs\Create\Uids::uniqIdShort();
|
||||
}
|
||||
|
||||
/**
|
||||
* create a unique id with the standard long hash type
|
||||
* defined in __hashLong
|
||||
*
|
||||
* @return string Unique ID with length of current default long hash
|
||||
* @deprecated Use \CoreLibs\Create\Uids::uniqIdLong() instead
|
||||
*/
|
||||
public static function __uniqIdLong(): string
|
||||
{
|
||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, '
|
||||
. '\CoreLibs\Create\Uids::uniqIdLong() class', E_USER_DEPRECATED);
|
||||
return \CoreLibs\Create\Uids::uniqIdLong();
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -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|null $log Logging class, default set if not set
|
||||
* @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,12 +65,12 @@ class ArrayIO extends \CoreLibs\DB\IO
|
||||
array $db_config,
|
||||
array $table_array,
|
||||
string $table_name,
|
||||
\CoreLibs\Debug\Logging $log = null,
|
||||
\CoreLibs\Logging\Logging $log,
|
||||
int $base_acl_level = 0,
|
||||
int $acl_admin = 0
|
||||
) {
|
||||
// instance db_io class
|
||||
parent::__construct($db_config, $log ?? new \CoreLibs\Debug\Logging());
|
||||
parent::__construct($db_config, $log);
|
||||
// more error vars for this class
|
||||
$this->error_string['1999'] = 'No table array or table name set';
|
||||
$this->error_string['1021'] = 'No Primary Key given';
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
899
src/DB/IO.php
899
src/DB/IO.php
File diff suppressed because it is too large
Load Diff
@@ -42,6 +42,15 @@ interface SqlFunctions
|
||||
*/
|
||||
public function __dbSendQuery(string $query): bool;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param string $query
|
||||
* @param array<mixed> $params
|
||||
* @return bool
|
||||
*/
|
||||
public function __dbSendQueryParams(string $query, array $params): bool;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
@@ -74,6 +83,24 @@ interface SqlFunctions
|
||||
*/
|
||||
public function __dbExecute(string $name, array $data): \PgSql\Result|false;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $query
|
||||
* @return bool
|
||||
*/
|
||||
public function __dbSendPrepare(string $name, string $query): bool;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param string $name
|
||||
* @param array<mixed> $params
|
||||
* @return bool
|
||||
*/
|
||||
public function __dbSendExecute(string $name, array $params): bool;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
@@ -99,6 +126,15 @@ interface SqlFunctions
|
||||
*/
|
||||
public function __dbFieldName(\PgSql\Result|false $cursor, int $i): string|false;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param \PgSql\Result|false $cursor
|
||||
* @param int $i
|
||||
* @return string|false
|
||||
*/
|
||||
public function __dbFieldType(\PgSql\Result|false $cursor, int $i): string|false;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
@@ -173,10 +209,17 @@ interface SqlFunctions
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param \PgSql\Result|false $cursor
|
||||
* @return string
|
||||
* @return array{0:string,1:string}
|
||||
*/
|
||||
public function __dbPrintError(\PgSql\Result|false $cursor = false): string;
|
||||
public function __dbPrintLastError(): array;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param \PgSql\Result|false $cursor
|
||||
* @return array{0:string,1:string}
|
||||
*/
|
||||
public function __dbPrintError(\PgSql\Result|false $cursor = false): array;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
|
||||
@@ -33,7 +33,11 @@
|
||||
* pg_affected_rows (*)
|
||||
* pg_fetch_array
|
||||
* pg_query
|
||||
* pg_query_params
|
||||
* pg_send_query
|
||||
* pg_send_query_params
|
||||
* pg_send_prepare
|
||||
* pg_send_execute
|
||||
* pg_get_result
|
||||
* pg_connection_busy
|
||||
* pg_close
|
||||
@@ -50,13 +54,14 @@ namespace CoreLibs\DB\SQL;
|
||||
// below no ignore is needed if we want to use PgSql interface checks with PHP 8.0
|
||||
// as main system. Currently all @var sets are written as object
|
||||
/** @#phan-file-suppress PhanUndeclaredTypeProperty,PhanUndeclaredTypeParameter,PhanUndeclaredTypeReturnType */
|
||||
/** @phan-file-suppress PhanTypeMismatchArgumentInternal, PhanTypeMismatchReturn */
|
||||
|
||||
class PgSQL implements Interface\SqlFunctions
|
||||
{
|
||||
/** @var string */
|
||||
private $last_error_query;
|
||||
private string $last_error_query;
|
||||
/** @var \PgSql\Connection|false */
|
||||
private $dbh;
|
||||
private \PgSql\Connection|false $dbh = false;
|
||||
|
||||
/**
|
||||
* queries last error query and returns true or false if error was set
|
||||
@@ -93,8 +98,7 @@ class PgSQL implements Interface\SqlFunctions
|
||||
}
|
||||
|
||||
/**
|
||||
* Proposed
|
||||
* wrapperf or pg_query_params for queries in the style of
|
||||
* wrapper for pg_query_params for queries in the style of
|
||||
* SELECT foo FROM bar WHERE foobar = $1
|
||||
*
|
||||
* @param string $query Query string with placeholders $1, ..
|
||||
@@ -132,6 +136,22 @@ class PgSQL implements Interface\SqlFunctions
|
||||
return $result ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* sends an async query to the server with params
|
||||
*
|
||||
* @param string $query Query string with placeholders $1, ..
|
||||
* @param array<mixed> $params Matching parameters for each placerhold
|
||||
* @return bool true/false Query sent successful status
|
||||
*/
|
||||
public function __dbSendQueryParams(string $query, array $params): bool
|
||||
{
|
||||
if (is_bool($this->dbh)) {
|
||||
return false;
|
||||
}
|
||||
$result = pg_send_query_params($this->dbh, $query, $params);
|
||||
return $result ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper for pg_get_result
|
||||
*
|
||||
@@ -208,6 +228,38 @@ class PgSQL implements Interface\SqlFunctions
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asnyc send for a prepared statement
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $query
|
||||
* @return bool
|
||||
*/
|
||||
public function __dbSendPrepare(string $name, string $query): bool
|
||||
{
|
||||
if (is_bool($this->dbh)) {
|
||||
return false;
|
||||
}
|
||||
$result = pg_send_prepare($this->dbh, $name, $query);
|
||||
return $result ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asnyc ssend for a prepared statement execution
|
||||
*
|
||||
* @param string $name
|
||||
* @param array<mixed> $params
|
||||
* @return bool
|
||||
*/
|
||||
public function __dbSendExecute(string $name, array $params): bool
|
||||
{
|
||||
if (is_bool($this->dbh)) {
|
||||
return false;
|
||||
}
|
||||
$result = pg_send_execute($this->dbh, $name, $params);
|
||||
return $result ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper for pg_num_rows
|
||||
*
|
||||
@@ -251,6 +303,21 @@ class PgSQL implements Interface\SqlFunctions
|
||||
return pg_field_name($cursor, $i);
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper for pg_field_name
|
||||
*
|
||||
* @param \PgSql\Result|false $cursor cursor
|
||||
* @param int $i field position
|
||||
* @return string|false field type name or false
|
||||
*/
|
||||
public function __dbFieldType(\PgSql\Result|false $cursor, int $i): string|false
|
||||
{
|
||||
if (is_bool($cursor)) {
|
||||
return false;
|
||||
}
|
||||
return pg_field_type($cursor, $i);
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper for pg_fetch_array
|
||||
* if through/true false, use __dbResultType(true)
|
||||
@@ -465,18 +532,37 @@ class PgSQL implements Interface\SqlFunctions
|
||||
return $this->dbh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns last error for active cursor
|
||||
*
|
||||
* @return array{0:string,1:string} prefix, error string
|
||||
*/
|
||||
public function __dbPrintLastError(): array
|
||||
{
|
||||
if (is_bool($this->dbh)) {
|
||||
return ['', ''];
|
||||
}
|
||||
if (!empty($error_message = pg_last_error($this->dbh))) {
|
||||
return [
|
||||
'-PostgreSQL-Error-Last-',
|
||||
$error_message
|
||||
];
|
||||
}
|
||||
return ['', ''];
|
||||
}
|
||||
|
||||
/**
|
||||
* reads the last error for this cursor and returns
|
||||
* html formatted string with error name
|
||||
*
|
||||
* @param \PgSql\Result|false $cursor cursor
|
||||
* or null
|
||||
* @return string error string
|
||||
* or null
|
||||
* @return array{0:string,1:string} prefix, error string
|
||||
*/
|
||||
public function __dbPrintError(\PgSql\Result|false $cursor = false): string
|
||||
public function __dbPrintError(\PgSql\Result|false $cursor = false): array
|
||||
{
|
||||
if (is_bool($this->dbh)) {
|
||||
return '';
|
||||
return ['', ''];
|
||||
}
|
||||
// run the query again for the error result here
|
||||
if ((is_bool($cursor)) && $this->last_error_query) {
|
||||
@@ -485,10 +571,12 @@ class PgSQL implements Interface\SqlFunctions
|
||||
$cursor = pg_get_result($this->dbh);
|
||||
}
|
||||
if ($cursor && $error_str = pg_result_error($cursor)) {
|
||||
return '-PostgreSQL-Error- '
|
||||
. $error_str;
|
||||
return [
|
||||
'-PostgreSQL-Error-',
|
||||
$error_str
|
||||
];
|
||||
} else {
|
||||
return '';
|
||||
return ['', ''];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -75,6 +75,11 @@ class FileWriter
|
||||
empty(self::$debug_folder) &&
|
||||
defined('BASE') && defined('LOG')
|
||||
) {
|
||||
/** @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',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
self::$debug_folder = BASE . LOG;
|
||||
}
|
||||
if (!is_writeable(self::$debug_folder)) {
|
||||
|
||||
@@ -1,880 +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')) {
|
||||
// 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'])) {
|
||||
// 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')) {
|
||||
// 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'] ??
|
||||
$GLOBALS['DEBUG_ALL'] ??
|
||||
false
|
||||
);
|
||||
$this->setLogLevelAll(
|
||||
'print',
|
||||
$this->options['print_all'] ??
|
||||
// for user login, should be handled outside like globals
|
||||
$_SESSION['DEBUG_ALL'] ??
|
||||
$GLOBALS['PRINT_ALL'] ??
|
||||
false
|
||||
);
|
||||
$this->setLogLevelAll(
|
||||
'echo',
|
||||
$this->options['echo_all'] ??
|
||||
$GLOBALS['ECHO_ALL'] ??
|
||||
false
|
||||
);
|
||||
|
||||
// GLOBAL rules for log writing
|
||||
// add file date is default on
|
||||
$this->setGetLogPrintFileDate(
|
||||
$this->options['print_file_date'] ??
|
||||
$GLOBALS['LOG_PRINT_FILE_DATE'] ??
|
||||
true
|
||||
);
|
||||
// all other logging file name flags are off
|
||||
$this->setLogPer(
|
||||
'level',
|
||||
$this->options['per_level'] ??
|
||||
$GLOBALS['LOG_PER_LEVEL'] ??
|
||||
false
|
||||
);
|
||||
$this->setLogPer(
|
||||
'class',
|
||||
$this->options['per_class'] ??
|
||||
$GLOBALS['LOG_PER_CLASS'] ??
|
||||
false
|
||||
);
|
||||
$this->setLogPer(
|
||||
'page',
|
||||
$this->options['per_page'] ??
|
||||
$GLOBALS['LOG_PER_PAGE'] ??
|
||||
false
|
||||
);
|
||||
$this->setLogPer(
|
||||
'run',
|
||||
$this->options['per_run'] ??
|
||||
$GLOBALS['LOG_PER_RUN'] ??
|
||||
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
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Get;
|
||||
|
||||
// NOTE: it is recommended to use gullvek\dotenv instead which is a copy of this
|
||||
|
||||
class DotEnv
|
||||
{
|
||||
/** @var string constant comment char, set to # */
|
||||
@@ -29,11 +31,17 @@ class DotEnv
|
||||
* 1 for file loadable, no data or data already loaded
|
||||
* 2 for file not readable or open failed
|
||||
* 3 for file not found
|
||||
* @deprecated Use composer package gullevek\dotenv instead -> \gullevek\dotenv\DotEnv::readEnvFile(...)
|
||||
*/
|
||||
public static function readEnvFile(
|
||||
string $path = __DIR__,
|
||||
string $env_file = '.env'
|
||||
): int {
|
||||
trigger_error(
|
||||
'\CoreLibs\Get\DotEnv is deprecated in favor for '
|
||||
. 'composer package gullevek\dotenv which is a copy of this',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// default -1;
|
||||
$status = -1;
|
||||
$env_file_target = $path . DIRECTORY_SEPARATOR . $env_file;
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Get;
|
||||
|
||||
/**
|
||||
* @deprecated use \CoreLibs\Get\DotEnv instead
|
||||
*/
|
||||
class ReadEnvFile
|
||||
{
|
||||
/**
|
||||
* parses .env file
|
||||
*
|
||||
* Rules for .env file
|
||||
* variable is any alphanumeric string followed by = on the same line
|
||||
* content starts with the first non space part
|
||||
* strings can be contained in "
|
||||
* strings MUST be contained in " if they are multiline
|
||||
* if string starts with " it will match until another " is found
|
||||
* anything AFTER " is ignored
|
||||
* if there are two variables with the same name only the first is used
|
||||
* variables are case sensitive
|
||||
*
|
||||
* @param string $path Folder to file, default is __DIR__
|
||||
* @param string $env_file What file to load, default is .env
|
||||
* @return int -1 other error
|
||||
* 0 for success full load
|
||||
* 1 for file loadable, but no data inside
|
||||
* 2 for file not readable or open failed
|
||||
* 3 for file not found
|
||||
* @deprecated Use \CoreLibs\Get\DotEnv::readEnvFile() instead
|
||||
*/
|
||||
public static function readEnvFile(
|
||||
string $path = __DIR__,
|
||||
string $env_file = '.env'
|
||||
): int {
|
||||
return \CoreLibs\Get\DotEnv::readEnvFile($path, $env_file);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -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
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* deprecated function calls
|
||||
* Language\Encoding::__mbMimeEncode -> Convert\MimeEncode::__mbMimeEncode
|
||||
* Langauge\Encoding::checkConvertEncoding -> Check\Encoding::checkConvertEncoding
|
||||
* Langauge\Encoding::setErrorChar -> Check\Encoding::setErrorChar
|
||||
* Langauge\Encoding::getErrorChar -> Check\Encoding::getErrorChar
|
||||
* Langauge\Encoding::convertEncoding -> Convert\Encoding::convertEncoding
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Language;
|
||||
|
||||
class Encoding
|
||||
{
|
||||
/**
|
||||
* wrapper function for mb mime convert
|
||||
* for correct conversion with long strings
|
||||
*
|
||||
* @param string $string string to encode
|
||||
* @param string $encoding target encoding
|
||||
* @param string $line_break default line break is \r\n
|
||||
* @return string encoded string
|
||||
* @deprecated Use \CoreLibs\Convert\MimeEncode::__mbMimeEncode();
|
||||
*/
|
||||
public static function __mbMimeEncode(
|
||||
string $string,
|
||||
string $encoding,
|
||||
string $line_break = "\r\n"
|
||||
): string {
|
||||
return \CoreLibs\Convert\MimeEncode::__mbMimeEncode($string, $encoding, $line_break);
|
||||
}
|
||||
|
||||
/**
|
||||
* set error char
|
||||
*
|
||||
* @param string|int|null $string The character to use to represent
|
||||
* error chars
|
||||
* "long" for long, "none" for none
|
||||
* or a valid code point in int
|
||||
* like 0x2234 (8756, ∴)
|
||||
* default character is ? (63)
|
||||
* if null is set then "none"
|
||||
* @return void
|
||||
* @deprecated Use \CoreLibs\Check\Encoding::setErrorChar();
|
||||
*/
|
||||
public static function setErrorChar(string|int|null $string): void
|
||||
{
|
||||
\CoreLibs\Check\Encoding::setErrorChar($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current set error character
|
||||
*
|
||||
* @param bool $return_substitute_func if set to true return the set
|
||||
* character from the php function
|
||||
* directly
|
||||
* @return string|int Set error character
|
||||
* @deprecated Use \CoreLibs\Check\Encoding::getErrorChar();
|
||||
*/
|
||||
public static function getErrorChar(bool $return_substitute_func = false): string|int
|
||||
{
|
||||
return \CoreLibs\Check\Encoding::getErrorChar($return_substitute_func);
|
||||
}
|
||||
|
||||
/**
|
||||
* test if a string can be safely convert between encodings.
|
||||
* mostly utf8 to shift jis
|
||||
* the default compare has a possibility of failure, especially with windows
|
||||
* it is recommended to the following in the script which uses this method:
|
||||
* mb_substitute_character(0x2234);
|
||||
* $class->mb_error_char = '∴';
|
||||
* if check to Shift JIS
|
||||
* if check to ISO-2022-JP
|
||||
* if check to ISO-2022-JP-MS
|
||||
* set three dots (∴) as wrong character for correct convert error detect
|
||||
* (this char is used, because it is one of the least used ones)
|
||||
*
|
||||
* @param string $string string to test
|
||||
* @param string $from_encoding encoding of string to test
|
||||
* @param string $to_encoding target encoding
|
||||
* @return array<string>|false false if no error or
|
||||
* array with failed characters
|
||||
* @deprecated Use \CoreLibs\Check\Encoding::checkConvertEncoding();
|
||||
*/
|
||||
public static function checkConvertEncoding(
|
||||
string $string,
|
||||
string $from_encoding,
|
||||
string $to_encoding
|
||||
): array|false {
|
||||
return \CoreLibs\Check\Encoding::checkConvertEncoding($string, $from_encoding, $to_encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* detects the source encoding of the string and if doesn't match
|
||||
* to the given target encoding it convert is
|
||||
* if source encoding is set and auto check is true (default) a second
|
||||
* check is done so that the source string encoding actually matches
|
||||
* will be skipped if source encoding detection is ascii
|
||||
*
|
||||
* @param string $string string to convert
|
||||
* @param string $to_encoding target encoding
|
||||
* @param string $source_encoding optional source encoding, will try to auto detect
|
||||
* @param bool $auto_check default true, if source encoding is set
|
||||
* check that the source is actually matching
|
||||
* to what we sav the source is
|
||||
* @return string encoding converted string
|
||||
* @deprecated Use \CoreLibs\Convert\Encoding::convertEncoding();
|
||||
*/
|
||||
public static function convertEncoding(
|
||||
string $string,
|
||||
string $to_encoding,
|
||||
string $source_encoding = '',
|
||||
bool $auto_check = true
|
||||
): string {
|
||||
return \CoreLibs\Convert\Encoding::convertEncoding(
|
||||
$string,
|
||||
$to_encoding,
|
||||
$source_encoding,
|
||||
$auto_check
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -14,12 +14,14 @@ class GetLocale
|
||||
/**
|
||||
* returns locale, lang, domain, encoding, path
|
||||
* from either parameter set or from sessions/config variables
|
||||
* NOTE: named constant usage is deprecated and will be removed in future
|
||||
*
|
||||
* @param string|null $locale override auto detect
|
||||
* @param string|null $domain override domain
|
||||
* @param string|null $encoding override encoding
|
||||
* @param string|null $path override path
|
||||
* @return array<string,string> locale, domain, encoding, path
|
||||
* @deprecated use GetLocale::setLocaleSession(...) instead
|
||||
*/
|
||||
public static function setLocale(
|
||||
?string $locale = null,
|
||||
@@ -27,6 +29,10 @@ class GetLocale
|
||||
?string $encoding = null,
|
||||
?string $path = null
|
||||
): array {
|
||||
trigger_error(
|
||||
'Use \CoreLibs\Language\GetLocale::setLocaleSession(...) instead',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// locale must match at least basic rules
|
||||
if (
|
||||
empty($locale) ||
|
||||
@@ -36,6 +42,10 @@ class GetLocale
|
||||
// parse from session (logged in)
|
||||
$locale = $_SESSION['DEFAULT_LOCALE'];
|
||||
} else {
|
||||
trigger_error(
|
||||
'setLocale: Unset $locale or unset SESSION locale is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// else parse from site locale
|
||||
$locale = defined('SITE_LOCALE') && !empty(SITE_LOCALE) ?
|
||||
SITE_LOCALE :
|
||||
@@ -50,8 +60,16 @@ class GetLocale
|
||||
empty($domain) ||
|
||||
!preg_match("/^\w+$/", $domain)
|
||||
) {
|
||||
// if no domain is set, fall back to content path
|
||||
$domain = str_replace('/', '', CONTENT_PATH);
|
||||
if (!empty($_SESSION['DEFAULT_DOMAIN'])) {
|
||||
$domain = $_SESSION['DEFAULT_DOMAIN'];
|
||||
} else {
|
||||
trigger_error(
|
||||
'setLocale: Unset $domain is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// if no domain is set, fall back to content path
|
||||
$domain = str_replace(DIRECTORY_SEPARATOR, '', CONTENT_PATH);
|
||||
}
|
||||
}
|
||||
// check that override encoding matches locale encoding
|
||||
// if locale encoding is set
|
||||
@@ -71,6 +89,10 @@ class GetLocale
|
||||
// else set from session
|
||||
$encoding = $_SESSION['DEFAULT_CHARSET'];
|
||||
} else {
|
||||
trigger_error(
|
||||
'setLocale: Short $locale with unset $encoding or unset SESSION encoding is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// else set from site encoding
|
||||
$encoding = defined('SITE_ENCODING') && !empty(SITE_ENCODING) ?
|
||||
SITE_ENCODING :
|
||||
@@ -85,7 +107,15 @@ class GetLocale
|
||||
empty($path) ||
|
||||
!is_dir($path)
|
||||
) {
|
||||
$path = BASE . INCLUDES . LOCALE;
|
||||
if (!empty($_SESSION['LOCALE_PATH'])) {
|
||||
$path = $_SESSION['LOCALE_PATH'];
|
||||
} else {
|
||||
trigger_error(
|
||||
'setLocale: Unset $path is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$path = BASE . INCLUDES . LOCALE;
|
||||
}
|
||||
}
|
||||
// extract lang & country from locale string, else set to en
|
||||
if (
|
||||
@@ -112,6 +142,113 @@ class GetLocale
|
||||
'path' => $path,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: For getting the login info via login class use ->loginGetLocale()
|
||||
*
|
||||
* Set locale from session or from override parameters
|
||||
* This is the prefered version to setLocale
|
||||
* It usese the following SESSION VARIABLES
|
||||
* DEFAULT_LOCALE
|
||||
* DEFAULT_DOMAIN
|
||||
* DEFAULT_CHARSET (should be set from DEFAULT_LOCALE)
|
||||
* LOCALE_PATH
|
||||
* in the return array, null set invalid information
|
||||
*
|
||||
* @param string $locale override locale
|
||||
* @param string $domain override domain
|
||||
* @param string $encoding override encoding
|
||||
* @param string $path override path
|
||||
* @return array<string,string> locale, domain, encoding, path
|
||||
* @return array<string,string|null> Return list of set locale information
|
||||
* @deprecated This version will be removed in a future version use ACL\Login->loginGetLocale() instead
|
||||
*/
|
||||
public static function setLocaleFromSession(
|
||||
string $locale,
|
||||
string $domain,
|
||||
string $encoding,
|
||||
string $path
|
||||
): array {
|
||||
// locale must match at least basic rules
|
||||
if (
|
||||
!empty($_SESSION['DEFAULT_LOCALE']) &&
|
||||
preg_match("/^[-A-Za-z0-9_.@]+$/", $_SESSION['DEFAULT_LOCALE'])
|
||||
) {
|
||||
// parse from session (logged in)
|
||||
$locale = $_SESSION['DEFAULT_LOCALE'];
|
||||
} elseif (
|
||||
empty($locale) ||
|
||||
!preg_match("/^[-A-Za-z0-9_.@]+$/", $locale)
|
||||
) {
|
||||
$locale = null;
|
||||
}
|
||||
// if domain is set, must be alphanumeric, if not unset
|
||||
if (
|
||||
!empty($_SESSION['DEFAULT_DOMAIN']) &&
|
||||
preg_match("/^\w+$/", $_SESSION['DEFAULT_DOMAIN'])
|
||||
) {
|
||||
$domain = $_SESSION['DEFAULT_DOMAIN'];
|
||||
} elseif (
|
||||
empty($domain) ||
|
||||
!preg_match("/^\w+$/", $domain)
|
||||
) {
|
||||
$domain = null;
|
||||
}
|
||||
// check that override encoding matches locale encoding
|
||||
// if locale encoding is set
|
||||
preg_match('/(?:\\.(?P<charset>[-A-Za-z0-9_]+))/', $locale ?? '', $matches);
|
||||
$locale_encoding = $matches['charset'] ?? null;
|
||||
if (!empty($locale_encoding)) {
|
||||
$encoding = strtoupper($locale_encoding);
|
||||
} elseif (
|
||||
!empty($_SESSION['DEFAULT_CHARSET']) &&
|
||||
preg_match("/^[-A-Za-z0-9_]+$/", $_SESSION['DEFAULT_CHARSET'])
|
||||
) {
|
||||
$encoding = $_SESSION['DEFAULT_CHARSET'];
|
||||
} elseif (
|
||||
empty($encoding) ||
|
||||
// not valid encoding
|
||||
!preg_match("/^[-A-Za-z0-9_]+$/", $encoding)
|
||||
) {
|
||||
$encoding = null;
|
||||
}
|
||||
// path checks if set, if not valid path unset to default BASE path
|
||||
if (
|
||||
!empty($_SESSION['LOCALE_PATH']) &&
|
||||
is_dir($_SESSION['LOCALE_PATH'])
|
||||
) {
|
||||
$path = $_SESSION['LOCALE_PATH'];
|
||||
} elseif (
|
||||
empty($path) ||
|
||||
!is_dir($path)
|
||||
) {
|
||||
$path = null;
|
||||
}
|
||||
// extract lang & country from locale string, else set to en
|
||||
if (
|
||||
preg_match(
|
||||
// lang
|
||||
'/^(?P<lang>[a-z]{2,3})'
|
||||
// country code
|
||||
. '(?:_(?P<country>[A-Z]{2}))?/',
|
||||
$locale ?? '',
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
$lang = ($matches['lang'] ?? 'en')
|
||||
// add country only if set
|
||||
. (!empty($matches['country']) ? '_' . $matches['country'] : '');
|
||||
} else {
|
||||
$lang = null;
|
||||
}
|
||||
return [
|
||||
'locale' => $locale,
|
||||
'lang' => $lang,
|
||||
'domain' => $domain,
|
||||
'encoding' => $encoding,
|
||||
'path' => $path,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -32,65 +32,87 @@ use CoreLibs\Language\Core\GetTextReader;
|
||||
|
||||
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 string $override_encoding = self::DEFAULT_CHARSET;
|
||||
/** @var string encoding set during the parse Locale */
|
||||
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
|
||||
* if locale is not empty will load translation
|
||||
* else getTranslator needs to be called
|
||||
*
|
||||
* @param string $locale language name, default empty string
|
||||
* will return self instance
|
||||
* @param string $domain override CONTENT_PATH . $encoding name for mo file
|
||||
* @param string $path path, if empty fallback on default internal path
|
||||
* @param string $locale language name, default empty string
|
||||
* will return self instance
|
||||
* @param string $domain override CONTENT_PATH . $encoding name for mo file
|
||||
* @param string $path path, if empty fallback on default internal path
|
||||
* @param string $encoding Optional encoding, should be set if locale has
|
||||
* no encoding, defaults to UTF-8
|
||||
*/
|
||||
public function __construct(
|
||||
string $locale = '',
|
||||
string $domain = '',
|
||||
string $path = ''
|
||||
string $path = '',
|
||||
string $encoding = ''
|
||||
) {
|
||||
// auto load language only if at least locale and domain is set
|
||||
if (!empty($locale) && !empty($domain)) {
|
||||
// New: path must be set too, or we fall through
|
||||
if (!empty($locale) && !empty($domain) && empty($path)) {
|
||||
/** @deprecated if locale and domain are set, path must be set too */
|
||||
trigger_error(
|
||||
'Empty path parameter is no longer allowed if locale and domain are set',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
if (!empty($locale) && !empty($domain) && !empty($path)) {
|
||||
// check hack if domain and path is switched
|
||||
// Note this can be removed in future versions
|
||||
if (strstr($domain, DIRECTORY_SEPARATOR) !== false) {
|
||||
/** @deprecated domain must be 2nd and path must be third parameter */
|
||||
trigger_error(
|
||||
'L10n constructor parameter switch is no longer supported. domain is 2nd, path is 3rd parameter',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$_domain = $path;
|
||||
$path = $domain;
|
||||
$domain = $_domain;
|
||||
}
|
||||
$this->getTranslator($locale, $domain, $path);
|
||||
$this->getTranslator($locale, $domain, $path, $encoding);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +124,6 @@ class L10n
|
||||
*/
|
||||
public static function getInstance(): L10n
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (empty(self::$instance)) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
@@ -122,15 +143,17 @@ class L10n
|
||||
/**
|
||||
* loads the mo file base on path, locale and domain set
|
||||
*
|
||||
* @param string $locale language name (optional), fallback is en
|
||||
* @param string $domain override CONTENT_PATH . $encoding name for mo file
|
||||
* @param string $path path, if empty fallback on default internal path
|
||||
* @param string $locale language name, if not set, try previous set
|
||||
* @param string $domain set name for mo file, if not set, try previous set
|
||||
* @param string $path path, if not set try to get from paths array, else self
|
||||
* @param string $override_encoding if locale does not env encoding set, use this one
|
||||
* @return GetTextReader the main gettext reader object
|
||||
*/
|
||||
public function getTranslator(
|
||||
string $locale = '',
|
||||
string $domain = '',
|
||||
string $path = ''
|
||||
string $path = '',
|
||||
string $override_encoding = '',
|
||||
): GetTextReader {
|
||||
// set local if not from parameter
|
||||
if (empty($locale)) {
|
||||
@@ -140,11 +163,16 @@ class L10n
|
||||
if (empty($domain)) {
|
||||
$domain = $this->domain;
|
||||
}
|
||||
// override encoding for unset
|
||||
if (!empty($override_encoding)) {
|
||||
$this->override_encoding = $override_encoding;
|
||||
}
|
||||
// store old settings
|
||||
$old_mofile = $this->mofile;
|
||||
$old_lang = $this->locale;
|
||||
$old_lang_set = $this->locale_set;
|
||||
$old_domain = $this->domain;
|
||||
$old_encoding = $this->encoding;
|
||||
$old_base_locale_path = $this->base_locale_path;
|
||||
$old_base_content_path = $this->base_content_path;
|
||||
|
||||
@@ -160,6 +188,11 @@ class L10n
|
||||
} elseif (
|
||||
defined('BASE') && defined('INCLUDES') && defined('LOCALE')
|
||||
) {
|
||||
/** @deprecated Do not use this anymore, define path on class load */
|
||||
trigger_error(
|
||||
'parameter $path must be set. Setting via BASE, INCLUDES and LOCALE constants is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// set fallback base path if constant set
|
||||
$this->base_locale_path = BASE . INCLUDES . LOCALE;
|
||||
} else {
|
||||
@@ -168,6 +201,7 @@ class L10n
|
||||
// now we loop over lang compositions to get the base path
|
||||
// then we check
|
||||
$locales = $this->listLocales($locale);
|
||||
$encoding = $this->getEncodingFromLocale($locale);
|
||||
foreach ($locales as $_locale) {
|
||||
$this->base_content_path = $_locale . DIRECTORY_SEPARATOR
|
||||
. 'LC_MESSAGES' . DIRECTORY_SEPARATOR;
|
||||
@@ -184,6 +218,7 @@ class L10n
|
||||
if (is_readable($this->mofile)) {
|
||||
// locale and domain current wanted
|
||||
$this->locale = $locale;
|
||||
$this->encoding = $encoding;
|
||||
$this->domain = $domain;
|
||||
// set empty domains path with current locale
|
||||
if (empty($this->domains[$locale])) {
|
||||
@@ -207,6 +242,7 @@ class L10n
|
||||
$this->mofile = $old_mofile;
|
||||
$this->locale = $old_lang;
|
||||
$this->locale_set = $old_lang_set;
|
||||
$this->encoding = $old_encoding;
|
||||
$this->domain = $old_domain;
|
||||
$this->base_locale_path = $old_base_locale_path;
|
||||
$this->base_content_path = $old_base_content_path;
|
||||
@@ -216,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;
|
||||
}
|
||||
|
||||
@@ -240,6 +283,40 @@ class L10n
|
||||
return $this->l10n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract encoding from Locale, or fallback to override one if not set
|
||||
*
|
||||
* @param string $locale
|
||||
* @return string
|
||||
*/
|
||||
private function getEncodingFromLocale(string $locale): string
|
||||
{
|
||||
// extract charset from $locale
|
||||
// if not set get override encoding
|
||||
preg_match('/(?:\\.(?P<charset>[-A-Za-z0-9_]+))/', $locale, $matches);
|
||||
return $matches['charset'] ?? $this->override_encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the local as array same to the GetLocale::setLocale return
|
||||
* This does not set from outside, but only what is set in the l10n class
|
||||
*
|
||||
* @return array{locale: string, lang: string, lang_short: string, domain: string, encoding: string, path: string}
|
||||
*/
|
||||
public function getLocaleAsArray(): array
|
||||
{
|
||||
$locale = L10n::parseLocale($this->getLocale());
|
||||
return [
|
||||
'locale' => $this->getLocale(),
|
||||
'lang' => ($locale['lang'] ?? '')
|
||||
. (!empty($locale['country']) ? '_' . $locale['country'] : ''),
|
||||
'lang_short' => $locale['lang'] ?? '',
|
||||
'domain' => $this->getDomain(),
|
||||
'encoding' => $this->getEncoding(),
|
||||
'path' => $this->getBaseLocalePath(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* parse the locale string for further processing
|
||||
*
|
||||
@@ -478,6 +555,37 @@ class L10n
|
||||
return $this->locale_set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set override encoding
|
||||
*
|
||||
* @param string $encoding
|
||||
* @return void
|
||||
*/
|
||||
public function setOverrideEncoding(string $encoding): void
|
||||
{
|
||||
$this->override_encoding = $encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* return current set override encoding
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOverrideEncoding(): string
|
||||
{
|
||||
return $this->override_encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Current set encoding
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEncoding(): string
|
||||
{
|
||||
return $this->encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current set language
|
||||
*
|
||||
@@ -571,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,136 +219,131 @@ 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 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|null $log Logging class, null auto set
|
||||
* @param \CoreLibs\Language\L10n|null $l10n l10n language class, null auto set
|
||||
* @param array<string,string>|null $locale locale array from ::setLocale,
|
||||
* null auto set
|
||||
* @param array<mixed>|null $table_arrays Override table array data
|
||||
* instead of try to load from
|
||||
* include file
|
||||
* @throws \Exception 1: No table_arrays set/no class found for my page name
|
||||
* @param array<mixed> $db_config db config array, mandatory
|
||||
* @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
|
||||
* @param array<mixed>|null $table_arrays Override table array data
|
||||
* instead of try to load from
|
||||
* include file
|
||||
* @throws \Exception 1: No table_arrays set/no class found for my page name
|
||||
*/
|
||||
public function __construct(
|
||||
array $db_config,
|
||||
?\CoreLibs\Debug\Logging $log = null,
|
||||
?\CoreLibs\Language\L10n $l10n = null,
|
||||
?array $locale = null,
|
||||
\CoreLibs\Logging\Logging $log,
|
||||
\CoreLibs\Language\L10n $l10n,
|
||||
array $login_acl,
|
||||
?array $table_arrays = null,
|
||||
) {
|
||||
// init logger if not set
|
||||
$this->log = $log ?? new \CoreLibs\Debug\Logging();
|
||||
$this->log = $log;
|
||||
// don't log per class
|
||||
$this->log->setLogPer('class', false);
|
||||
// if pass on locale is null
|
||||
if ($locale === null) {
|
||||
$locale = \CoreLibs\Language\GetLocale::setLocale();
|
||||
}
|
||||
$this->log->unsetLogFlag(\CoreLibs\Logging\Logger\Flag::per_class);
|
||||
// init the language class
|
||||
$this->l = $l10n ?? new \CoreLibs\Language\L10n(
|
||||
$locale['locale'],
|
||||
$locale['domain'],
|
||||
$locale['path'],
|
||||
);
|
||||
// legacy lang vars set
|
||||
$this->l = $l10n;
|
||||
// parse and read, legacy stuff
|
||||
$locale = $this->l->getLocaleAsArray();
|
||||
$this->encoding = $locale['encoding'];
|
||||
$this->lang = $locale['lang'];
|
||||
// get first part from lang
|
||||
$this->lang_short = explode('_', $locale['lang'])[0];
|
||||
$this->domain = $this->l->getDomain();
|
||||
$this->lang_dir = $this->l->getBaseLocalePath();
|
||||
$this->lang_short = $locale['lang_short'];
|
||||
$this->domain = $locale['domain'];
|
||||
$this->lang_dir = $locale['path'];
|
||||
// load config array
|
||||
// get table array definitions for current page name
|
||||
|
||||
$this->login_acl = $login_acl;
|
||||
// security settings
|
||||
$this->base_acl_level = (int)$_SESSION['BASE_ACL_LEVEL'];
|
||||
$this->acl_admin = (int)$_SESSION['ADMIN'];
|
||||
$this->base_acl_level = $this->login_acl['base'] ?? 0;
|
||||
$this->acl_admin = $this->login_acl['admin'] ?? 0;
|
||||
|
||||
// replace any non valid variable names and set my page name
|
||||
$this->my_page_name = str_replace(
|
||||
@@ -386,7 +381,6 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
|
||||
$this->base_acl_level,
|
||||
$this->acl_admin
|
||||
);
|
||||
// $this->log->debug('SESSION FORM', 'sessin: ' . $this->log->prAr($_SESSION));
|
||||
// here should be a check if the config_array is correct ...
|
||||
if (isset($config_array['show_fields']) && is_array($config_array['show_fields'])) {
|
||||
$this->field_array = $config_array['show_fields'];
|
||||
@@ -395,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);
|
||||
@@ -492,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)) {
|
||||
@@ -834,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;
|
||||
}
|
||||
|
||||
@@ -1961,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'] =
|
||||
@@ -2624,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
|
||||
|
||||
@@ -12,6 +12,7 @@ class Image
|
||||
{
|
||||
/**
|
||||
* converts picture to a thumbnail with max x and max y size
|
||||
* TOOD: needs mandatory options for ImageMagic convert, paths, etc folders
|
||||
*
|
||||
* @param string $pic source image file with or without path
|
||||
* @param int $size_x maximum size width
|
||||
@@ -158,25 +159,27 @@ class Image
|
||||
* if both are set, those are the max sizes (aspect ration is always ekpt)
|
||||
* - if path is not given will cache folder for current path set
|
||||
*
|
||||
* @param string $filename source file name with full path
|
||||
* @param int $thumb_width thumbnail width
|
||||
* @param int $thumb_height thumbnail height
|
||||
* @param string|null $thumbnail_path altnerative path for thumbnails
|
||||
* @param bool $create_dummy if we encounter an invalid file
|
||||
* create a dummy image file and return it
|
||||
* @param bool $use_cache default to true, set to false to skip
|
||||
* creating new image if exists
|
||||
* @param bool $high_quality default to true, uses sample version,
|
||||
* set to false to not use (default true)
|
||||
* to use quick but less nice version
|
||||
* @param int $jpeg_quality default 80, set image quality for jpeg only
|
||||
* @return string|false thumbnail with path
|
||||
* @param string $filename source file name with full path
|
||||
* @param int $thumb_width thumbnail width
|
||||
* @param int $thumb_height thumbnail height
|
||||
* @param string|null $cache_folder path for thumbnail cache
|
||||
* @param string|null $web_folder frontend path for output
|
||||
* @param bool $create_dummy if we encounter an invalid file
|
||||
* create a dummy image file and return it
|
||||
* @param bool $use_cache default to true, set to false to skip
|
||||
* creating new image if exists
|
||||
* @param bool $high_quality default to true, uses sample version,
|
||||
* set to false to not use (default true)
|
||||
* to use quick but less nice version
|
||||
* @param int $jpeg_quality default 80, set image quality for jpeg only
|
||||
* @return string|false thumbnail with path
|
||||
*/
|
||||
public static function createThumbnailSimple(
|
||||
string $filename,
|
||||
int $thumb_width = 0,
|
||||
int $thumb_height = 0,
|
||||
?string $thumbnail_path = null,
|
||||
?string $cache_folder = null, // will be not null in future
|
||||
?string $web_folder = null,
|
||||
bool $create_dummy = true,
|
||||
bool $use_cache = true,
|
||||
bool $high_quality = true,
|
||||
@@ -185,233 +188,246 @@ class Image
|
||||
$thumbnail = false;
|
||||
// $this->debug('IMAGE PREPARE', "FILE: $filename (exists "
|
||||
// .(string)file_exists($filename)."), WIDTH: $thumb_width, HEIGHT: $thumb_height");
|
||||
if (
|
||||
$cache_folder === null ||
|
||||
$web_folder === null
|
||||
) {
|
||||
/** @deprecated Do use cache folder and web folder parameters */
|
||||
trigger_error(
|
||||
'params $cache_folder and $web_folder must be set. Setting via constants is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
// NOTE: we need to depracte this
|
||||
$cache_folder = BASE . LAYOUT . CONTENT_PATH . CACHE . IMAGES;
|
||||
$web_folder = LAYOUT . CACHE . IMAGES;
|
||||
if (!is_dir($cache_folder)) {
|
||||
if (false === mkdir($cache_folder)) {
|
||||
$cache_folder = BASE . LAYOUT . CONTENT_PATH . CACHE;
|
||||
$web_folder = LAYOUT . CACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
// check that input image exists and is either jpeg or png
|
||||
// also fail if the basic CACHE folder does not exist at all
|
||||
if (
|
||||
file_exists($filename) &&
|
||||
is_dir(BASE . LAYOUT . CONTENT_PATH . CACHE) &&
|
||||
is_writable(BASE . LAYOUT . CONTENT_PATH . CACHE)
|
||||
!file_exists($filename) ||
|
||||
!is_dir($cache_folder) ||
|
||||
!is_writable($cache_folder)
|
||||
) {
|
||||
// $this->debug('IMAGE PREPARE', "FILENAME OK, THUMB WIDTH/HEIGHT OK");
|
||||
[$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [];
|
||||
$thumbnail_write_path = null;
|
||||
$thumbnail_web_path = null;
|
||||
// path set first
|
||||
if (
|
||||
$img_type == IMAGETYPE_JPEG ||
|
||||
$img_type == IMAGETYPE_PNG ||
|
||||
$create_dummy === true
|
||||
) {
|
||||
// $this->debug('IMAGE PREPARE', "IMAGE TYPE OK: ".$inc_width.'x'.$inc_height);
|
||||
// set thumbnail paths
|
||||
$thumbnail_write_path = BASE . LAYOUT . CONTENT_PATH . CACHE . IMAGES;
|
||||
$thumbnail_web_path = LAYOUT . CACHE . IMAGES;
|
||||
// if images folder in cache does not exist create it, if failed, fall back to base cache folder
|
||||
if (!is_dir($thumbnail_write_path)) {
|
||||
if (false === mkdir($thumbnail_write_path)) {
|
||||
$thumbnail_write_path = BASE . LAYOUT . CONTENT_PATH . CACHE;
|
||||
$thumbnail_web_path = LAYOUT . CACHE;
|
||||
}
|
||||
}
|
||||
return $thumbnail;
|
||||
}
|
||||
// $this->debug('IMAGE PREPARE', "FILENAME OK, THUMB WIDTH/HEIGHT OK");
|
||||
[$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [];
|
||||
$thumbnail_write_path = null;
|
||||
$thumbnail_web_path = null;
|
||||
// path set first
|
||||
if (
|
||||
$img_type == IMAGETYPE_JPEG ||
|
||||
$img_type == IMAGETYPE_PNG ||
|
||||
$create_dummy === true
|
||||
) {
|
||||
// $this->debug('IMAGE PREPARE', "IMAGE TYPE OK: ".$inc_width.'x'.$inc_height);
|
||||
// set thumbnail paths
|
||||
$thumbnail_write_path = $cache_folder;
|
||||
$thumbnail_web_path = $web_folder;
|
||||
}
|
||||
// do resize or fall back on dummy run
|
||||
if (
|
||||
$img_type == IMAGETYPE_JPEG ||
|
||||
$img_type == IMAGETYPE_PNG
|
||||
) {
|
||||
// if missing width or height in thumb, use the set one
|
||||
if ($thumb_width == 0) {
|
||||
$thumb_width = $inc_width;
|
||||
}
|
||||
// do resize or fall back on dummy run
|
||||
if (
|
||||
$img_type == IMAGETYPE_JPEG ||
|
||||
$img_type == IMAGETYPE_PNG
|
||||
) {
|
||||
// if missing width or height in thumb, use the set one
|
||||
if ($thumb_width == 0) {
|
||||
$thumb_width = $inc_width;
|
||||
}
|
||||
if ($thumb_height == 0) {
|
||||
$thumb_height = $inc_height;
|
||||
}
|
||||
// check resize parameters
|
||||
if ($inc_width > $thumb_width || $inc_height > $thumb_height) {
|
||||
$thumb_width_r = 0;
|
||||
$thumb_height_r = 0;
|
||||
// we need to keep the aspect ration on longest side
|
||||
if (
|
||||
($inc_height > $inc_width &&
|
||||
// and the height is bigger than thumb set
|
||||
$inc_height > $thumb_height) ||
|
||||
// or the height is smaller or equal width
|
||||
// but the width for the thumb is equal to the image height
|
||||
($inc_height <= $inc_width &&
|
||||
$inc_width == $thumb_width
|
||||
)
|
||||
) {
|
||||
// $this->debug('IMAGE PREPARE', 'HEIGHT > WIDTH');
|
||||
$ratio = $inc_height / $thumb_height;
|
||||
$thumb_width_r = (int)ceil($inc_width / $ratio);
|
||||
$thumb_height_r = $thumb_height;
|
||||
} else {
|
||||
// $this->debug('IMAGE PREPARE', 'WIDTH > HEIGHT');
|
||||
$ratio = $inc_width / $thumb_width;
|
||||
$thumb_width_r = $thumb_width;
|
||||
$thumb_height_r = (int)ceil($inc_height / $ratio);
|
||||
}
|
||||
// $this->debug('IMAGE PREPARE', "Ratio: $ratio, Target size $thumb_width_r x $thumb_height_r");
|
||||
// set output thumbnail name
|
||||
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-'
|
||||
. $thumb_width_r . 'x' . $thumb_height_r;
|
||||
if (
|
||||
$use_cache === false ||
|
||||
!file_exists($thumbnail_write_path . $thumbnail)
|
||||
) {
|
||||
// image, copy source image, offset in image, source x/y, new size, source image size
|
||||
$thumb = imagecreatetruecolor($thumb_width_r, $thumb_height_r);
|
||||
if ($thumb === false) {
|
||||
return false;
|
||||
}
|
||||
if ($img_type == IMAGETYPE_PNG) {
|
||||
$imagecolorallocatealpha = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
|
||||
if ($imagecolorallocatealpha === false) {
|
||||
return false;
|
||||
}
|
||||
// preservere transaprency
|
||||
imagecolortransparent(
|
||||
$thumb,
|
||||
$imagecolorallocatealpha
|
||||
);
|
||||
imagealphablending($thumb, false);
|
||||
imagesavealpha($thumb, true);
|
||||
}
|
||||
$source = null;
|
||||
switch ($img_type) {
|
||||
case IMAGETYPE_JPEG:
|
||||
$source = imagecreatefromjpeg($filename);
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
$source = imagecreatefrompng($filename);
|
||||
break;
|
||||
}
|
||||
// check that we have a source image resource
|
||||
if ($source !== null && $source !== false) {
|
||||
// resize no shift
|
||||
if ($high_quality === true) {
|
||||
imagecopyresized(
|
||||
$thumb,
|
||||
$source,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$thumb_width_r,
|
||||
$thumb_height_r,
|
||||
$inc_width,
|
||||
$inc_height
|
||||
);
|
||||
} else {
|
||||
imagecopyresampled(
|
||||
$thumb,
|
||||
$source,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$thumb_width_r,
|
||||
$thumb_height_r,
|
||||
$inc_width,
|
||||
$inc_height
|
||||
);
|
||||
}
|
||||
// write file
|
||||
switch ($img_type) {
|
||||
case IMAGETYPE_JPEG:
|
||||
imagejpeg($thumb, $thumbnail_write_path . $thumbnail, $jpeg_quality);
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
imagepng($thumb, $thumbnail_write_path . $thumbnail);
|
||||
break;
|
||||
}
|
||||
// free up resources (in case we are called in a loop)
|
||||
imagedestroy($source);
|
||||
imagedestroy($thumb);
|
||||
} else {
|
||||
$thumbnail = false;
|
||||
}
|
||||
}
|
||||
if ($thumb_height == 0) {
|
||||
$thumb_height = $inc_height;
|
||||
}
|
||||
// check resize parameters
|
||||
if ($inc_width > $thumb_width || $inc_height > $thumb_height) {
|
||||
$thumb_width_r = 0;
|
||||
$thumb_height_r = 0;
|
||||
// we need to keep the aspect ration on longest side
|
||||
if (
|
||||
($inc_height > $inc_width &&
|
||||
// and the height is bigger than thumb set
|
||||
$inc_height > $thumb_height) ||
|
||||
// or the height is smaller or equal width
|
||||
// but the width for the thumb is equal to the image height
|
||||
($inc_height <= $inc_width &&
|
||||
$inc_width == $thumb_width
|
||||
)
|
||||
) {
|
||||
// $this->debug('IMAGE PREPARE', 'HEIGHT > WIDTH');
|
||||
$ratio = $inc_height / $thumb_height;
|
||||
$thumb_width_r = (int)ceil($inc_width / $ratio);
|
||||
$thumb_height_r = $thumb_height;
|
||||
} else {
|
||||
// we just copy over the image as is, we never upscale
|
||||
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-' . $inc_width . 'x' . $inc_height;
|
||||
if (
|
||||
$use_cache === false ||
|
||||
!file_exists($thumbnail_write_path . $thumbnail)
|
||||
) {
|
||||
copy($filename, $thumbnail_write_path . $thumbnail);
|
||||
}
|
||||
// $this->debug('IMAGE PREPARE', 'WIDTH > HEIGHT');
|
||||
$ratio = $inc_width / $thumb_width;
|
||||
$thumb_width_r = $thumb_width;
|
||||
$thumb_height_r = (int)ceil($inc_height / $ratio);
|
||||
}
|
||||
// add output path
|
||||
if ($thumbnail !== false) {
|
||||
$thumbnail = $thumbnail_web_path . $thumbnail;
|
||||
}
|
||||
} elseif ($create_dummy === true) {
|
||||
// create dummy image in the thumbnail size
|
||||
// if one side is missing, use the other side to create a square
|
||||
if (!$thumb_width) {
|
||||
$thumb_width = $thumb_height;
|
||||
}
|
||||
if (!$thumb_height) {
|
||||
$thumb_height = $thumb_width;
|
||||
}
|
||||
// do we have an image already?
|
||||
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-' . $thumb_width . 'x' . $thumb_height;
|
||||
// $this->debug('IMAGE PREPARE', "Ratio: $ratio, Target size $thumb_width_r x $thumb_height_r");
|
||||
// set output thumbnail name
|
||||
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-'
|
||||
. $thumb_width_r . 'x' . $thumb_height_r;
|
||||
if (
|
||||
$use_cache === false ||
|
||||
!file_exists($thumbnail_write_path . $thumbnail)
|
||||
) {
|
||||
// if both are unset, set to 250
|
||||
if ($thumb_height == 0) {
|
||||
$thumb_height = 250;
|
||||
}
|
||||
if ($thumb_width == 0) {
|
||||
$thumb_width = 250;
|
||||
}
|
||||
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
|
||||
// image, copy source image, offset in image, source x/y, new size, source image size
|
||||
$thumb = imagecreatetruecolor($thumb_width_r, $thumb_height_r);
|
||||
if ($thumb === false) {
|
||||
return false;
|
||||
}
|
||||
// add outside border px = 5% (rounded up)
|
||||
// eg 50px -> 2.5px
|
||||
$gray = imagecolorallocate($thumb, 200, 200, 200);
|
||||
$white = imagecolorallocate($thumb, 255, 255, 255);
|
||||
if ($gray === false || $white === false) {
|
||||
return false;
|
||||
if ($img_type == IMAGETYPE_PNG) {
|
||||
$imagecolorallocatealpha = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
|
||||
if ($imagecolorallocatealpha === false) {
|
||||
return false;
|
||||
}
|
||||
// preservere transaprency
|
||||
imagecolortransparent(
|
||||
$thumb,
|
||||
$imagecolorallocatealpha
|
||||
);
|
||||
imagealphablending($thumb, false);
|
||||
imagesavealpha($thumb, true);
|
||||
}
|
||||
// fill gray background
|
||||
imagefill($thumb, 0, 0, $gray);
|
||||
// now create rectangle
|
||||
if (imagesx($thumb) < imagesy($thumb)) {
|
||||
$width = (int)round(imagesx($thumb) / 100 * 5);
|
||||
$source = null;
|
||||
switch ($img_type) {
|
||||
case IMAGETYPE_JPEG:
|
||||
$source = imagecreatefromjpeg($filename);
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
$source = imagecreatefrompng($filename);
|
||||
break;
|
||||
}
|
||||
// check that we have a source image resource
|
||||
if ($source !== null && $source !== false) {
|
||||
// resize no shift
|
||||
if ($high_quality === true) {
|
||||
imagecopyresized(
|
||||
$thumb,
|
||||
$source,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$thumb_width_r,
|
||||
$thumb_height_r,
|
||||
$inc_width,
|
||||
$inc_height
|
||||
);
|
||||
} else {
|
||||
imagecopyresampled(
|
||||
$thumb,
|
||||
$source,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$thumb_width_r,
|
||||
$thumb_height_r,
|
||||
$inc_width,
|
||||
$inc_height
|
||||
);
|
||||
}
|
||||
// write file
|
||||
switch ($img_type) {
|
||||
case IMAGETYPE_JPEG:
|
||||
imagejpeg($thumb, $thumbnail_write_path . $thumbnail, $jpeg_quality);
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
imagepng($thumb, $thumbnail_write_path . $thumbnail);
|
||||
break;
|
||||
}
|
||||
// free up resources (in case we are called in a loop)
|
||||
imagedestroy($source);
|
||||
imagedestroy($thumb);
|
||||
} else {
|
||||
$width = (int)round(imagesy($thumb) / 100 * 5);
|
||||
$thumbnail = false;
|
||||
}
|
||||
imagefilledrectangle(
|
||||
$thumb,
|
||||
0 + $width,
|
||||
0 + $width,
|
||||
imagesx($thumb) - $width,
|
||||
imagesy($thumb) - $width,
|
||||
$white
|
||||
);
|
||||
// add "No valid images source"
|
||||
// OR add circle
|
||||
// * find center
|
||||
// * width/height is 75% of size - border
|
||||
// smaller size is taken
|
||||
$base_width = imagesx($thumb) > imagesy($thumb) ? imagesy($thumb) : imagesx($thumb);
|
||||
// get 75% width
|
||||
$cross_width = (int)round((($base_width - ($width * 2)) / 100 * 75) / 2);
|
||||
$center_x = (int)round(imagesx($thumb) / 2);
|
||||
$center_y = (int)round(imagesy($thumb) / 2);
|
||||
imagefilledellipse($thumb, $center_x, $center_y, $cross_width, $cross_width, $gray);
|
||||
// find top left and bottom left for first line
|
||||
imagepng($thumb, $thumbnail_write_path . $thumbnail);
|
||||
}
|
||||
// add web path
|
||||
} else {
|
||||
// we just copy over the image as is, we never upscale
|
||||
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-' . $inc_width . 'x' . $inc_height;
|
||||
if (
|
||||
$use_cache === false ||
|
||||
!file_exists($thumbnail_write_path . $thumbnail)
|
||||
) {
|
||||
copy($filename, $thumbnail_write_path . $thumbnail);
|
||||
}
|
||||
}
|
||||
// add output path
|
||||
if ($thumbnail !== false) {
|
||||
$thumbnail = $thumbnail_web_path . $thumbnail;
|
||||
}
|
||||
} elseif ($create_dummy === true) {
|
||||
// create dummy image in the thumbnail size
|
||||
// if one side is missing, use the other side to create a square
|
||||
if (!$thumb_width) {
|
||||
$thumb_width = $thumb_height;
|
||||
}
|
||||
if (!$thumb_height) {
|
||||
$thumb_height = $thumb_width;
|
||||
}
|
||||
// do we have an image already?
|
||||
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-' . $thumb_width . 'x' . $thumb_height;
|
||||
if (
|
||||
$use_cache === false ||
|
||||
!file_exists($thumbnail_write_path . $thumbnail)
|
||||
) {
|
||||
// if both are unset, set to 250
|
||||
if ($thumb_height == 0) {
|
||||
$thumb_height = 250;
|
||||
}
|
||||
if ($thumb_width == 0) {
|
||||
$thumb_width = 250;
|
||||
}
|
||||
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
|
||||
if ($thumb === false) {
|
||||
return false;
|
||||
}
|
||||
// add outside border px = 5% (rounded up)
|
||||
// eg 50px -> 2.5px
|
||||
$gray = imagecolorallocate($thumb, 200, 200, 200);
|
||||
$white = imagecolorallocate($thumb, 255, 255, 255);
|
||||
if ($gray === false || $white === false) {
|
||||
return false;
|
||||
}
|
||||
// fill gray background
|
||||
imagefill($thumb, 0, 0, $gray);
|
||||
// now create rectangle
|
||||
if (imagesx($thumb) < imagesy($thumb)) {
|
||||
$width = (int)round(imagesx($thumb) / 100 * 5);
|
||||
} else {
|
||||
$width = (int)round(imagesy($thumb) / 100 * 5);
|
||||
}
|
||||
imagefilledrectangle(
|
||||
$thumb,
|
||||
0 + $width,
|
||||
0 + $width,
|
||||
imagesx($thumb) - $width,
|
||||
imagesy($thumb) - $width,
|
||||
$white
|
||||
);
|
||||
// add "No valid images source"
|
||||
// OR add circle
|
||||
// * find center
|
||||
// * width/height is 75% of size - border
|
||||
// smaller size is taken
|
||||
$base_width = imagesx($thumb) > imagesy($thumb) ? imagesy($thumb) : imagesx($thumb);
|
||||
// get 75% width
|
||||
$cross_width = (int)round((($base_width - ($width * 2)) / 100 * 75) / 2);
|
||||
$center_x = (int)round(imagesx($thumb) / 2);
|
||||
$center_y = (int)round(imagesy($thumb) / 2);
|
||||
imagefilledellipse($thumb, $center_x, $center_y, $cross_width, $cross_width, $gray);
|
||||
// find top left and bottom left for first line
|
||||
imagepng($thumb, $thumbnail_write_path . $thumbnail);
|
||||
}
|
||||
// add web path
|
||||
$thumbnail = $thumbnail_web_path . $thumbnail;
|
||||
}
|
||||
// either return false or the thumbnail name + output path web
|
||||
return $thumbnail;
|
||||
|
||||
@@ -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
|
||||
/**
|
||||
@@ -160,23 +158,42 @@ class SmartyExtend extends \Smarty
|
||||
* also registers the getvar caller plugin
|
||||
*
|
||||
* @param \CoreLibs\Language\L10n $l10n l10n language class
|
||||
* @param array<string,string> $locale locale data read from setLocale
|
||||
* @param string|null $cache_id
|
||||
* @param string|null $compile_id
|
||||
*/
|
||||
public function __construct(\CoreLibs\Language\L10n $l10n, array $locale)
|
||||
{
|
||||
public function __construct(
|
||||
\CoreLibs\Language\L10n $l10n,
|
||||
?string $cache_id = null,
|
||||
?string $compile_id = null
|
||||
) {
|
||||
// trigger deprecation
|
||||
if (
|
||||
$cache_id === null ||
|
||||
$compile_id === null
|
||||
) {
|
||||
/** @deprecated SmartyExtend::__construct call without parameters */
|
||||
trigger_error(
|
||||
'Calling SmartyExtend::__construct without paramters is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
// set variables (to be deprecated)
|
||||
$cache_id = $cache_id ??
|
||||
(defined('CACHE_ID') ? CACHE_ID : '');
|
||||
$compile_id = $compile_id ??
|
||||
(defined('COMPILE_ID') ? COMPILE_ID : '');
|
||||
// call basic smarty
|
||||
// or Smarty::__construct();
|
||||
parent::__construct();
|
||||
// iinit lang
|
||||
$this->l10n = $l10n;
|
||||
// parse and read, legacy stuff
|
||||
$locale = $this->l10n->getLocaleAsArray();
|
||||
$this->encoding = $locale['encoding'];
|
||||
$this->lang = $locale['lang'];
|
||||
// get first part from lang
|
||||
$this->lang_short = explode('_', $locale['lang'])[0];
|
||||
$this->domain = $this->l10n->getDomain();
|
||||
$this->locale_set = $this->l10n->getLocaleSet();
|
||||
$this->lang_dir = $this->l10n->getBaseLocalePath();
|
||||
$this->lang_short = $locale['lang_short'];
|
||||
$this->domain = $locale['domain'];
|
||||
$this->lang_dir = $locale['path'];
|
||||
|
||||
// opt load functions so we can use legacy init for smarty run perhaps
|
||||
\CoreLibs\Language\L10n::loadFunctions();
|
||||
@@ -191,8 +208,8 @@ class SmartyExtend extends \Smarty
|
||||
$this->page_name = \CoreLibs\Get\System::getPageName();
|
||||
|
||||
// set internal settings
|
||||
$this->CACHE_ID = defined('CACHE_ID') ? CACHE_ID : '';
|
||||
$this->COMPILE_ID = defined('COMPILE_ID') ? COMPILE_ID : '';
|
||||
$this->CACHE_ID = $cache_id;
|
||||
$this->COMPILE_ID = $compile_id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,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)
|
||||
) {
|
||||
@@ -211,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)
|
||||
) {
|
||||
@@ -256,11 +275,70 @@ class SmartyExtend extends \Smarty
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSmartyPaths(): void
|
||||
{
|
||||
|
||||
/**
|
||||
* sets all internal paths and names that need to be passed on
|
||||
* to the smarty template
|
||||
*
|
||||
* @param string|null $set_includes INCLUDES
|
||||
* @param string|null $set_template_path TEMPLATE_PATH
|
||||
* @param string|null $set_javascript JAVASCRIPT
|
||||
* @param string|null $set_css CSS
|
||||
* @param string|null $set_font FONT
|
||||
* @param string|null $set_pictures PICTURES
|
||||
* @param string|null $set_cache_pictures CACHE_PICTURES
|
||||
* @param string|null $set_cache_pictures_root CACHE_PICTURES_ROOT
|
||||
* @param string|null $set_master_template_name MASTAER_TEMPLATE_NAME
|
||||
* @return void
|
||||
*/
|
||||
public function setSmartyPaths(
|
||||
?string $set_includes = null,
|
||||
?string $set_template_path = null,
|
||||
?string $set_javascript = null,
|
||||
?string $set_css = null,
|
||||
?string $set_font = null,
|
||||
?string $set_pictures = null,
|
||||
?string $set_cache_pictures = null,
|
||||
?string $set_cache_pictures_root = null,
|
||||
?string $set_master_template_name = null,
|
||||
): void {
|
||||
// trigger deprecation
|
||||
if (
|
||||
$set_includes === null ||
|
||||
$set_template_path === null ||
|
||||
$set_javascript === null ||
|
||||
$set_css === null ||
|
||||
$set_font === null ||
|
||||
$set_pictures === null ||
|
||||
$set_cache_pictures === null ||
|
||||
$set_cache_pictures_root === null
|
||||
) {
|
||||
/** @deprecated setSmartyPaths call without parameters */
|
||||
trigger_error(
|
||||
'Calling setSmartyPaths without paramters is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
// set variables (to be deprecated)
|
||||
$set_master_template_name = $set_master_template_name ??
|
||||
(defined('MASTER_TEMPLATE_NAME') ? MASTER_TEMPLATE_NAME : '');
|
||||
$set_includes = $set_includes ??
|
||||
BASE . INCLUDES;
|
||||
$set_template_path = $set_template_path ??
|
||||
BASE . INCLUDES . TEMPLATES . CONTENT_PATH;
|
||||
$set_javascript = $set_javascript ?? LAYOUT . JS;
|
||||
$set_css = $set_css ?? LAYOUT . CSS;
|
||||
$set_font = $set_font ?? LAYOUT . FONT;
|
||||
$set_pictures = $set_pictures ?? LAYOUT . IMAGES;
|
||||
$set_cache_pictures = $set_cache_pictures ?? LAYOUT . CACHE;
|
||||
$set_cache_pictures_root = $set_cache_pictures_root ??
|
||||
ROOT . $set_cache_pictures;
|
||||
|
||||
// master template
|
||||
if (empty($this->MASTER_TEMPLATE_NAME)) {
|
||||
$this->MASTER_TEMPLATE_NAME = MASTER_TEMPLATE_NAME;
|
||||
if (
|
||||
empty($this->MASTER_TEMPLATE_NAME)
|
||||
) {
|
||||
$this->MASTER_TEMPLATE_NAME = $set_master_template_name;
|
||||
}
|
||||
|
||||
// set include & template names
|
||||
@@ -276,15 +354,15 @@ class SmartyExtend extends \Smarty
|
||||
$this->CSS_TEMPLATE_NAME = str_replace('.tpl', '.css', $this->CONTENT_INCLUDE);
|
||||
|
||||
// set basic template path (tmp)
|
||||
$this->INCLUDES = BASE . INCLUDES; // no longer in templates, only global
|
||||
$this->TEMPLATE_PATH = BASE . INCLUDES . TEMPLATES . CONTENT_PATH;
|
||||
$this->INCLUDES = $set_includes; // no longer in templates, only global
|
||||
$this->TEMPLATE_PATH = $set_template_path;
|
||||
$this->setTemplateDir($this->TEMPLATE_PATH);
|
||||
$this->JAVASCRIPT = LAYOUT . JS;
|
||||
$this->CSS = LAYOUT . CSS;
|
||||
$this->FONT = LAYOUT . FONT;
|
||||
$this->PICTURES = LAYOUT . IMAGES;
|
||||
$this->CACHE_PICTURES = LAYOUT . CACHE;
|
||||
$this->CACHE_PICTURES_ROOT = ROOT . $this->CACHE_PICTURES;
|
||||
$this->JAVASCRIPT = $set_javascript;
|
||||
$this->CSS = $set_css;
|
||||
$this->FONT = $set_font;
|
||||
$this->PICTURES = $set_pictures;
|
||||
$this->CACHE_PICTURES = $set_cache_pictures;
|
||||
$this->CACHE_PICTURES_ROOT = $set_cache_pictures_root;
|
||||
// check if we have an external file with the template name
|
||||
if (
|
||||
file_exists($this->INCLUDES . $this->INC_TEMPLATE_NAME) &&
|
||||
@@ -305,7 +383,7 @@ class SmartyExtend extends \Smarty
|
||||
// set all the additional CSS/JS parths
|
||||
$this->setSmartCoreIncludeCssJs();
|
||||
// check if template names exist
|
||||
if (!$this->MASTER_TEMPLATE_NAME) {
|
||||
if (empty($this->MASTER_TEMPLATE_NAME)) {
|
||||
exit('MASTER TEMPLATE is not set');
|
||||
} elseif (!file_exists($this->getTemplateDir()[0] . DIRECTORY_SEPARATOR . $this->MASTER_TEMPLATE_NAME)) {
|
||||
// abort if master template could not be found
|
||||
@@ -320,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
|
||||
@@ -330,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';
|
||||
}
|
||||
}
|
||||
@@ -345,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>
|
||||
@@ -354,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';
|
||||
}
|
||||
}
|
||||
@@ -374,35 +452,194 @@ class SmartyExtend extends \Smarty
|
||||
* wrapper call for setSmartyVars
|
||||
* this is for frontend type and will not set any only admin needed variables
|
||||
*
|
||||
* @param array<string,string> $options list with the following value:
|
||||
* compile_dir :BASE . TEMPLATES_C
|
||||
* cache_dir :BASE . CACHE
|
||||
* js :JS
|
||||
* css :CSS
|
||||
* font :FONT
|
||||
* default_encoding :DEFAULT_ENCODING
|
||||
* g_title :G_TITLE
|
||||
* stylesheet :STYLESHEET
|
||||
* javascript :JAVASCRIPT
|
||||
* @param array<string,mixed> $smarty_data array of three keys
|
||||
* that hold smarty set strings
|
||||
* HEADER, DATA, DEBUG_DATA
|
||||
* @return void
|
||||
*/
|
||||
public function setSmartyVarsFrontend(): void
|
||||
{
|
||||
$this->setSmartyVars();
|
||||
public function setSmartyVarsFrontend(
|
||||
array $options,
|
||||
array $smarty_data
|
||||
): void {
|
||||
$this->setSmartyVars(
|
||||
false,
|
||||
$smarty_data,
|
||||
null,
|
||||
$options['compile_dir'] ?? null,
|
||||
$options['cache_dir'] ?? null,
|
||||
$options['js'] ?? null,
|
||||
$options['css'] ?? null,
|
||||
$options['font'] ?? null,
|
||||
$options['default_encoding'] ?? null,
|
||||
$options['g_title'] ?? null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$options['stylesheet'] ?? null,
|
||||
$options['javascript'] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper call for setSmartyVars
|
||||
* this is only for admin interface and will set additional variables
|
||||
* @param array<string,string> $options list with the following value:
|
||||
* compile_dir :BASE . TEMPLATES_C
|
||||
* cache_dir :BASE . CACHE
|
||||
* js :JS
|
||||
* css :CSS
|
||||
* font :FONT
|
||||
* default_encoding :DEFAULT_ENCODING
|
||||
* g_title :G_TITLE
|
||||
* admin_stylesheet :ADMIN_STYLESHEET
|
||||
* admin_javascript :ADMIN_JAVASCRIPT
|
||||
* page_width :PAGE_WIDTH
|
||||
* content_path :CONTENT_PATH
|
||||
* user_name :_SESSION['USER_NAME']
|
||||
* @param \CoreLibs\Admin\Backend|null $cms Optinal Admin Backend for
|
||||
* smarty variables merge
|
||||
* @return void
|
||||
*/
|
||||
public function setSmartyVarsAdmin(): void
|
||||
{
|
||||
$this->setSmartyVars(true);
|
||||
public function setSmartyVarsAdmin(
|
||||
array $options,
|
||||
?\CoreLibs\Admin\Backend $cms = null
|
||||
): void {
|
||||
// if we have cms data, check for array blocks and build
|
||||
$smarty_data = [];
|
||||
if ($cms !== null) {
|
||||
$smarty_data = [
|
||||
'HEADER' => $cms->HEADER,
|
||||
'DATA' => $cms->DATA,
|
||||
'DEBUG_DATA' => $cms->DEBUG_DATA
|
||||
];
|
||||
}
|
||||
$this->setSmartyVars(
|
||||
true,
|
||||
$smarty_data,
|
||||
$cms,
|
||||
$options['compile_dir'] ?? null,
|
||||
$options['cache_dir'] ?? null,
|
||||
$options['js'] ?? null,
|
||||
$options['css'] ?? null,
|
||||
$options['font'] ?? null,
|
||||
$options['g_title'] ?? null,
|
||||
$options['default_encoding'] ?? null,
|
||||
$options['admin_stylesheet'] ?? null,
|
||||
$options['admin_javascript'] ?? null,
|
||||
$options['page_width'] ?? null,
|
||||
$options['content_path'] ?? null,
|
||||
$options['user_name'] ?? null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* set smarty pass on variables, sub template names and finally calls the smarty parser
|
||||
* set smarty pass on variables, sub template names and
|
||||
* finally calls the smarty parser
|
||||
*
|
||||
* @param boolean $admin_call default false, will set admin only variables
|
||||
* @param bool $admin_call default false
|
||||
* will set admin only variables
|
||||
* @param array<string,mixed> $smarty_data smarty data to merge
|
||||
* @param \CoreLibs\Admin\Backend|null $cms Optinal Admin Backend for
|
||||
* smarty variables merge
|
||||
* @param string|null $compile_dir BASE . TEMPLATES_C
|
||||
* @param string|null $cache_dir BASE . CACHE
|
||||
* @param string|null $set_js JS
|
||||
* @param string|null $set_css CSS
|
||||
* @param string|null $set_font FONT
|
||||
* @param string|null $set_default_encoding DEFAULT_ENCODING
|
||||
* @param string|null $set_g_title G_TITLE
|
||||
* @param string|null $set_admin_stylesheet ADMIN_STYLESHEET
|
||||
* @param string|null $set_admin_javascript ADMIN_JAVASCRIPT
|
||||
* @param string|null $set_page_width PAGE_WIDTH
|
||||
* @param string|null $set_content_path CONTENT_PATH (only if $cms set and admin)
|
||||
* @param string|null $set_user_name _SESSION['USER_NAME']
|
||||
* @param string|null $set_stylesheet STYLESHEET
|
||||
* @param string|null $set_javascript JAVASCRIPT
|
||||
* @return void
|
||||
*/
|
||||
private function setSmartyVars($admin_call = false): void
|
||||
{
|
||||
/** @var \CoreLibs\Admin\Backend This is an assumption */
|
||||
global $cms;
|
||||
if (is_object($cms)) {
|
||||
$this->mergeCmsSmartyVars($cms);
|
||||
private function setSmartyVars(
|
||||
bool $admin_call,
|
||||
array $smarty_data = [],
|
||||
?\CoreLibs\Admin\Backend $cms = null,
|
||||
?string $compile_dir = null,
|
||||
?string $cache_dir = null,
|
||||
?string $set_js = null,
|
||||
?string $set_css = null,
|
||||
?string $set_font = null,
|
||||
?string $set_default_encoding = null,
|
||||
?string $set_g_title = null,
|
||||
?string $set_admin_stylesheet = null,
|
||||
?string $set_admin_javascript = null,
|
||||
?string $set_page_width = null,
|
||||
?string $set_content_path = null,
|
||||
?string $set_user_name = null,
|
||||
?string $set_stylesheet = null,
|
||||
?string $set_javascript = null,
|
||||
): void {
|
||||
// trigger deprecation
|
||||
if (
|
||||
$compile_dir === null ||
|
||||
$cache_dir === null ||
|
||||
$set_css === null ||
|
||||
$set_font === null ||
|
||||
$set_js === null ||
|
||||
$set_default_encoding === null ||
|
||||
$set_g_title === null ||
|
||||
(
|
||||
$admin_call === true && (
|
||||
$set_admin_stylesheet === null ||
|
||||
$set_admin_javascript === null ||
|
||||
$set_page_width === null ||
|
||||
$set_user_name === null
|
||||
)
|
||||
) ||
|
||||
(
|
||||
$admin_call === false && (
|
||||
$set_stylesheet === null ||
|
||||
$set_javascript === null
|
||||
)
|
||||
) ||
|
||||
(
|
||||
$admin_call === true && $cms !== null && $set_content_path === null
|
||||
)
|
||||
) {
|
||||
/** @deprecated setSmartyVars call without parameters */
|
||||
trigger_error(
|
||||
'Calling setSmartyVars without paramters is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
// set variables (will be deprecated)
|
||||
$compile_dir = $compile_dir ?? BASE . TEMPLATES_C;
|
||||
$cache_dir = $cache_dir ?? BASE . CACHE;
|
||||
$set_css = $set_css ?? CSS;
|
||||
$set_font = $set_font ?? FONT;
|
||||
$set_js = $set_js ?? JS;
|
||||
$set_default_encoding = $set_default_encoding ?? DEFAULT_ENCODING;
|
||||
$set_g_title = $set_g_title ?? G_TITLE;
|
||||
$set_admin_stylesheet = $set_admin_stylesheet ?? ADMIN_STYLESHEET;
|
||||
$set_admin_javascript = $set_admin_javascript ?? ADMIN_JAVASCRIPT;
|
||||
$set_page_width = $set_page_width ?? PAGE_WIDTH;
|
||||
$set_content_path = $set_content_path ?? CONTENT_PATH;
|
||||
$set_stylesheet = $set_stylesheet ?? STYLESHEET;
|
||||
$set_javascript = $set_javascript ?? JAVASCRIPT;
|
||||
$set_user_name = $set_user_name ?? $_SESSION['USER_NAME'] ?? '';
|
||||
// merge additional smarty data
|
||||
$this->mergeCmsSmartyVars($smarty_data);
|
||||
|
||||
// trigger flags
|
||||
$this->HEADER['USE_PROTOTYPE'] = $this->USE_PROTOTYPE;
|
||||
@@ -431,25 +668,42 @@ class SmartyExtend extends \Smarty
|
||||
|
||||
// default CMS settings
|
||||
// define all needed smarty stuff for the general HTML/page building
|
||||
$this->HEADER['CSS'] = CSS;
|
||||
$this->HEADER['FONT'] = FONT;
|
||||
$this->HEADER['JS'] = JS;
|
||||
$this->HEADER['CSS'] = $set_css;
|
||||
$this->HEADER['FONT'] = $set_font;
|
||||
$this->HEADER['JS'] = $set_js;
|
||||
$this->HEADER['ENCODING'] = $this->encoding;
|
||||
$this->HEADER['DEFAULT_ENCODING'] = DEFAULT_ENCODING;
|
||||
$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
|
||||
if (
|
||||
$cms === null &&
|
||||
isset($GLOBALS['cms'])
|
||||
) {
|
||||
/** @deprecated setSmartyVars globals cms is deprecated */
|
||||
trigger_error(
|
||||
'Calling setSmartyVars without cms parameter when needed is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
// this is ugly
|
||||
$cms = $cms ?? $GLOBALS['cms'] ?? null;
|
||||
// set ACL extra show
|
||||
if (is_object($cms)) {
|
||||
if ($cms instanceof \CoreLibs\Admin\Backend) {
|
||||
$this->DATA['show_ea_extra'] = $cms->acl['show_ea_extra'] ?? false;
|
||||
$this->DATA['ADMIN'] = $cms->acl['admin'] ?? 0;
|
||||
// top menu
|
||||
$this->DATA['nav_menu'] = $cms->adbTopMenu();
|
||||
$this->DATA['nav_menu'] = $cms->adbTopMenu(
|
||||
$set_content_path
|
||||
);
|
||||
$this->DATA['nav_menu_count'] = count($this->DATA['nav_menu']);
|
||||
// messages = ['msg' =>, 'class' => 'error/warning/...']
|
||||
$this->DATA['messages'] = $cms->messages;
|
||||
@@ -461,11 +715,13 @@ class SmartyExtend extends \Smarty
|
||||
$this->DATA['messages'] = [];
|
||||
}
|
||||
// set style sheets
|
||||
$this->HEADER['STYLESHEET'] = $this->ADMIN_STYLESHEET ? $this->ADMIN_STYLESHEET : ADMIN_STYLESHEET;
|
||||
$this->HEADER['JAVASCRIPT'] = $this->ADMIN_JAVASCRIPT ? $this->ADMIN_JAVASCRIPT : ADMIN_JAVASCRIPT;
|
||||
$this->HEADER['STYLESHEET'] = !empty($this->ADMIN_STYLESHEET) ?
|
||||
$this->ADMIN_STYLESHEET : $set_admin_stylesheet;
|
||||
$this->HEADER['JAVASCRIPT'] = !empty($this->ADMIN_JAVASCRIPT) ?
|
||||
$this->ADMIN_JAVASCRIPT : $set_admin_javascript;
|
||||
// the page name
|
||||
$this->DATA['page_name'] = $this->page_name;
|
||||
$this->DATA['table_width'] = !empty($this->PAGE_WIDTH) ?: PAGE_WIDTH;
|
||||
$this->DATA['table_width'] = !empty($this->PAGE_WIDTH) ?: $set_page_width;
|
||||
$this->DATA['form_name'] = $this->DATA['FORM_NAME'];
|
||||
// for tinymce special
|
||||
$this->DATA['TINYMCE_LANG'] = $this->lang_short;
|
||||
@@ -474,14 +730,16 @@ class SmartyExtend extends \Smarty
|
||||
// debug data, if DEBUG flag is on, this data is print out
|
||||
$this->DEBUG_DATA['DEBUG'] = $this->DEBUG_TMPL;
|
||||
} else {
|
||||
$this->HEADER['STYLESHEET'] = $this->FRONTEND_STYLESHEET ? $this->FRONTEND_STYLESHEET : STYLESHEET;
|
||||
$this->HEADER['JAVASCRIPT'] = $this->FRONTEND_JAVASCRIPT ? $this->FRONTEND_JAVASCRIPT : JAVASCRIPT;
|
||||
$this->HEADER['STYLESHEET'] = !empty($this->FRONTEND_STYLESHEET) ?
|
||||
$this->FRONTEND_STYLESHEET : $set_stylesheet;
|
||||
$this->HEADER['JAVASCRIPT'] = !empty($this->FRONTEND_JAVASCRIPT) ?
|
||||
$this->FRONTEND_JAVASCRIPT : $set_javascript;
|
||||
}
|
||||
// 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)))
|
||||
. (defined('G_TITLE') ? ' - ' . $this->l10n->__(G_TITLE) : '') :
|
||||
. (!empty($set_g_title) ? '-' . $this->l10n->__($set_g_title) : '') :
|
||||
$this->l10n->__($this->L_TITLE);
|
||||
|
||||
// LANG
|
||||
@@ -491,7 +749,7 @@ class SmartyExtend extends \Smarty
|
||||
$this->DATA['JS_FLATPICKR'] = $this->JS_FLATPICKR;
|
||||
$this->DATA['JS_FILE_UPLOADER'] = $this->JS_FILE_UPLOADER;
|
||||
// user name
|
||||
$this->DATA['USER_NAME'] = !empty($_SESSION['USER_NAME']) ? $_SESSION['USER_NAME'] : '';
|
||||
$this->DATA['USER_NAME'] = $set_user_name;
|
||||
// the template part to include into the body
|
||||
$this->DATA['TEMPLATE_NAME'] = $this->TEMPLATE_NAME;
|
||||
$this->DATA['CONTENT_INCLUDE'] = $this->CONTENT_INCLUDE;
|
||||
@@ -499,24 +757,24 @@ class SmartyExtend extends \Smarty
|
||||
$this->DATA['JS_TRANSLATE'] = $this->JS_TRANSLATE ?? null;
|
||||
$this->DATA['PAGE_FILE_NAME'] = str_replace('.php', '', $this->page_name) . '.tpl';
|
||||
// render page
|
||||
$this->renderSmarty();
|
||||
$this->renderSmarty($compile_dir, $cache_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* merge outside object HEADER/DATA/DEBUG_DATA vars into the smarty class
|
||||
*
|
||||
* @param object $cms object that has header/data/debug_data
|
||||
* @param array<string,mixed> $smarty_data array that has header/data/debug_data
|
||||
* @return void
|
||||
*/
|
||||
public function mergeCmsSmartyVars(object $cms): void
|
||||
public function mergeCmsSmartyVars(array $smarty_data): void
|
||||
{
|
||||
// array merge HEADER, DATA, DEBUG DATA
|
||||
foreach (['HEADER', 'DATA', 'DEBUG_DATA'] as $ext_smarty) {
|
||||
if (
|
||||
isset($cms->{$ext_smarty}) &&
|
||||
is_array($cms->{$ext_smarty})
|
||||
isset($smarty_data[$ext_smarty]) &&
|
||||
is_array($smarty_data[$ext_smarty])
|
||||
) {
|
||||
$this->{$ext_smarty} = array_merge($this->{$ext_smarty}, $cms->{$ext_smarty});
|
||||
$this->{$ext_smarty} = array_merge($this->{$ext_smarty}, $smarty_data[$ext_smarty]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -524,21 +782,39 @@ class SmartyExtend extends \Smarty
|
||||
/**
|
||||
* render smarty data (can be called sepparate)
|
||||
*
|
||||
* @param string|null $compile_dir BASE . TEMPLATES_C
|
||||
* @param string|null $cache_dir BASE . CACHE
|
||||
* @return void
|
||||
*/
|
||||
public function renderSmarty(): void
|
||||
{
|
||||
public function renderSmarty(
|
||||
?string $compile_dir = null,
|
||||
?string $cache_dir = null
|
||||
): void {
|
||||
// trigger deprecation
|
||||
if (
|
||||
$compile_dir === null ||
|
||||
$cache_dir === null
|
||||
) {
|
||||
/** @deprecated renderSmarty call without parameters */
|
||||
trigger_error(
|
||||
'Calling renderSmarty without paramters is deprecated',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
// set vars (to be deprecated)
|
||||
$compile_dir = $compile_dir ?? BASE . TEMPLATES_C;
|
||||
$cache_dir = $cache_dir ?? BASE . CACHE;
|
||||
// create main data array
|
||||
$this->CONTENT_DATA = array_merge($this->HEADER, $this->DATA, $this->DEBUG_DATA);
|
||||
// data is 1:1 mapping (all vars, values, etc)
|
||||
foreach ($this->CONTENT_DATA as $key => $value) {
|
||||
$this->assign($key, $value);
|
||||
}
|
||||
if (is_dir(BASE . TEMPLATES_C)) {
|
||||
$this->setCompileDir(BASE . TEMPLATES_C);
|
||||
if (is_dir($compile_dir)) {
|
||||
$this->setCompileDir($compile_dir);
|
||||
}
|
||||
if (is_dir(BASE . CACHE)) {
|
||||
$this->setCacheDir(BASE . CACHE);
|
||||
if (is_dir($cache_dir)) {
|
||||
$this->setCacheDir($cache_dir);
|
||||
}
|
||||
$this->display(
|
||||
$this->MASTER_TEMPLATE_NAME,
|
||||
|
||||
@@ -50,9 +50,22 @@ for (
|
||||
is_file($__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php')
|
||||
) {
|
||||
// load enviorment file if it exists
|
||||
\CoreLibs\Get\DotEnv::readEnvFile(
|
||||
\gullevek\dotEnv\DotEnv::readEnvFile(
|
||||
$__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH
|
||||
);
|
||||
// find trigger name "admin/" or "frontend/" in the getcwd() folder
|
||||
$folder = '';
|
||||
foreach (['admin', 'frontend'] as $_folder) {
|
||||
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $_folder)) {
|
||||
$folder = $_folder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if content path is empty, fallback is default
|
||||
if (empty($folder)) {
|
||||
$folder = 'default';
|
||||
}
|
||||
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
|
||||
// load master config file that loads all other config files
|
||||
require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php';
|
||||
break;
|
||||
@@ -62,17 +75,5 @@ for (
|
||||
if (!defined('DIR')) {
|
||||
exit('Base config could not be loaded');
|
||||
}
|
||||
// find trigger name "admin/" or "frontend/" in the getcwd() folder
|
||||
foreach (['admin', 'frontend'] as $folder) {
|
||||
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $folder)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if content path is empty, fallback is default
|
||||
/** @phpstan-ignore-next-line can be empty */
|
||||
if (empty($folder)) {
|
||||
$folder = 'default';
|
||||
}
|
||||
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
|
||||
|
||||
// __END__
|
||||
|
||||
40
test/phpunit/AAASetupData/CoreLibsAAASetupDataTest.php
Normal file
40
test/phpunit/AAASetupData/CoreLibsAAASetupDataTest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Test base setup
|
||||
* @testdox AAASetupData\AAASetupDataTest just setup BASE
|
||||
*/
|
||||
final class CoreLibsAAASetupDataTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Covers nothing
|
||||
*
|
||||
* @testdox Just setup BASE
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetupData(): void
|
||||
{
|
||||
if (!defined('BASE')) {
|
||||
define(
|
||||
'BASE',
|
||||
str_replace('/configs', '', __DIR__)
|
||||
. DIRECTORY_SEPARATOR
|
||||
);
|
||||
}
|
||||
$this->assertEquals(
|
||||
str_replace('/configs', '', __DIR__)
|
||||
. DIRECTORY_SEPARATOR,
|
||||
BASE,
|
||||
'BASE Path set check'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
1
test/phpunit/AAASetupData/includes
Symbolic link
1
test/phpunit/AAASetupData/includes
Symbolic link
@@ -0,0 +1 @@
|
||||
../Language/includes/
|
||||
1
test/phpunit/AAASetupData/log
Symbolic link
1
test/phpunit/AAASetupData/log
Symbolic link
@@ -0,0 +1 @@
|
||||
../Debug/log/
|
||||
@@ -7,6 +7,14 @@ namespace tests;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
/*
|
||||
Not yet covered tests:
|
||||
- loginGetLocale
|
||||
- loginGetHeaderColor
|
||||
- loginGetPages
|
||||
- loginGetEuid
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test class for ACL\Login
|
||||
* @coversDefaultClass \CoreLibs\ACL\Login
|
||||
@@ -60,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(
|
||||
@@ -120,8 +125,6 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
// define('LOGIN_DB_SCHEMA', '');
|
||||
|
||||
// SHOULD SET
|
||||
// PASSWORD_MIN_LENGTH (d9)
|
||||
// PASSWORD_MAX_LENGTH (d255)
|
||||
// DEFAULT_ACL_LEVEL (d80)
|
||||
|
||||
// OPT:
|
||||
@@ -261,6 +264,8 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
'GROUP_ACL_LEVEL' => -1,
|
||||
'PAGES_ACL_LEVEL' => [],
|
||||
'USER_ACL_LEVEL' => -1,
|
||||
'USER_ADDITIONAL_ACL' => [],
|
||||
'GROUP_ADDITIONAL_ACL' => [],
|
||||
'UNIT_UID' => [
|
||||
'AdminAccess' => 1,
|
||||
],
|
||||
@@ -274,6 +279,7 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
'data' => [
|
||||
'test' => 'value',
|
||||
],
|
||||
'additional_acl' => []
|
||||
],
|
||||
],
|
||||
// 'UNIT_DEFAULT' => '',
|
||||
@@ -1106,7 +1112,22 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
|
||||
/** @var \CoreLibs\ACL\Login&MockObject */
|
||||
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
|
||||
->setConstructorArgs([self::$db, self::$log, $session_mock, false])
|
||||
->setConstructorArgs([
|
||||
self::$db,
|
||||
self::$log,
|
||||
$session_mock,
|
||||
[
|
||||
'auto_login' => false,
|
||||
'default_acl_level' => 80,
|
||||
'logout_target' => '',
|
||||
'site_locale' => 'en_US.UTF-8',
|
||||
'site_domain' => 'admin',
|
||||
'site_encoding' => 'UTF-8',
|
||||
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'includes' . DIRECTORY_SEPARATOR
|
||||
. 'locale' . DIRECTORY_SEPARATOR,
|
||||
]
|
||||
])
|
||||
->onlyMethods(['loginTerminate', 'loginReadPageName', 'loginPrintLogin'])
|
||||
->getMock();
|
||||
$login_mock->expects($this->any())
|
||||
@@ -1774,7 +1795,22 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
);
|
||||
/** @var \CoreLibs\ACL\Login&MockObject */
|
||||
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
|
||||
->setConstructorArgs([self::$db, self::$log, $session_mock, false])
|
||||
->setConstructorArgs([
|
||||
self::$db,
|
||||
self::$log,
|
||||
$session_mock,
|
||||
[
|
||||
'auto_login' => false,
|
||||
'default_acl_level' => 80,
|
||||
'logout_target' => '',
|
||||
'site_locale' => 'en_US.UTF-8',
|
||||
'site_domain' => 'admin',
|
||||
'site_encoding' => 'UTF-8',
|
||||
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'includes' . DIRECTORY_SEPARATOR
|
||||
. 'locale' . DIRECTORY_SEPARATOR,
|
||||
]
|
||||
])
|
||||
->onlyMethods(['loginTerminate'])
|
||||
->getMock();
|
||||
$login_mock->expects($this->any())
|
||||
@@ -1873,7 +1909,22 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
);
|
||||
/** @var \CoreLibs\ACL\Login&MockObject */
|
||||
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
|
||||
->setConstructorArgs([self::$db, self::$log, $session_mock, false])
|
||||
->setConstructorArgs([
|
||||
self::$db,
|
||||
self::$log,
|
||||
$session_mock,
|
||||
[
|
||||
'auto_login' => false,
|
||||
'default_acl_level' => 80,
|
||||
'logout_target' => '',
|
||||
'site_locale' => 'en_US.UTF-8',
|
||||
'site_domain' => 'admin',
|
||||
'site_encoding' => 'UTF-8',
|
||||
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'includes' . DIRECTORY_SEPARATOR
|
||||
. 'locale' . DIRECTORY_SEPARATOR,
|
||||
]
|
||||
])
|
||||
->onlyMethods(['loginTerminate'])
|
||||
->getMock();
|
||||
$login_mock->expects($this->any())
|
||||
@@ -1946,7 +1997,22 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
);
|
||||
/** @var \CoreLibs\ACL\Login&MockObject */
|
||||
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
|
||||
->setConstructorArgs([self::$db, self::$log, $session_mock, false])
|
||||
->setConstructorArgs([
|
||||
self::$db,
|
||||
self::$log,
|
||||
$session_mock,
|
||||
[
|
||||
'auto_login' => false,
|
||||
'default_acl_level' => 80,
|
||||
'logout_target' => '',
|
||||
'site_locale' => 'en_US.UTF-8',
|
||||
'site_domain' => 'admin',
|
||||
'site_encoding' => 'UTF-8',
|
||||
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'includes' . DIRECTORY_SEPARATOR
|
||||
. 'locale' . DIRECTORY_SEPARATOR,
|
||||
]
|
||||
])
|
||||
->onlyMethods(['loginTerminate'])
|
||||
->getMock();
|
||||
$login_mock->expects($this->any())
|
||||
@@ -2027,7 +2093,22 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
);
|
||||
/** @var \CoreLibs\ACL\Login&MockObject */
|
||||
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
|
||||
->setConstructorArgs([self::$db, self::$log, $session_mock, false])
|
||||
->setConstructorArgs([
|
||||
self::$db,
|
||||
self::$log,
|
||||
$session_mock,
|
||||
[
|
||||
'auto_login' => false,
|
||||
'default_acl_level' => 80,
|
||||
'logout_target' => '',
|
||||
'site_locale' => 'en_US.UTF-8',
|
||||
'site_domain' => 'admin',
|
||||
'site_encoding' => 'UTF-8',
|
||||
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
|
||||
. 'includes' . DIRECTORY_SEPARATOR
|
||||
. 'locale' . DIRECTORY_SEPARATOR,
|
||||
]
|
||||
])
|
||||
->onlyMethods(['loginTerminate'])
|
||||
->getMock();
|
||||
$login_mock->expects($this->any())
|
||||
1
test/phpunit/ACL/includes
Symbolic link
1
test/phpunit/ACL/includes
Symbolic link
@@ -0,0 +1 @@
|
||||
../AAASetupData/includes
|
||||
@@ -31,6 +31,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
|
||||
4,
|
||||
'b',
|
||||
'c' => 'test',
|
||||
'single' => 'single',
|
||||
'same' => 'same',
|
||||
'deep' => [
|
||||
'sub' => [
|
||||
@@ -288,6 +289,188 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function arraySearchKeyProvider(): array
|
||||
{
|
||||
/*
|
||||
0: search in array
|
||||
1: search keys
|
||||
2: flat flag
|
||||
3: prefix flag
|
||||
4: expected array
|
||||
*/
|
||||
return [
|
||||
// single
|
||||
'find single, standard' => [
|
||||
0 => self::$array,
|
||||
1 => ['single'],
|
||||
2 => null,
|
||||
3 => null,
|
||||
4 => [
|
||||
0 => [
|
||||
'value' => 'single',
|
||||
'path' => ['single'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'find single, prefix' => [
|
||||
0 => self::$array,
|
||||
1 => ['single'],
|
||||
2 => null,
|
||||
3 => true,
|
||||
4 => [
|
||||
'single' => [
|
||||
0 => [
|
||||
'value' => 'single',
|
||||
'path' => ['single'],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'find single, flat' => [
|
||||
0 => self::$array,
|
||||
1 => ['single'],
|
||||
2 => true,
|
||||
3 => null,
|
||||
4 => [
|
||||
'single',
|
||||
],
|
||||
],
|
||||
'find single, flat, prefix' => [
|
||||
0 => self::$array,
|
||||
1 => ['single'],
|
||||
2 => true,
|
||||
3 => true,
|
||||
4 => [
|
||||
'single' => [
|
||||
'single',
|
||||
],
|
||||
],
|
||||
],
|
||||
// not found
|
||||
'not found, standard' => [
|
||||
0 => self::$array,
|
||||
1 => ['NOT FOUND'],
|
||||
2 => null,
|
||||
3 => null,
|
||||
4 => [],
|
||||
],
|
||||
'not found, standard, prefix' => [
|
||||
0 => self::$array,
|
||||
1 => ['NOT FOUND'],
|
||||
2 => null,
|
||||
3 => true,
|
||||
4 => [
|
||||
'NOT FOUND' => [],
|
||||
],
|
||||
],
|
||||
'not found, flat' => [
|
||||
0 => self::$array,
|
||||
1 => ['NOT FOUND'],
|
||||
2 => true,
|
||||
3 => null,
|
||||
4 => [],
|
||||
],
|
||||
'not found, flat, prefix' => [
|
||||
0 => self::$array,
|
||||
1 => ['NOT FOUND'],
|
||||
2 => true,
|
||||
3 => true,
|
||||
4 => [
|
||||
'NOT FOUND' => [],
|
||||
],
|
||||
],
|
||||
// multi
|
||||
'multiple found, standard' => [
|
||||
0 => self::$array,
|
||||
1 => ['same'],
|
||||
2 => null,
|
||||
3 => null,
|
||||
4 => [
|
||||
[
|
||||
'value' => 'same',
|
||||
'path' => ['a', 'same', ],
|
||||
],
|
||||
[
|
||||
'value' => 'same',
|
||||
'path' => ['same', ],
|
||||
],
|
||||
[
|
||||
'value' => 'same',
|
||||
'path' => ['deep', 'sub', 'same', ],
|
||||
],
|
||||
]
|
||||
],
|
||||
'multiple found, flat' => [
|
||||
0 => self::$array,
|
||||
1 => ['same'],
|
||||
2 => true,
|
||||
3 => null,
|
||||
4 => ['same', 'same', 'same', ],
|
||||
],
|
||||
// search with multiple
|
||||
'search multiple, standard' => [
|
||||
0 => self::$array,
|
||||
1 => ['single', 'nested'],
|
||||
2 => null,
|
||||
3 => null,
|
||||
4 => [
|
||||
[
|
||||
'value' => 'single',
|
||||
'path' => ['single'],
|
||||
],
|
||||
[
|
||||
'value' => 'bar',
|
||||
'path' => ['deep', 'sub', 'nested', ],
|
||||
],
|
||||
],
|
||||
],
|
||||
'search multiple, prefix' => [
|
||||
0 => self::$array,
|
||||
1 => ['single', 'nested'],
|
||||
2 => null,
|
||||
3 => true,
|
||||
4 => [
|
||||
'single' => [
|
||||
[
|
||||
'value' => 'single',
|
||||
'path' => ['single'],
|
||||
],
|
||||
],
|
||||
'nested' => [
|
||||
[
|
||||
'value' => 'bar',
|
||||
'path' => ['deep', 'sub', 'nested', ],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'search multiple, flat' => [
|
||||
0 => self::$array,
|
||||
1 => ['single', 'nested'],
|
||||
2 => true,
|
||||
3 => null,
|
||||
4 => [
|
||||
'single', 'bar',
|
||||
],
|
||||
],
|
||||
'search multiple, flat, prefix' => [
|
||||
0 => self::$array,
|
||||
1 => ['single', 'nested'],
|
||||
2 => true,
|
||||
3 => true,
|
||||
4 => [
|
||||
'single' => ['single', ],
|
||||
'nested' => ['bar', ],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* provides array listing for the merge test
|
||||
*
|
||||
@@ -691,6 +874,44 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers::arraySearchKey
|
||||
* @dataProvider arraySearchKeyProvider
|
||||
* @testdox arraySearchKey Search array with keys and flat: $flat, prefix: $prefix [$_dataName]
|
||||
*
|
||||
* @param array $input
|
||||
* @param array $needles
|
||||
* @param bool|null $flat
|
||||
* @param bool|null $prefix
|
||||
* @param array $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testArraySearchKey(
|
||||
array $input,
|
||||
array $needles,
|
||||
?bool $flat,
|
||||
?bool $prefix,
|
||||
array $expected
|
||||
): void {
|
||||
if ($flat === null && $prefix === null) {
|
||||
$result = \CoreLibs\Combined\ArrayHandler::arraySearchKey($input, $needles);
|
||||
} elseif ($flat === null) {
|
||||
$result = \CoreLibs\Combined\ArrayHandler::arraySearchKey($input, $needles, prefix: $prefix);
|
||||
} elseif ($prefix === null) {
|
||||
$result = \CoreLibs\Combined\ArrayHandler::arraySearchKey($input, $needles, flat: $flat);
|
||||
} else {
|
||||
$result = \CoreLibs\Combined\ArrayHandler::arraySearchKey($input, $needles, $flat, $prefix);
|
||||
}
|
||||
// print "E: " . print_r($expected, true) . "\n";
|
||||
// print "R: " . print_r($result, true) . "\n";
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$result
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
@@ -738,7 +959,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
|
||||
$warning = array_shift($arrays);
|
||||
|
||||
// phpunit 10.0 compatible
|
||||
$this->expectExceptionMessage(($warning));
|
||||
$this->expectExceptionMessage($warning);
|
||||
|
||||
\CoreLibs\Combined\ArrayHandler::arrayMergeRecursive(...$arrays);
|
||||
|
||||
@@ -1,310 +0,0 @@
|
||||
<?php // phpcs:disable Generic.Files.LineLength
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Test class for Language\GetLocale
|
||||
*
|
||||
* @coversDefaultClass \CoreLibs\Language\GetLocale
|
||||
* @testdox \CoreLibs\Language\GetLocale method tests
|
||||
*/
|
||||
final class CoreLibsLanguageGetLocaleTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* set all constant variables that must be set before call
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
// default web page encoding setting
|
||||
if (!defined('DEFAULT_ENCODING')) {
|
||||
define('DEFAULT_ENCODING', 'UTF-8');
|
||||
}
|
||||
if (!defined('DEFAULT_LOCALE')) {
|
||||
// default lang + encoding
|
||||
define('DEFAULT_LOCALE', 'en_US.UTF-8');
|
||||
}
|
||||
// site
|
||||
if (!defined('SITE_ENCODING')) {
|
||||
define('SITE_ENCODING', DEFAULT_ENCODING);
|
||||
}
|
||||
if (!defined('SITE_LOCALE')) {
|
||||
define('SITE_LOCALE', DEFAULT_LOCALE);
|
||||
}
|
||||
// just set
|
||||
if (!defined('BASE')) {
|
||||
define('BASE', str_replace('/configs', '', __DIR__) . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
if (!defined('INCLUDES')) {
|
||||
define('INCLUDES', 'includes' . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
if (!defined('LANG')) {
|
||||
define('LANG', 'lang' . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
if (!defined('LOCALE')) {
|
||||
define('LOCALE', 'locale' . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
if (!defined('CONTENT_PATH')) {
|
||||
define('CONTENT_PATH', 'frontend' . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
// array session
|
||||
$_SESSION = [];
|
||||
global $_SESSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* all the test data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function setLocaleProvider(): array
|
||||
{
|
||||
return [
|
||||
// 0: locale
|
||||
// 1: domain
|
||||
// 2: encoding
|
||||
// 3: path
|
||||
// 4: SESSION: DEFAULT_LOCALE
|
||||
// 5: SESSION: DEFAULT_CHARSET
|
||||
// 6: expected array
|
||||
'no params, all default constants' => [
|
||||
// lang, domain, encoding, path
|
||||
null, null, null, null,
|
||||
// SESSION DEFAULT_LOCALE, SESSION: DEFAULT_CHARSET
|
||||
null, null,
|
||||
// return array
|
||||
[
|
||||
'locale' => 'en_US.UTF-8',
|
||||
'lang' => 'en_US',
|
||||
'domain' => 'frontend',
|
||||
'encoding' => 'UTF-8',
|
||||
'path' => "/^\/(.*\/)?includes\/locale\/$/",
|
||||
],
|
||||
],
|
||||
'no params, session charset and lang' => [
|
||||
// lang, domain, encoding, path
|
||||
null, null, null, null,
|
||||
// SESSION DEFAULT_LOCALE, SESSION: DEFAULT_CHARSET
|
||||
'ja_JP', 'UTF-8',
|
||||
// return array
|
||||
[
|
||||
'locale' => 'ja_JP',
|
||||
'lang' => 'ja_JP',
|
||||
'domain' => 'frontend',
|
||||
'encoding' => 'UTF-8',
|
||||
'path' => "/^\/(.*\/)?includes\/locale\/$/",
|
||||
],
|
||||
],
|
||||
'no params, session charset and lang short' => [
|
||||
// lang, domain, encoding, path
|
||||
null, null, null, null,
|
||||
// SESSION DEFAULT_LOCALE, SESSION: DEFAULT_CHARSET
|
||||
'ja', 'UTF-8',
|
||||
// return array
|
||||
[
|
||||
'locale' => 'ja',
|
||||
'lang' => 'ja',
|
||||
'domain' => 'frontend',
|
||||
'encoding' => 'UTF-8',
|
||||
'path' => "/^\/(.*\/)?includes\/locale\/$/",
|
||||
],
|
||||
],
|
||||
// param lang (no sessions)
|
||||
'locale param only, no sessions' => [
|
||||
// lang, domain, encoding, path
|
||||
'ja.UTF-8', null, null, null,
|
||||
// SESSION DEFAULT_LOCALE, SESSION: DEFAULT_CHARSET
|
||||
null, null,
|
||||
// return array
|
||||
[
|
||||
'locale' => 'ja.UTF-8',
|
||||
'lang' => 'ja',
|
||||
'domain' => 'frontend',
|
||||
'encoding' => 'UTF-8',
|
||||
'path' => "/^\/(.*\/)?includes\/locale\/$/",
|
||||
],
|
||||
],
|
||||
// different locale setting
|
||||
'locale complex param only, no sessions' => [
|
||||
// lang, domain, encoding, path
|
||||
'ja_JP.SJIS', null, null, null,
|
||||
// SESSION DEFAULT_LOCALE, SESSION: DEFAULT_CHARSET
|
||||
null, null,
|
||||
// return array
|
||||
[
|
||||
'locale' => 'ja_JP.SJIS',
|
||||
'lang' => 'ja_JP',
|
||||
'domain' => 'frontend',
|
||||
'encoding' => 'SJIS',
|
||||
'path' => "/^\/(.*\/)?includes\/locale\/$/",
|
||||
],
|
||||
],
|
||||
// param lang and domain (no override)
|
||||
'locale, domain params, no sessions' => [
|
||||
// lang, domain, encoding, path
|
||||
'ja.UTF-8', 'admin', null, null,
|
||||
// SESSION DEFAULT_LOCALE, SESSION: DEFAULT_CHARSET
|
||||
null, null,
|
||||
// return array
|
||||
[
|
||||
'locale' => 'ja.UTF-8',
|
||||
'lang' => 'ja',
|
||||
'domain' => 'admin',
|
||||
'encoding' => 'UTF-8',
|
||||
'path' => "/^\/(.*\/)?includes\/locale\/$/",
|
||||
],
|
||||
],
|
||||
// param lang and domain (no override)
|
||||
'locale, domain, encoding params, no sessions' => [
|
||||
// lang, domain, encoding, path
|
||||
'ja.UTF-8', 'admin', 'UTF-8', null,
|
||||
// SESSION DEFAULT_LOCALE, SESSION: DEFAULT_CHARSET
|
||||
null, null,
|
||||
// return array
|
||||
[
|
||||
'locale' => 'ja.UTF-8',
|
||||
'lang' => 'ja',
|
||||
'domain' => 'admin',
|
||||
'encoding' => 'UTF-8',
|
||||
'path' => "/^\/(.*\/)?includes\/locale\/$/",
|
||||
],
|
||||
],
|
||||
// lang, domain, path (no override)
|
||||
'locale, domain and path, no sessions' => [
|
||||
// lang, domain, encoding, path
|
||||
'ja.UTF-8', 'admin', '', __DIR__ . '/locale_other/',
|
||||
// SESSION DEFAULT_LOCALE, SESSION: DEFAULT_CHARSET
|
||||
null, null,
|
||||
// return array
|
||||
[
|
||||
'locale' => 'ja.UTF-8',
|
||||
'lang' => 'ja',
|
||||
'domain' => 'admin',
|
||||
'encoding' => 'UTF-8',
|
||||
'path' => "/^\/(.*\/)?locale_other\/$/",
|
||||
],
|
||||
],
|
||||
// all params set (no override)
|
||||
'all parameter, no sessions' => [
|
||||
// lang, domain, encoding, path
|
||||
'ja', 'admin', 'UTF-8', __DIR__ . '/locale_other/',
|
||||
// SESSION DEFAULT_LOCALE, SESSION: DEFAULT_CHARSET
|
||||
null, null,
|
||||
// return array
|
||||
[
|
||||
'locale' => 'ja',
|
||||
'lang' => 'ja',
|
||||
'domain' => 'admin',
|
||||
'encoding' => 'UTF-8',
|
||||
'path' => "/^\/(.*\/)?locale_other\/$/",
|
||||
],
|
||||
],
|
||||
// param lang and domain (no override)
|
||||
'long locale, domain, encoding params, no sessions' => [
|
||||
// lang, domain, encoding, path
|
||||
'de_CH.UTF-8@euro', 'admin', 'UTF-8', null,
|
||||
// SESSION DEFAULT_LOCALE, SESSION: DEFAULT_CHARSET
|
||||
null, null,
|
||||
// return array
|
||||
[
|
||||
'locale' => 'de_CH.UTF-8@euro',
|
||||
'lang' => 'de_CH',
|
||||
'domain' => 'admin',
|
||||
'encoding' => 'UTF-8',
|
||||
'path' => "/^\/(.*\/)?includes\/locale\/$/",
|
||||
],
|
||||
],
|
||||
// TODO invalid params (bad path) (no override)
|
||||
// TODO param calls, but with override set
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::setLocale
|
||||
* @dataProvider setLocaleProvider
|
||||
* @testdox lang settings lang $language, domain $domain, encoding $encoding, path $path; session lang: $SESSION_DEFAULT_LOCALE, session char: $SESSION_DEFAULT_CHARSET [$_dataName]
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testsetLocale(
|
||||
?string $language,
|
||||
?string $domain,
|
||||
?string $encoding,
|
||||
?string $path,
|
||||
?string $SESSION_DEFAULT_LOCALE,
|
||||
?string $SESSION_DEFAULT_CHARSET,
|
||||
array $expected
|
||||
): void {
|
||||
$return_lang_settings = [];
|
||||
global $_SESSION;
|
||||
// set override
|
||||
if ($SESSION_DEFAULT_LOCALE !== null) {
|
||||
$_SESSION['DEFAULT_LOCALE'] = $SESSION_DEFAULT_LOCALE;
|
||||
}
|
||||
if ($SESSION_DEFAULT_CHARSET !== null) {
|
||||
$_SESSION['DEFAULT_CHARSET'] = $SESSION_DEFAULT_CHARSET;
|
||||
}
|
||||
// function call
|
||||
if ($language === null && $domain === null && $encoding === null && $path === null) {
|
||||
$return_lang_settings = \CoreLibs\Language\GetLocale::setLocale();
|
||||
} elseif ($language !== null && $domain === null && $encoding === null && $path === null) {
|
||||
$return_lang_settings = \CoreLibs\Language\GetLocale::setLocale(
|
||||
$language
|
||||
);
|
||||
} elseif ($language !== null && $domain !== null && $encoding === null && $path === null) {
|
||||
$return_lang_settings = \CoreLibs\Language\GetLocale::setLocale(
|
||||
$language,
|
||||
$domain
|
||||
);
|
||||
} elseif ($language !== null && $domain !== null && $encoding !== null && $path === null) {
|
||||
$return_lang_settings = \CoreLibs\Language\GetLocale::setLocale(
|
||||
$language,
|
||||
$domain,
|
||||
$encoding
|
||||
);
|
||||
} else {
|
||||
$return_lang_settings = \CoreLibs\Language\GetLocale::setLocale(
|
||||
$language,
|
||||
$domain,
|
||||
$encoding,
|
||||
$path
|
||||
);
|
||||
}
|
||||
// print "RETURN: " . print_r($return_lang_settings, true) . "\n";
|
||||
|
||||
foreach (
|
||||
[
|
||||
'locale', 'lang', 'domain', 'encoding', 'path'
|
||||
] as $key
|
||||
) {
|
||||
$value = $expected[$key];
|
||||
if (strpos($value, "/") === 0) {
|
||||
// this is regex
|
||||
$this->assertMatchesRegularExpression(
|
||||
$value,
|
||||
$return_lang_settings[$key],
|
||||
'assert regex failed for ' . $key
|
||||
);
|
||||
} else {
|
||||
// assert equal
|
||||
$this->assertEquals(
|
||||
$value,
|
||||
$return_lang_settings[$key],
|
||||
'assert equal failed for ' . $key
|
||||
);
|
||||
}
|
||||
}
|
||||
// unset all vars
|
||||
$_SESSION = [];
|
||||
unset($GLOBALS['OVERRIDE_LANG']);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,11 +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
|
||||
*
|
||||
@@ -23,7 +25,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
* 1: expected
|
||||
* 2: override
|
||||
* override:
|
||||
* - constant for COSNTANTS
|
||||
* - constant for CONSTANTS
|
||||
* - global for _GLOBALS
|
||||
*
|
||||
* @return array
|
||||
@@ -33,17 +35,20 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
return [
|
||||
'log folder set' => [
|
||||
[
|
||||
'log_folder' => '/tmp'
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
|
||||
'file_id' => 'testClassInit'
|
||||
],
|
||||
[
|
||||
'log_folder' => '/tmp/',
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
|
||||
'debug_all' => false,
|
||||
'print_all' => false,
|
||||
],
|
||||
[]
|
||||
],
|
||||
'nothing set' => [
|
||||
null,
|
||||
[
|
||||
'file_id' => 'testClassInit'
|
||||
],
|
||||
[
|
||||
'log_folder' => getcwd() . DIRECTORY_SEPARATOR,
|
||||
'debug_all' => false,
|
||||
@@ -51,30 +56,33 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
],
|
||||
[]
|
||||
],
|
||||
'no options set, constant set' => [
|
||||
null,
|
||||
'no options set, constant set [DEPRECATED]' => [
|
||||
[
|
||||
'log_folder' => str_replace('/configs', '', __DIR__)
|
||||
. DIRECTORY_SEPARATOR . 'log/',
|
||||
'file_id' => 'testClassInit'
|
||||
],
|
||||
[
|
||||
'log_folder' => str_replace(DIRECTORY_SEPARATOR . 'configs', '', __DIR__)
|
||||
. DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR,
|
||||
'debug_all' => false,
|
||||
'print_all' => false,
|
||||
],
|
||||
[
|
||||
'constant' => [
|
||||
'BASE' => str_replace('/configs', '', __DIR__)
|
||||
'BASE' => str_replace(DIRECTORY_SEPARATOR . 'configs', '', __DIR__)
|
||||
. DIRECTORY_SEPARATOR,
|
||||
'LOG' => 'log/'
|
||||
'LOG' => 'log' . DIRECTORY_SEPARATOR
|
||||
]
|
||||
]
|
||||
],
|
||||
'standard test set' => [
|
||||
[
|
||||
'log_folder' => '/tmp',
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
|
||||
'file_id' => 'testClassInit',
|
||||
'debug_all' => true,
|
||||
'print_all' => true,
|
||||
],
|
||||
[
|
||||
'log_folder' => '/tmp/',
|
||||
'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
|
||||
'debug_all' => true,
|
||||
'print_all' => true,
|
||||
],
|
||||
@@ -89,35 +97,66 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
* @dataProvider optionsProvider
|
||||
* @testdox init test [$_dataName]
|
||||
*
|
||||
* @param array|null $options
|
||||
* @param array $options
|
||||
* @param array $expected
|
||||
* @param array $override
|
||||
* @return void
|
||||
*/
|
||||
public function testClassInit(?array $options, array $expected, array $override): void
|
||||
public function testClassInit(array $options, array $expected, array $override): void
|
||||
{
|
||||
if (!empty($override['constant'])) {
|
||||
foreach ($override['constant'] as $var => $value) {
|
||||
define($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 ($options === null) {
|
||||
$log = new \CoreLibs\Debug\Logging();
|
||||
} else {
|
||||
$log = new \CoreLibs\Debug\Logging($options);
|
||||
// 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);
|
||||
}
|
||||
$log = new \CoreLibs\Debug\LoggingLegacy($options);
|
||||
// reset error handler
|
||||
restore_error_handler();
|
||||
// check that settings match
|
||||
$this->assertEquals(
|
||||
$expected['log_folder'],
|
||||
$log->getSetting('log_folder')
|
||||
$log->getSetting('log_folder'),
|
||||
'log folder not matching'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected['debug_all'],
|
||||
$log->getSetting('debug_output_all')
|
||||
$log->getSetting('debug_output_all'),
|
||||
'debug all flag not matching'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected['print_all'],
|
||||
$log->getSetting('print_output_all')
|
||||
$log->getSetting('print_output_all'),
|
||||
'print all flag not matching'
|
||||
);
|
||||
// print "LOG: " . $log->getSetting('log_folder') . "\n";
|
||||
// print "DEBUG: " . $log->getSetting('debug_output_all') . "\n";
|
||||
@@ -134,17 +173,23 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
// 0: options
|
||||
// 1: expected
|
||||
// 2: override
|
||||
// 3: exception message
|
||||
return [
|
||||
'no log id set' => [
|
||||
null,
|
||||
[
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
],
|
||||
[
|
||||
'log_file_id' => ''
|
||||
],
|
||||
[]
|
||||
[],
|
||||
null
|
||||
],
|
||||
// set log id manually afterwards
|
||||
'set log id manually' => [
|
||||
null,
|
||||
[
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
],
|
||||
[
|
||||
'log_file_id' => '',
|
||||
'set_log_file_id' => 'abc123',
|
||||
@@ -154,21 +199,26 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
'values' => [
|
||||
'log_file_id' => 'abc123'
|
||||
]
|
||||
]
|
||||
],
|
||||
null
|
||||
],
|
||||
// set log id from options
|
||||
'set log id via options' => [
|
||||
[
|
||||
'file_id' => 'abc456',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
],
|
||||
[
|
||||
'log_file_id' => 'abc456'
|
||||
],
|
||||
[]
|
||||
[],
|
||||
null
|
||||
],
|
||||
// set log id from GLOBALS [DEPRECATED]
|
||||
'set log id via globals' => [
|
||||
null,
|
||||
'set log id via globals [DEPRECATED]' => [
|
||||
[
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
],
|
||||
[
|
||||
'log_file_id' => 'def123'
|
||||
],
|
||||
@@ -176,11 +226,14 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
'globals' => [
|
||||
'LOG_FILE_ID' => 'def123'
|
||||
]
|
||||
]
|
||||
],
|
||||
'options: file_id must be set. Setting via LOG_FILE_ID global variable is deprecated'
|
||||
],
|
||||
// set log id from CONSTANT [DEPRECATED]
|
||||
'set log id via constant' => [
|
||||
null,
|
||||
'set log id via constant [DEPRECATED]' => [
|
||||
[
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
],
|
||||
[
|
||||
'log_file_id' => 'ghi123'
|
||||
],
|
||||
@@ -192,12 +245,14 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
'constant' => [
|
||||
'LOG_FILE_ID' => 'ghi123'
|
||||
]
|
||||
]
|
||||
],
|
||||
'options: file_id must be set. Setting via LOG_FILE_ID constant is deprecated'
|
||||
],
|
||||
// invalid, keep previous set
|
||||
'invalid log id' => [
|
||||
[
|
||||
'file_id' => 'jkl456'
|
||||
'file_id' => 'jkl456',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
],
|
||||
[
|
||||
'log_file_id' => 'jkl456',
|
||||
@@ -207,7 +262,8 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
'values' => [
|
||||
'log_file_id' => './#'
|
||||
]
|
||||
]
|
||||
],
|
||||
null
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -219,13 +275,18 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
* @dataProvider logIdOptionsProvider
|
||||
* @testdox log id set/get tests [$_dataName]
|
||||
*
|
||||
* @param array|null $options
|
||||
* @param array $options
|
||||
* @param array $expected
|
||||
* @param array $override
|
||||
* @param string|null $deprecation_message until we remove the old code
|
||||
* @return void
|
||||
*/
|
||||
public function testLogId(?array $options, array $expected, array $override): void
|
||||
{
|
||||
public function testLogId(
|
||||
array $options,
|
||||
array $expected,
|
||||
array $override,
|
||||
?string $deprecation_message
|
||||
): void {
|
||||
// we need to set with file_id option, globals LOG_FILE_ID, constant LOG_FILE_ID
|
||||
if (!empty($override['constant'])) {
|
||||
foreach ($override['constant'] as $var => $value) {
|
||||
@@ -237,11 +298,20 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
$GLOBALS[$var] = $value;
|
||||
}
|
||||
}
|
||||
if ($options === null) {
|
||||
$log = new \CoreLibs\Debug\Logging();
|
||||
} else {
|
||||
$log = new \CoreLibs\Debug\Logging($options);
|
||||
if (!empty($override['constant']) || !empty($override['globals'])) {
|
||||
// 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\Debug\LoggingLegacy($options);
|
||||
// reset error handler
|
||||
restore_error_handler();
|
||||
// check current
|
||||
$this->assertEquals(
|
||||
$log->getLogId(),
|
||||
@@ -316,7 +386,10 @@ 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
|
||||
]);
|
||||
// set and check
|
||||
$this->assertEquals(
|
||||
$log->setLogLevelAll($type, $flag),
|
||||
@@ -438,7 +511,10 @@ 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
|
||||
]);
|
||||
// set
|
||||
$this->assertEquals(
|
||||
$log->setLogLevel($type, $flag, $debug_on),
|
||||
@@ -517,7 +593,10 @@ 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
|
||||
]);
|
||||
// set and check
|
||||
$this->assertEquals(
|
||||
$log->setLogPer($type, $set),
|
||||
@@ -546,7 +625,10 @@ 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
|
||||
]);
|
||||
// set and check
|
||||
$this->assertEquals(
|
||||
$log->setGetLogPrintFileDate($input),
|
||||
@@ -612,7 +694,10 @@ 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
|
||||
]);
|
||||
$this->assertEquals(
|
||||
$log->prAr($input),
|
||||
$expected
|
||||
@@ -673,7 +758,10 @@ 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
|
||||
]);
|
||||
$return = '';
|
||||
if ($true === null && $false === null) {
|
||||
$return = $log->prBl($input);
|
||||
@@ -845,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(
|
||||
@@ -959,9 +1047,16 @@ final class CoreLibsDebugLoggingTest extends TestCase
|
||||
public function testLogUniqueId(bool $option, bool $override): void
|
||||
{
|
||||
if ($option === true) {
|
||||
$log = new \CoreLibs\Debug\Logging(['per_run' => $option]);
|
||||
$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
|
||||
]);
|
||||
$log->setLogUniqueId();
|
||||
}
|
||||
$per_run_id = $log->getLogUniqueId();
|
||||
@@ -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'
|
||||
);
|
||||
}
|
||||
3
test/phpunit/Debug/log/.gitignore
vendored
Normal file
3
test/phpunit/Debug/log/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*log
|
||||
*LOG
|
||||
!.gitignore
|
||||
@@ -77,21 +77,24 @@ final class CoreLibsGetDotEnvTest extends TestCase
|
||||
'file' => 'cannot_read.env',
|
||||
'status' => 2,
|
||||
'content' => [],
|
||||
'chmod' => '000',
|
||||
// 0000
|
||||
'chmod' => '100000',
|
||||
],
|
||||
'empty file' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'empty.env',
|
||||
'status' => 1,
|
||||
'content' => [],
|
||||
'chmod' => null,
|
||||
// 0664
|
||||
'chmod' => '100664',
|
||||
],
|
||||
'override all' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
'file' => 'test.env',
|
||||
'status' => 0,
|
||||
'content' => $dot_env_content,
|
||||
'chmod' => null,
|
||||
// 0664
|
||||
'chmod' => '100664',
|
||||
],
|
||||
'override directory' => [
|
||||
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
|
||||
@@ -124,6 +127,16 @@ final class CoreLibsGetDotEnvTest extends TestCase
|
||||
array $expected_env,
|
||||
?string $chmod
|
||||
): void {
|
||||
if (
|
||||
!empty($chmod) &&
|
||||
$chmod == '100000' &&
|
||||
getmyuid() == 0
|
||||
) {
|
||||
$this->markTestSkipped(
|
||||
"Skip cannot read file test because run user is root"
|
||||
);
|
||||
return;
|
||||
}
|
||||
// if we have file + chmod set
|
||||
$old_chmod = null;
|
||||
if (
|
||||
@@ -134,6 +147,20 @@ final class CoreLibsGetDotEnvTest extends TestCase
|
||||
$old_chmod = fileperms($folder . DIRECTORY_SEPARATOR . $file);
|
||||
chmod($folder . DIRECTORY_SEPARATOR . $file, octdec($chmod));
|
||||
}
|
||||
$message = '\CoreLibs\Get\DotEnv is deprecated in favor for '
|
||||
. 'composer package gullevek\dotenv which is a copy of this';
|
||||
// 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
|
||||
);
|
||||
// tests are never run -> deprecated
|
||||
if (is_file($folder . DIRECTORY_SEPARATOR . $file)) {
|
||||
chmod($folder . DIRECTORY_SEPARATOR . $file, 0664);
|
||||
}
|
||||
$this->expectExceptionMessage($message);
|
||||
if ($folder !== null && $file !== null) {
|
||||
$status = DotEnv::readEnvFile($folder, $file);
|
||||
} elseif ($folder !== null) {
|
||||
@@ -141,6 +168,7 @@ final class CoreLibsGetDotEnvTest extends TestCase
|
||||
} else {
|
||||
$status = DotEnv::readEnvFile();
|
||||
}
|
||||
restore_error_handler();
|
||||
$this->assertEquals(
|
||||
$status,
|
||||
$expected_status,
|
||||
@@ -153,8 +181,9 @@ final class CoreLibsGetDotEnvTest extends TestCase
|
||||
'Assert _ENV correct'
|
||||
);
|
||||
// if we have file and chmod unset
|
||||
if ($old_chmod !== null) {
|
||||
chmod($folder . DIRECTORY_SEPARATOR . $file, $old_chmod);
|
||||
print "Write mode: $old_chmod\n";
|
||||
if ($old_chmod !== null && $chmod == '100000') {
|
||||
chmod($folder . DIRECTORY_SEPARATOR . $file, 0664);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user