Compare commits

..

14 Commits

Author SHA1 Message Date
67a8e1a533 Switch from parameter list to options list for SmartyExtend var set
The SmartyExtend var set mothod calls switched to options list
2023-03-13 09:27:46 +09:00
38788dddce CoreLibs v8.0.5 release 2023-03-10 15:30:06 +09:00
cf196d56dd Bug fix in SmartyExtend set vars calls 2023-03-10 15:27:45 +09:00
0cb76c8db2 CoreLibs v8.0.3 release 2023-03-10 15:13:43 +09:00
db02bdd102 CoreLibs data update for v8.0.3 2023-03-10 15:11:58 +09:00
d9b71a64b3 Published v8.0.2 2023-03-09 16:59:18 +09:00
f410d761ba Remove deprecated classes and methods, deprecate all named constants
All named constants used inside classes have been deprecated and
must now be set from method calls, class init, etc
2023-03-09 16:41:55 +09:00
fb4b9f3f81 Sync phpunit subfolder layout from master development 2023-03-02 16:16:36 +09:00
1e94cd7b57 Update last published version 2023-03-02 15:42:52 +09:00
cba6a3f969 Remove old Check\Jason replaced by Convert\Json 2023-03-02 15:39:05 +09:00
bea8629d10 ReadMe updates, add composer releae documentation 2023-03-02 09:12:51 +09:00
b2751872a3 Published v8.0.0 and remove debug output in publish script 2023-03-01 07:20:11 +09:00
0a80abe8a4 PHP 8.1 base version update 2023-02-28 18:04:42 +09:00
1d220f25eb Setup basic publish script for gitea and gitlab 2023-02-28 11:26:02 +09:00
106 changed files with 3054 additions and 1832 deletions

View File

@@ -0,0 +1,40 @@
# Create new package in system gitea/gitlab/composer.egplusww.jp
## Prepare
The following things must have been done:
- full phpstan check/phan check where possible
- a valid version tag `vX.Y.Z` must have been created and pushed to all services
## Publish
To do the final publish
### GITEA and GITLAB
Run `publish/publish.sh` script to create composer packages.
This will automatically run all commands to create the packages
### composer.egplusww.jp web host
For the local composer package host.
update `/storage/var/www/html/composer/www/pacakges.json` file with new version and commit
The entry is a copy of the `composer.json` with the following new entries:
```json
{
...,
"version": "X.Y.Z",
...
"dist": {
"url": "https://git.egplusww.jp/Composer/CoreLibs-Composer-All/archive/vX.Y.Z.zip",
"type": "zip"
},
...
}
```
run `git pull egra-gitea master` on udon-core in `/var/www/html/composer/www`

View File

@@ -22,4 +22,4 @@ Alternative setup composer local zip file repot:
## Install package ## Install package
`composer require egrajp/corelibs-composer-all:^7.11` `composer require egrajp/corelibs-composer-all:^8.0`

View File

@@ -19,10 +19,11 @@
"php": ">=8.1" "php": ">=8.1"
}, },
"require-dev": { "require-dev": {
"phpstan/phpstan": "1.10.x-dev", "phpstan/phpstan": "^1.10",
"phan/phan": "v5.x-dev", "phan/phan": "v5.x-dev",
"phpunit/phpunit": "^9", "phpunit/phpunit": "^9",
"egrajp/smarty-extended": "^4.3" "egrajp/smarty-extended": "^4.3",
"vimeo/psalm": "^5.0@dev"
}, },
"repositories": { "repositories": {
"git.egplusww.jp.Composer": { "git.egplusww.jp.Composer": {

View File

@@ -6,8 +6,6 @@ parameters:
level: 8 # max is now 9 level: 8 # max is now 9
checkMissingCallableSignature: true checkMissingCallableSignature: true
treatPhpDocTypesAsCertain: false treatPhpDocTypesAsCertain: false
strictRules:
allRules: false
paths: paths:
- %currentWorkingDirectory%/src - %currentWorkingDirectory%/src
bootstrapFiles: bootstrapFiles:
@@ -27,9 +25,9 @@ parameters:
#- # this error is ignore because of the PHP 8.0 to 8.1 change for pg_*, only for 8.0 or lower #- # this error is ignore because of the PHP 8.0 to 8.1 change for pg_*, only for 8.0 or lower
# message: "#^Parameter \\#1 \\$(result|connection) of function pg_\\w+ expects resource(\\|null)?, object\\|resource(\\|bool)? given\\.$#" # message: "#^Parameter \\#1 \\$(result|connection) of function pg_\\w+ expects resource(\\|null)?, object\\|resource(\\|bool)? given\\.$#"
# path: %currentWorkingDirectory%/www/lib/CoreLibs/DB/SQL/PgSQL.php # path: %currentWorkingDirectory%/www/lib/CoreLibs/DB/SQL/PgSQL.php
- # this is for 8.1 or newer # - # this is for 8.1 or newer
message: "#^Parameter \\#1 \\$(result|connection) of function pg_\\w+ expects PgSql\\\\(Result|Connection(\\|string)?(\\|null)?), object\\|resource given\\.$#" # message: "#^Parameter \\#1 \\$(result|connection) of function pg_\\w+ expects PgSql\\\\(Result|Connection(\\|string)?(\\|null)?), object\\|resource given\\.$#"
path: %currentWorkingDirectory%/src/DB/SQL/PgSQL.php # path: %currentWorkingDirectory%/src/DB/SQL/PgSQL.php
# this is ignored for now # this is ignored for now
# - '#Expression in empty\(\) is always falsy.#' # - '#Expression in empty\(\) is always falsy.#'
# - # -

2
publish/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.zip
.env*

1
publish/last.published Normal file
View File

@@ -0,0 +1 @@
8.0.4

60
publish/publish.sh Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env bash
BASE_FOLDER=$(dirname $(readlink -f $0))"/";
VERSION=$(git tag --list | sort -V | tail -n1 | sed -e "s/^v//");
file_last_published="${BASE_FOLDER}last.published";
if [ -z "${VERSION}" ]; then
echo "Version must be set in the form x.y.z without any leading characters";
exit;
fi;
# compare version, if different or newer, deploy
if [ -f "${file_last_published}" ]; then
LAST_PUBLISHED_VERSION=$(cat ${file_last_published});
if $(dpkg --compare-versions "${VERSION}" le "${LAST_PUBLISHED_VERSION}"); then
echo "git tag version ${VERSION} is not newer than previous published version ${LAST_PUBLISHED_VERSION}";
exit;
fi;
fi;
# read in the .env.deploy file and we must have
# GITLAB_USER
# GITLAB_TOKEN
# GITEA_DEPLOY_TOKEN
if [ ! -f "${BASE_FOLDER}.env.deploy" ]; then
echo "Deploy enviroment file .env.deploy is missing";
exit;
fi;
set -o allexport;
cd ${BASE_FOLDER};
source .env.deploy;
cd -;
set +o allexport;
# gitea
if [ ! -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;
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};
echo "${VERSION}" > "${file_last_published}";
else
echo "Missing either GITEA_USER or GITEA_TOKEN environment variable";
fi;
# gitlab
if [ ! -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";
curl --data branch=master \
--header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
"https://gitlab-na.factory.tools/api/v4/projects/950/packages/composer";
echo "${VERSION}" > "${file_last_published}";
else
echo "Missing GITLAB_DEPLOY_TOKEN environment variable";
fi;
# __END__

View File

@@ -131,6 +131,31 @@ class Login
// it will be set back to 255 // it will be set back to 255
/** @var int */ /** @var int */
private $password_max_length = 255; private $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 */ /** @var array<string> can have several regexes, if nothing set, all is ok */
private $password_valid_chars = [ private $password_valid_chars = [
// '^(?=.*\d)(?=.*[A-Za-z])[0-9A-Za-z!@#$%]{8,}$', // '^(?=.*\d)(?=.*[A-Za-z])[0-9A-Za-z!@#$%]{8,}$',
@@ -157,7 +182,7 @@ class Login
private $acl = []; private $acl = [];
/** @var array<mixed> */ /** @var array<mixed> */
private $default_acl_list = []; private $default_acl_list = [];
/** @var array<int|string,mixed> Reverse list to lookup level from type */ /** @var array<string,int> Reverse list to lookup level from type */
private $default_acl_list_type = []; private $default_acl_list_type = [];
/** @var int default ACL level to be based on if nothing set */ /** @var int default ACL level to be based on if nothing set */
private $default_acl_level = 0; private $default_acl_level = 0;
@@ -167,6 +192,17 @@ class Login
/** @var bool */ /** @var bool */
private $login_is_ajax_page = false; private $login_is_ajax_page = false;
// settings
/** @var array<string,mixed> options */
private $options = [];
/** @var array<string,string> locale options: locale, domain, encoding (opt), path */
private $locale = [
'locale' => '',
'domain' => '',
'encoding' => '',
'path' => '',
];
/** @var \CoreLibs\Debug\Logging logger */ /** @var \CoreLibs\Debug\Logging logger */
public $log; public $log;
/** @var \CoreLibs\DB\IO database */ /** @var \CoreLibs\DB\IO database */
@@ -183,15 +219,14 @@ class Login
* @param \CoreLibs\DB\IO $db Database connection class * @param \CoreLibs\DB\IO $db Database connection class
* @param \CoreLibs\Debug\Logging $log Logging class * @param \CoreLibs\Debug\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class * @param \CoreLibs\Create\Session $session Session interface class
* @param bool $auto_login [default true] Auto login flag, legacy * @param array<string,mixed> $options Login ACL settings
* If set to true will run login * $auto_login [default true] DEPRECATED, moved into options
* during construction
*/ */
public function __construct( public function __construct(
\CoreLibs\DB\IO $db, \CoreLibs\DB\IO $db,
\CoreLibs\Debug\Logging $log, \CoreLibs\Debug\Logging $log,
\CoreLibs\Create\Session $session, \CoreLibs\Create\Session $session,
bool $auto_login = true array $options = []
) { ) {
// attach db class // attach db class
$this->db = $db; $this->db = $db;
@@ -202,6 +237,13 @@ class Login
// attach session class // attach session class
$this->session = $session; $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) // string key, msg: string, flag: e (error), o (ok)
$this->login_error_msg = [ $this->login_error_msg = [
'0' => [ '0' => [
@@ -332,14 +374,14 @@ class Login
'type' => $res['type'], 'type' => $res['type'],
'name' => $res['name'] 'name' => $res['name']
]; ];
$this->default_acl_list_type[$res['type']] = $res['level']; $this->default_acl_list_type[(string)$res['type']] = (int)$res['level'];
} }
// write that into the session // write that into the session
$_SESSION['DEFAULT_ACL_LIST'] = $this->default_acl_list; $_SESSION['DEFAULT_ACL_LIST'] = $this->default_acl_list;
$_SESSION['DEFAULT_ACL_LIST_TYPE'] = $this->default_acl_list_type; $_SESSION['DEFAULT_ACL_LIST_TYPE'] = $this->default_acl_list_type;
// this will be deprecated // this will be deprecated
if ($auto_login === true) { if ($this->options['auto_login'] === true) {
$this->loginMainCall(); $this->loginMainCall();
} }
} }
@@ -384,6 +426,192 @@ class Login
// **** PRIVATE INTERNAL // **** 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 * Checks for all flags and sets error codes for each
* In order: * In order:
@@ -691,6 +919,7 @@ class Login
// rgb: nnn.n for each // rgb: nnn.n for each
// hsl: nnn.n for first, nnn.n% for 2nd, 3rd // hsl: nnn.n for first, nnn.n% for 2nd, 3rd
// Check\Colors::validateColor() // Check\Colors::validateColor()
// LANGUAGE/LOCALE/ENCODING:
$_SESSION['LANG'] = $res['locale'] ?? 'en'; $_SESSION['LANG'] = $res['locale'] ?? 'en';
$_SESSION['DEFAULT_CHARSET'] = $res['encoding'] ?? 'UTF-8'; $_SESSION['DEFAULT_CHARSET'] = $res['encoding'] ?? 'UTF-8';
$_SESSION['DEFAULT_LOCALE'] = $_SESSION['LANG'] $_SESSION['DEFAULT_LOCALE'] = $_SESSION['LANG']
@@ -980,13 +1209,72 @@ class Login
// $this->debug('ACL', $this->print_ar($this->acl)); // $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 * checks if the password is in a valid format
* *
* @param string $password the new password * @param string $password the new password
* @return bool true or false if valid password or not * @return bool true or false if valid password or not
*/ */
private function loginPasswordChangeValidPassword($password): bool private function loginPasswordChangeValidPassword(string $password): bool
{ {
$is_valid_password = true; $is_valid_password = true;
// check for valid in regex arrays in list // check for valid in regex arrays in list
@@ -1048,7 +1336,7 @@ class Login
$res = $this->db->dbReturnRow($q); $res = $this->db->dbReturnRow($q);
if ( if (
!is_array($res) || !is_array($res) ||
(is_array($res) && empty($res['edit_user_id'])) empty($res['edit_user_id'])
) { ) {
// username wrong // username wrong
$this->login_error = 201; $this->login_error = 201;
@@ -1068,9 +1356,11 @@ class Login
} }
if ( if (
!is_array($res) || !is_array($res) ||
(is_array($res) && empty($res['edit_user_id']) ||
(empty($res['edit_user_id']) || !$this->loginPasswordCheck(
!$this->loginPasswordCheck($res['old_password_hash'], $this->pw_old_password))) $res['old_password_hash'],
$this->pw_old_password
)
) { ) {
// old password wrong // old password wrong
$this->login_error = 202; $this->login_error = 202;
@@ -1124,7 +1414,7 @@ class Login
* *
* @return string|null html data for login page, or null for nothing * @return string|null html data for login page, or null for nothing
*/ */
private function loginCreateLoginHTML() private function loginCreateLoginHTML(): ?string
{ {
$html_string = null; $html_string = null;
// if permission is ok, return null // if permission is ok, return null
@@ -1421,8 +1711,12 @@ EOM;
* @param string $username login user username * @param string $username login user username
* @return void has no return * @return void has no return
*/ */
private function writeLog(string $event, string $data, $error = '', string $username = ''): void private function writeLog(
{ string $event,
string $data,
string|int $error = '',
string $username = ''
): void {
if ($this->login) { if ($this->login) {
$this->action = 'Login'; $this->action = 'Login';
} elseif ($this->logout) { } elseif ($this->logout) {
@@ -1507,50 +1801,9 @@ EOM;
echo '<b>No active session found</b>'; echo '<b>No active session found</b>';
$this->loginTerminate(2000); $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 // set internal page name
$this->page_name = $this->loginReadPageName(); $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, // set global is ajax page for if we show the data directly,
// or need to pass it back // or need to pass it back
// to the continue AJAX class for output back to the user // to the continue AJAX class for output back to the user
@@ -1602,20 +1855,8 @@ EOM;
$this->pw_old_password = $_POST['pw_old_password'] ?? ''; $this->pw_old_password = $_POST['pw_old_password'] ?? '';
$this->pw_new_password = $_POST['pw_new_password'] ?? ''; $this->pw_new_password = $_POST['pw_new_password'] ?? '';
$this->pw_new_password_confirm = $_POST['pw_new_password_confirm'] ?? ''; $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 // disallow user list for password change
$this->pw_change_deny_users = ['admin']; $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 // max login counts before error reporting
$this->max_login_error_count = 10; $this->max_login_error_count = 10;
// users that never get locked, even if they are set strict // users that never get locked, even if they are set strict
@@ -1628,26 +1869,13 @@ EOM;
// logsout user // logsout user
$this->loginLogoutUser(); $this->loginLogoutUser();
// ** LANGUAGE SET AFTER LOGIN ** // ** LANGUAGE SET AFTER LOGIN **
// set the locale $this->loginSetLocale();
if ( // load translator
$this->session->checkActiveSession() === true && $this->l = new \CoreLibs\Language\L10n(
!empty($_SESSION['DEFAULT_LOCALE']) $this->locale['locale'],
) { $this->locale['domain'],
$locale = $_SESSION['DEFAULT_LOCALE']; $this->locale['path']
} 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);
// if the password change flag is okay, run the password change method // if the password change flag is okay, run the password change method
if ($this->password_change) { if ($this->password_change) {
$this->loginPasswordChange(); $this->loginPasswordChange();
@@ -1663,18 +1891,21 @@ EOM;
// if variable AJAX flag is not set, show output // if variable AJAX flag is not set, show output
// else pass through for ajax work // else pass through for ajax work
if ($this->login_is_ajax_page === false) { 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) { if ($this->login_html !== null) {
// echo $this->login_html; // echo $this->login_html;
$this->loginPrintLogin(); $this->loginPrintLogin();
} }
// do not go anywhere, quit processing here // do not go anywhere, quit processing here
// do something with possible debug data? // do something with possible debug data?
if (TARGET == 'live' || TARGET == 'remote') { if (
in_array($this->options['target'], ['live', 'remove'])
) {
// login // login
$this->log->setLogLevelAll('debug', DEBUG ? true : false); $this->log->setLogLevelAll('debug', $this->options['debug']);
$this->log->setLogLevelAll('echo', false); $this->log->setLogLevelAll('echo', false);
$this->log->setLogLevelAll('print', DEBUG ? true : false); $this->log->setLogLevelAll('print', $this->options['debug']);
} }
$status_msg = $this->log->printErrorMsg(); $status_msg = $this->log->printErrorMsg();
// if ($this->echo_output_all) { // if ($this->echo_output_all) {
@@ -1794,10 +2025,9 @@ EOM;
// check that numeric, positive numeric, not longer than max input string lenght // check that numeric, positive numeric, not longer than max input string lenght
// and not short than min password length // and not short than min password length
if ( if (
is_numeric($length) &&
$length >= $this->password_min_length_max && $length >= $this->password_min_length_max &&
$length <= $this->password_max_length && $length <= $this->password_max_length &&
$length <= 255 $length <= self::PASSWORD_MAX_LENGTH
) { ) {
$this->password_min_length = $length; $this->password_min_length = $length;
return true; return true;
@@ -2069,9 +2299,12 @@ EOM;
* @param string $type Type name to look in the acl list * @param string $type Type name to look in the acl list
* @return int|bool Either int level or false for not found * @return int|bool Either int level or false for not found
*/ */
public function loginGetAclListFromType(string $type) public function loginGetAclListFromType(string $type): int|bool
{ {
return $this->default_acl_list_type[$type] ?? false; if (!isset($this->default_acl_list_type[$type])) {
return false;
}
return (int)$this->default_acl_list_type[$type];
} }
/** /**
@@ -2081,7 +2314,7 @@ EOM;
* @return bool true/false: if the edit access is not * @return bool true/false: if the edit access is not
* in the valid list: false * in the valid list: false
*/ */
public function loginCheckEditAccess($edit_access_id): bool public function loginCheckEditAccess(?int $edit_access_id): bool
{ {
if ($edit_access_id === null) { if ($edit_access_id === null) {
return false; return false;
@@ -2122,8 +2355,10 @@ EOM;
* @param string|int $data_key key value to search for * @param string|int $data_key key value to search for
* @return bool|string false for not found or string for found data * @return bool|string false for not found or string for found data
*/ */
public function loginGetEditAccessData(int $edit_access_id, $data_key) public function loginGetEditAccessData(
{ int $edit_access_id,
string|int $data_key
): bool|string {
if (!isset($_SESSION['UNIT'][$edit_access_id]['data'][$data_key])) { if (!isset($_SESSION['UNIT'][$edit_access_id]['data'][$data_key])) {
return false; return false;
} }
@@ -2137,9 +2372,12 @@ EOM;
* @param string $uid Edit Access UID to look for * @param string $uid Edit Access UID to look for
* @return int|bool Either primary key in int or false in bool for not found * @return int|bool Either primary key in int or false in bool for not found
*/ */
public function loginGetEditAccessIdFromUid(string $uid) public function loginGetEditAccessIdFromUid(string $uid): int|bool
{ {
return $_SESSION['UNIT_UID'][$uid] ?? false; if (!isset($_SESSION['UNIT_UID'][$uid])) {
return false;
}
return (int)$_SESSION['UNIT_UID'][$uid];
} }
/** /**
@@ -2204,10 +2442,59 @@ EOM;
* @param string|int $data_key * @param string|int $data_key
* @return bool|string * @return bool|string
*/ */
public function loginSetEditAccessData(int $edit_access_id, $data_key) public function loginSetEditAccessData(
{ int $edit_access_id,
string|int $data_key
): bool|string {
return $this->loginGetEditAccessData($edit_access_id, $data_key); 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 $this->euid;
}
} }
// __END__ // __END__

View File

@@ -121,14 +121,14 @@ class Backend
* @param \CoreLibs\Debug\Logging $log Logging class * @param \CoreLibs\Debug\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class * @param \CoreLibs\Create\Session $session Session interface class
* @param \CoreLibs\Language\L10n $l10n l10n language 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( public function __construct(
\CoreLibs\DB\IO $db, \CoreLibs\DB\IO $db,
\CoreLibs\Debug\Logging $log, \CoreLibs\Debug\Logging $log,
\CoreLibs\Create\Session $session, \CoreLibs\Create\Session $session,
\CoreLibs\Language\L10n $l10n, \CoreLibs\Language\L10n $l10n,
array $locale ?int $set_default_acl_level = null
) { ) {
// attach db class // attach db class
$this->db = $db; $this->db = $db;
@@ -141,12 +141,12 @@ class Backend
// get the language sub class & init it // get the language sub class & init it
$this->l = $l10n; $this->l = $l10n;
// parse and read, legacy stuff // parse and read, legacy stuff
$locale = $this->l->getLocaleAsArray();
$this->encoding = $locale['encoding']; $this->encoding = $locale['encoding'];
$this->lang = $locale['lang']; $this->lang = $locale['lang'];
// get first part from lang $this->lang_short = $locale['lang_short'];
$this->lang_short = explode('_', $locale['lang'])[0]; $this->domain = $locale['domain'];
$this->domain = $this->l->getDomain(); $this->lang_dir = $locale['path'];
$this->lang_dir = $this->l->getBaseLocalePath();
// set the page name // set the page name
$this->page_name = \CoreLibs\Get\System::getPageName(); $this->page_name = \CoreLibs\Get\System::getPageName();
@@ -156,7 +156,14 @@ class Backend
$this->$_action = $_POST[$_action] ?? ''; $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 // queue key
if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action)) { 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 $event any kind of event description,
* @param string|array<mixed> $data any kind of data related to that event * @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 $write_type write type can bei STRING or BINARY
* @param string|null $db_schema override target schema
* @return void * @return void
*/ */
public function adbEditLog( public function adbEditLog(
string $event = '', string $event = '',
$data = '', string|array $data = '',
string $write_type = 'STRING' string $write_type = 'STRING',
?string $db_schema = null
): void { ): void {
$data_binary = ''; $data_binary = '';
$data_write = '';
if ($write_type == 'BINARY') { if ($write_type == 'BINARY') {
$data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data))); $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') { if ($write_type == 'STRING') {
$data_binary = ''; $data_binary = '';
$data = $this->db->dbEscapeString(serialize($data)); $data_write = $this->db->dbEscapeString(serialize($data));
} }
// check schema /** @var string $DB_SCHEMA check schema */
$SCHEMA = 'public'; $DB_SCHEMA = 'public';
/** @phpstan-ignore-next-line */ if ($db_schema !== null) {
if (defined('LOGIN_DB_SCHEMA') && !empty(LOGIN_DB_SCHEMA)) { $DB_SCHEMA = $db_schema;
$SCHEMA = LOGIN_DB_SCHEMA; } elseif (!empty($this->db->dbGetSchema())) {
} elseif ($this->db->dbGetSchema()) { $DB_SCHEMA = $this->db->dbGetSchema();
$SCHEMA = $this->db->dbGetSchema();
} elseif (defined('PUBLIC_SCHEMA')) {
$SCHEMA = PUBLIC_SCHEMA;
} }
/** @phpstan-ignore-next-line for whatever reason $SCHEMA is seen as possible array */ $q = "INSERT INTO " . $DB_SCHEMA . ".edit_log "
$q = "INSERT INTO " . $SCHEMA . ".edit_log "
. "(euid, event_date, event, data, data_binary, page, " . "(euid, event_date, event, data, data_binary, page, "
. "ip, user_agent, referer, script_name, query_string, server_name, http_host, " . "ip, user_agent, referer, script_name, query_string, server_name, http_host, "
. "http_accept, http_accept_charset, http_accept_encoding, session_id, " . "http_accept, http_accept_charset, http_accept_encoding, session_id, "
@@ -229,10 +235,12 @@ class Backend
'NULL') 'NULL')
. ", " . ", "
. "NOW(), " . "NOW(), "
. "'" . $this->db->dbEscapeString((string)$event) . "', '" . $data . "', " . "'" . $this->db->dbEscapeString((string)$event) . "', "
. "'" . $data_binary . "', '" . $this->db->dbEscapeString((string)$this->page_name) . "', " . "'" . $data_write . "', "
. "'" . @$_SERVER["REMOTE_ADDR"] . "', " . "'" . $data_binary . "', "
. "'" . $this->db->dbEscapeString(@$_SERVER['HTTP_USER_AGENT']) . "', " . "'" . $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['HTTP_REFERER'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['SCRIPT_FILENAME'] ?? '') . "', " . "'" . $this->db->dbEscapeString($_SERVER['SCRIPT_FILENAME'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['QUERY_STRING'] ?? '') . "', " . "'" . $this->db->dbEscapeString($_SERVER['QUERY_STRING'] ?? '') . "', "
@@ -262,7 +270,7 @@ class Backend
* @param string|int $menu_show_flag * @param string|int $menu_show_flag
* @return string|int * @return string|int
*/ */
public function adbSetMenuShowFlag($menu_show_flag) public function adbSetMenuShowFlag(string|int $menu_show_flag): string|int
{ {
// must be string or int // must be string or int
$this->menu_show_flag = $menu_show_flag; $this->menu_show_flag = $menu_show_flag;
@@ -274,7 +282,7 @@ class Backend
* *
* @return string|int * @return string|int
*/ */
public function adbGetMenuShowFlag() public function adbGetMenuShowFlag(): string|int
{ {
return $this->menu_show_flag; return $this->menu_show_flag;
} }
@@ -282,11 +290,25 @@ class Backend
/** /**
* menu creater (from login menu session pages) * 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) * @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) { if ($this->menu_show_flag) {
$flag = $this->menu_show_flag; $flag = $this->menu_show_flag;
} }
@@ -377,7 +399,7 @@ class Backend
\CoreLibs\Get\System::getPageName() == $data['filename'] && \CoreLibs\Get\System::getPageName() == $data['filename'] &&
(!isset($data['hostname']) || ( (!isset($data['hostname']) || (
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; $selected = 1;
@@ -427,69 +449,6 @@ class Backend
}; };
return $enabled; 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, $key, $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($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 = ''
) {
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 * wrapper function to fill up the mssages array
* *
@@ -523,15 +482,16 @@ class Backend
/** /**
* writes live queue * writes live queue
* *
* @param string $queue_key string to identfy the queue * @param string $queue_key string to identfy the queue
* @param string $type [description] * @param string $type [description]
* @param string $target [description] * @param string $target [description]
* @param string $data [description] * @param string $data [description]
* @param string $key_name [description] * @param string $key_name [description]
* @param string $key_value [description] * @param string $key_value [description]
* @param ?string $associate [description] * @param string|null $associate [description]
* @param ?string $file [description] * @param string|null $file [description]
* @return void has no return * @param string|null $db_schema override target schema
* @return void
*/ */
public function adbLiveQueue( public function adbLiveQueue(
string $queue_key, string $queue_key,
@@ -541,19 +501,17 @@ class Backend
string $key_name, string $key_name,
string $key_value, string $key_value,
string $associate = null, string $associate = null,
string $file = null string $file = null,
string $db_schema = null,
): void { ): void {
/** @phpstan-ignore-next-line */ /** @var string $DB_SCHEMA check schema */
if (defined('GLOBAL_DB_SCHEMA') && !empty(GLOBAL_DB_SCHEMA)) { $DB_SCHEMA = 'public';
$SCHEMA = GLOBAL_DB_SCHEMA; if ($db_schema !== null) {
} elseif ($this->db->dbGetSchema()) { $DB_SCHEMA = $db_schema;
$SCHEMA = $this->db->dbGetSchema(); } elseif (!empty($this->db->dbGetSchema())) {
} elseif (defined('PUBLIC_SCHEMA')) { $DB_SCHEMA = $this->db->dbGetSchema();
$SCHEMA = PUBLIC_SCHEMA;
} else {
$SCHEMA = 'public';
} }
$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" . "queue_key, key_value, key_name, type, target, data, group_key, action, associate, file"
. ") VALUES (" . ") VALUES ("
. "'" . $this->db->dbEscapeString($queue_key) . "', '" . $this->db->dbEscapeString($key_value) . "', " . "'" . $this->db->dbEscapeString($queue_key) . "', '" . $this->db->dbEscapeString($key_value) . "', "
@@ -569,28 +527,28 @@ class Backend
* Basic class holds exact the same, except the Year/Month/Day/etc strings * Basic class holds exact the same, except the Year/Month/Day/etc strings
* are translated in this call * are translated in this call
* *
* @param int $year year YYYY * @param int|string $year year YYYY
* @param int $month month m * @param int|string $month month m
* @param int $day day d * @param int|string $day day d
* @param int $hour hour H * @param int|string $hour hour H
* @param int $min min i * @param int|string $min min i
* @param string $suffix additional info printed after the date time * @param string $suffix additional info printed after the date time
* variable in the drop down * variable in the drop down
* also used for ID in the on change JS call * also used for ID in the on change JS call
* @param int $min_steps default is 1 (minute), can set to anything, * @param int $min_steps default is 1 (minute), can set to anything,
* is used as sum up from 0 * is used as sum up from 0
* @param bool $name_pos_back default false, if set to true, * @param bool $name_pos_back default false, if set to true,
* the name will be printend * the name will be printend
* after the drop down and not before the drop down * after the drop down and not before the drop down
* @return string HTML formated strings for drop down lists * @return string HTML formated strings for drop down lists
* of date and time * of date and time
*/ */
public function adbPrintDateTime( public function adbPrintDateTime(
$year, int|string $year,
$month, int|string $month,
$day, int|string $day,
$hour, int|string $hour,
$min, int|string $min,
string $suffix = '', string $suffix = '',
int $min_steps = 1, int $min_steps = 1,
bool $name_pos_back = false bool $name_pos_back = false

View File

@@ -35,6 +35,8 @@ class EditBase
private $form; private $form;
/** @var \CoreLibs\Debug\Logging */ /** @var \CoreLibs\Debug\Logging */
public $log; public $log;
/** @var \CoreLibs\ACL\Login */
public $login;
/** /**
* construct form generator * construct form generator
@@ -42,18 +44,24 @@ class EditBase
* @param array<mixed> $db_config db config array, mandatory * @param array<mixed> $db_config db config array, mandatory
* @param \CoreLibs\Debug\Logging $log Logging class, null auto set * @param \CoreLibs\Debug\Logging $log Logging class, null auto set
* @param \CoreLibs\Language\L10n $l10n l10n language class, null auto set * @param \CoreLibs\Language\L10n $l10n l10n language class, null auto set
* @param array<string,string> $locale locale array from ::setLocale, * @param \CoreLibs\ACL\Login $login login class for ACL settings
* null auto set * @param array<string,mixed> $options Various settings options
*/ */
public function __construct( public function __construct(
array $db_config, array $db_config,
\CoreLibs\Debug\Logging $log, \CoreLibs\Debug\Logging $log,
\CoreLibs\Language\L10n $l10n, \CoreLibs\Language\L10n $l10n,
array $locale \CoreLibs\ACL\Login $login,
array $options
) { ) {
$this->log = $log; $this->log = $log;
$this->login = $login;
// smarty template engine (extended Translation version) // 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 // turn off set log per class
$log->setLogPer('class', false); $log->setLogPer('class', false);
@@ -62,7 +70,7 @@ class EditBase
$db_config, $db_config,
$log, $log,
$l10n, $l10n,
$locale $this->login->loginGetAcl()
); );
if ($this->form->mobile_phone) { if ($this->form->mobile_phone) {
echo "I am sorry, but this page cannot be viewed by a 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 * all edit pages
* *
* @param string $set_root
* @param string $set_content_path
* @return void * @return void
*/ */
private function editPageFlow(): void private function editPageFlow(
{ string $set_root,
string $set_content_path,
): void {
// set table width // set table width
$table_width = '100%'; $table_width = '100%';
// load call only if id is set // load call only if id is set
@@ -268,23 +280,16 @@ class EditBase
// MENU START // MENU START
// request some session vars // request some session vars
if (empty($_SESSION['HEADER_COLOR'])) { $this->DATA['HEADER_COLOR'] = $this->login->loginGetHeaderColor() ?? '#E0E2FF';
$this->DATA['HEADER_COLOR'] = '#E0E2FF'; $this->DATA['USER_NAME'] = $this->login->loginGetAcl()['user_name'] ?? '';
} else { $this->DATA['EUID'] = $this->login->loginGetEuid();
$this->DATA['HEADER_COLOR'] = $_SESSION['HEADER_COLOR']; $this->DATA['GROUP_NAME'] = $this->login->loginGetAcl()['group_name'] ?? '';
} $this->DATA['ACCESS_LEVEL'] = $this->login->loginGetAcl()['base'] ?? '';
$this->DATA['USER_NAME'] = $_SESSION['USER_NAME']; // below is old and to removed when edit_body.tpl is updates
$this->DATA['EUID'] = $_SESSION['EUID']; $this->DATA['GROUP_LEVEL'] = $this->DATA['ACCESS_LEVEL'];
$this->DATA['GROUP_NAME'] = $_SESSION['GROUP_NAME']; $PAGES = $this->login->loginGetPages();
$this->DATA['GROUP_LEVEL'] = $_SESSION['GROUP_ACL_LEVEL'];
$PAGES = $_SESSION['PAGES'];
//$this->form->log->debug('menu', $this->form->log->prAr($PAGES)); //$this->form->log->debug('menu', $this->form->log->prAr($PAGES));
// build nav from $PAGES ...
if (!isset($PAGES) || !is_array($PAGES)) {
$PAGES = [];
}
$menuarray = []; $menuarray = [];
foreach ($PAGES as $PAGE_CUID => $PAGE_DATA) { foreach ($PAGES as $PAGE_CUID => $PAGE_DATA) {
if ($PAGE_DATA['menu'] && $PAGE_DATA['online']) { if ($PAGE_DATA['menu'] && $PAGE_DATA['online']) {
@@ -334,7 +339,7 @@ class EditBase
$menu_element['filename'] == \CoreLibs\Get\System::getPageName() && $menu_element['filename'] == \CoreLibs\Get\System::getPageName() &&
(!isset($menu_element['hostname']) || ( (!isset($menu_element['hostname']) || (
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; $position = $i;
@@ -431,7 +436,7 @@ class EditBase
$search_glob = []; $search_glob = [];
foreach ($folders as $folder) { foreach ($folders as $folder) {
// make sure this folder actually exists // make sure this folder actually exists
if (is_dir(ROOT . $folder)) { if (is_dir($set_root . $folder)) {
foreach ($files as $file) { foreach ($files as $file) {
$search_glob[] = $folder . $file; $search_glob[] = $folder . $file;
} }
@@ -534,31 +539,74 @@ class EditBase
* @throws Exception * @throws Exception
* @throws SmartyException * @throws SmartyException
*/ */
public function editBaseRun() 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 // set the template dir
// WARNING: this has a special check for the mailing tool layout (old layout) // WARNING: this has a special check for the mailing tool layout (old no layout folder)
if (defined('LAYOUT')) { if (!defined('LAYOUT')) {
$this->smarty->setTemplateDir(BASE . INCLUDES . TEMPLATES . CONTENT_PATH); trigger_error(
$this->DATA['css'] = LAYOUT . CSS; 'EditBase with unset LAYOUT is deprecated',
$this->DATA['js'] = LAYOUT . JS; E_USER_DEPRECATED
} else { );
$this->smarty->setTemplateDir(TEMPLATES); $this->smarty->setTemplateDir(TEMPLATES);
$this->DATA['css'] = CSS; $this->DATA['css'] = CSS;
$this->DATA['js'] = JS; $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 // define all needed smarty stuff for the general HTML/page building
$this->HEADER['CSS'] = CSS; $this->HEADER['CSS'] = $set_css;
$this->HEADER['DEFAULT_ENCODING'] = DEFAULT_ENCODING; $this->HEADER['DEFAULT_ENCODING'] = $set_default_encoding;
/** @phpstan-ignore-next-line because ADMIN_STYLESHEET can be null */ $this->HEADER['STYLESHEET'] = $set_admin_stylesheet;
$this->HEADER['STYLESHEET'] = $ADMIN_STYLESHEET ?? ADMIN_STYLESHEET;
// main run // main run
if ($this->form->my_page_name == 'edit_order') { if ($this->form->my_page_name == 'edit_order') {
$this->editOrderPage(); $this->editOrderPage();
} else { } else {
$this->editPageFlow(); $this->editPageFlow(
$set_root,
$set_content_path
);
} }
// debug data, if DEBUG flag is on, this data is print out // debug data, if DEBUG flag is on, this data is print out
@@ -571,11 +619,11 @@ class EditBase
foreach ($CONTENT_DATA as $key => $value) { foreach ($CONTENT_DATA as $key => $value) {
$this->smarty->assign($key, $value); $this->smarty->assign($key, $value);
} }
if (is_dir(BASE . TEMPLATES_C)) { if (is_dir($compile_dir)) {
$this->smarty->setCompileDir(BASE . TEMPLATES_C); $this->smarty->setCompileDir($compile_dir);
} }
if (is_dir(BASE . CACHE)) { if (is_dir($cache_dir)) {
$this->smarty->setCacheDir(BASE . CACHE); $this->smarty->setCacheDir($cache_dir);
} }
$this->smarty->display( $this->smarty->display(
$this->EDIT_TEMPLATE, $this->EDIT_TEMPLATE,

View File

@@ -672,9 +672,6 @@ class Basic
public static function arrayToString(array $array, string $connect_char): string public static function arrayToString(array $array, string $connect_char): string
{ {
trigger_error('Method ' . __METHOD__ . ' is deprecated, use join()', E_USER_DEPRECATED); trigger_error('Method ' . __METHOD__ . ' is deprecated, use join()', E_USER_DEPRECATED);
if (!is_array($array)) {
$array = [];
}
return join($connect_char, $array); return join($connect_char, $array);
} }
@@ -992,7 +989,7 @@ class Basic
int $jpeg_quality = 80 int $jpeg_quality = 80
) { ) {
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Output\Image::createThumbnailSimple()', E_USER_DEPRECATED); 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);
} }
/** /**

View File

@@ -42,8 +42,11 @@ class Colors
* @param int|false $hsl_flag flag to check for hsl type * @param int|false $hsl_flag flag to check for hsl type
* @return bool True if no error, False if error * @return bool True if no error, False if error
*/ */
private static function rgbHslContentCheck(string $color, $rgb_flag, $hsl_flag): bool private static function rgbHslContentCheck(
{ string $color,
int|false $rgb_flag,
int|false $hsl_flag
): bool {
// extract string between () and split into elements // extract string between () and split into elements
preg_match("/\((.*)\)/", $color, $matches); preg_match("/\((.*)\)/", $color, $matches);
if ( if (

View File

@@ -25,7 +25,7 @@ class Encoding
* if null is set then "none" * if null is set then "none"
* @return void * @return void
*/ */
public static function setErrorChar($string): void public static function setErrorChar(string|int|null $string): void
{ {
if (empty($string)) { if (empty($string)) {
$string = 'none'; $string = 'none';
@@ -52,7 +52,7 @@ class Encoding
* directly * directly
* @return string|int Set error character * @return string|int Set error character
*/ */
public static function getErrorChar(bool $return_substitute_func = false) public static function getErrorChar(bool $return_substitute_func = false): string|int
{ {
// return mb_substitute_character(); // return mb_substitute_character();
if ($return_substitute_func === true) { if ($return_substitute_func === true) {
@@ -78,14 +78,14 @@ class Encoding
* @param string $string string to test * @param string $string string to test
* @param string $from_encoding encoding of string to test * @param string $from_encoding encoding of string to test
* @param string $to_encoding target encoding * @param string $to_encoding target encoding
* @return bool|array<string> false if no error or * @return array<string>|false false if no error or
* array with failed characters * array with failed characters
*/ */
public static function checkConvertEncoding( public static function checkConvertEncoding(
string $string, string $string,
string $from_encoding, string $from_encoding,
string $to_encoding string $to_encoding
) { ): array|false {
// convert to target encoding and convert back // convert to target encoding and convert back
$temp = mb_convert_encoding($string, $to_encoding, $from_encoding); $temp = mb_convert_encoding($string, $to_encoding, $from_encoding);
$compare = mb_convert_encoding($temp, $from_encoding, $to_encoding); $compare = mb_convert_encoding($temp, $from_encoding, $to_encoding);

View File

@@ -1,41 +0,0 @@
<?php
/*
* DEPRECATED: Use correct Convert\Json:: instead
*/
declare(strict_types=1);
namespace CoreLibs\Check;
use CoreLibs\Convert\Json;
class Jason
{
/**
* @param string|null $json a json string, or null data
* @param bool $override if set to true, then on json error
* set original value as array
* @return array<mixed> returns an array from the json values
* @deprecated Use Json::jsonConvertToArray()
*/
public static function jsonConvertToArray(?string $json, bool $override = false): array
{
return Json::jsonConvertToArray($json, $override);
}
/**
* @param bool|boolean $return_string [default=false] if set to true
* it will return the message string and not
* the error number
* @return int|string Either error number (0 for no error)
* or error string ('' for no error)
* @deprecated Use Json::jsonGetLastError()
*/
public static function jsonGetLastError(bool $return_string = false)
{
return Json::jsonGetLastError($return_string);
}
}
// __END__

View File

@@ -21,12 +21,12 @@ class ArrayHandler
* the needle can be found in the * the needle can be found in the
* haystack array * haystack array
*/ */
public static function arraySearchRecursive($needle, array $haystack, ?string $key_search_for = null): array public static function arraySearchRecursive(
{ string|int $needle,
array $haystack,
?string $key_search_for = null
): array {
$path = []; $path = [];
if (!is_array($haystack)) {
$haystack = [];
}
if ( if (
$key_search_for != null && $key_search_for != null &&
array_key_exists($key_search_for, $haystack) && array_key_exists($key_search_for, $haystack) &&
@@ -72,7 +72,7 @@ class ArrayHandler
* *
* @param string|int $needle needle (search for) * @param string|int $needle needle (search for)
* @param array<mixed> $haystack haystack (search in) * @param array<mixed> $haystack haystack (search in)
* @param string|int $key_search_for the key to look for in * @param string|int|null $key_search_for the key to look for in
* @param bool $old [true], if set to false will * @param bool $old [true], if set to false will
* return new flat layout * return new flat layout
* @param array<mixed>|null $path recursive call for previous path * @param array<mixed>|null $path recursive call for previous path
@@ -80,9 +80,9 @@ class ArrayHandler
* the element was found * the element was found
*/ */
public static function arraySearchRecursiveAll( public static function arraySearchRecursiveAll(
$needle, string|int $needle,
array $haystack, array $haystack,
$key_search_for, string|int|null $key_search_for,
bool $old = true, bool $old = true,
?array $path = null ?array $path = null
): ?array { ): ?array {
@@ -101,10 +101,6 @@ class ArrayHandler
$path['work'] = []; $path['work'] = [];
} }
} }
// should not be needed because it would trigger a php mehtod error
if (!is_array($haystack)) {
$haystack = [];
}
// go through the array, // go through the array,
foreach ($haystack as $_key => $_value) { foreach ($haystack as $_key => $_value) {
@@ -152,17 +148,18 @@ class ArrayHandler
* array search simple. looks for key, value combination, if found, returns true * array search simple. looks for key, value combination, if found, returns true
* on default does not strict check, so string '4' will match int 4 and vica versa * on default does not strict check, so string '4' will match int 4 and vica versa
* *
* @param array<mixed> $array search in as array * @param array<mixed> $array search in as array
* @param string|int $key key (key to search in) * @param string|int $key key (key to search in)
* @param string|int $value value (what to find) * @param string|int|bool $value value (what to find)
* @param bool $strict [false], if set to true, will strict check key/value * @param bool $strict [false], if set to true, will strict check key/value
* @return bool true on found, false on not found * @return bool true on found, false on not found
*/ */
public static function arraySearchSimple(array $array, $key, $value, bool $strict = false): bool public static function arraySearchSimple(
{ array $array,
if (!is_array($array)) { string|int $key,
$array = []; string|int|bool $value,
} bool $strict = false
): bool {
foreach ($array as $_key => $_value) { foreach ($array as $_key => $_value) {
// if value is an array, we search // if value is an array, we search
if (is_array($_value)) { if (is_array($_value)) {
@@ -189,9 +186,9 @@ class ArrayHandler
* bool key flag: true: handle keys as string or int * bool key flag: true: handle keys as string or int
* default false: all keys are string * default false: all keys are string
* *
* @return array<mixed>|bool merged array * @return array<mixed>|false merged array
*/ */
public static function arrayMergeRecursive() public static function arrayMergeRecursive(): array|false
{ {
// croak on not enough arguemnts (we need at least two) // croak on not enough arguemnts (we need at least two)
if (func_num_args() < 2) { if (func_num_args() < 2) {
@@ -264,10 +261,10 @@ class ArrayHandler
* @param array<mixed> $needle elements to search for * @param array<mixed> $needle elements to search for
* @param array<mixed> $haystack array where the $needle elements should * @param array<mixed> $haystack array where the $needle elements should
* be searched int * be searched int
* @return array<mixed>|bool either the found elements or * @return array<mixed>|false either the found elements or
* false for nothing found or error * false for nothing found or error
*/ */
public static function inArrayAny(array $needle, array $haystack) public static function inArrayAny(array $needle, array $haystack): array|false
{ {
$found = []; $found = [];
foreach ($needle as $element) { foreach ($needle as $element) {
@@ -291,8 +288,12 @@ class ArrayHandler
* @param bool $set_only flag to return all (default), or set only * @param bool $set_only flag to return all (default), or set only
* @return array<mixed> associative array * @return array<mixed> associative array
*/ */
public static function genAssocArray(array $db_array, $key, $value, bool $set_only = false): array public static function genAssocArray(
{ array $db_array,
string|int|bool $key,
string|int|bool $value,
bool $set_only = false
): array {
$ret_array = []; $ret_array = [];
// do this to only run count once // do this to only run count once
for ($i = 0, $iMax = count($db_array); $i < $iMax; $i++) { for ($i = 0, $iMax = count($db_array); $i < $iMax; $i++) {
@@ -385,11 +386,8 @@ class ArrayHandler
* and will be pushed up * and will be pushed up
* @return array<mixed> modified, flattened array * @return array<mixed> modified, flattened array
*/ */
public static function arrayFlatForKey(array $array, $search): array public static function arrayFlatForKey(array $array, string|int $search): array
{ {
if (!is_array($array)) {
$array = [];
}
foreach ($array as $key => $value) { foreach ($array as $key => $value) {
// if it is not an array do just nothing // if it is not an array do just nothing
if (!is_array($value)) { if (!is_array($value)) {

View File

@@ -74,7 +74,7 @@ class DateTime
* @return string formated date+time in Y-M-D h:m:s ms * @return string formated date+time in Y-M-D h:m:s ms
*/ */
public static function dateStringFormat( public static function dateStringFormat(
$timestamp, int|float $timestamp,
bool $show_micro = false, bool $show_micro = false,
bool $micro_as_float = false bool $micro_as_float = false
): string { ): string {
@@ -100,8 +100,10 @@ class DateTime
* @param bool $show_micro show micro seconds, default true * @param bool $show_micro show micro seconds, default true
* @return string interval formatted string or string as is * @return string interval formatted string or string as is
*/ */
public static function timeStringFormat($timestamp, bool $show_micro = true): string public static function timeStringFormat(
{ string|int|float $timestamp,
bool $show_micro = true
): string {
// check if the timestamp has any h/m/s/ms inside, if yes skip // check if the timestamp has any h/m/s/ms inside, if yes skip
if (!preg_match("/(h|m|s|ms)/", (string)$timestamp)) { if (!preg_match("/(h|m|s|ms)/", (string)$timestamp)) {
list($timestamp, $ms) = array_pad(explode('.', (string)round((float)$timestamp, 4)), 2, null); list($timestamp, $ms) = array_pad(explode('.', (string)round((float)$timestamp, 4)), 2, null);
@@ -157,7 +159,7 @@ class DateTime
* @param string|int|float $timestring formatted interval * @param string|int|float $timestring formatted interval
* @return string|int|float converted float interval, or string as is * @return string|int|float converted float interval, or string as is
*/ */
public static function stringToTime($timestring) public static function stringToTime(string|int|float $timestring): string|int|float
{ {
$timestamp = 0; $timestamp = 0;
if (preg_match("/(d|h|m|s|ms)/", (string)$timestring)) { if (preg_match("/(d|h|m|s|ms)/", (string)$timestring)) {
@@ -247,9 +249,9 @@ class DateTime
* @param string $date a date string in the format YYYY-MM-DD * @param string $date a date string in the format YYYY-MM-DD
* @return bool true if valid date, false if date not valid * @return bool true if valid date, false if date not valid
*/ */
public static function checkDate($date): bool public static function checkDate(string $date): bool
{ {
if (!$date) { if (empty($date)) {
return false; return false;
} }
list ($year, $month, $day) = array_pad( list ($year, $month, $day) = array_pad(
@@ -324,7 +326,7 @@ class DateTime
* @return int|bool false on error * @return int|bool false on error
* or int -1 (s<e)/0 (s=e)/1 (s>e) as difference * or int -1 (s<e)/0 (s=e)/1 (s>e) as difference
*/ */
public static function compareDate($start_date, $end_date) public static function compareDate(string $start_date, string $end_date): int|bool
{ {
// pre check for empty or wrong // pre check for empty or wrong
if ($start_date == '--' || $end_date == '--' || !$start_date || !$end_date) { if ($start_date == '--' || $end_date == '--' || !$start_date || !$end_date) {
@@ -367,7 +369,7 @@ class DateTime
* @return int|bool false for error * @return int|bool false for error
* or -1 (s<e)/0 (s=e)/1 (s>e) as difference * or -1 (s<e)/0 (s=e)/1 (s>e) as difference
*/ */
public static function compareDateTime($start_datetime, $end_datetime) public static function compareDateTime(string $start_datetime, string $end_datetime): int|bool
{ {
// pre check for empty or wrong // pre check for empty or wrong
if ($start_datetime == '--' || $end_datetime == '--' || !$start_datetime || !$end_datetime) { if ($start_datetime == '--' || $end_datetime == '--' || !$start_datetime || !$end_datetime) {
@@ -402,8 +404,11 @@ class DateTime
* @param bool $return_named return array type, false (default), true for named * @param bool $return_named return array type, false (default), true for named
* @return array<mixed> 0/overall, 1/weekday, 2/weekend * @return array<mixed> 0/overall, 1/weekday, 2/weekend
*/ */
public static function calcDaysInterval($start_date, $end_date, bool $return_named = false): array public static function calcDaysInterval(
{ string $start_date,
string $end_date,
bool $return_named = false
): array {
// pos 0 all, pos 1 weekday, pos 2 weekend // pos 0 all, pos 1 weekday, pos 2 weekend
$days = []; $days = [];
// if anything invalid, return 0,0,0 // if anything invalid, return 0,0,0

View File

@@ -39,7 +39,7 @@ class Byte
* @return string converted byte number (float) with suffix * @return string converted byte number (float) with suffix
* @throws \Exception 1: no valid flag set * @throws \Exception 1: no valid flag set
*/ */
public static function humanReadableByteFormat($bytes, int $flags = 0): string public static function humanReadableByteFormat(string|int|float $bytes, int $flags = 0): string
{ {
// if not numeric, return as is // if not numeric, return as is
if (is_numeric($bytes)) { if (is_numeric($bytes)) {
@@ -121,7 +121,7 @@ class Byte
* @return string|int|float converted value or original value * @return string|int|float converted value or original value
* @throws \Exception 1: no valid flag set * @throws \Exception 1: no valid flag set
*/ */
public static function stringByteFormat($number, int $flags = 0) public static function stringByteFormat(string|int|float $number, int $flags = 0): string|int|float
{ {
// use SI 1000 mod and not 1024 mod // use SI 1000 mod and not 1024 mod
if ($flags & self::BYTE_FORMAT_SI) { if ($flags & self::BYTE_FORMAT_SI) {

View File

@@ -31,8 +31,12 @@ class Colors
* @return string|bool rgb in hex values with leading # if set, * @return string|bool rgb in hex values with leading # if set,
* false for invalid color * false for invalid color
*/ */
public static function rgb2hex(int $red, int $green, int $blue, bool $hex_prefix = true) public static function rgb2hex(
{ int $red,
int $green,
int $blue,
bool $hex_prefix = true
): string|bool {
$hex_color = ''; $hex_color = '';
if ($hex_prefix === true) { if ($hex_prefix === true) {
$hex_color = '#'; $hex_color = '#';
@@ -61,7 +65,7 @@ class Colors
string $hexStr, string $hexStr,
bool $return_as_string = false, bool $return_as_string = false,
string $seperator = ',' string $seperator = ','
) { ): string|array|bool {
$hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string $hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string
if (!is_string($hexStr)) { if (!is_string($hexStr)) {
return false; return false;
@@ -99,7 +103,7 @@ class Colors
* @return array<int|float>|bool Hue, Sat, Brightness/Value * @return array<int|float>|bool Hue, Sat, Brightness/Value
* false for input value error * false for input value error
*/ */
public static function rgb2hsb(int $red, int $green, int $blue) public static function rgb2hsb(int $red, int $green, int $blue): array|bool
{ {
// check that rgb is from 0 to 255 // check that rgb is from 0 to 255
foreach (['red', 'green', 'blue'] as $c) { foreach (['red', 'green', 'blue'] as $c) {
@@ -146,7 +150,7 @@ class Colors
* @return array<int>|bool 0 red/1 green/2 blue array as 0-255 * @return array<int>|bool 0 red/1 green/2 blue array as 0-255
* false for input value error * false for input value error
*/ */
public static function hsb2rgb(float $H, float $S, float $V) public static function hsb2rgb(float $H, float $S, float $V): array|bool
{ {
// check that H is 0 to 359, 360 = 0 // check that H is 0 to 359, 360 = 0
// and S and V are 0 to 1 // and S and V are 0 to 1
@@ -232,7 +236,7 @@ class Colors
* @return array<float>|bool hue/sat/luminance * @return array<float>|bool hue/sat/luminance
* false for input value error * false for input value error
*/ */
public static function rgb2hsl(int $red, int $green, int $blue) public static function rgb2hsl(int $red, int $green, int $blue): array|bool
{ {
// check that rgb is from 0 to 255 // check that rgb is from 0 to 255
foreach (['red', 'green', 'blue'] as $c) { foreach (['red', 'green', 'blue'] as $c) {
@@ -285,11 +289,8 @@ class Colors
* @param float $lum luminance: 0-100 * @param float $lum luminance: 0-100
* @return array<int,float|int>|bool red/blue/green 0-255 each * @return array<int,float|int>|bool red/blue/green 0-255 each
*/ */
public static function hsl2rgb(float $hue, float $sat, float $lum) public static function hsl2rgb(float $hue, float $sat, float $lum): array|bool
{ {
if (!is_numeric($hue)) {
return false;
}
if ($hue == 360) { if ($hue == 360) {
$hue = 0; $hue = 0;
} }

View File

@@ -19,7 +19,7 @@ class Html
* @param mixed $string string to html encode * @param mixed $string string to html encode
* @return mixed if string, encoded, else as is (eg null) * @return mixed if string, encoded, else as is (eg null)
*/ */
public static function htmlent($string) public static function htmlent(mixed $string): mixed
{ {
if (is_string($string)) { if (is_string($string)) {
return htmlentities($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); return htmlentities($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
@@ -52,7 +52,7 @@ class Html
* @return ?string returns checked or selected, * @return ?string returns checked or selected,
* else returns null * else returns null
*/ */
public static function checked($haystack, string $needle, int $type = 0): ?string public static function checked(array|string $haystack, string $needle, int $type = 0): ?string
{ {
if (is_array($haystack)) { if (is_array($haystack)) {
if (in_array($needle, $haystack)) { if (in_array($needle, $haystack)) {

View File

@@ -51,13 +51,13 @@ class Json
/** /**
* returns human readable string for json errors thrown in jsonConvertToArray * returns human readable string for json errors thrown in jsonConvertToArray
* *
* @param bool|boolean $return_string [default=false] if set to true * @param bool $return_string [default=false] if set to true
* it will return the message string and not * it will return the message string and not
* the error number * the error number
* @return int|string Either error number (0 for no error) * @return int|string Either error number (0 for no error)
* or error string ('' for no error) * or error string ('' for no error)
*/ */
public static function jsonGetLastError(bool $return_string = false) public static function jsonGetLastError(bool $return_string = false): int|string
{ {
$json_error_string = ''; $json_error_string = '';
// valid errors as of php 8.0 // valid errors as of php 8.0

View File

@@ -48,7 +48,7 @@ class Math
* @param string|int|float $number string or number to check * @param string|int|float $number string or number to check
* @return float if not number, then returns 0, else original input * @return float if not number, then returns 0, else original input
*/ */
public static function initNumeric($number): float public static function initNumeric(string|int|float $number): float
{ {
if (!is_numeric($number)) { if (!is_numeric($number)) {
return 0; return 0;

View File

@@ -90,33 +90,6 @@ class Hash
{ {
return hash(self::STANDARD_HASH_LONG, $string); 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__ // __END__

View File

@@ -32,7 +32,7 @@ class RandomKey
* *
* @return void has no return * @return void has no return
*/ */
private static function initRandomKeyData() private static function initRandomKeyData(): void
{ {
// random key generation base string // random key generation base string
self::$key_range = join('', array_merge( self::$key_range = join('', array_merge(
@@ -52,7 +52,6 @@ class RandomKey
private static function validateRandomKeyLenght(int $key_length): bool private static function validateRandomKeyLenght(int $key_length): bool
{ {
if ( if (
is_numeric($key_length) &&
$key_length > 0 && $key_length > 0 &&
$key_length <= self::$max_key_length $key_length <= self::$max_key_length
) { ) {

View File

@@ -18,19 +18,6 @@ class Session
/** @var string list for errors */ /** @var string list for errors */
private $session_intern_error_str = ''; private $session_intern_error_str = '';
/**
* Start session
* startSession should be called for complete check
* If this is called without any name set before the php.ini name is
* used.
*
* @return void
*/
protected function startSessionCall(): void
{
session_start();
}
/** /**
* init a session, if array is empty or array does not have session_name set * init a session, if array is empty or array does not have session_name set
* then no auto init is run * then no auto init is run
@@ -44,6 +31,19 @@ class Session
} }
} }
/**
* Start session
* startSession should be called for complete check
* If this is called without any name set before the php.ini name is
* used.
*
* @return void
*/
protected function startSessionCall(): void
{
session_start();
}
/** /**
* check if we are in CLI, we set this, so we can mock this * check if we are in CLI, we set this, so we can mock this
* Not this is just a wrapper for the static System::checkCLI call * Not this is just a wrapper for the static System::checkCLI call
@@ -116,7 +116,7 @@ class Session
* @param string|null $session_name * @param string|null $session_name
* @return string|bool * @return string|bool
*/ */
public function startSession(?string $session_name = null) public function startSession(?string $session_name = null): string|bool
{ {
// we can't start sessions on command line // we can't start sessions on command line
if ($this->checkCliStatus()) { if ($this->checkCliStatus()) {
@@ -163,7 +163,7 @@ class Session
* *
* @return string|bool * @return string|bool
*/ */
public function getSessionId() public function getSessionId(): string|bool
{ {
return session_id(); return session_id();
} }
@@ -173,7 +173,7 @@ class Session
* *
* @return string|bool * @return string|bool
*/ */
public function getSessionName() public function getSessionName(): string|bool
{ {
return session_name(); return session_name();
} }
@@ -275,7 +275,7 @@ class Session
* @param mixed $value value to set (can be anything) * @param mixed $value value to set (can be anything)
* @return void * @return void
*/ */
public function setS($name, $value): void public function setS(string|int $name, mixed $value): void
{ {
$_SESSION[$name] = $value; $_SESSION[$name] = $value;
} }
@@ -286,7 +286,7 @@ class Session
* @param string|int $name value key to get from _SESSION * @param string|int $name value key to get from _SESSION
* @return mixed value stored in _SESSION * @return mixed value stored in _SESSION
*/ */
public function getS($name) public function getS(string|int $name): mixed
{ {
return $_SESSION[$name] ?? ''; return $_SESSION[$name] ?? '';
} }
@@ -297,7 +297,7 @@ class Session
* @param string|int $name Name to check for * @param string|int $name Name to check for
* @return bool True for set, False fornot set * @return bool True for set, False fornot set
*/ */
public function issetS($name): bool public function issetS(string|int $name): bool
{ {
return isset($_SESSION[$name]); return isset($_SESSION[$name]);
} }
@@ -308,7 +308,7 @@ class Session
* @param string|int $name _SESSION key name to remove * @param string|int $name _SESSION key name to remove
* @return void * @return void
*/ */
public function unsetS($name): void public function unsetS(string|int $name): void
{ {
if (isset($_SESSION[$name])) { if (isset($_SESSION[$name])) {
unset($_SESSION[$name]); unset($_SESSION[$name]);
@@ -325,7 +325,7 @@ class Session
* @param mixed $value * @param mixed $value
* @return void * @return void
*/ */
public function __set($name, $value): void public function __set(string|int $name, mixed $value): void
{ {
$_SESSION[$name] = $value; $_SESSION[$name] = $value;
} }
@@ -334,13 +334,14 @@ class Session
* Undocumented function * Undocumented function
* *
* @param string|int $name * @param string|int $name
* @return mixed * @return mixed If name is not found, it will return null
*/ */
public function __get($name) public function __get(string|int $name): mixed
{ {
if (isset($_SESSION[$name])) { if (isset($_SESSION[$name])) {
return $_SESSION[$name]; return $_SESSION[$name];
} }
return null;
} }
/** /**
@@ -349,7 +350,7 @@ class Session
* @param string|int $name * @param string|int $name
* @return bool * @return bool
*/ */
public function __isset($name): bool public function __isset(string|int $name): bool
{ {
return isset($_SESSION[$name]); return isset($_SESSION[$name]);
} }
@@ -360,7 +361,7 @@ class Session
* @param string|int $name * @param string|int $name
* @return void * @return void
*/ */
public function __unset($name): void public function __unset(string|int $name): void
{ {
if (isset($_SESSION[$name])) { if (isset($_SESSION[$name])) {
unset($_SESSION[$name]); unset($_SESSION[$name]);

View File

@@ -57,7 +57,7 @@ class ArrayIO extends \CoreLibs\DB\IO
* @param array<mixed> $db_config db connection config * @param array<mixed> $db_config db connection config
* @param array<mixed> $table_array table array config * @param array<mixed> $table_array table array config
* @param string $table_name table name string * @param string $table_name table name string
* @param \CoreLibs\Debug\Logging|null $log Logging class, default set if not set * @param \CoreLibs\Debug\Logging $log Logging class
* @param int $base_acl_level Set base acl level, if needed * @param int $base_acl_level Set base acl level, if needed
* @param int $acl_admin Flag if this is an admin ACL access level * @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 $db_config,
array $table_array, array $table_array,
string $table_name, string $table_name,
\CoreLibs\Debug\Logging $log = null, \CoreLibs\Debug\Logging $log,
int $base_acl_level = 0, int $base_acl_level = 0,
int $acl_admin = 0 int $acl_admin = 0
) { ) {
// instance db_io class // instance db_io class
parent::__construct($db_config, $log ?? new \CoreLibs\Debug\Logging()); parent::__construct($db_config, $log);
// more error vars for this class // more error vars for this class
$this->error_string['1999'] = 'No table array or table name set'; $this->error_string['1999'] = 'No table array or table name set';
$this->error_string['1021'] = 'No Primary Key given'; $this->error_string['1021'] = 'No Primary Key given';
@@ -137,7 +137,7 @@ class ArrayIO extends \CoreLibs\DB\IO
* @param string $text any html encoded string * @param string $text any html encoded string
* @return string decoded html string * @return string decoded html string
*/ */
public function convertData($text): string public function convertData(string $text): string
{ {
$text = str_replace('&lt;b&gt;', '<b>', $text); $text = str_replace('&lt;b&gt;', '<b>', $text);
$text = str_replace('&lt;/b&gt;', '</b>', $text); $text = str_replace('&lt;/b&gt;', '</b>', $text);
@@ -156,7 +156,7 @@ class ArrayIO extends \CoreLibs\DB\IO
* @param string $text encoded html string * @param string $text encoded html string
* @return string decoded html string * @return string decoded html string
*/ */
public function convertEntities($text): string public function convertEntities(string $text): string
{ {
$text = str_replace('&lt;', '<', $text); $text = str_replace('&lt;', '<', $text);
$text = str_replace('&gt;', '>', $text); $text = str_replace('&gt;', '>', $text);
@@ -172,7 +172,7 @@ class ArrayIO extends \CoreLibs\DB\IO
* @param bool $write write to error message, default false * @param bool $write write to error message, default false
* @return string the array data as html string entry * @return string the array data as html string entry
*/ */
public function dbDumpArray($write = false): string public function dbDumpArray(bool $write = false): string
{ {
reset($this->table_array); reset($this->table_array);
$string = ''; $string = '';
@@ -192,7 +192,7 @@ class ArrayIO extends \CoreLibs\DB\IO
* *
* @return bool true if pk value is set, else false * @return bool true if pk value is set, else false
*/ */
public function dbCheckPkSet() public function dbCheckPkSet(): bool
{ {
// if pk_id is set, overrule ... // if pk_id is set, overrule ...
if ($this->pk_id) { if ($this->pk_id) {
@@ -210,10 +210,10 @@ class ArrayIO extends \CoreLibs\DB\IO
/** /**
* resets the whole array values * resets the whole array values
* @param boolean $reset_pk true if we want to reset the pk too * @param bool $reset_pk true if we want to reset the pk too
* @return void has no return * @return void has no return
*/ */
public function dbResetArray($reset_pk = false): void public function dbResetArray(bool $reset_pk = false): void
{ {
reset($this->table_array); reset($this->table_array);
foreach (array_keys($this->table_array) as $column) { foreach (array_keys($this->table_array) as $column) {
@@ -230,10 +230,10 @@ class ArrayIO extends \CoreLibs\DB\IO
* *
* @param array<mixed> $table_array optional override for table array set * @param array<mixed> $table_array optional override for table array set
* set this as new table array too * set this as new table array too
* @param boolean $acl_limit [false], if set to true, well do ACL limit check * @param bool $acl_limit [false], if set to true, well do ACL limit check
* @return array<mixed> returns the table array that was deleted * @return array<mixed> returns the table array that was deleted
*/ */
public function dbDelete($table_array = [], $acl_limit = false) public function dbDelete(array $table_array = [], bool $acl_limit = false): array
{ {
// is array and has values, override set and set new // is array and has values, override set and set new
if (is_array($table_array) && count($table_array)) { if (is_array($table_array) && count($table_array)) {
@@ -294,12 +294,12 @@ class ArrayIO extends \CoreLibs\DB\IO
/** /**
* reads one row into the array * reads one row into the array
* *
* @param boolean $edit on true convert data, else as is * @param bool $edit on true convert data, else as is
* @param array<mixed> $table_array optional table array, overwrites * @param array<mixed> $table_array optional table array, overwrites
* internal set array * internal set array
* @return array<mixed> set table array with values * @return array<mixed> set table array with values
*/ */
public function dbRead($edit = false, $table_array = []) public function dbRead(bool $edit = false, array $table_array = []): array
{ {
// if array give, overrules internal array // if array give, overrules internal array
if (is_array($table_array) && count($table_array)) { if (is_array($table_array) && count($table_array)) {
@@ -381,9 +381,9 @@ class ArrayIO extends \CoreLibs\DB\IO
/** /**
* writes one set into DB or updates one set (if PK exists) * writes one set into DB or updates one set (if PK exists)
* *
* @param boolean $addslashes old convert entities and set set escape * @param bool $addslashes old convert entities and set set escape
* @param array<mixed> $table_array optional table array, overwrites internal one * @param array<mixed> $table_array optional table array, overwrites internal one
* @param boolean $acl_limit [false], if set to true, well do ACL limit check * @param bool $acl_limit [false], if set to true, well do ACL limit check
* @return array<mixed> table array or null * @return array<mixed> table array or null
*/ */
public function dbWrite( public function dbWrite(
@@ -391,7 +391,7 @@ class ArrayIO extends \CoreLibs\DB\IO
array $table_array = [], array $table_array = [],
bool $acl_limit = false bool $acl_limit = false
): array { ): array {
if (is_array($table_array) && count($table_array)) { if (count($table_array)) {
$this->table_array = $table_array; $this->table_array = $table_array;
} }
// PK ID check // PK ID check
@@ -475,13 +475,12 @@ class ArrayIO extends \CoreLibs\DB\IO
$this->table_array[$column]['type'] != 'view' && $this->table_array[$column]['type'] != 'view' &&
strlen($column) > 0 && strlen($column) > 0 &&
// no acl limiter // no acl limiter
($acl_limit === false ||
( (
$acl_limit === false ||
// acl limit is true, min edit must be at larger than set // acl limit is true, min edit must be at larger than set
$acl_limit === true &&
$this->base_acl_level >= $this->base_acl_level >=
($this->table_array[$column]['min_edit_acl'] ?? 100) ($this->table_array[$column]['min_edit_acl'] ?? 100)
)) )
) { ) {
// for password use hidden value if main is not set // for password use hidden value if main is not set
if ( if (
@@ -528,7 +527,7 @@ class ArrayIO extends \CoreLibs\DB\IO
} }
$q_data .= $_value; $q_data .= $_value;
} elseif (isset($this->table_array[$column]['bool'])) { } elseif (isset($this->table_array[$column]['bool'])) {
// boolean storeage (reverse check on ifset) // bool storage (reverse check on ifset)
$q_data .= "'" . $this->dbBoolean($this->table_array[$column]['value'], true) . "'"; $q_data .= "'" . $this->dbBoolean($this->table_array[$column]['value'], true) . "'";
} elseif ( } elseif (
isset($this->table_array[$column]['interval']) || isset($this->table_array[$column]['interval']) ||

View File

@@ -12,7 +12,7 @@
* 2013/10/10, prepare/excute were added, including auto RETURNING primary key if * 2013/10/10, prepare/excute were added, including auto RETURNING primary key if
* possible for any INSERT query in exec or prepare/execute, better debugging and * possible for any INSERT query in exec or prepare/execute, better debugging and
* data dumping. Proper string escape wrapper, special db exec writer for complex * data dumping. Proper string escape wrapper, special db exec writer for complex
* array inserts in auto calls. boolean converter from postresql to php * array inserts in auto calls. bool converter from postresql to php
* *
* 2003/12/08, one major change: renamed db_exec_ext to db_return, as it has not * 2003/12/08, one major change: renamed db_exec_ext to db_return, as it has not
* much in common with the normal db_exec wrapper, as it was written only for * much in common with the normal db_exec wrapper, as it was written only for
@@ -168,7 +168,7 @@
* - all HTML from the query data (color codes, etc) via flag to debug call * - all HTML from the query data (color codes, etc) via flag to debug call
* *
* HISTORY: * HISTORY:
* 2008/10/25 (cs) add db_boolean to fix the postgres to php boolean var problem * 2008/10/25 (cs) add db_boolean to fix the postgres to php bool var problem
* (TODO: implement this in any select return) * (TODO: implement this in any select return)
* 2008/07/03 (cs) add db_write_data function, original written for inventory tool "invSQLWriteData" * 2008/07/03 (cs) add db_write_data function, original written for inventory tool "invSQLWriteData"
* 2008/04/16 (cs) add db_escape_string function for correct string escape * 2008/04/16 (cs) add db_escape_string function for correct string escape
@@ -288,7 +288,7 @@ class IO
private $query; // the query string at the moment private $query; // the query string at the moment
// only inside // only inside
// basic vars // basic vars
/** @var object|resource|bool|int|null */ // replace object with PgSql\Connection| /** @var \PgSql\Connection|false|null */ // replace object with PgSql\Connection|
private $dbh; // the dbh handler, if disconnected by command is null, bool:false/int:-1 on error, private $dbh; // the dbh handler, if disconnected by command is null, bool:false/int:-1 on error,
/** @var bool */ /** @var bool */
private $db_debug = false; // DB_DEBUG ... (if set prints out debug msgs) private $db_debug = false; // DB_DEBUG ... (if set prints out debug msgs)
@@ -315,7 +315,7 @@ class IO
/** @var array<mixed,mixed> */ /** @var array<mixed,mixed> */
private $cursor_ext; // hash of hashes private $cursor_ext; // hash of hashes
// per query vars // per query vars
/** @var object|resource|bool */ // replace object with PgSql\Result /** @var \PgSql\Result|false */ // replace object with PgSql\Result
private $cursor; // actual cursor (DBH) private $cursor; // actual cursor (DBH)
/** @var int */ /** @var int */
private $num_rows; // how many rows have been found private $num_rows; // how many rows have been found
@@ -378,16 +378,16 @@ class IO
/** /**
* main DB concstructor with auto connection to DB and failure set on failed connection * main DB concstructor with auto connection to DB and failure set on failed connection
* @param array<mixed> $db_config DB configuration array * @param array<mixed> $db_config DB configuration array
* @param \CoreLibs\Debug\Logging|null $log Logging class * @param \CoreLibs\Debug\Logging $log Logging class
* @param bool|null $db_debug_override Overrides debug settings in db_config * @param bool|null $db_debug_override Overrides debug settings in db_config
*/ */
public function __construct( public function __construct(
array $db_config, array $db_config,
?\CoreLibs\Debug\Logging $log = null, \CoreLibs\Debug\Logging $log,
?bool $db_debug_override = null ?bool $db_debug_override = null
) { ) {
// attach logger // attach logger
$this->log = $log ?? new \CoreLibs\Debug\Logging(); $this->log = $log;
// sets the names (for connect/reconnect) // sets the names (for connect/reconnect)
$this->db_name = $db_config['db_name'] ?? ''; $this->db_name = $db_config['db_name'] ?? '';
$this->db_user = $db_config['db_user'] ?? ''; $this->db_user = $db_config['db_user'] ?? '';
@@ -405,9 +405,9 @@ class IO
$db_debug_override ?? $db_debug_override ??
// from db config setting // from db config setting
$db_config['db_debug'] ?? $db_config['db_debug'] ??
// should be handled from outside // [DEPRECATED] should be handled from outside
$_SESSION['DB_DEBUG'] ?? $_SESSION['DB_DEBUG'] ??
// globals should be deprecated // [DEPRECATED] globals should be deprecated
$GLOBALS['DB_DEBUG'] ?? $GLOBALS['DB_DEBUG'] ??
false false
); );
@@ -495,15 +495,15 @@ class IO
* OTOH this whole class is so PgSQL specific * OTOH this whole class is so PgSQL specific
* that non PgSQL doesn't make much sense anymore * that non PgSQL doesn't make much sense anymore
* *
* @return \CoreLibs\DB\SQL\PgSQL|null DB functions object or false on error * @return SQL\PgSQL|null DB functions object or false on error
*/ */
private function __loadDBFunctions() private function __loadDBFunctions(): SQL\PgSQL|null
{ {
$db_functions = null; $db_functions = null;
switch ($this->db_type) { switch ($this->db_type) {
// list of valid DB function objects // list of valid DB function objects
case 'pgsql': case 'pgsql':
$db_functions = new \CoreLibs\DB\SQL\PgSQL(); $db_functions = new SQL\PgSQL();
break; break;
// if non set or none matching abort // if non set or none matching abort
default: default:
@@ -566,7 +566,7 @@ class IO
*/ */
private function __closeDB(): void private function __closeDB(): void
{ {
if (!empty($this->dbh) && $this->dbh !== false) { if (!empty($this->dbh)) {
$this->db_functions->__dbClose(); $this->db_functions->__dbClose();
$this->dbh = null; $this->dbh = null;
} }
@@ -632,9 +632,6 @@ class IO
private function __printArray(array $array): string private function __printArray(array $array): string
{ {
$string = ''; $string = '';
if (!is_array($array)) {
$array = [];
}
foreach ($array as $key => $value) { foreach ($array as $key => $value) {
$string .= $this->nbsp . '<b>' . $key . '</b> => '; $string .= $this->nbsp . '<b>' . $key . '</b> => ';
if (is_array($value)) { if (is_array($value)) {
@@ -701,7 +698,7 @@ class IO
/** /**
* Check if there is a cursor and write this cursors error info * Check if there is a cursor and write this cursors error info
* @param object|resource|bool $cursor current cursor for pg_result_error, * @param \PgSql\Result|false $cursor current cursor for pg_result_error,
* pg_last_error too, but pg_result_error * pg_last_error too, but pg_result_error
* is more accurate (PgSql\Result) * is more accurate (PgSql\Result)
* @return array<mixed> Pos 0: if we could get the method where it was called * @return array<mixed> Pos 0: if we could get the method where it was called
@@ -709,7 +706,7 @@ class IO
* Pos 1: if we have the pg_error_string from last error * Pos 1: if we have the pg_error_string from last error
* if nothing then empty string * if nothing then empty string
*/ */
private function __dbErrorPreprocessor($cursor = false): array private function __dbErrorPreprocessor(\PgSql\Result|false $cursor = false): array
{ {
$pg_error_string = ''; $pg_error_string = '';
// 1 = self/__dbErrorPreprocessor, 2 = __dbError, __dbWarning, // 1 = self/__dbErrorPreprocessor, 2 = __dbError, __dbWarning,
@@ -774,12 +771,15 @@ class IO
/** /**
* write an error * write an error
* @param integer $error_id Any Error ID, used in debug message string * @param integer $error_id Any Error ID, used in debug message string
* @param object|resource|bool $cursor Optional cursor, passed on to preprocessor * @param \PgSql\Result|false $cursor Optional cursor, passed on to preprocessor
* @param string $msg optional message added to debug * @param string $msg optional message added to debug
* @return void * @return void
*/ */
protected function __dbError(int $error_id, $cursor = false, string $msg = ''): void protected function __dbError(
{ int $error_id,
\PgSql\Result|false $cursor = false,
string $msg = ''
): void {
$error_id = (string)$error_id; $error_id = (string)$error_id;
[$where_called, $pg_error_string] = $this->__dbErrorPreprocessor($cursor); [$where_called, $pg_error_string] = $this->__dbErrorPreprocessor($cursor);
// write error msg ... // write error msg ...
@@ -798,12 +798,15 @@ class IO
/** /**
* write a warning * write a warning
* @param integer $warning_id Integer warning id added to debug * @param integer $warning_id Integer warning id added to debug
* @param object|resource|bool $cursor Optional cursor, passed on to preprocessor * @param \PgSql\Result|false $cursor Optional cursor, passed on to preprocessor
* @param string $msg optional message added to debug * @param string $msg optional message added to debug
* @return void * @return void
*/ */
protected function __dbWarning(int $warning_id, $cursor = false, string $msg = ''): void protected function __dbWarning(
{ int $warning_id,
\PgSql\Result|false $cursor = false,
string $msg = ''
): void {
$warning_id = (string)$warning_id; $warning_id = (string)$warning_id;
[$where_called, $pg_error_string] = $this->__dbErrorPreprocessor($cursor); [$where_called, $pg_error_string] = $this->__dbErrorPreprocessor($cursor);
$this->__dbDebug( $this->__dbDebug(
@@ -821,18 +824,18 @@ class IO
/** /**
* if there is the 'to_encoding' var set, * if there is the 'to_encoding' var set,
* and the field is in the wrong encoding converts it to the target * and the field is in the wrong encoding converts it to the target
* @param array<mixed>|bool|null $row Array from fetch_row * @param array<mixed>|false $row Array from fetch_row
* @return array<mixed>|bool Convert fetch_row array, or false * @return array<mixed>|false Convert fetch_row array, or false
*/ */
private function __dbConvertEncoding($row) private function __dbConvertEncoding(array|false $row): array|false
{ {
if ($row === null) { if (is_bool($row)) {
return false; return false;
} }
// only do if array, else pass through row (can be false) // only do if array, else pass through row (can be false)
if ( if (
!is_array($row) || !is_array($row) ||
empty($this->to_encoding)// || empty($this->db_encoding) empty($this->to_encoding)
) { ) {
return $row; return $row;
} }
@@ -914,7 +917,7 @@ class IO
* check if there is another query running, or do we hang after a * check if there is another query running, or do we hang after a
* PHP error * PHP error
* @param integer $timeout_seconds For complex timeout waits, default 3 seconds * @param integer $timeout_seconds For complex timeout waits, default 3 seconds
* @return boolean True for connection OK, else false * @return bool True for connection OK, else false
*/ */
private function __dbCheckConnectionOk(int $timeout_seconds = 3): bool private function __dbCheckConnectionOk(int $timeout_seconds = 3): bool
{ {
@@ -932,7 +935,7 @@ class IO
* dbReturn * dbReturn
* Read data from previous written data cache * Read data from previous written data cache
* @param string $query_hash The hash for the current query * @param string $query_hash The hash for the current query
* @param boolean $assoc_only Only return assoc value (key named) * @param bool $assoc_only Only return assoc value (key named)
* @return array<mixed> Current position query data from cache * @return array<mixed> Current position query data from cache
*/ */
private function __dbReturnCacheRead(string $query_hash, bool $assoc_only): array private function __dbReturnCacheRead(string $query_hash, bool $assoc_only): array
@@ -983,10 +986,11 @@ class IO
* - sets internal hash for query * - sets internal hash for query
* - checks multiple call count * - checks multiple call count
* @param string $query query string * @param string $query query string
* @param string $pk_name primary key [if set to NULL no returning will be added] * @param string $pk_name primary key
* @return string|bool queryt hash OR boolean false on error * [if set to NULL no returning will be added]
* @return string|false queryt hash OR bool false on error
*/ */
private function __dbPrepareExec(string $query, string $pk_name) private function __dbPrepareExec(string $query, string $pk_name): string|false
{ {
// reset current cursor before exec // reset current cursor before exec
$this->cursor = false; $this->cursor = false;
@@ -1152,10 +1156,10 @@ class IO
* insert_id_ext [DEPRECATED, all in insert_id_arr] * insert_id_ext [DEPRECATED, all in insert_id_arr]
* - holds all returning as array * - holds all returning as array
* TODO: Only use insert_id_arr and use functions to get ok array or single * TODO: Only use insert_id_arr and use functions to get ok array or single
* @param boolean $returning_id * @param bool $returning_id
* @param string $query * @param string $query
* @param string|null $pk_name * @param string|null $pk_name
* @param object|resource|bool $cursor (PgSql\Result) * @param \PgSql\Result|false $cursor (PgSql\Result)
* @param string|null $stm_name If not null, is dbExecutre run * @param string|null $stm_name If not null, is dbExecutre run
* @return void * @return void
*/ */
@@ -1163,7 +1167,7 @@ class IO
bool $returning_id, bool $returning_id,
string $query, string $query,
?string $pk_name, ?string $pk_name,
$cursor, \PgSql\Result|false $cursor,
?string $stm_name = null ?string $stm_name = null
): void { ): void {
// $this->log->debug('DB SET INSERT ID', 'Ret: ' . ($returning_id ? 'Y' : 'N') // $this->log->debug('DB SET INSERT ID', 'Ret: ' . ($returning_id ? 'Y' : 'N')
@@ -1271,10 +1275,10 @@ class IO
/** /**
* get certain settings like username, db name * get certain settings like username, db name
* @param string $name what setting to query * @param string $name what setting to query
* @return mixed setting value, if not allowed name return false * @return int|string|bool setting value, if not allowed name return false
*/ */
public function dbGetSetting(string $name) public function dbGetSetting(string $name): int|string|bool
{ {
$setting = ''; $setting = '';
switch ($name) { switch ($name) {
@@ -1373,7 +1377,7 @@ class IO
* extended version info, can access all additional information data * extended version info, can access all additional information data
* @param string $parameter Array parameter name, if not valid returns * @param string $parameter Array parameter name, if not valid returns
* empty string * empty string
* @param boolean $strip Strip extended server info string, default true * @param bool $strip Strip extended server info string, default true
* eg nn.n (other info) will only return nn.n * eg nn.n (other info) will only return nn.n
* @return string Parameter value * @return string Parameter value
*/ */
@@ -1392,14 +1396,15 @@ class IO
} }
/** /**
* returns boolean true or false if the string matches the database version * returns bool true or false if the string matches the database version
* @param string $compare string to match in type =X.Y, >X.Y, <X.Y, <=X.Y, >=X.Y * @param string $compare string to match in type =X.Y, >X.Y, <X.Y, <=X.Y, >=X.Y
* @return bool true for ok, false on not ok * @return bool true for ok, false on not ok
*/ */
public function dbCompareVersion(string $compare): bool public function dbCompareVersion(string $compare): bool
{ {
$matches = []; $matches = [];
// compare has =, >, < prefix, and gets stripped, if the rest is not X.Y format then error // compare has =, >, < prefix, and gets stripped
// if the rest is not X.Y format then error
preg_match("/^([<>=]{1,})(\d{1,})\.(\d{1,})/", $compare, $matches); preg_match("/^([<>=]{1,})(\d{1,})\.(\d{1,})/", $compare, $matches);
$compare = $matches[1]; $compare = $matches[1];
$to_master = $matches[2]; $to_master = $matches[2];
@@ -1464,7 +1469,7 @@ class IO
* else current cursor * else current cursor
* @return string Formated string with all the data in the array * @return string Formated string with all the data in the array
*/ */
public function dbDumpData($query = ''): string public function dbDumpData(string $query = ''): string
{ {
// set start array // set start array
if ($query) { if ($query) {
@@ -1490,7 +1495,7 @@ class IO
* @param string|int|float|bool $string string to escape * @param string|int|float|bool $string string to escape
* @return string escaped string * @return string escaped string
*/ */
public function dbEscapeString($string): string public function dbEscapeString(string|int|float|bool $string): string
{ {
return $this->db_functions->__dbEscapeString($string); return $this->db_functions->__dbEscapeString($string);
} }
@@ -1501,7 +1506,7 @@ class IO
* @param string|int|float|bool $string string to escape * @param string|int|float|bool $string string to escape
* @return string escaped string * @return string escaped string
*/ */
public function dbEscapeLiteral($string): string public function dbEscapeLiteral(string|int|float|bool $string): string
{ {
return $this->db_functions->__dbEscapeLiteral($string); return $this->db_functions->__dbEscapeLiteral($string);
} }
@@ -1538,11 +1543,11 @@ class IO
/** /**
* clear up any data for valid DB insert * clear up any data for valid DB insert
* @param int|float|string|null $value to escape data * @param int|float|string|bool|null $value to escape data
* @param string $kbn escape trigger type * @param string $kbn escape trigger type
* @return string escaped value * @return string escaped value
*/ */
public function dbSqlEscape($value, string $kbn = '') public function dbSqlEscape(int|float|string|bool|null $value, string $kbn = ''): string
{ {
switch ($kbn) { switch ($kbn) {
case 'i': case 'i':
@@ -1551,24 +1556,35 @@ class IO
case 'f': case 'f':
$value = empty($value) ? 'NULL' : floatval($value); $value = empty($value) ? 'NULL' : floatval($value);
break; break;
// string (null is null, else is string)
case 't': case 't':
$value = $value === null ? $value = $value === null ?
'NULL' : 'NULL' :
"'" . $this->dbEscapeString($value) . "'"; "'" . $this->dbEscapeString($value) . "'";
break; break;
// string litereal (null is null, else is stirng)
case 'tl': case 'tl':
$value = $value === null ? $value = $value === null ?
'NULL' : 'NULL' :
$this->dbEscapeLiteral($value); $this->dbEscapeLiteral($value);
break; break;
// what is d? // escape string, set empty to null
case 'd': case 'd':
$value = empty($value) ? 'NULL' : "'" . $this->dbEscapeString($value) . "'"; $value = empty($value) ?
'NULL' :
"'" . $this->dbEscapeString($value) . "'";
break;
// escape string literal, set empty to null
case 'dl':
$value = empty($value) ?
'NULL' :
$this->dbEscapeLiteral($value);
break; break;
// bytea data // bytea data
case 'by': case 'by':
$value = empty($value) ? 'NULL' : $this->dbEscapeBytea((string)$value); $value = empty($value) ? 'NULL' : $this->dbEscapeBytea((string)$value);
break; break;
// bool
case 'b': case 'b':
if (is_float($value)) { if (is_float($value)) {
$value = (int)$value; $value = (int)$value;
@@ -1577,6 +1593,7 @@ class IO
'NULL' : 'NULL' :
"'" . $this->dbBoolean($value, true) . "'"; "'" . $this->dbBoolean($value, true) . "'";
break; break;
// int, but with empty value is 0
case 'i2': case 'i2':
$value = empty($value) ? 0 : intval($value); $value = empty($value) ? 0 : intval($value);
break; break;
@@ -1590,14 +1607,14 @@ class IO
/** /**
* if the input is a single char 't' or 'f * if the input is a single char 't' or 'f
* it will return the boolean value instead * it will return the bool value instead
* also converts smallint 1/0 to true false * also converts smallint 1/0 to true false
* @param string|bool|int $string 't' / 'f' or any string, or bool true/false * @param string|bool|int $string 't' / 'f' or any string, or bool true/false
* @param boolean $rev do reverse (bool to string) * @param bool $rev do reverse (bool to string)
* @return bool|string correct php boolean true/false * @return bool|string correct php bool true/false
* or postgresql 't'/'f' * or postgresql 't'/'f'
*/ */
public function dbBoolean($string, $rev = false) public function dbBoolean(string|bool|int $string, bool $rev = false): bool|string
{ {
if (!$rev) { if (!$rev) {
if ($string == 't' || $string == 'true') { if ($string == 't' || $string == 'true') {
@@ -1696,9 +1713,9 @@ class IO
* returns an array of the table with columns and values. FALSE on no table found * returns an array of the table with columns and values. FALSE on no table found
* @param string $table table name * @param string $table table name
* @param string $schema optional schema name * @param string $schema optional schema name
* @return array<mixed>|bool array of table data, false on error (table not found) * @return array<mixed>|false array of table data, false on error (table not found)
*/ */
public function dbShowTableMetaData(string $table, string $schema = '') public function dbShowTableMetaData(string $table, string $schema = ''): array|false
{ {
$this->__dbErrorReset(); $this->__dbErrorReset();
$table = (!empty($schema) ? $schema . '.' : '') . $table; $table = (!empty($schema) ? $schema . '.' : '') . $table;
@@ -1736,14 +1753,14 @@ class IO
* NO_CACHE/3: don't write cache * NO_CACHE/3: don't write cache
* @param bool $assoc_only True to only returned the named and not * @param bool $assoc_only True to only returned the named and not
* index position ones * index position ones
* @return array<mixed>|bool return array data or false on error/end * @return array<mixed>|false return array data or false on error/end
* @#suppress PhanTypeMismatchDimFetch * @#suppress PhanTypeMismatchDimFetch
*/ */
public function dbReturn( public function dbReturn(
string $query, string $query,
int $cache = self::USE_CACHE, int $cache = self::USE_CACHE,
bool $assoc_only = false bool $assoc_only = false
) { ): array|false {
$this->__dbErrorReset(); $this->__dbErrorReset();
if (!$query) { if (!$query) {
$this->__dbError(11); $this->__dbError(11);
@@ -1754,7 +1771,7 @@ class IO
// pre declare array // pre declare array
if (!isset($this->cursor_ext[$query_hash])) { if (!isset($this->cursor_ext[$query_hash])) {
$this->cursor_ext[$query_hash] = [ $this->cursor_ext[$query_hash] = [
// cursor, null: unset, 1: finished read/cache, 2: object/resource reading // cursor, null: unset, 1: finished read/cache, 2: object reading
'cursor' => null, 'cursor' => null,
// cached data // cached data
'data' => [], 'data' => [],
@@ -2000,9 +2017,9 @@ class IO
* if pk name is table name and _id, pk_name * if pk name is table name and _id, pk_name
* is not needed to be set * is not needed to be set
* if NULL is given here, no RETURNING will be auto added * if NULL is given here, no RETURNING will be auto added
* @return object|resource|bool cursor for this query or false on error (PgSql\Result) * @return \PgSql\Result|false cursor for this query or false on error
*/ */
public function dbExec(string $query = '', string $pk_name = '') public function dbExec(string $query = '', string $pk_name = ''): \PgSql\Result|false
{ {
$this->__dbErrorReset(); $this->__dbErrorReset();
// prepare and check if we can actually run it // prepare and check if we can actually run it
@@ -2031,7 +2048,7 @@ class IO
/** /**
* executes a cursor and returns the data, if no more data 0 will be returned * executes a cursor and returns the data, if no more data 0 will be returned
* @param object|resource|bool $cursor the cursor from db_exec or * @param \PgSql\Result|false $cursor the cursor from db_exec or
* pg_query/pg_exec/mysql_query * pg_query/pg_exec/mysql_query
* if not set will use internal cursor, * if not set will use internal cursor,
* if not found, stops with 0 (error) * if not found, stops with 0 (error)
@@ -2039,9 +2056,9 @@ class IO
* @param bool $assoc_only false is default, * @param bool $assoc_only false is default,
* if true only named rows, * if true only named rows,
* not numbered index rows * not numbered index rows
* @return array<mixed>|bool row array or false on error * @return array<mixed>|false row array or false on error
*/ */
public function dbFetchArray($cursor = false, bool $assoc_only = false) public function dbFetchArray(\PgSql\Result|false $cursor = false, bool $assoc_only = false): array|false
{ {
$this->__dbErrorReset(); $this->__dbErrorReset();
// set last available cursor if none set or false // set last available cursor if none set or false
@@ -2064,9 +2081,9 @@ class IO
* returns the FIRST row of the given query * returns the FIRST row of the given query
* @param string $query the query to be executed * @param string $query the query to be executed
* @param bool $assoc_only if true, only return assoc entry (default false) * @param bool $assoc_only if true, only return assoc entry (default false)
* @return array<mixed>|bool row array or false on error * @return array<mixed>|false row array or false on error
*/ */
public function dbReturnRow(string $query, bool $assoc_only = false) public function dbReturnRow(string $query, bool $assoc_only = false): array|false
{ {
$this->__dbErrorReset(); $this->__dbErrorReset();
if (!$query) { if (!$query) {
@@ -2091,9 +2108,9 @@ class IO
* createds an array of hashes of the query (all data) * createds an array of hashes of the query (all data)
* @param string $query the query to be executed * @param string $query the query to be executed
* @param bool $assoc_only if true, only name ref are returned (default true) * @param bool $assoc_only if true, only name ref are returned (default true)
* @return array<mixed>|bool array of hashes (row -> fields), false on error * @return array<mixed>|false array of hashes (row -> fields), false on error
*/ */
public function dbReturnArray(string $query, bool $assoc_only = true) public function dbReturnArray(string $query, bool $assoc_only = true): array|false
{ {
$this->__dbErrorReset(); $this->__dbErrorReset();
if (!$query) { if (!$query) {
@@ -2151,41 +2168,44 @@ class IO
* returns the full array for cursor ext * returns the full array for cursor ext
* or cursor for one query * or cursor for one query
* or detail data fonr one query cursor data * or detail data fonr one query cursor data
* @param string|null $query Query string, if not null convert to hash * @param string|null $query Query string, if not null convert to hash
* and return set cursor ext for only this * and return set cursor ext for only this
* if not found or null return null * if not found or null return null
* @return array<mixed>|string|int|resource|object|null * @param string $query_field [=''] optional query field to get
* Cursor Extended array full if no parameter * @return array<mixed>|string|int|\PgSql\Result|null
* Key is hash string from query run * Cursor Extended array full if no parameter
* Or cursor data entry if query field is set * Key is hash string from query run
* If nothing found return null * Or cursor data entry if query field is set
* If nothing found return null
*/ */
public function dbGetCursorExt($query = null, string $query_field = '') public function dbGetCursorExt(
{ $query = null,
if ($query !== null) { string $query_field = ''
$query_hash = $this->dbGetQueryHash($query); ): array|string|int|\PgSql\Result|null {
if ( if ($query === null) {
is_array($this->cursor_ext) && return $this->cursor_ext;
isset($this->cursor_ext[$query_hash]) }
) { $query_hash = $this->dbGetQueryHash($query);
if (empty($query_field)) { if (
return $this->cursor_ext[$query_hash]; is_array($this->cursor_ext) &&
} else { isset($this->cursor_ext[$query_hash])
return $this->cursor_ext[$query_hash][$query_field] ?? null; ) {
} if (empty($query_field)) {
} else { return $this->cursor_ext[$query_hash];
return null; } else {
} return $this->cursor_ext[$query_hash][$query_field] ?? null;
}
} else {
return null;
} }
return $this->cursor_ext;
} }
/** /**
* returns the current position the read out * returns the current position the read out
* @param string $query query to find in cursor_ext * @param string $query query to find in cursor_ext
* @return int|bool query position (row pos), false on error * @return int|false query position (row pos), false on error
*/ */
public function dbGetCursorPos(string $query) public function dbGetCursorPos(string $query): int|false
{ {
$this->__dbErrorReset(); $this->__dbErrorReset();
if (!$query) { if (!$query) {
@@ -2199,9 +2219,9 @@ class IO
/** /**
* returns the number of rows for the current select query * returns the number of rows for the current select query
* @param string $query query to find in cursor_ext * @param string $query query to find in cursor_ext
* @return int|bool query position (row pos), false on error * @return int|false query position (row pos), false on error
*/ */
public function dbGetCursorNumRows(string $query) public function dbGetCursorNumRows(string $query): int|false
{ {
$this->__dbErrorReset(); $this->__dbErrorReset();
if (!$query) { if (!$query) {
@@ -2253,11 +2273,14 @@ class IO
* @param string $stm_name statement name * @param string $stm_name statement name
* @param string $query queryt string to run * @param string $query queryt string to run
* @param string $pk_name optional primary key * @param string $pk_name optional primary key
* @return bool|object|resource false on error, true on warning or * @return \PgSql\Result|bool false on error, true on warning or
* result on full ok (PgSql\Result) * result on full ok
*/ */
public function dbPrepare(string $stm_name, string $query, string $pk_name = '') public function dbPrepare(
{ string $stm_name,
string $query,
string $pk_name = ''
): \PgSql\Result|bool {
$this->__dbErrorReset(); $this->__dbErrorReset();
$matches = []; $matches = [];
if (!$query) { if (!$query) {
@@ -2361,9 +2384,9 @@ class IO
* runs a prepare query * runs a prepare query
* @param string $stm_name statement name for the query to run * @param string $stm_name statement name for the query to run
* @param array<mixed> $data data to run for this query, empty array for none * @param array<mixed> $data data to run for this query, empty array for none
* @return mixed false on error, or result on OK * @return \PgSql\Result|false false on error, or result on OK
*/ */
public function dbExecute(string $stm_name, array $data = []) public function dbExecute(string $stm_name, array $data = []): \PgSql\Result|false
{ {
$this->__dbErrorReset(); $this->__dbErrorReset();
// if no DB Handler drop out // if no DB Handler drop out
@@ -2483,11 +2506,10 @@ class IO
/** /**
* checks a previous async query and returns data if finished * checks a previous async query and returns data if finished
* NEEDS : dbExecAsync * NEEDS : dbExecAsync
* @return bool|object|resource cursor resource if the query is still running, * @return \PgSql\Result|bool cursor resource if the query is still running,
* false if an error occured or cursor of that query * false if an error occured or cursor of that query
* (PgSql\Result)
*/ */
public function dbCheckAsync() public function dbCheckAsync(): \PgSql\Result|bool
{ {
$this->__dbErrorReset(); $this->__dbErrorReset();
// if there is actually a async query there // if there is actually a async query there
@@ -2547,7 +2569,7 @@ class IO
* @param int $primary_key id key to decide if we write insert or update * @param int $primary_key id key to decide if we write insert or update
* @param string $table name for the target table * @param string $table name for the target table
* @param array<mixed> $data data array to override _POST data * @param array<mixed> $data data array to override _POST data
* @return int|bool primary key * @return int|false primary key
*/ */
public function dbWriteData( public function dbWriteData(
array $write_array, array $write_array,
@@ -2555,13 +2577,7 @@ class IO
int $primary_key, int $primary_key,
string $table, string $table,
array $data = [] array $data = []
) { ): int|false {
if (!is_array($write_array)) {
$write_array = [];
}
if (!is_array($not_write_array)) {
$not_write_array = [];
}
$not_write_update_array = []; $not_write_update_array = [];
return $this->dbWriteDataExt( return $this->dbWriteDataExt(
$write_array, $write_array,
@@ -2586,16 +2602,16 @@ class IO
* to write during update (optional) * to write during update (optional)
* @param array<mixed> $data optional array with data * @param array<mixed> $data optional array with data
* if not _POST vars are used * if not _POST vars are used
* @return int|bool primary key * @return int|false primary key
*/ */
public function dbWriteDataExt( public function dbWriteDataExt(
array $write_array, array $write_array,
$primary_key, int|string|array $primary_key,
string $table, string $table,
array $not_write_array = [], array $not_write_array = [],
array $not_write_update_array = [], array $not_write_update_array = [],
array $data = [] array $data = []
) { ): int|false {
if (!is_array($primary_key)) { if (!is_array($primary_key)) {
$primary_key = [ $primary_key = [
'row' => $table . '_id', 'row' => $table . '_id',
@@ -2711,7 +2727,10 @@ class IO
$primary_key['value'] = $this->dbGetInsertPK(); $primary_key['value'] = $this->dbGetInsertPK();
} }
// if there is not priamry key value field return false // if there is not priamry key value field return false
return $primary_key['value'] ?? false; if (!is_numeric($primary_key['value'])) {
return false;
}
return (int)$primary_key['value'];
} }
// *************************** // ***************************
@@ -2724,7 +2743,7 @@ class IO
* @param bool|null $debug true/false or null for just getting current set * @param bool|null $debug true/false or null for just getting current set
* @return bool Current debug flag as set * @return bool Current debug flag as set
*/ */
public function dbSetDebug($debug = null): bool public function dbSetDebug(?bool $debug = null): bool
{ {
if ($debug !== null) { if ($debug !== null) {
$this->db_debug = $debug; $this->db_debug = $debug;
@@ -2805,7 +2824,7 @@ class IO
* @return bool False on failure to find schema value or set schema, * @return bool False on failure to find schema value or set schema,
* True on successful set * True on successful set
*/ */
public function dbSetSchema(string $db_schema) public function dbSetSchema(string $db_schema): bool
{ {
$this->__dbErrorReset(); $this->__dbErrorReset();
if (empty($db_schema)) { if (empty($db_schema)) {
@@ -2934,9 +2953,9 @@ class IO
/** /**
* Return current database handler * Return current database handler
* @return object|resource|bool|int|null * @return \PgSql\Connection|false|null
*/ */
public function dbGetDbh() public function dbGetDbh(): \PgSql\Connection|false|null
{ {
return $this->dbh; return $this->dbh;
} }
@@ -2992,7 +3011,7 @@ class IO
* *
* @return array<mixed>|string|int|null Current insert query primary key * @return array<mixed>|string|int|null Current insert query primary key
*/ */
public function dbGetInsertPK() public function dbGetInsertPK(): array|string|int|null
{ {
if (empty($this->insert_id_pk_name)) { if (empty($this->insert_id_pk_name)) {
return null; return null;
@@ -3016,7 +3035,7 @@ class IO
* @param integer|null $pos * @param integer|null $pos
* @return array<mixed>|string|int|null * @return array<mixed>|string|int|null
*/ */
public function dbGetReturningExt(?string $key = null, ?int $pos = null) public function dbGetReturningExt(?string $key = null, ?int $pos = null): array|string|int|null
{ {
// return as is if key is null // return as is if key is null
if ($key === null) { if ($key === null) {
@@ -3110,7 +3129,7 @@ class IO
* Not ethat returnin_id also can return false * Not ethat returnin_id also can return false
* but will not set an error entry * but will not set an error entry
*/ */
public function dbGetPrepareCursorValue(string $stm_name, string $key) public function dbGetPrepareCursorValue(string $stm_name, string $key): null|string|int|bool
{ {
// if no statement name // if no statement name
if (empty($stm_name)) { if (empty($stm_name)) {
@@ -3159,8 +3178,8 @@ class IO
* Sets error number that was last * Sets error number that was last
* So we always have the last error number stored even if a new * So we always have the last error number stored even if a new
* one is created * one is created
* @param boolean $transform Set to true to transform into id + error message * @param bool $transform Set to true to transform into id + error message
* @return string Last error number as string or error message * @return string Last error number as string or error message
*/ */
public function dbGetLastError(bool $transform = false): string public function dbGetLastError(bool $transform = false): string
{ {
@@ -3180,10 +3199,10 @@ class IO
/** /**
* Sets warning number that was last * Sets warning number that was last
* So we always have the last warning number stored even if a new one is created * So we always have the last warning number stored even if a new one is created
* @param boolean $transform Set to true to transform into id + warning message * @param bool $transform Set to true to transform into id + warning message
* @return string Last Warning number as string or warning message * @return string Last Warning number as string or warning message
*/ */
public function dbGetLastWarning(bool $transform = false) public function dbGetLastWarning(bool $transform = false): string
{ {
// if no warning, return empty // if no warning, return empty
if (empty($this->warning_id)) { if (empty($this->warning_id)) {
@@ -3221,119 +3240,11 @@ class IO
* Null for error * Null for error
* @deprecated Use ->dbGetInsertPK(); * @deprecated Use ->dbGetInsertPK();
*/ */
public function dbGetReturning() public function dbGetReturning(): array|string|int|bool|null
{ {
return $this->dbGetInsertPK(); return $this->dbGetInsertPK();
} }
/**
* returns the db init error
* if failed to connect it is set to true
* else false
* @return bool connection failure status
* @deprecated Use dbGetConnectionStatus() and True means correct connection
*/
public function getConnectionStatus(): bool
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, '
. 'use dbGetConnectionStatus() with True for successful connection', E_USER_DEPRECATED);
// reverse because before it was reverse
return $this->dbGetConnectionStatus() ? false : true;
}
/**
* Sets error number that was last
* So we always have the last error number stored even if a new one is created
* @return int last error number
* @deprecated Use dbGetLastError()
*/
public function getHadError(): int
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use dbGetLastError()', E_USER_DEPRECATED);
return (int)$this->dbGetLastError();
}
/**
* Sets warning number that was last
* So we always have the last warning number stored even if a new one is created
* @return int last error number
* @deprecated Use dbGetLastWarning()
*/
public function getHadWarning(): int
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use dbGetLastWarning()', E_USER_DEPRECATED);
return (int)$this->dbGetLastWarning();
}
/**
* old call for getInserReturnExt
* @param string|null $key See above
* @return array<mixed>|string|int|bool|null See above
* @deprecated use getReturningExt($key = null) instead
*/
public function getInsertReturn($key = null)
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use getReturningExt($key = null)', E_USER_DEPRECATED);
return $this->dbGetReturningExt($key);
}
/**
* DEPRECATED: getReturning
* @return array<mixed>|string|int|bool|null [DEPRECATED]
* @deprecated use dbGetReturning() instead
*/
public function getReturning()
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use dbGetReturning()', E_USER_DEPRECATED);
return $this->dbGetInsertPK();
}
/**
* DEPRECATED: getInsertPK
* @return array<mixed>|string|int|bool|null [DEPRECATED]
* @deprecated use dbGetInsertPK() instead
*/
public function getInsertPK()
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use dbGetInsertPK()', E_USER_DEPRECATED);
return $this->dbGetInsertPK();
}
/**
* DEPRECATED: getReturningExt
* @param string|null $key [DEPRECATED]
* @return array<mixed>|string|bool|int|null [DEPRECATED]
* @deprecated use dbGetReturningExt($key = null) instead
*/
public function getReturningExt($key = null)
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use dbGetReturningExt($key = null)', E_USER_DEPRECATED);
return $this->dbGetReturningExt($key);
}
/**
* DEPRECATED: getCursorExt
* @param string|null $q [DEPRECATED]
* @return array<mixed>|string|int|resource|object|null [DEPRECATED]
* @deprecated use dbGetCursorExt($q = null) instead
*/
public function getCursorExt($q = null)
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use dbGetCursorExt($q = null)', E_USER_DEPRECATED);
return $this->dbGetCursorExt($q);
}
/**
* DEPRECATED: getNumRows
* @return int|null [DEPRECATED]
* @deprecated use dbGetNumRows() instead
*/
public function getNumRows()
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use dbGetNumRows()', E_USER_DEPRECATED);
return $this->dbGetNumRows();
}
// end if db class // end if db class
} }

View File

@@ -6,7 +6,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace CoreLibs\DB\SQL\SqlInterface; namespace CoreLibs\DB\SQL\Interface;
interface SqlFunctions interface SqlFunctions
{ {
@@ -21,33 +21,33 @@ interface SqlFunctions
* Undocumented function * Undocumented function
* *
* @param string $query * @param string $query
* @return object|resource|bool * @return \PgSql\Result|false
*/ */
public function __dbQuery(string $query); public function __dbQuery(string $query): \PgSql\Result|false;
/** /**
* Undocumented function * Undocumented function
* *
* @param string $query * @param string $query
* @param array<mixed> $params * @param array<mixed> $params
* @return object|resource|bool * @return \PgSql\Result|false
*/ */
public function __dbQueryParams(string $query, array $params); public function __dbQueryParams(string $query, array $params): \PgSql\Result|false;
/** /**
* Undocumented function * Undocumented function
* *
* @param string $query * @param string $query
* @return boolean * @return bool
*/ */
public function __dbSendQuery(string $query): bool; public function __dbSendQuery(string $query): bool;
/** /**
* Undocumented function * Undocumented function
* *
* @return object|resource|bool * @return \PgSql\Result|false
*/ */
public function __dbGetResult(); public function __dbGetResult(): \PgSql\Result|false;
/** /**
* Undocumented function * Undocumented function
@@ -61,85 +61,85 @@ interface SqlFunctions
* *
* @param string $name * @param string $name
* @param string $query * @param string $query
* @return object|resource|bool * @return \PgSql\Result|false
*/ */
public function __dbPrepare(string $name, string $query); public function __dbPrepare(string $name, string $query): \PgSql\Result|false;
/** /**
* Undocumented function * Undocumented function
* *
* @param string $name * @param string $name
* @param array<mixed> $data * @param array<mixed> $data
* @return object|resource|bool * @return \PgSql\Result|false
*/ */
public function __dbExecute(string $name, array $data); public function __dbExecute(string $name, array $data): \PgSql\Result|false;
/** /**
* Undocumented function * Undocumented function
* *
* @param object|resource|bool $cursor * @param \PgSql\Result|false $cursor
* @return integer * @return int
*/ */
public function __dbNumRows($cursor): int; public function __dbNumRows(\PgSql\Result|false $cursor): int;
/** /**
* Undocumented function * Undocumented function
* *
* @param object|resource|bool $cursor * @param \PgSql\Result|false $cursor
* @return integer * @return int
*/ */
public function __dbNumFields($cursor): int; public function __dbNumFields(\PgSql\Result|false $cursor): int;
/** /**
* Undocumented function * Undocumented function
* *
* @param object|resource|bool $cursor * @param \PgSql\Result|false $cursor
* @param int $i * @param int $i
* @return string|bool * @return string|false
*/ */
public function __dbFieldName($cursor, int $i); public function __dbFieldName(\PgSql\Result|false $cursor, int $i): string|false;
/** /**
* Undocumented function * Undocumented function
* *
* @param object|resource|bool $cursor * @param \PgSql\Result|false $cursor
* @param int $result_type * @param int $result_type
* @return array<mixed>|bool * @return array<mixed>|bool
*/ */
public function __dbFetchArray($cursor, int $result_type = PGSQL_BOTH); public function __dbFetchArray(\PgSql\Result|false $cursor, int $result_type = PGSQL_BOTH);
/** /**
* Undocumented function * Undocumented function
* *
* @param boolean $assoc_type * @param bool $assoc_type
* @return integer * @return int
*/ */
public function __dbResultType(bool $assoc_type = true): int; public function __dbResultType(bool $assoc_type = true): int;
/** /**
* Undocumented function * Undocumented function
* *
* @param object|resource|bool $cursor * @param \PgSql\Result|false $cursor
* @return array<mixed>|bool * @return array<mixed>|bool
*/ */
public function __dbFetchAll($cursor); public function __dbFetchAll(\PgSql\Result|false $cursor): array|bool;
/** /**
* Undocumented function * Undocumented function
* *
* @param object|resource|bool $cursor * @param \PgSql\Result|false $cursor
* @return integer * @return int
*/ */
public function __dbAffectedRows($cursor): int; public function __dbAffectedRows(\PgSql\Result|false $cursor): int;
/** /**
* Undocumented function * Undocumented function
* *
* @param string $query * @param string $query
* @param string|null $pk_name * @param string|null $pk_name
* @return string|integer|false * @return string|int|false
*/ */
public function __dbInsertId(string $query, ?string $pk_name); public function __dbInsertId(string $query, ?string $pk_name): string|int|false;
/** /**
* Undocumented function * Undocumented function
@@ -148,7 +148,7 @@ interface SqlFunctions
* @param string $schema * @param string $schema
* @return string|bool * @return string|bool
*/ */
public function __dbPrimaryKey(string $table, string $schema = ''); public function __dbPrimaryKey(string $table, string $schema = ''): string|bool;
/** /**
* Undocumented function * Undocumented function
@@ -157,9 +157,9 @@ interface SqlFunctions
* @param string $db_user * @param string $db_user
* @param string $db_pass * @param string $db_pass
* @param string $db_name * @param string $db_name
* @param integer $db_port * @param int $db_port
* @param string $db_ssl * @param string $db_ssl
* @return object|resource|bool * @return \PgSql\Connection|false
*/ */
public function __dbConnect( public function __dbConnect(
string $db_host, string $db_host,
@@ -168,24 +168,24 @@ interface SqlFunctions
string $db_name, string $db_name,
int $db_port, int $db_port,
string $db_ssl = 'allow' string $db_ssl = 'allow'
); ): \PgSql\Connection|false;
/** /**
* Undocumented function * Undocumented function
* *
* @param object|resource|bool $cursor * @param \PgSql\Result|false $cursor
* @return string * @return string
*/ */
public function __dbPrintError($cursor = false): string; public function __dbPrintError(\PgSql\Result|false $cursor = false): string;
/** /**
* Undocumented function * Undocumented function
* *
* @param string $table * @param string $table
* @param boolean $extended * @param bool $extended
* @return array<mixed>|bool * @return array<mixed>|bool
*/ */
public function __dbMetaData(string $table, $extended = true); public function __dbMetaData(string $table, bool $extended = true): array|bool;
/** /**
* Undocumented function * Undocumented function
@@ -193,7 +193,7 @@ interface SqlFunctions
* @param string|int|float|bool $string * @param string|int|float|bool $string
* @return string * @return string
*/ */
public function __dbEscapeString($string): string; public function __dbEscapeString(string|int|float|bool $string): string;
/** /**
* Undocumented function * Undocumented function
@@ -201,7 +201,7 @@ interface SqlFunctions
* @param string|int|float|bool $string * @param string|int|float|bool $string
* @return string * @return string
*/ */
public function __dbEscapeLiteral($string): string; public function __dbEscapeLiteral(string|int|float|bool $string): string;
/** /**
* Undocumented function * Undocumented function
@@ -230,15 +230,15 @@ interface SqlFunctions
/** /**
* Undocumented function * Undocumented function
* *
* @return boolean * @return bool
*/ */
public function __dbConnectionBusy(): bool; public function __dbConnectionBusy(): bool;
/** /**
* Undocumented function * Undocumented function
* *
* @param integer $timeout_seconds * @param int $timeout_seconds
* @return boolean * @return bool
*/ */
public function __dbConnectionBusySocketWait(int $timeout_seconds = 3): bool; public function __dbConnectionBusySocketWait(int $timeout_seconds = 3): bool;
@@ -253,8 +253,8 @@ interface SqlFunctions
* Undocumented function * Undocumented function
* *
* @param string $array_text * @param string $array_text
* @param integer $start * @param int $start
* @param integer|null $end * @param int|null $end
* @return array<mixed>|null * @return array<mixed>|null
*/ */
public function __dbArrayParse( public function __dbArrayParse(
@@ -275,7 +275,7 @@ interface SqlFunctions
* Undocumented function * Undocumented function
* *
* @param string $db_schema * @param string $db_schema
* @return integer * @return int
*/ */
public function __dbSetSchema(string $db_schema): int; public function __dbSetSchema(string $db_schema): int;
@@ -290,7 +290,7 @@ interface SqlFunctions
* Undocumented function * Undocumented function
* *
* @param string $db_encoding * @param string $db_encoding
* @return integer * @return int
*/ */
public function __dbSetEncoding(string $db_encoding): int; public function __dbSetEncoding(string $db_encoding): int;

View File

@@ -51,12 +51,11 @@ namespace CoreLibs\DB\SQL;
// as main system. Currently all @var sets are written as object // as main system. Currently all @var sets are written as object
/** @#phan-file-suppress PhanUndeclaredTypeProperty,PhanUndeclaredTypeParameter,PhanUndeclaredTypeReturnType */ /** @#phan-file-suppress PhanUndeclaredTypeProperty,PhanUndeclaredTypeParameter,PhanUndeclaredTypeReturnType */
class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions class PgSQL implements Interface\SqlFunctions
{ {
/** @var string */ /** @var string */
private $last_error_query; private $last_error_query;
// NOTE for PHP 8.1 this is no longer a resource /** @var \PgSql\Connection|false */
/** @var object|resource|bool */ // replace object with PgSql\Connection
private $dbh; private $dbh;
/** /**
@@ -77,12 +76,12 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* wrapper for pg_query, catches error and stores it in class var * wrapper for pg_query, catches error and stores it in class var
* *
* @param string $query Query string * @param string $query Query string
* @return object|resource|bool query result (PgSql\Result) * @return \PgSql\Result|false query result
*/ */
public function __dbQuery(string $query) public function __dbQuery(string $query): \PgSql\Result|false
{ {
$this->last_error_query = ''; $this->last_error_query = '';
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return false; return false;
} }
// read out the query status and save the query if needed // read out the query status and save the query if needed
@@ -100,12 +99,12 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* *
* @param string $query Query string with placeholders $1, .. * @param string $query Query string with placeholders $1, ..
* @param array<mixed> $params Matching parameters for each placerhold * @param array<mixed> $params Matching parameters for each placerhold
* @return object|resource|bool Query result (PgSql\Result) * @return \PgSql\Result|false Query result
*/ */
public function __dbQueryParams(string $query, array $params) public function __dbQueryParams(string $query, array $params): \PgSql\Result|false
{ {
$this->last_error_query = ''; $this->last_error_query = '';
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return false; return false;
} }
// parse query and get all $n entries // parse query and get all $n entries
@@ -126,7 +125,7 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
*/ */
public function __dbSendQuery(string $query): bool public function __dbSendQuery(string $query): bool
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return false; return false;
} }
$result = pg_send_query($this->dbh, $query); $result = pg_send_query($this->dbh, $query);
@@ -136,12 +135,12 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
/** /**
* wrapper for pg_get_result * wrapper for pg_get_result
* *
* @return object|resource|bool resource handler or false for error (PgSql\Result) * @return \PgSql\Result|false resource handler or false for error
*/ */
public function __dbGetResult() public function __dbGetResult(): \PgSql\Result|false
{ {
$this->last_error_query = ''; $this->last_error_query = '';
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return false; return false;
} }
$result = pg_get_result($this->dbh); $result = pg_get_result($this->dbh);
@@ -161,7 +160,7 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
*/ */
public function __dbClose(): void public function __dbClose(): void
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return; return;
} }
if (pg_connection_status($this->dbh) === PGSQL_CONNECTION_OK) { if (pg_connection_status($this->dbh) === PGSQL_CONNECTION_OK) {
@@ -175,12 +174,12 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* *
* @param string $name statement name * @param string $name statement name
* @param string $query query string * @param string $query query string
* @return object|resource|bool prepare statement handler or * @return \PgSql\Result|false prepare statement handler or
* false for error (PgSql\Result) * false for error
*/ */
public function __dbPrepare(string $name, string $query) public function __dbPrepare(string $name, string $query): \PgSql\Result|false
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return false; return false;
} }
$result = pg_prepare($this->dbh, $name, $query); $result = pg_prepare($this->dbh, $name, $query);
@@ -195,11 +194,11 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* *
* @param string $name statement name * @param string $name statement name
* @param array<mixed> $data data array * @param array<mixed> $data data array
* @return object|resource|bool returns status or false for error (PgSql\Result) * @return \PgSql\Result|false returns status or false for error
*/ */
public function __dbExecute(string $name, array $data) public function __dbExecute(string $name, array $data): \PgSql\Result|false
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return false; return false;
} }
$result = pg_execute($this->dbh, $name, $data); $result = pg_execute($this->dbh, $name, $data);
@@ -212,12 +211,12 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
/** /**
* wrapper for pg_num_rows * wrapper for pg_num_rows
* *
* @param object|resource|bool $cursor cursor PgSql\Result (former resource) * @param \PgSql\Result|false $cursor cursor
* @return int number of rows, -1 on error * @return int number of rows, -1 on error
*/ */
public function __dbNumRows($cursor): int public function __dbNumRows(\PgSql\Result|false $cursor): int
{ {
if ($cursor === false || is_bool($cursor)) { if (is_bool($cursor)) {
return -1; return -1;
} }
return pg_num_rows($cursor); return pg_num_rows($cursor);
@@ -226,12 +225,12 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
/** /**
* wrapper for pg_num_fields * wrapper for pg_num_fields
* *
* @param object|resource|bool $cursor cursor PgSql\Result (former resource) * @param \PgSql\Result|false $cursor cursor
* @return int number for fields in result, -1 on error * @return int number for fields in result, -1 on error
*/ */
public function __dbNumFields($cursor): int public function __dbNumFields(\PgSql\Result|false $cursor): int
{ {
if ($cursor === false || is_bool($cursor)) { if (is_bool($cursor)) {
return -1; return -1;
} }
return pg_num_fields($cursor); return pg_num_fields($cursor);
@@ -240,13 +239,13 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
/** /**
* wrapper for pg_field_name * wrapper for pg_field_name
* *
* @param object|resource|bool $cursor cursor PgSql\Result (former resource) * @param \PgSql\Result|false $cursor cursor
* @param int $i field position * @param int $i field position
* @return string|bool name or false on error * @return string|false name or false on error
*/ */
public function __dbFieldName($cursor, int $i) public function __dbFieldName(\PgSql\Result|false $cursor, int $i): string|false
{ {
if ($cursor === false || is_bool($cursor)) { if (is_bool($cursor)) {
return false; return false;
} }
return pg_field_name($cursor, $i); return pg_field_name($cursor, $i);
@@ -256,13 +255,13 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* wrapper for pg_fetch_array * wrapper for pg_fetch_array
* if through/true false, use __dbResultType(true) * if through/true false, use __dbResultType(true)
* *
* @param object|resource|bool $cursor cursor PgSql\Result (former resource) * @param \PgSql\Result|false $cursor cursor
* @param int $result_type result type as int number * @param int $result_type result type as int number
* @return array<mixed>|bool array result data or false on end/error * @return array<mixed>|false array result data or false on end/error
*/ */
public function __dbFetchArray($cursor, int $result_type = PGSQL_BOTH) public function __dbFetchArray(\PgSql\Result|false $cursor, int $result_type = PGSQL_BOTH): array|false
{ {
if ($cursor === false || is_bool($cursor)) { if (is_bool($cursor)) {
return false; return false;
} }
// result type is passed on as is [should be checked] // result type is passed on as is [should be checked]
@@ -287,12 +286,12 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
/** /**
* wrapper for pg_fetch_all * wrapper for pg_fetch_all
* *
* @param object|resource|bool $cursor cursor PgSql\Result (former resource) * @param \PgSql\Result|false $cursor cursor
* @return array<mixed>|bool data array or false for end/error * @return array<mixed>|false data array or false for end/error
*/ */
public function __dbFetchAll($cursor) public function __dbFetchAll(\PgSql\Result|false $cursor): array|false
{ {
if ($cursor === false || is_bool($cursor)) { if (is_bool($cursor)) {
return false; return false;
} }
return pg_fetch_all($cursor); return pg_fetch_all($cursor);
@@ -301,12 +300,12 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
/** /**
* wrapper for pg_affected_rows * wrapper for pg_affected_rows
* *
* @param object|resource|bool $cursor cursor PgSql\Result (former resource) * @param \PgSql\Result|false $cursor cursor
* @return int affected rows, 0 for none, -1 for error * @return int affected rows, 0 for none, -1 for error
*/ */
public function __dbAffectedRows($cursor): int public function __dbAffectedRows(\PgSql\Result|false $cursor): int
{ {
if ($cursor === false || is_bool($cursor)) { if (is_bool($cursor)) {
return -1; return -1;
} }
return pg_affected_rows($cursor); return pg_affected_rows($cursor);
@@ -323,7 +322,7 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* @param string|null $pk_name primary key name, if '' then auto detect * @param string|null $pk_name primary key name, if '' then auto detect
* @return string|int|false primary key value * @return string|int|false primary key value
*/ */
public function __dbInsertId(string $query, ?string $pk_name) public function __dbInsertId(string $query, ?string $pk_name): string|int|false
{ {
// only if an insert has been done // only if an insert has been done
if (preg_match("/^insert /i", $query)) { if (preg_match("/^insert /i", $query)) {
@@ -371,7 +370,7 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* @param string $schema optional schema name, '' for default * @param string $schema optional schema name, '' for default
* @return string|bool primary key name or false if not found * @return string|bool primary key name or false if not found
*/ */
public function __dbPrimaryKey(string $table, string $schema = '') public function __dbPrimaryKey(string $table, string $schema = ''): string|bool
{ {
if ($table) { if ($table) {
// check if schema set is different from schema given, // check if schema set is different from schema given,
@@ -426,7 +425,7 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* @param string $db_name databse name * @param string $db_name databse name
* @param integer $db_port port (int, 5432 is default) * @param integer $db_port port (int, 5432 is default)
* @param string $db_ssl SSL (allow is default) * @param string $db_ssl SSL (allow is default)
* @return object|resource|bool db handler PgSql\Connection or false on error * @return \PgSql\Connection|false db handler or false on error
*/ */
public function __dbConnect( public function __dbConnect(
string $db_host, string $db_host,
@@ -435,7 +434,7 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
string $db_name, string $db_name,
int $db_port, int $db_port,
string $db_ssl = 'allow' string $db_ssl = 'allow'
) { ): \PgSql\Connection|false {
if (empty($db_name)) { if (empty($db_name)) {
return false; return false;
} }
@@ -470,22 +469,22 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* reads the last error for this cursor and returns * reads the last error for this cursor and returns
* html formatted string with error name * html formatted string with error name
* *
* @param bool|object|resource $cursor cursor PgSql\Result (former resource) * @param \PgSql\Result|false $cursor cursor
* or null * or null
* @return string error string * @return string error string
*/ */
public function __dbPrintError($cursor = false): string public function __dbPrintError(\PgSql\Result|false $cursor = false): string
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return ''; return '';
} }
// run the query again for the error result here // run the query again for the error result here
if (($cursor === false || is_bool($cursor)) && $this->last_error_query) { if ((is_bool($cursor)) && $this->last_error_query) {
pg_send_query($this->dbh, $this->last_error_query); pg_send_query($this->dbh, $this->last_error_query);
$this->last_error_query = ''; $this->last_error_query = '';
$cursor = pg_get_result($this->dbh); $cursor = pg_get_result($this->dbh);
} }
if ($cursor && !is_bool($cursor) && $error_str = pg_result_error($cursor)) { if ($cursor && $error_str = pg_result_error($cursor)) {
return '-PostgreSQL-Error- ' return '-PostgreSQL-Error- '
. $error_str; . $error_str;
} else { } else {
@@ -500,9 +499,9 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* @param bool $extended show extended info (default true) * @param bool $extended show extended info (default true)
* @return array<mixed>|bool array data for the table info or false on error * @return array<mixed>|bool array data for the table info or false on error
*/ */
public function __dbMetaData(string $table, $extended = true) public function __dbMetaData(string $table, bool $extended = true): array|bool
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return false; return false;
} }
// needs to prefixed with @ or it throws a warning on not existing table // needs to prefixed with @ or it throws a warning on not existing table
@@ -515,9 +514,9 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* @param string|int|float|bool $string any string/int/float/bool * @param string|int|float|bool $string any string/int/float/bool
* @return string excaped string * @return string excaped string
*/ */
public function __dbEscapeString($string): string public function __dbEscapeString(string|int|float|bool $string): string
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return ''; return '';
} }
return pg_escape_string($this->dbh, (string)$string); return pg_escape_string($this->dbh, (string)$string);
@@ -531,9 +530,9 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* @param string|int|float|bool $string any string/int/float/bool * @param string|int|float|bool $string any string/int/float/bool
* @return string excaped string including quites * @return string excaped string including quites
*/ */
public function __dbEscapeLiteral($string): string public function __dbEscapeLiteral(string|int|float|bool $string): string
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return (string)''; return (string)'';
} }
// for phpstan, thinks this is string|false? // for phpstan, thinks this is string|false?
@@ -549,7 +548,7 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
*/ */
public function __dbEscapeIdentifier(string $string): string public function __dbEscapeIdentifier(string $string): string
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return ''; return '';
} }
// for phpstan, thinks this is string|false? // for phpstan, thinks this is string|false?
@@ -564,7 +563,7 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
*/ */
public function __dbEscapeBytea(string $data): string public function __dbEscapeBytea(string $data): string
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return ''; return '';
} }
return pg_escape_bytea($this->dbh, $data); return pg_escape_bytea($this->dbh, $data);
@@ -584,11 +583,12 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
/** /**
* wrapper for pg_connection_busy * wrapper for pg_connection_busy
* *
* @return bool True if connection is busy, False if not or no db connection at all * @return bool True if connection is busy
* False if not or no db connection at all
*/ */
public function __dbConnectionBusy(): bool public function __dbConnectionBusy(): bool
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return false; return false;
} }
return pg_connection_busy($this->dbh); return pg_connection_busy($this->dbh);
@@ -597,13 +597,13 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
/** /**
* Experimental wrapper with scoket timetout * Experimental wrapper with scoket timetout
* *
* @param integer $timeout_seconds Wait how many seconds on timeout * @param integer $timeout_seconds Wait how many seconds on timeout
* @return boolean True if connection is busy, or false on * @return bool True if connection is busy, or false on
* not busy or no db connection at all * not busy or no db connection at all
*/ */
public function __dbConnectionBusySocketWait(int $timeout_seconds = 3): bool public function __dbConnectionBusySocketWait(int $timeout_seconds = 3): bool
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return false; return false;
} }
$busy = pg_connection_busy($this->dbh); $busy = pg_connection_busy($this->dbh);
@@ -626,14 +626,14 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* On default 'version' will be stripped of any space attached info * On default 'version' will be stripped of any space attached info
* eg 13.5 (other info) will return only 13.5 * eg 13.5 (other info) will return only 13.5
* *
* @param string $parameter Parameter string to extract from array * @param string $parameter Parameter string to extract from array
* @param boolean $strip If parameter is server strip out on default * @param bool $strip If parameter is server strip out on default
* Set to false to get original string AS is * Set to false to get original string AS is
* @return string The parameter value * @return string The parameter value
*/ */
public function __dbVersionInfo(string $parameter, bool $strip = true): string public function __dbVersionInfo(string $parameter, bool $strip = true): string
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return ''; return '';
} }
// extract element // extract element
@@ -655,7 +655,7 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
*/ */
public function __dbVersionInfoParameterList(): array public function __dbVersionInfoParameterList(): array
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return []; return [];
} }
return array_keys(pg_version($this->dbh)); return array_keys(pg_version($this->dbh));
@@ -670,7 +670,7 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
*/ */
public function __dbVersion(): string public function __dbVersion(): string
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return ''; return '';
} }
// array has client, protocol, server, we just return server stripped // array has client, protocol, server, we just return server stripped
@@ -762,9 +762,9 @@ class PgSQL implements \CoreLibs\DB\SQL\SqlInterface\SqlFunctions
* @param string $parameter Parameter to query * @param string $parameter Parameter to query
* @return string|bool Settings value as string * @return string|bool Settings value as string
*/ */
public function __dbParameter(string $parameter) public function __dbParameter(string $parameter): string|bool
{ {
if ($this->dbh === false || is_bool($this->dbh)) { if (is_bool($this->dbh)) {
return false; return false;
} }
if (empty($parameter)) { if (empty($parameter)) {

View File

@@ -75,6 +75,11 @@ class FileWriter
empty(self::$debug_folder) && empty(self::$debug_folder) &&
defined('BASE') && defined('LOG') 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; self::$debug_folder = BASE . LOG;
} }
if (!is_writeable(self::$debug_folder)) { if (!is_writeable(self::$debug_folder)) {

View File

@@ -136,6 +136,11 @@ class Logging
$this->log_folder = $this->options['log_folder'] ?? ''; $this->log_folder = $this->options['log_folder'] ?? '';
// legacy flow, check must set constants // legacy flow, check must set constants
if (empty($this->log_folder) && defined('BASE') && defined('LOG')) { 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 // make sure this is writeable, else skip
$this->log_folder = BASE . LOG; $this->log_folder = BASE . LOG;
} }
@@ -175,6 +180,11 @@ class Logging
if (!empty($this->options['file_id'])) { if (!empty($this->options['file_id'])) {
$this->setLogId($this->options['file_id']); $this->setLogId($this->options['file_id']);
} elseif (!empty($GLOBALS['LOG_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 // legacy flow, should be removed and only set via options
$this->setLogId($GLOBALS['LOG_FILE_ID']); $this->setLogId($GLOBALS['LOG_FILE_ID']);
// TODO trigger deprecation error // TODO trigger deprecation error
@@ -183,6 +193,11 @@ class Logging
// E_USER_DEPRECATED // E_USER_DEPRECATED
// ); // );
} elseif (defined('LOG_FILE_ID')) { } 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 // legacy flow, should be removed and only set via options
$this->setLogId(LOG_FILE_ID); $this->setLogId(LOG_FILE_ID);
// trigger deprecation error // trigger deprecation error
@@ -236,22 +251,22 @@ class Logging
'debug', 'debug',
$this->options['debug_all'] ?? $this->options['debug_all'] ??
// for user login, should be handled outside like globals // for user login, should be handled outside like globals
$_SESSION['DEBUG_ALL'] ?? $_SESSION['DEBUG_ALL'] ?? // DEPRECATED
$GLOBALS['DEBUG_ALL'] ?? $GLOBALS['DEBUG_ALL'] ?? // DEPRECATED
false false
); );
$this->setLogLevelAll( $this->setLogLevelAll(
'print', 'print',
$this->options['print_all'] ?? $this->options['print_all'] ??
// for user login, should be handled outside like globals // for user login, should be handled outside like globals
$_SESSION['DEBUG_ALL'] ?? $_SESSION['DEBUG_ALL'] ?? // DEPRECATED
$GLOBALS['PRINT_ALL'] ?? $GLOBALS['PRINT_ALL'] ?? // DEPRECATED
false false
); );
$this->setLogLevelAll( $this->setLogLevelAll(
'echo', 'echo',
$this->options['echo_all'] ?? $this->options['echo_all'] ??
$GLOBALS['ECHO_ALL'] ?? $GLOBALS['ECHO_ALL'] ?? // DEPRECATED
false false
); );
@@ -259,32 +274,32 @@ class Logging
// add file date is default on // add file date is default on
$this->setGetLogPrintFileDate( $this->setGetLogPrintFileDate(
$this->options['print_file_date'] ?? $this->options['print_file_date'] ??
$GLOBALS['LOG_PRINT_FILE_DATE'] ?? $GLOBALS['LOG_PRINT_FILE_DATE'] ?? // DEPRECATED
true true
); );
// all other logging file name flags are off // all other logging file name flags are off
$this->setLogPer( $this->setLogPer(
'level', 'level',
$this->options['per_level'] ?? $this->options['per_level'] ??
$GLOBALS['LOG_PER_LEVEL'] ?? $GLOBALS['LOG_PER_LEVEL'] ?? // DEPRECATED
false false
); );
$this->setLogPer( $this->setLogPer(
'class', 'class',
$this->options['per_class'] ?? $this->options['per_class'] ??
$GLOBALS['LOG_PER_CLASS'] ?? $GLOBALS['LOG_PER_CLASS'] ?? // DEPRECATED
false false
); );
$this->setLogPer( $this->setLogPer(
'page', 'page',
$this->options['per_page'] ?? $this->options['per_page'] ??
$GLOBALS['LOG_PER_PAGE'] ?? $GLOBALS['LOG_PER_PAGE'] ?? // DEPRECATED
false false
); );
$this->setLogPer( $this->setLogPer(
'run', 'run',
$this->options['per_run'] ?? $this->options['per_run'] ??
$GLOBALS['LOG_PER_RUN'] ?? $GLOBALS['LOG_PER_RUN'] ?? // DEPRECATED
false false
); );
// set log per date // set log per date
@@ -413,7 +428,7 @@ class Logging
* @param string $name what variable to return * @param string $name what variable to return
* @return mixed can be anything, bool, string, int, array * @return mixed can be anything, bool, string, int, array
*/ */
public function getSetting(string $name) //:mixed DOES not work with PHP 7.4 public function getSetting(string $name): mixed
{ {
// for debug purpose only // for debug purpose only
return $this->{$name}; return $this->{$name};
@@ -550,9 +565,9 @@ class Logging
* @param string $flag on/off * @param string $flag on/off
* @param string|null $level if not null then check if this array entry is set * @param string|null $level if not null then check if this array entry is set
* else return false * else return false
* @return bool|array<mixed> if $level is null, return array, else boolean true/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) public function getLogLevel(string $type, string $flag, ?string $level = null): array|bool
{ {
// abort if not valid type // abort if not valid type
if (!in_array($type, ['debug', 'echo', 'print'])) { if (!in_array($type, ['debug', 'echo', 'print'])) {

View File

@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace CoreLibs\Get; namespace CoreLibs\Get;
// NOTE: it is recommended to use gullvek\dotenv instead which is a copy of this
class DotEnv class DotEnv
{ {
/** @var string constant comment char, set to # */ /** @var string constant comment char, set to # */
@@ -29,11 +31,17 @@ class DotEnv
* 1 for file loadable, no data or data already loaded * 1 for file loadable, no data or data already loaded
* 2 for file not readable or open failed * 2 for file not readable or open failed
* 3 for file not found * 3 for file not found
* @deprecated Use composer package gullevek\dotenv instead -> \gullevek\dotenv\DotEnv::readEnvFile(...)
*/ */
public static function readEnvFile( public static function readEnvFile(
string $path = __DIR__, string $path = __DIR__,
string $env_file = '.env' string $env_file = '.env'
): int { ): 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; // default -1;
$status = -1; $status = -1;
$env_file_target = $path . DIRECTORY_SEPARATOR . $env_file; $env_file_target = $path . DIRECTORY_SEPARATOR . $env_file;

View 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__

View File

@@ -122,7 +122,7 @@ class GetTextReader
* @param bool $enable_cache Enable or disable caching * @param bool $enable_cache Enable or disable caching
* of strings (default on) * of strings (default on)
*/ */
public function __construct($Reader, bool $enable_cache = true) public function __construct(FileReader|bool $Reader, bool $enable_cache = true)
{ {
// If there isn't a StreamReader, turn on short circuit mode. // If there isn't a StreamReader, turn on short circuit mode.
if ((!is_object($Reader) && !$Reader) || (is_object($Reader) && $Reader->error)) { if ((!is_object($Reader) && !$Reader) || (is_object($Reader) && $Reader->error)) {

View File

@@ -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): 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)
{
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 bool|array<string> 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
) {
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__

View File

@@ -14,12 +14,14 @@ class GetLocale
/** /**
* returns locale, lang, domain, encoding, path * returns locale, lang, domain, encoding, path
* from either parameter set or from sessions/config variables * 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 $locale override auto detect
* @param string|null $domain override domain * @param string|null $domain override domain
* @param string|null $encoding override encoding * @param string|null $encoding override encoding
* @param string|null $path override path * @param string|null $path override path
* @return array<string,string> locale, domain, encoding, path * @return array<string,string> locale, domain, encoding, path
* @deprecated use GetLocale::setLocaleSession(...) instead
*/ */
public static function setLocale( public static function setLocale(
?string $locale = null, ?string $locale = null,
@@ -27,6 +29,10 @@ class GetLocale
?string $encoding = null, ?string $encoding = null,
?string $path = null ?string $path = null
): array { ): array {
trigger_error(
'Use \CoreLibs\Language\GetLocale::setLocaleSession(...) instead',
E_USER_DEPRECATED
);
// locale must match at least basic rules // locale must match at least basic rules
if ( if (
empty($locale) || empty($locale) ||
@@ -36,6 +42,10 @@ class GetLocale
// parse from session (logged in) // parse from session (logged in)
$locale = $_SESSION['DEFAULT_LOCALE']; $locale = $_SESSION['DEFAULT_LOCALE'];
} else { } else {
trigger_error(
'setLocale: Unset $locale or unset SESSION locale is deprecated',
E_USER_DEPRECATED
);
// else parse from site locale // else parse from site locale
$locale = defined('SITE_LOCALE') && !empty(SITE_LOCALE) ? $locale = defined('SITE_LOCALE') && !empty(SITE_LOCALE) ?
SITE_LOCALE : SITE_LOCALE :
@@ -50,8 +60,16 @@ class GetLocale
empty($domain) || empty($domain) ||
!preg_match("/^\w+$/", $domain) !preg_match("/^\w+$/", $domain)
) { ) {
// if no domain is set, fall back to content path if (!empty($_SESSION['DEFAULT_DOMAIN'])) {
$domain = str_replace('/', '', CONTENT_PATH); $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 // check that override encoding matches locale encoding
// if locale encoding is set // if locale encoding is set
@@ -71,6 +89,10 @@ class GetLocale
// else set from session // else set from session
$encoding = $_SESSION['DEFAULT_CHARSET']; $encoding = $_SESSION['DEFAULT_CHARSET'];
} else { } else {
trigger_error(
'setLocale: Short $locale with unset $encoding or unset SESSION encoding is deprecated',
E_USER_DEPRECATED
);
// else set from site encoding // else set from site encoding
$encoding = defined('SITE_ENCODING') && !empty(SITE_ENCODING) ? $encoding = defined('SITE_ENCODING') && !empty(SITE_ENCODING) ?
SITE_ENCODING : SITE_ENCODING :
@@ -85,7 +107,15 @@ class GetLocale
empty($path) || empty($path) ||
!is_dir($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 // extract lang & country from locale string, else set to en
if ( if (
@@ -112,6 +142,113 @@ class GetLocale
'path' => $path, '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__ // __END__

View File

@@ -32,12 +32,18 @@ use CoreLibs\Language\Core\GetTextReader;
class L10n class L10n
{ {
/** @var string the default fallback encoding if nothing is set */
public const DEFAULT_CHARSET = 'UTF-8';
/** @var string the current locale */ /** @var string the current locale */
private $locale = ''; private $locale = '';
/** @var string the SET locale as WHERE the domain file is */ /** @var string the SET locale as WHERE the domain file is */
private $locale_set = ''; private $locale_set = '';
/** @var string the default selected/active domain */ /** @var string the default selected/active domain */
private $domain = ''; private $domain = '';
/** @var string encoding, as from locale or set from outside */
private $override_encoding = self::DEFAULT_CHARSET;
/** @var string encoding set during the parse Locale */
private $encoding = '';
/** @var array<string,array<string,GetTextReader>> locale > domain = translator */ /** @var array<string,array<string,GetTextReader>> locale > domain = translator */
private $domains = []; private $domains = [];
/** @var array<string,string> bound paths for domains */ /** @var array<string,string> bound paths for domains */
@@ -71,26 +77,42 @@ class L10n
* if locale is not empty will load translation * if locale is not empty will load translation
* else getTranslator needs to be called * else getTranslator needs to be called
* *
* @param string $locale language name, default empty string * @param string $locale language name, default empty string
* will return self instance * will return self instance
* @param string $domain override CONTENT_PATH . $encoding name for mo file * @param string $domain override CONTENT_PATH . $encoding name for mo file
* @param string $path path, if empty fallback on default internal path * @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( public function __construct(
string $locale = '', string $locale = '',
string $domain = '', string $domain = '',
string $path = '' string $path = '',
string $encoding = ''
) { ) {
// auto load language only if at least locale and domain is set // 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 // check hack if domain and path is switched
// Note this can be removed in future versions // Note this can be removed in future versions
if (strstr($domain, DIRECTORY_SEPARATOR) !== false) { 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; $_domain = $path;
$path = $domain; $path = $domain;
$domain = $_domain; $domain = $_domain;
} }
$this->getTranslator($locale, $domain, $path); $this->getTranslator($locale, $domain, $path, $encoding);
} }
} }
@@ -122,15 +144,17 @@ class L10n
/** /**
* loads the mo file base on path, locale and domain set * loads the mo file base on path, locale and domain set
* *
* @param string $locale language name (optional), fallback is en * @param string $locale language name, if not set, try previous set
* @param string $domain override CONTENT_PATH . $encoding name for mo file * @param string $domain set name for mo file, if not set, try previous set
* @param string $path path, if empty fallback on default internal path * @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 * @return GetTextReader the main gettext reader object
*/ */
public function getTranslator( public function getTranslator(
string $locale = '', string $locale = '',
string $domain = '', string $domain = '',
string $path = '' string $path = '',
string $override_encoding = '',
): GetTextReader { ): GetTextReader {
// set local if not from parameter // set local if not from parameter
if (empty($locale)) { if (empty($locale)) {
@@ -140,11 +164,16 @@ class L10n
if (empty($domain)) { if (empty($domain)) {
$domain = $this->domain; $domain = $this->domain;
} }
// override encoding for unset
if (!empty($override_encoding)) {
$this->override_encoding = $override_encoding;
}
// store old settings // store old settings
$old_mofile = $this->mofile; $old_mofile = $this->mofile;
$old_lang = $this->locale; $old_lang = $this->locale;
$old_lang_set = $this->locale_set; $old_lang_set = $this->locale_set;
$old_domain = $this->domain; $old_domain = $this->domain;
$old_encoding = $this->encoding;
$old_base_locale_path = $this->base_locale_path; $old_base_locale_path = $this->base_locale_path;
$old_base_content_path = $this->base_content_path; $old_base_content_path = $this->base_content_path;
@@ -160,6 +189,11 @@ class L10n
} elseif ( } elseif (
defined('BASE') && defined('INCLUDES') && defined('LOCALE') 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 // set fallback base path if constant set
$this->base_locale_path = BASE . INCLUDES . LOCALE; $this->base_locale_path = BASE . INCLUDES . LOCALE;
} else { } else {
@@ -168,6 +202,7 @@ class L10n
// now we loop over lang compositions to get the base path // now we loop over lang compositions to get the base path
// then we check // then we check
$locales = $this->listLocales($locale); $locales = $this->listLocales($locale);
$encoding = $this->getEncodingFromLocale($locale);
foreach ($locales as $_locale) { foreach ($locales as $_locale) {
$this->base_content_path = $_locale . DIRECTORY_SEPARATOR $this->base_content_path = $_locale . DIRECTORY_SEPARATOR
. 'LC_MESSAGES' . DIRECTORY_SEPARATOR; . 'LC_MESSAGES' . DIRECTORY_SEPARATOR;
@@ -184,6 +219,7 @@ class L10n
if (is_readable($this->mofile)) { if (is_readable($this->mofile)) {
// locale and domain current wanted // locale and domain current wanted
$this->locale = $locale; $this->locale = $locale;
$this->encoding = $encoding;
$this->domain = $domain; $this->domain = $domain;
// set empty domains path with current locale // set empty domains path with current locale
if (empty($this->domains[$locale])) { if (empty($this->domains[$locale])) {
@@ -207,6 +243,7 @@ class L10n
$this->mofile = $old_mofile; $this->mofile = $old_mofile;
$this->locale = $old_lang; $this->locale = $old_lang;
$this->locale_set = $old_lang_set; $this->locale_set = $old_lang_set;
$this->encoding = $old_encoding;
$this->domain = $old_domain; $this->domain = $old_domain;
$this->base_locale_path = $old_base_locale_path; $this->base_locale_path = $old_base_locale_path;
$this->base_content_path = $old_base_content_path; $this->base_content_path = $old_base_content_path;
@@ -240,6 +277,40 @@ class L10n
return $this->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 * parse the locale string for further processing
* *
@@ -478,6 +549,37 @@ class L10n
return $this->locale_set; 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 * get current set language
* *

View File

@@ -13,27 +13,27 @@ class Elements
/** /**
* print the date/time drop downs, used in any queue/send/insert at date/time place * print the date/time drop downs, used in any queue/send/insert at date/time place
* *
* @param int $year year YYYY * @param int|string $year year YYYY
* @param int $month month m * @param int|string $month month m
* @param int $day day d * @param int|string $day day d
* @param int $hour hour H * @param int|string $hour hour H
* @param int $min min i * @param int|string $min min i
* @param string $suffix additional info printed after the date time * @param string $suffix additional info printed after the date time
* variable in the drop down * variable in the drop down
* also used for ID in the on change JS call * also used for ID in the on change JS call
* @param int $min_steps default is 1 (minute), can set to anything, * @param int $min_steps default is 1 (minute), can set to anything,
* is used as sum up from 0 * is used as sum up from 0
* @param bool $name_pos_back default false, if set to true, * @param bool $name_pos_back default false, if set to true,
* the name will be printend after the drop down * the name will be printend after the drop down
* and not before the drop down * and not before the drop down
* @return string HTML formated strings for drop down lists of date and time * @return string HTML formated strings for drop down lists of date and time
*/ */
public static function printDateTime( public static function printDateTime(
$year, int|string $year,
$month, int|string $month,
$day, int|string $day,
$hour, int|string $hour,
$min, int|string $min,
string $suffix = '', string $suffix = '',
int $min_steps = 1, int $min_steps = 1,
bool $name_pos_back = false bool $name_pos_back = false

View File

@@ -277,6 +277,8 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
private $acl_admin = 0; private $acl_admin = 0;
/** @var array<mixed> */ /** @var array<mixed> */
public $security_level; public $security_level;
/** @var array<string,mixed> Login ACL */
public $login_acl = [];
// layout publics // layout publics
/** @var int */ /** @var int */
public $table_width; public $table_width;
@@ -305,50 +307,42 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
/** /**
* construct form generator * construct form generator
* *
* @param array<mixed> $db_config db config array, mandatory * @param array<mixed> $db_config db config array, mandatory
* @param \CoreLibs\Debug\Logging|null $log Logging class, null auto set * @param \CoreLibs\Debug\Logging $log Logging class
* @param \CoreLibs\Language\L10n|null $l10n l10n language class, null auto set * @param \CoreLibs\Language\L10n $l10n l10n language class
* @param array<string,string>|null $locale locale array from ::setLocale, * @param array<string,mixed> $login_acl Login ACL array,
* null auto set * at least base/admin should be set
* @param array<mixed>|null $table_arrays Override table array data * @param array<mixed>|null $table_arrays Override table array data
* instead of try to load from * instead of try to load from
* include file * include file
* @throws \Exception 1: No table_arrays set/no class found for my page name * @throws \Exception 1: No table_arrays set/no class found for my page name
*/ */
public function __construct( public function __construct(
array $db_config, array $db_config,
?\CoreLibs\Debug\Logging $log = null, \CoreLibs\Debug\Logging $log,
?\CoreLibs\Language\L10n $l10n = null, \CoreLibs\Language\L10n $l10n,
?array $locale = null, array $login_acl,
?array $table_arrays = null, ?array $table_arrays = null,
) { ) {
// init logger if not set // init logger if not set
$this->log = $log ?? new \CoreLibs\Debug\Logging(); $this->log = $log;
// don't log per class // don't log per class
$this->log->setLogPer('class', false); $this->log->setLogPer('class', false);
// if pass on locale is null
if ($locale === null) {
$locale = \CoreLibs\Language\GetLocale::setLocale();
}
// init the language class // init the language class
$this->l = $l10n ?? new \CoreLibs\Language\L10n( $this->l = $l10n;
$locale['locale'], // parse and read, legacy stuff
$locale['domain'], $locale = $this->l->getLocaleAsArray();
$locale['path'],
);
// legacy lang vars set
$this->encoding = $locale['encoding']; $this->encoding = $locale['encoding'];
$this->lang = $locale['lang']; $this->lang = $locale['lang'];
// get first part from lang $this->lang_short = $locale['lang_short'];
$this->lang_short = explode('_', $locale['lang'])[0]; $this->domain = $locale['domain'];
$this->domain = $this->l->getDomain(); $this->lang_dir = $locale['path'];
$this->lang_dir = $this->l->getBaseLocalePath();
// load config array // load config array
// get table array definitions for current page name // get table array definitions for current page name
$this->login_acl = $login_acl;
// security settings // security settings
$this->base_acl_level = (int)$_SESSION['BASE_ACL_LEVEL']; $this->base_acl_level = $this->login_acl['base'] ?? 0;
$this->acl_admin = (int)$_SESSION['ADMIN']; $this->acl_admin = $this->login_acl['admin'] ?? 0;
// replace any non valid variable names and set my page name // replace any non valid variable names and set my page name
$this->my_page_name = str_replace( $this->my_page_name = str_replace(
@@ -386,7 +380,6 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
$this->base_acl_level, $this->base_acl_level,
$this->acl_admin $this->acl_admin
); );
// $this->log->debug('SESSION FORM', 'sessin: ' . $this->log->prAr($_SESSION));
// here should be a check if the config_array is correct ... // here should be a check if the config_array is correct ...
if (isset($config_array['show_fields']) && is_array($config_array['show_fields'])) { if (isset($config_array['show_fields']) && is_array($config_array['show_fields'])) {
$this->field_array = $config_array['show_fields']; $this->field_array = $config_array['show_fields'];
@@ -731,9 +724,6 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
empty($this->table_array['protected']['value']) && empty($this->table_array['protected']['value']) &&
!$this->error !$this->error
) { ) {
if (!is_array($element_list)) {
$element_list = [];
}
for ($i = 0, $i_max = count($element_list); $i < $i_max; $i++) { for ($i = 0, $i_max = count($element_list); $i < $i_max; $i++) {
// $this->log->debug('form_error', 'Array: ' // $this->log->debug('form_error', 'Array: '
// . is_array($this->element_list[$element_list[$i]]['read_data']) . ' | ' // . is_array($this->element_list[$element_list[$i]]['read_data']) . ' | '
@@ -2294,11 +2284,9 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
} }
} }
} }
if (is_array($hidden_array)) { reset($hidden_array);
reset($hidden_array); foreach ($hidden_array as $key => $value) {
foreach ($hidden_array as $key => $value) { $hidden[] = ['key' => $key, 'value' => $value];
$hidden[] = ['key' => $key, 'value' => $value];
}
} }
return $hidden; return $hidden;
} }

View File

@@ -12,6 +12,7 @@ class Image
{ {
/** /**
* converts picture to a thumbnail with max x and max y size * 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 string $pic source image file with or without path
* @param int $size_x maximum size width * @param int $size_x maximum size width
@@ -22,7 +23,7 @@ class Image
* if empty ROOT is choosen * if empty ROOT is choosen
* @param string $cache_source cache path, if not given TMP is used * @param string $cache_source cache path, if not given TMP is used
* @param bool $clear_cache if set to true, will create thumb all the tame * @param bool $clear_cache if set to true, will create thumb all the tame
* @return string|bool thumbnail name, or false for error * @return string|false thumbnail name, or false for error
*/ */
public static function createThumbnail( public static function createThumbnail(
string $pic, string $pic,
@@ -32,7 +33,7 @@ class Image
string $path = '', string $path = '',
string $cache_source = '', string $cache_source = '',
bool $clear_cache = false bool $clear_cache = false
) { ): string|false {
// get image type flags // get image type flags
$image_types = [ $image_types = [
1 => 'gif', 1 => 'gif',
@@ -73,7 +74,7 @@ class Image
$create_file = false; $create_file = false;
$delete_filename = ''; $delete_filename = '';
// check if we can skip the PDF creation: if we have size, if do not have type, we assume type png // check if we can skip the PDF creation: if we have size, if do not have type, we assume type png
if (!$type && is_numeric($size_x) && is_numeric($size_y)) { if (!$type) {
$check_thumb = $tmp_src . 'thumb_' . $pic . '_' . $size_x . 'x' . $size_y . '.' . $image_types[3]; $check_thumb = $tmp_src . 'thumb_' . $pic . '_' . $size_x . 'x' . $size_y . '.' . $image_types[3];
if (!is_file($check_thumb)) { if (!is_file($check_thumb)) {
$create_file = true; $create_file = true;
@@ -100,10 +101,10 @@ class Image
[$width, $height, $type] = getimagesize($filename) ?: []; [$width, $height, $type] = getimagesize($filename) ?: [];
} }
// if no size given, set size to original // if no size given, set size to original
if (!$size_x || $size_x < 1 || !is_numeric($size_x)) { if (!$size_x || $size_x < 1) {
$size_x = $width; $size_x = $width;
} }
if (!$size_y || $size_y < 1 || !is_numeric($size_y)) { if (!$size_y || $size_y < 1) {
$size_y = $height; $size_y = $height;
} }
$thumb = 'thumb_' . $pic . '_' . $size_x . 'x' . $size_y . '.' . $image_types[$type]; $thumb = 'thumb_' . $pic . '_' . $size_x . 'x' . $size_y . '.' . $image_types[$type];
@@ -158,260 +159,275 @@ class Image
* if both are set, those are the max sizes (aspect ration is always ekpt) * 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 * - if path is not given will cache folder for current path set
* *
* @param string $filename source file name with full path * @param string $filename source file name with full path
* @param int $thumb_width thumbnail width * @param int $thumb_width thumbnail width
* @param int $thumb_height thumbnail height * @param int $thumb_height thumbnail height
* @param string|null $thumbnail_path altnerative path for thumbnails * @param string|null $cache_folder path for thumbnail cache
* @param bool $create_dummy if we encounter an invalid file * @param string|null $web_folder frontend path for output
* create a dummy image file and return it * @param bool $create_dummy if we encounter an invalid file
* @param bool $use_cache default to true, set to false to skip * create a dummy image file and return it
* creating new image if exists * @param bool $use_cache default to true, set to false to skip
* @param bool $high_quality default to true, uses sample version, * creating new image if exists
* set to false to not use (default true) * @param bool $high_quality default to true, uses sample version,
* to use quick but less nice version * set to false to not use (default true)
* @param int $jpeg_quality default 80, set image quality for jpeg only * to use quick but less nice version
* @return string|bool thumbnail with path * @param int $jpeg_quality default 80, set image quality for jpeg only
* @return string|false thumbnail with path
*/ */
public static function createThumbnailSimple( public static function createThumbnailSimple(
string $filename, string $filename,
int $thumb_width = 0, int $thumb_width = 0,
int $thumb_height = 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 $create_dummy = true,
bool $use_cache = true, bool $use_cache = true,
bool $high_quality = true, bool $high_quality = true,
int $jpeg_quality = 80 int $jpeg_quality = 80
) { ): string|false {
$thumbnail = false; $thumbnail = false;
// $this->debug('IMAGE PREPARE', "FILE: $filename (exists " // $this->debug('IMAGE PREPARE', "FILE: $filename (exists "
// .(string)file_exists($filename)."), WIDTH: $thumb_width, HEIGHT: $thumb_height"); // .(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 // check that input image exists and is either jpeg or png
// also fail if the basic CACHE folder does not exist at all // also fail if the basic CACHE folder does not exist at all
if ( if (
file_exists($filename) && !file_exists($filename) ||
is_dir(BASE . LAYOUT . CONTENT_PATH . CACHE) && !is_dir($cache_folder) ||
is_writable(BASE . LAYOUT . CONTENT_PATH . CACHE) !is_writable($cache_folder)
) { ) {
// $this->debug('IMAGE PREPARE', "FILENAME OK, THUMB WIDTH/HEIGHT OK"); return $thumbnail;
[$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: []; }
$thumbnail_write_path = null; // $this->debug('IMAGE PREPARE', "FILENAME OK, THUMB WIDTH/HEIGHT OK");
$thumbnail_web_path = null; [$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [];
// path set first $thumbnail_write_path = null;
if ( $thumbnail_web_path = null;
$img_type == IMAGETYPE_JPEG || // path set first
$img_type == IMAGETYPE_PNG || if (
$create_dummy === true $img_type == IMAGETYPE_JPEG ||
) { $img_type == IMAGETYPE_PNG ||
// $this->debug('IMAGE PREPARE', "IMAGE TYPE OK: ".$inc_width.'x'.$inc_height); $create_dummy === true
// set thumbnail paths ) {
$thumbnail_write_path = BASE . LAYOUT . CONTENT_PATH . CACHE . IMAGES; // $this->debug('IMAGE PREPARE', "IMAGE TYPE OK: ".$inc_width.'x'.$inc_height);
$thumbnail_web_path = LAYOUT . CACHE . IMAGES; // set thumbnail paths
// if images folder in cache does not exist create it, if failed, fall back to base cache folder $thumbnail_write_path = $cache_folder;
if (!is_dir($thumbnail_write_path)) { $thumbnail_web_path = $web_folder;
if (false === mkdir($thumbnail_write_path)) { }
$thumbnail_write_path = BASE . LAYOUT . CONTENT_PATH . CACHE; // do resize or fall back on dummy run
$thumbnail_web_path = LAYOUT . CACHE; 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 ($thumb_height == 0) {
if ( $thumb_height = $inc_height;
$img_type == IMAGETYPE_JPEG || }
$img_type == IMAGETYPE_PNG // check resize parameters
) { if ($inc_width > $thumb_width || $inc_height > $thumb_height) {
// if missing width or height in thumb, use the set one $thumb_width_r = 0;
if ($thumb_width == 0) { $thumb_height_r = 0;
$thumb_width = $inc_width; // we need to keep the aspect ration on longest side
} if (
if ($thumb_height == 0) { ($inc_height > $inc_width &&
$thumb_height = $inc_height; // and the height is bigger than thumb set
} $inc_height > $thumb_height) ||
// check resize parameters // or the height is smaller or equal width
if ($inc_width > $thumb_width || $inc_height > $thumb_height) { // but the width for the thumb is equal to the image height
$thumb_width_r = 0; ($inc_height <= $inc_width &&
$thumb_height_r = 0; $inc_width == $thumb_width
// we need to keep the aspect ration on longest side )
if ( ) {
($inc_height > $inc_width && // $this->debug('IMAGE PREPARE', 'HEIGHT > WIDTH');
// and the height is bigger than thumb set $ratio = $inc_height / $thumb_height;
$inc_height > $thumb_height) || $thumb_width_r = (int)ceil($inc_width / $ratio);
// or the height is smaller or equal width $thumb_height_r = $thumb_height;
// 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;
}
}
} else { } else {
// we just copy over the image as is, we never upscale // $this->debug('IMAGE PREPARE', 'WIDTH > HEIGHT');
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-' . $inc_width . 'x' . $inc_height; $ratio = $inc_width / $thumb_width;
if ( $thumb_width_r = $thumb_width;
$use_cache === false || $thumb_height_r = (int)ceil($inc_height / $ratio);
!file_exists($thumbnail_write_path . $thumbnail)
) {
copy($filename, $thumbnail_write_path . $thumbnail);
}
} }
// add output path // $this->debug('IMAGE PREPARE', "Ratio: $ratio, Target size $thumb_width_r x $thumb_height_r");
if ($thumbnail !== false) { // set output thumbnail name
$thumbnail = $thumbnail_web_path . $thumbnail; $thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-'
} . $thumb_width_r . 'x' . $thumb_height_r;
} 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 ( if (
$use_cache === false || $use_cache === false ||
!file_exists($thumbnail_write_path . $thumbnail) !file_exists($thumbnail_write_path . $thumbnail)
) { ) {
// if both are unset, set to 250 // image, copy source image, offset in image, source x/y, new size, source image size
if ($thumb_height == 0) { $thumb = imagecreatetruecolor($thumb_width_r, $thumb_height_r);
$thumb_height = 250;
}
if ($thumb_width == 0) {
$thumb_width = 250;
}
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
if ($thumb === false) { if ($thumb === false) {
return false; return false;
} }
// add outside border px = 5% (rounded up) if ($img_type == IMAGETYPE_PNG) {
// eg 50px -> 2.5px $imagecolorallocatealpha = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
$gray = imagecolorallocate($thumb, 200, 200, 200); if ($imagecolorallocatealpha === false) {
$white = imagecolorallocate($thumb, 255, 255, 255); return false;
if ($gray === false || $white === false) { }
return false; // preservere transaprency
imagecolortransparent(
$thumb,
$imagecolorallocatealpha
);
imagealphablending($thumb, false);
imagesavealpha($thumb, true);
} }
// fill gray background $source = null;
imagefill($thumb, 0, 0, $gray); switch ($img_type) {
// now create rectangle case IMAGETYPE_JPEG:
if (imagesx($thumb) < imagesy($thumb)) { $source = imagecreatefromjpeg($filename);
$width = (int)round(imagesx($thumb) / 100 * 5); 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 { } 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; $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 // either return false or the thumbnail name + output path web
return $thumbnail; return $thumbnail;
@@ -425,7 +441,7 @@ class Image
* @param string $filename path + filename to rotate. This file must be writeable * @param string $filename path + filename to rotate. This file must be writeable
* @return void * @return void
*/ */
public static function correctImageOrientation($filename): void public static function correctImageOrientation(string $filename): void
{ {
// function exists & file is writeable, else do nothing // function exists & file is writeable, else do nothing
if (!function_exists('exif_read_data') || !is_writeable($filename)) { if (!function_exists('exif_read_data') || !is_writeable($filename)) {

View File

@@ -160,23 +160,42 @@ class SmartyExtend extends \Smarty
* also registers the getvar caller plugin * also registers the getvar caller plugin
* *
* @param \CoreLibs\Language\L10n $l10n l10n language class * @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 // call basic smarty
// or Smarty::__construct(); // or Smarty::__construct();
parent::__construct(); parent::__construct();
// iinit lang // iinit lang
$this->l10n = $l10n; $this->l10n = $l10n;
// parse and read, legacy stuff // parse and read, legacy stuff
$locale = $this->l10n->getLocaleAsArray();
$this->encoding = $locale['encoding']; $this->encoding = $locale['encoding'];
$this->lang = $locale['lang']; $this->lang = $locale['lang'];
// get first part from lang $this->lang_short = $locale['lang_short'];
$this->lang_short = explode('_', $locale['lang'])[0]; $this->domain = $locale['domain'];
$this->domain = $this->l10n->getDomain(); $this->lang_dir = $locale['path'];
$this->locale_set = $this->l10n->getLocaleSet();
$this->lang_dir = $this->l10n->getBaseLocalePath();
// opt load functions so we can use legacy init for smarty run perhaps // opt load functions so we can use legacy init for smarty run perhaps
\CoreLibs\Language\L10n::loadFunctions(); \CoreLibs\Language\L10n::loadFunctions();
@@ -191,8 +210,8 @@ class SmartyExtend extends \Smarty
$this->page_name = \CoreLibs\Get\System::getPageName(); $this->page_name = \CoreLibs\Get\System::getPageName();
// set internal settings // set internal settings
$this->CACHE_ID = defined('CACHE_ID') ? CACHE_ID : ''; $this->CACHE_ID = $cache_id;
$this->COMPILE_ID = defined('COMPILE_ID') ? COMPILE_ID : ''; $this->COMPILE_ID = $compile_id;
} }
/** /**
@@ -256,11 +275,70 @@ class SmartyExtend extends \Smarty
* *
* @return void * @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 // master template
if (empty($this->MASTER_TEMPLATE_NAME)) { if (
$this->MASTER_TEMPLATE_NAME = MASTER_TEMPLATE_NAME; empty($this->MASTER_TEMPLATE_NAME)
) {
$this->MASTER_TEMPLATE_NAME = $set_master_template_name;
} }
// set include & template names // set include & template names
@@ -276,15 +354,15 @@ class SmartyExtend extends \Smarty
$this->CSS_TEMPLATE_NAME = str_replace('.tpl', '.css', $this->CONTENT_INCLUDE); $this->CSS_TEMPLATE_NAME = str_replace('.tpl', '.css', $this->CONTENT_INCLUDE);
// set basic template path (tmp) // set basic template path (tmp)
$this->INCLUDES = BASE . INCLUDES; // no longer in templates, only global $this->INCLUDES = $set_includes; // no longer in templates, only global
$this->TEMPLATE_PATH = BASE . INCLUDES . TEMPLATES . CONTENT_PATH; $this->TEMPLATE_PATH = $set_template_path;
$this->setTemplateDir($this->TEMPLATE_PATH); $this->setTemplateDir($this->TEMPLATE_PATH);
$this->JAVASCRIPT = LAYOUT . JS; $this->JAVASCRIPT = $set_javascript;
$this->CSS = LAYOUT . CSS; $this->CSS = $set_css;
$this->FONT = LAYOUT . FONT; $this->FONT = $set_font;
$this->PICTURES = LAYOUT . IMAGES; $this->PICTURES = $set_pictures;
$this->CACHE_PICTURES = LAYOUT . CACHE; $this->CACHE_PICTURES = $set_cache_pictures;
$this->CACHE_PICTURES_ROOT = ROOT . $this->CACHE_PICTURES; $this->CACHE_PICTURES_ROOT = $set_cache_pictures_root;
// check if we have an external file with the template name // check if we have an external file with the template name
if ( if (
file_exists($this->INCLUDES . $this->INC_TEMPLATE_NAME) && file_exists($this->INCLUDES . $this->INC_TEMPLATE_NAME) &&
@@ -305,7 +383,7 @@ class SmartyExtend extends \Smarty
// set all the additional CSS/JS parths // set all the additional CSS/JS parths
$this->setSmartCoreIncludeCssJs(); $this->setSmartCoreIncludeCssJs();
// check if template names exist // check if template names exist
if (!$this->MASTER_TEMPLATE_NAME) { if (empty($this->MASTER_TEMPLATE_NAME)) {
exit('MASTER TEMPLATE is not set'); exit('MASTER TEMPLATE is not set');
} elseif (!file_exists($this->getTemplateDir()[0] . DIRECTORY_SEPARATOR . $this->MASTER_TEMPLATE_NAME)) { } elseif (!file_exists($this->getTemplateDir()[0] . DIRECTORY_SEPARATOR . $this->MASTER_TEMPLATE_NAME)) {
// abort if master template could not be found // abort if master template could not be found
@@ -374,33 +452,183 @@ class SmartyExtend extends \Smarty
* wrapper call for setSmartyVars * wrapper call for setSmartyVars
* this is for frontend type and will not set any only admin needed variables * 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 \CoreLibs\Admin\Backend|null $cms Optinal Admin Backend for
* smarty variables merge
* @return void * @return void
*/ */
public function setSmartyVarsFrontend(): void public function setSmartyVarsFrontend(
{ array $options,
$this->setSmartyVars(); ?\CoreLibs\Admin\Backend $cms
): void {
$this->setSmartyVars(
false,
$cms,
$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,
$options['stylesheet'] ?? null,
$options['javascript'] ?? null
);
} }
/** /**
* wrapper call for setSmartyVars * wrapper call for setSmartyVars
* this is only for admin interface and will set additional variables * 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
* user_name :_SESSION['USER_NAME']
* @param \CoreLibs\Admin\Backend|null $cms Optinal Admin Backend for
* smarty variables merge
* @return void
*/ */
public function setSmartyVarsAdmin(): void public function setSmartyVarsAdmin(
{ array $options,
$this->setSmartyVars(true); ?\CoreLibs\Admin\Backend $cms = null
): void {
$this->setSmartyVars(
true,
$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['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 \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_user_name _SESSION['USER_NAME']
* @param string|null $set_stylesheet STYLESHEET
* @param string|null $set_javascript JAVASCRIPT
* @return void * @return void
*/ */
private function setSmartyVars($admin_call = false): void private function setSmartyVars(
{ bool $admin_call,
/** @var \CoreLibs\Admin\Backend This is an assumption */ ?\CoreLibs\Admin\Backend $cms = null,
global $cms; ?string $compile_dir = null,
if (is_object($cms)) { ?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_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
)
)
) {
/** @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_stylesheet = $set_stylesheet ?? STYLESHEET;
$set_javascript = $set_javascript ?? JAVASCRIPT;
$set_user_name = $set_user_name ?? $_SESSION['USER_NAME'] ?? '';
// 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;
if ($cms instanceof \CoreLibs\Admin\Backend) {
$this->mergeCmsSmartyVars($cms); $this->mergeCmsSmartyVars($cms);
} }
@@ -431,11 +659,11 @@ class SmartyExtend extends \Smarty
// default CMS settings // default CMS settings
// define all needed smarty stuff for the general HTML/page building // define all needed smarty stuff for the general HTML/page building
$this->HEADER['CSS'] = CSS; $this->HEADER['CSS'] = $set_css;
$this->HEADER['FONT'] = FONT; $this->HEADER['FONT'] = $set_font;
$this->HEADER['JS'] = JS; $this->HEADER['JS'] = $set_js;
$this->HEADER['ENCODING'] = $this->encoding; $this->HEADER['ENCODING'] = $this->encoding;
$this->HEADER['DEFAULT_ENCODING'] = DEFAULT_ENCODING; $this->HEADER['DEFAULT_ENCODING'] = $set_default_encoding;
// form name // form name
$this->DATA['FORM_NAME'] = !$this->FORM_NAME ? $this->DATA['FORM_NAME'] = !$this->FORM_NAME ?
@@ -445,7 +673,7 @@ class SmartyExtend extends \Smarty
// special for admin // special for admin
if ($admin_call === true) { if ($admin_call === true) {
// set ACL extra show // 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['show_ea_extra'] = $cms->acl['show_ea_extra'] ?? false;
$this->DATA['ADMIN'] = $cms->acl['admin'] ?? 0; $this->DATA['ADMIN'] = $cms->acl['admin'] ?? 0;
// top menu // top menu
@@ -461,11 +689,13 @@ class SmartyExtend extends \Smarty
$this->DATA['messages'] = []; $this->DATA['messages'] = [];
} }
// set style sheets // set style sheets
$this->HEADER['STYLESHEET'] = $this->ADMIN_STYLESHEET ? $this->ADMIN_STYLESHEET : ADMIN_STYLESHEET; $this->HEADER['STYLESHEET'] = !empty($this->ADMIN_STYLESHEET) ?
$this->HEADER['JAVASCRIPT'] = $this->ADMIN_JAVASCRIPT ? $this->ADMIN_JAVASCRIPT : ADMIN_JAVASCRIPT; $this->ADMIN_STYLESHEET : $set_admin_stylesheet;
$this->HEADER['JAVASCRIPT'] = !empty($this->ADMIN_JAVASCRIPT) ?
$this->ADMIN_JAVASCRIPT : $set_admin_javascript;
// the page name // the page name
$this->DATA['page_name'] = $this->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']; $this->DATA['form_name'] = $this->DATA['FORM_NAME'];
// for tinymce special // for tinymce special
$this->DATA['TINYMCE_LANG'] = $this->lang_short; $this->DATA['TINYMCE_LANG'] = $this->lang_short;
@@ -474,14 +704,16 @@ class SmartyExtend extends \Smarty
// debug data, if DEBUG flag is on, this data is print out // debug data, if DEBUG flag is on, this data is print out
$this->DEBUG_DATA['DEBUG'] = $this->DEBUG_TMPL; $this->DEBUG_DATA['DEBUG'] = $this->DEBUG_TMPL;
} else { } else {
$this->HEADER['STYLESHEET'] = $this->FRONTEND_STYLESHEET ? $this->FRONTEND_STYLESHEET : STYLESHEET; $this->HEADER['STYLESHEET'] = !empty($this->FRONTEND_STYLESHEET) ?
$this->HEADER['JAVASCRIPT'] = $this->FRONTEND_JAVASCRIPT ? $this->FRONTEND_JAVASCRIPT : JAVASCRIPT; $this->FRONTEND_STYLESHEET : $set_stylesheet;
$this->HEADER['JAVASCRIPT'] = !empty($this->FRONTEND_JAVASCRIPT) ?
$this->FRONTEND_JAVASCRIPT : $set_javascript;
} }
// html title // html title
// set local page title // set local page title
$this->HEADER['HTML_TITLE'] = !$this->L_TITLE ? $this->HEADER['HTML_TITLE'] = !$this->L_TITLE ?
ucfirst(str_replace('_', ' ', \CoreLibs\Get\System::getPageName(1))) 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); $this->l10n->__($this->L_TITLE);
// LANG // LANG
@@ -491,7 +723,7 @@ class SmartyExtend extends \Smarty
$this->DATA['JS_FLATPICKR'] = $this->JS_FLATPICKR; $this->DATA['JS_FLATPICKR'] = $this->JS_FLATPICKR;
$this->DATA['JS_FILE_UPLOADER'] = $this->JS_FILE_UPLOADER; $this->DATA['JS_FILE_UPLOADER'] = $this->JS_FILE_UPLOADER;
// user name // 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 // the template part to include into the body
$this->DATA['TEMPLATE_NAME'] = $this->TEMPLATE_NAME; $this->DATA['TEMPLATE_NAME'] = $this->TEMPLATE_NAME;
$this->DATA['CONTENT_INCLUDE'] = $this->CONTENT_INCLUDE; $this->DATA['CONTENT_INCLUDE'] = $this->CONTENT_INCLUDE;
@@ -499,16 +731,16 @@ class SmartyExtend extends \Smarty
$this->DATA['JS_TRANSLATE'] = $this->JS_TRANSLATE ?? null; $this->DATA['JS_TRANSLATE'] = $this->JS_TRANSLATE ?? null;
$this->DATA['PAGE_FILE_NAME'] = str_replace('.php', '', $this->page_name) . '.tpl'; $this->DATA['PAGE_FILE_NAME'] = str_replace('.php', '', $this->page_name) . '.tpl';
// render page // render page
$this->renderSmarty(); $this->renderSmarty($compile_dir, $cache_dir);
} }
/** /**
* merge outside object HEADER/DATA/DEBUG_DATA vars into the smarty class * merge outside object HEADER/DATA/DEBUG_DATA vars into the smarty class
* *
* @param object $cms object that has header/data/debug_data * @param \CoreLibs\Admin\Backend $cms object that has header/data/debug_data
* @return void * @return void
*/ */
public function mergeCmsSmartyVars(object $cms): void public function mergeCmsSmartyVars(\CoreLibs\Admin\Backend $cms): void
{ {
// array merge HEADER, DATA, DEBUG DATA // array merge HEADER, DATA, DEBUG DATA
foreach (['HEADER', 'DATA', 'DEBUG_DATA'] as $ext_smarty) { foreach (['HEADER', 'DATA', 'DEBUG_DATA'] as $ext_smarty) {
@@ -524,21 +756,39 @@ class SmartyExtend extends \Smarty
/** /**
* render smarty data (can be called sepparate) * render smarty data (can be called sepparate)
* *
* @param string|null $compile_dir BASE . TEMPLATES_C
* @param string|null $cache_dir BASE . CACHE
* @return void * @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 // create main data array
$this->CONTENT_DATA = array_merge($this->HEADER, $this->DATA, $this->DEBUG_DATA); $this->CONTENT_DATA = array_merge($this->HEADER, $this->DATA, $this->DEBUG_DATA);
// data is 1:1 mapping (all vars, values, etc) // data is 1:1 mapping (all vars, values, etc)
foreach ($this->CONTENT_DATA as $key => $value) { foreach ($this->CONTENT_DATA as $key => $value) {
$this->assign($key, $value); $this->assign($key, $value);
} }
if (is_dir(BASE . TEMPLATES_C)) { if (is_dir($compile_dir)) {
$this->setCompileDir(BASE . TEMPLATES_C); $this->setCompileDir($compile_dir);
} }
if (is_dir(BASE . CACHE)) { if (is_dir($cache_dir)) {
$this->setCacheDir(BASE . CACHE); $this->setCacheDir($cache_dir);
} }
$this->display( $this->display(
$this->MASTER_TEMPLATE_NAME, $this->MASTER_TEMPLATE_NAME,

View File

@@ -50,9 +50,22 @@ for (
is_file($__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php') is_file($__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php')
) { ) {
// load enviorment file if it exists // load enviorment file if it exists
\CoreLibs\Get\DotEnv::readEnvFile( \gullevek\dotEnv\DotEnv::readEnvFile(
$__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH $__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 // load master config file that loads all other config files
require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php'; require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php';
break; break;
@@ -62,17 +75,5 @@ for (
if (!defined('DIR')) { if (!defined('DIR')) {
exit('Base config could not be loaded'); 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__ // __END__

View 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__

View File

@@ -0,0 +1 @@
../Language/includes/

View File

@@ -0,0 +1 @@
../Debug/log/

View File

@@ -7,6 +7,14 @@ namespace tests;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\MockObject;
/*
Not yet covered tests:
- loginGetLocale
- loginGetHeaderColor
- loginGetPages
- loginGetEuid
*/
/** /**
* Test class for ACL\Login * Test class for ACL\Login
* @coversDefaultClass \CoreLibs\ACL\Login * @coversDefaultClass \CoreLibs\ACL\Login
@@ -120,8 +128,6 @@ final class CoreLibsACLLoginTest extends TestCase
// define('LOGIN_DB_SCHEMA', ''); // define('LOGIN_DB_SCHEMA', '');
// SHOULD SET // SHOULD SET
// PASSWORD_MIN_LENGTH (d9)
// PASSWORD_MAX_LENGTH (d255)
// DEFAULT_ACL_LEVEL (d80) // DEFAULT_ACL_LEVEL (d80)
// OPT: // OPT:
@@ -1106,7 +1112,22 @@ final class CoreLibsACLLoginTest extends TestCase
/** @var \CoreLibs\ACL\Login&MockObject */ /** @var \CoreLibs\ACL\Login&MockObject */
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class) $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']) ->onlyMethods(['loginTerminate', 'loginReadPageName', 'loginPrintLogin'])
->getMock(); ->getMock();
$login_mock->expects($this->any()) $login_mock->expects($this->any())
@@ -1729,7 +1750,7 @@ final class CoreLibsACLLoginTest extends TestCase
], ],
20 20
], ],
'invalud search' => [ 'invalid search' => [
12, 12,
'foo', 'foo',
[], [],
@@ -1774,7 +1795,22 @@ final class CoreLibsACLLoginTest extends TestCase
); );
/** @var \CoreLibs\ACL\Login&MockObject */ /** @var \CoreLibs\ACL\Login&MockObject */
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class) $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']) ->onlyMethods(['loginTerminate'])
->getMock(); ->getMock();
$login_mock->expects($this->any()) $login_mock->expects($this->any())
@@ -1873,7 +1909,22 @@ final class CoreLibsACLLoginTest extends TestCase
); );
/** @var \CoreLibs\ACL\Login&MockObject */ /** @var \CoreLibs\ACL\Login&MockObject */
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class) $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']) ->onlyMethods(['loginTerminate'])
->getMock(); ->getMock();
$login_mock->expects($this->any()) $login_mock->expects($this->any())
@@ -1946,7 +1997,22 @@ final class CoreLibsACLLoginTest extends TestCase
); );
/** @var \CoreLibs\ACL\Login&MockObject */ /** @var \CoreLibs\ACL\Login&MockObject */
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class) $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']) ->onlyMethods(['loginTerminate'])
->getMock(); ->getMock();
$login_mock->expects($this->any()) $login_mock->expects($this->any())
@@ -2027,7 +2093,22 @@ final class CoreLibsACLLoginTest extends TestCase
); );
/** @var \CoreLibs\ACL\Login&MockObject */ /** @var \CoreLibs\ACL\Login&MockObject */
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class) $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']) ->onlyMethods(['loginTerminate'])
->getMock(); ->getMock();
$login_mock->expects($this->any()) $login_mock->expects($this->any())

1
test/phpunit/ACL/includes Symbolic link
View File

@@ -0,0 +1 @@
../AAASetupData/includes

View File

@@ -107,6 +107,13 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
*/ */
public function arraySearchRecursiveAllProvider(): array public function arraySearchRecursiveAllProvider(): array
{ {
/*
0: $needle,
1: array $input,
2: ?string $key_search_for,
3: bool $flag,
4: array $expected
*/
return [ return [
'find value' => [ 'find value' => [
0 => 'bar', 0 => 'bar',
@@ -172,6 +179,13 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
*/ */
public function arraySearchSimpleProvider(): array public function arraySearchSimpleProvider(): array
{ {
/*
0: array $input,
1: $key,
2: $value,
3: bool $flag,
4: bool $expected
*/
return [ return [
'key/value exist' => [ 'key/value exist' => [
0 => self::$array, 0 => self::$array,
@@ -665,7 +679,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
* *
* @param array $input * @param array $input
* @param string|int $key * @param string|int $key
* @param string|int $value * @param string|int|bool $value
* @param bool $expected * @param bool $expected
* @return void * @return void
*/ */
@@ -724,7 +738,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
$warning = array_shift($arrays); $warning = array_shift($arrays);
// phpunit 10.0 compatible // phpunit 10.0 compatible
$this->expectExceptionMessage(($warning)); $this->expectExceptionMessage($warning);
\CoreLibs\Combined\ArrayHandler::arrayMergeRecursive(...$arrays); \CoreLibs\Combined\ArrayHandler::arrayMergeRecursive(...$arrays);

View File

@@ -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__

View File

@@ -1253,10 +1253,14 @@ final class CoreLibsDBIOTest extends TestCase
'string value literal' => ['string literal', 'tl', '\'string literal\'',], 'string value literal' => ['string literal', 'tl', '\'string literal\'',],
'empty string value literal' => ['', 'tl', '\'\'',], 'empty string value literal' => ['', 'tl', '\'\'',],
'null string value literal' => [null, 'tl', 'NULL',], 'null string value literal' => [null, 'tl', 'NULL',],
// ?d (I have no idea what that does, is like string) // escape string, but set all empty strings to null ('' is null)
'string value d' => ['string d', 'd', '\'string d\'',], 'string value d' => ['string d', 'd', '\'string d\'',],
'empty string value d' => ['', 'd', 'NULL',], 'empty string value d' => ['', 'd', 'NULL',],
'null string value d' => [null, 'd', 'NULL',], 'null string value d' => [null, 'd', 'NULL',],
// escape literal string, but set all empty strings to null ('' is null)
'string value literal d' => ['string d', 'dl', '\'string d\'',],
'empty string value literal d' => ['', 'dl', 'NULL',],
'null string value literal d' => [null, 'dl', 'NULL',],
// by bytea // by bytea
'string value d' => ['string d', 'by', '\x737472696e672064',], 'string value d' => ['string d', 'by', '\x737472696e672064',],
'empty string value d' => ['', 'by', 'NULL',], 'empty string value d' => ['', 'by', 'NULL',],
@@ -1281,7 +1285,7 @@ final class CoreLibsDBIOTest extends TestCase
* @dataProvider sqlEscapeProvider * @dataProvider sqlEscapeProvider
* @testdox Input value $input as $flag to $expected [$_dataName] * @testdox Input value $input as $flag to $expected [$_dataName]
* *
* @param int|float|string|null $input * @param int|float|string|bool|null $input
* @param string $flag * @param string $flag
* @param int|float|string $expected * @param int|float|string $expected
* @return void * @return void

View File

@@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
*/ */
final class CoreLibsDebugLoggingTest extends TestCase final class CoreLibsDebugLoggingTest extends TestCase
{ {
private const LOG_FOLDER = __DIR__ . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR;
/** /**
* test set for options BASIC * test set for options BASIC
* *
@@ -33,17 +34,20 @@ final class CoreLibsDebugLoggingTest extends TestCase
return [ return [
'log folder set' => [ '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, 'debug_all' => false,
'print_all' => false, 'print_all' => false,
], ],
[] []
], ],
'nothing set' => [ 'nothing set' => [
null, [
'file_id' => 'testClassInit'
],
[ [
'log_folder' => getcwd() . DIRECTORY_SEPARATOR, 'log_folder' => getcwd() . DIRECTORY_SEPARATOR,
'debug_all' => false, 'debug_all' => false,
@@ -51,30 +55,33 @@ final class CoreLibsDebugLoggingTest extends TestCase
], ],
[] []
], ],
'no options set, constant set' => [ 'no options set, constant set [DEPRECATED]' => [
null,
[ [
'log_folder' => str_replace('/configs', '', __DIR__) 'file_id' => 'testClassInit'
. DIRECTORY_SEPARATOR . 'log/', ],
[
'log_folder' => str_replace(DIRECTORY_SEPARATOR . 'configs', '', __DIR__)
. DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR,
'debug_all' => false, 'debug_all' => false,
'print_all' => false, 'print_all' => false,
], ],
[ [
'constant' => [ 'constant' => [
'BASE' => str_replace('/configs', '', __DIR__) 'BASE' => str_replace(DIRECTORY_SEPARATOR . 'configs', '', __DIR__)
. DIRECTORY_SEPARATOR, . DIRECTORY_SEPARATOR,
'LOG' => 'log/' 'LOG' => 'log' . DIRECTORY_SEPARATOR
] ]
] ]
], ],
'standard test set' => [ 'standard test set' => [
[ [
'log_folder' => '/tmp', 'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
'file_id' => 'testClassInit',
'debug_all' => true, 'debug_all' => true,
'print_all' => true, 'print_all' => true,
], ],
[ [
'log_folder' => '/tmp/', 'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
'debug_all' => true, 'debug_all' => true,
'print_all' => true, 'print_all' => true,
], ],
@@ -89,35 +96,66 @@ final class CoreLibsDebugLoggingTest extends TestCase
* @dataProvider optionsProvider * @dataProvider optionsProvider
* @testdox init test [$_dataName] * @testdox init test [$_dataName]
* *
* @param array|null $options * @param array $options
* @param array $expected * @param array $expected
* @param array $override * @param array $override
* @return void * @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'])) { if (!empty($override['constant'])) {
foreach ($override['constant'] as $var => $value) { 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) { // if not log folder and constant set -> expect E_USER_DEPRECATION
$log = new \CoreLibs\Debug\Logging(); if (!empty($override['constant']) && empty($options['log_folder'])) {
} else { // the deprecation message
$log = new \CoreLibs\Debug\Logging($options); $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\Logging($options);
// reset error handler
restore_error_handler();
// check that settings match // check that settings match
$this->assertEquals( $this->assertEquals(
$expected['log_folder'], $expected['log_folder'],
$log->getSetting('log_folder') $log->getSetting('log_folder'),
'log folder not matching'
); );
$this->assertEquals( $this->assertEquals(
$expected['debug_all'], $expected['debug_all'],
$log->getSetting('debug_output_all') $log->getSetting('debug_output_all'),
'debug all flag not matching'
); );
$this->assertEquals( $this->assertEquals(
$expected['print_all'], $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 "LOG: " . $log->getSetting('log_folder') . "\n";
// print "DEBUG: " . $log->getSetting('debug_output_all') . "\n"; // print "DEBUG: " . $log->getSetting('debug_output_all') . "\n";
@@ -134,17 +172,23 @@ final class CoreLibsDebugLoggingTest extends TestCase
// 0: options // 0: options
// 1: expected // 1: expected
// 2: override // 2: override
// 3: exception message
return [ return [
'no log id set' => [ 'no log id set' => [
null, [
'log_folder' => self::LOG_FOLDER,
],
[ [
'log_file_id' => '' 'log_file_id' => ''
], ],
[] [],
null
], ],
// set log id manually afterwards // set log id manually afterwards
'set log id manually' => [ 'set log id manually' => [
null, [
'log_folder' => self::LOG_FOLDER,
],
[ [
'log_file_id' => '', 'log_file_id' => '',
'set_log_file_id' => 'abc123', 'set_log_file_id' => 'abc123',
@@ -154,21 +198,26 @@ final class CoreLibsDebugLoggingTest extends TestCase
'values' => [ 'values' => [
'log_file_id' => 'abc123' 'log_file_id' => 'abc123'
] ]
] ],
null
], ],
// set log id from options // set log id from options
'set log id via options' => [ 'set log id via options' => [
[ [
'file_id' => 'abc456', 'file_id' => 'abc456',
'log_folder' => self::LOG_FOLDER,
], ],
[ [
'log_file_id' => 'abc456' 'log_file_id' => 'abc456'
], ],
[] [],
null
], ],
// set log id from GLOBALS [DEPRECATED] // set log id from GLOBALS [DEPRECATED]
'set log id via globals' => [ 'set log id via globals [DEPRECATED]' => [
null, [
'log_folder' => self::LOG_FOLDER,
],
[ [
'log_file_id' => 'def123' 'log_file_id' => 'def123'
], ],
@@ -176,11 +225,14 @@ final class CoreLibsDebugLoggingTest extends TestCase
'globals' => [ 'globals' => [
'LOG_FILE_ID' => 'def123' '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 from CONSTANT [DEPRECATED]
'set log id via constant' => [ 'set log id via constant [DEPRECATED]' => [
null, [
'log_folder' => self::LOG_FOLDER,
],
[ [
'log_file_id' => 'ghi123' 'log_file_id' => 'ghi123'
], ],
@@ -192,12 +244,14 @@ final class CoreLibsDebugLoggingTest extends TestCase
'constant' => [ 'constant' => [
'LOG_FILE_ID' => 'ghi123' 'LOG_FILE_ID' => 'ghi123'
] ]
] ],
'options: file_id must be set. Setting via LOG_FILE_ID constant is deprecated'
], ],
// invalid, keep previous set // invalid, keep previous set
'invalid log id' => [ 'invalid log id' => [
[ [
'file_id' => 'jkl456' 'file_id' => 'jkl456',
'log_folder' => self::LOG_FOLDER,
], ],
[ [
'log_file_id' => 'jkl456', 'log_file_id' => 'jkl456',
@@ -207,7 +261,8 @@ final class CoreLibsDebugLoggingTest extends TestCase
'values' => [ 'values' => [
'log_file_id' => './#' 'log_file_id' => './#'
] ]
] ],
null
] ]
]; ];
} }
@@ -219,13 +274,18 @@ final class CoreLibsDebugLoggingTest extends TestCase
* @dataProvider logIdOptionsProvider * @dataProvider logIdOptionsProvider
* @testdox log id set/get tests [$_dataName] * @testdox log id set/get tests [$_dataName]
* *
* @param array|null $options * @param array $options
* @param array $expected * @param array $expected
* @param array $override * @param array $override
* @param string|null $deprecation_message until we remove the old code
* @return void * @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 // we need to set with file_id option, globals LOG_FILE_ID, constant LOG_FILE_ID
if (!empty($override['constant'])) { if (!empty($override['constant'])) {
foreach ($override['constant'] as $var => $value) { foreach ($override['constant'] as $var => $value) {
@@ -237,11 +297,20 @@ final class CoreLibsDebugLoggingTest extends TestCase
$GLOBALS[$var] = $value; $GLOBALS[$var] = $value;
} }
} }
if ($options === null) { if (!empty($override['constant']) || !empty($override['globals'])) {
$log = new \CoreLibs\Debug\Logging(); // convert E_USER_DEPRECATED to a exception
} else { set_error_handler(
$log = new \CoreLibs\Debug\Logging($options); 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\Logging($options);
// reset error handler
restore_error_handler();
// check current // check current
$this->assertEquals( $this->assertEquals(
$log->getLogId(), $log->getLogId(),
@@ -316,7 +385,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
bool $expected_get bool $expected_get
): void { ): void {
// neutral start with default // neutral start with default
$log = new \CoreLibs\Debug\Logging(); $log = new \CoreLibs\Debug\Logging([
'file_id' => 'testSetGetLogLevelAll',
'log_folder' => self::LOG_FOLDER
]);
// set and check // set and check
$this->assertEquals( $this->assertEquals(
$log->setLogLevelAll($type, $flag), $log->setLogLevelAll($type, $flag),
@@ -438,7 +510,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
$expected_get $expected_get
): void { ): void {
// neutral start with default // neutral start with default
$log = new \CoreLibs\Debug\Logging(); $log = new \CoreLibs\Debug\Logging([
'file_id' => 'testSetGetLogLevel',
'log_folder' => self::LOG_FOLDER
]);
// set // set
$this->assertEquals( $this->assertEquals(
$log->setLogLevel($type, $flag, $debug_on), $log->setLogLevel($type, $flag, $debug_on),
@@ -517,7 +592,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
bool $expected_get bool $expected_get
): void { ): void {
// neutral start with default // neutral start with default
$log = new \CoreLibs\Debug\Logging(); $log = new \CoreLibs\Debug\Logging([
'file_id' => 'testSetGetLogPer',
'log_folder' => self::LOG_FOLDER
]);
// set and check // set and check
$this->assertEquals( $this->assertEquals(
$log->setLogPer($type, $set), $log->setLogPer($type, $set),
@@ -546,7 +624,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
public function testSetGetLogPrintFileDate(bool $input, bool $expected_set, bool $expected_get): void public function testSetGetLogPrintFileDate(bool $input, bool $expected_set, bool $expected_get): void
{ {
// neutral start with default // neutral start with default
$log = new \CoreLibs\Debug\Logging(); $log = new \CoreLibs\Debug\Logging([
'file_id' => 'testSetGetLogPrintFileDate',
'log_folder' => self::LOG_FOLDER
]);
// set and check // set and check
$this->assertEquals( $this->assertEquals(
$log->setGetLogPrintFileDate($input), $log->setGetLogPrintFileDate($input),
@@ -612,7 +693,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
*/ */
public function testPrAr(array $input, string $expected): void public function testPrAr(array $input, string $expected): void
{ {
$log = new \CoreLibs\Debug\Logging(); $log = new \CoreLibs\Debug\Logging([
'file_id' => 'testPrAr',
'log_folder' => self::LOG_FOLDER
]);
$this->assertEquals( $this->assertEquals(
$log->prAr($input), $log->prAr($input),
$expected $expected
@@ -673,7 +757,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
*/ */
public function testPrBl(bool $input, ?string $true, ?string $false, string $expected): void public function testPrBl(bool $input, ?string $true, ?string $false, string $expected): void
{ {
$log = new \CoreLibs\Debug\Logging(); $log = new \CoreLibs\Debug\Logging([
'file_id' => 'testPrBl',
'log_folder' => self::LOG_FOLDER
]);
$return = ''; $return = '';
if ($true === null && $false === null) { if ($true === null && $false === null) {
$return = $log->prBl($input); $return = $log->prBl($input);
@@ -959,9 +1046,16 @@ final class CoreLibsDebugLoggingTest extends TestCase
public function testLogUniqueId(bool $option, bool $override): void public function testLogUniqueId(bool $option, bool $override): void
{ {
if ($option === true) { if ($option === true) {
$log = new \CoreLibs\Debug\Logging(['per_run' => $option]); $log = new \CoreLibs\Debug\Logging([
'file_id' => 'testLogUniqueId',
'log_folder' => self::LOG_FOLDER,
'per_run' => $option
]);
} else { } else {
$log = new \CoreLibs\Debug\Logging(); $log = new \CoreLibs\Debug\Logging([
'file_id' => 'testLogUniqueId',
'log_folder' => self::LOG_FOLDER
]);
$log->setLogUniqueId(); $log->setLogUniqueId();
} }
$per_run_id = $log->getLogUniqueId(); $per_run_id = $log->getLogUniqueId();

3
test/phpunit/Debug/log/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*log
*LOG
!.gitignore

View File

@@ -77,21 +77,24 @@ final class CoreLibsGetDotEnvTest extends TestCase
'file' => 'cannot_read.env', 'file' => 'cannot_read.env',
'status' => 2, 'status' => 2,
'content' => [], 'content' => [],
'chmod' => '000', // 0000
'chmod' => '100000',
], ],
'empty file' => [ 'empty file' => [
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv', 'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
'file' => 'empty.env', 'file' => 'empty.env',
'status' => 1, 'status' => 1,
'content' => [], 'content' => [],
'chmod' => null, // 0664
'chmod' => '100664',
], ],
'override all' => [ 'override all' => [
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv', 'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
'file' => 'test.env', 'file' => 'test.env',
'status' => 0, 'status' => 0,
'content' => $dot_env_content, 'content' => $dot_env_content,
'chmod' => null, // 0664
'chmod' => '100664',
], ],
'override directory' => [ 'override directory' => [
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv', 'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
@@ -124,6 +127,16 @@ final class CoreLibsGetDotEnvTest extends TestCase
array $expected_env, array $expected_env,
?string $chmod ?string $chmod
): void { ): 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 // if we have file + chmod set
$old_chmod = null; $old_chmod = null;
if ( if (
@@ -134,6 +147,20 @@ final class CoreLibsGetDotEnvTest extends TestCase
$old_chmod = fileperms($folder . DIRECTORY_SEPARATOR . $file); $old_chmod = fileperms($folder . DIRECTORY_SEPARATOR . $file);
chmod($folder . DIRECTORY_SEPARATOR . $file, octdec($chmod)); 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) { if ($folder !== null && $file !== null) {
$status = DotEnv::readEnvFile($folder, $file); $status = DotEnv::readEnvFile($folder, $file);
} elseif ($folder !== null) { } elseif ($folder !== null) {
@@ -141,6 +168,7 @@ final class CoreLibsGetDotEnvTest extends TestCase
} else { } else {
$status = DotEnv::readEnvFile(); $status = DotEnv::readEnvFile();
} }
restore_error_handler();
$this->assertEquals( $this->assertEquals(
$status, $status,
$expected_status, $expected_status,
@@ -153,8 +181,9 @@ final class CoreLibsGetDotEnvTest extends TestCase
'Assert _ENV correct' 'Assert _ENV correct'
); );
// if we have file and chmod unset // if we have file and chmod unset
if ($old_chmod !== null) { print "Write mode: $old_chmod\n";
chmod($folder . DIRECTORY_SEPARATOR . $file, $old_chmod); if ($old_chmod !== null && $chmod == '100000') {
chmod($folder . DIRECTORY_SEPARATOR . $file, 0664);
} }
} }
} }

View File

@@ -0,0 +1,568 @@
<?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
{
public const SITE_ENCODING = 'UTF-8';
public const SITE_LOCALE = 'en_US.UTF-8';
public const SITE_DOMAIN = 'admin';
public const LOCALE_PATH = __DIR__ . DIRECTORY_SEPARATOR
. 'includes' . DIRECTORY_SEPARATOR
. 'locale' . DIRECTORY_SEPARATOR;
/**
* 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<mixed>
*/
/* public function setLocaleProvider(): array
{
return [
// 0: locale
// 1: domain
// 2: encoding
// 3: path
// 4: SESSION: DEFAULT_LOCALE
// 5: SESSION: DEFAULT_CHARSET
// 6: expected array
// 7: deprecation message
'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\/$/",
],
'setLocale: Unset $locale or unset SESSION locale is deprecated',
],
'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\/$/",
],
'setLocale: Unset $domain is deprecated'
],
'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\/$/",
],
'setLocale: Unset $domain is deprecated',
],
// 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\/$/",
],
'setLocale: Unset $domain is deprecated',
],
// 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\/$/",
],
'setLocale: Unset $domain is deprecated',
],
// 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\/$/",
],
'setLocale: Unset $path is deprecated',
],
// 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\/$/",
],
'setLocale: Unset $path is deprecated'
],
// 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\/$/",
],
null
],
// 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\/$/",
],
null
],
// 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\/$/",
],
'setLocale: Unset $path is deprecated',
],
// 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]
*
* @param string|null $language
* @param string|null $domain
* @param string|null $encoding
* @param string|null $path
* @param string|null $SESSION_DEFAULT_LOCALE
* @param string|null $SESSION_DEFAULT_CHARSET
* @param array<mixed> $expected
* @param string|null $deprecation_message
* @return void
*/
/* public function testsetLocale(
?string $language,
?string $domain,
?string $encoding,
?string $path,
?string $SESSION_DEFAULT_LOCALE,
?string $SESSION_DEFAULT_CHARSET,
array $expected,
?string $deprecation_message
): 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;
}
if ($deprecation_message !== null) {
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);
}
// 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
);
}
restore_error_handler();
// 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']);
} */
/**
* all the test data
*
* @return array<mixed>
*/
public function setLocaleFromSessionProvider(): array
{
return [
// 0: locale
// 1: domain
// 2: encoding
// 3: path
// 4: SESSION: DEFAULT_LOCALE
// 5: SESSION: DEFAULT_CHARSET
// 5: SESSION: DEFAULT_DOMAIN
// 6: SESSION: LOCALE_PATH
// 6: expected array
// 7: deprecation message
'all session vars set' => [
// lang, domain, encoding, path
self::SITE_LOCALE, self::SITE_DOMAIN, self::SITE_ENCODING, self::LOCALE_PATH,
// SESSION SETTINGS: locale, charset, domain, path
'ja_JP.UTF-8', 'UTF-8', 'admin', __DIR__ . '/locale_other/',
// return array
[
'locale' => 'ja_JP.UTF-8',
'lang' => 'ja_JP',
'domain' => 'admin',
'encoding' => 'UTF-8',
'path' => "/^\/(.*\/)?locale_other\/$/",
],
],
// param lang and domain (no override)
'no session set, only parameters' => [
// lang, domain, encoding, path
self::SITE_LOCALE, self::SITE_DOMAIN, self::SITE_ENCODING, self::LOCALE_PATH,
// SESSION SETTINGS: locale, charset, domain, path
null, null, null, null,
// return array
[
'locale' => 'en_US.UTF-8',
'lang' => 'en_US',
'domain' => 'admin',
'encoding' => 'UTF-8',
'path' => "/^\/(.*\/)?includes\/locale\/$/",
],
],
// special parse session check for locales
'all session vars set, short lang' => [
// lang, domain, encoding, path
self::SITE_LOCALE, self::SITE_DOMAIN, self::SITE_ENCODING, self::LOCALE_PATH,
// SESSION SETTINGS: locale, charset, domain, path
'ja', 'UTF-8', 'admin', __DIR__ . '/locale_other/',
// return array
[
'locale' => 'ja',
'lang' => 'ja',
'domain' => 'admin',
'encoding' => 'UTF-8',
'path' => "/^\/(.*\/)?locale_other\/$/",
],
],
// lang with modifier
// param lang and domain (no override)
'long locale, domain, encoding params, no sessions' => [
// lang, domain, encoding, path
self::SITE_LOCALE, self::SITE_DOMAIN, self::SITE_ENCODING, self::LOCALE_PATH,
// SESSION SETTINGS: locale, charset, domain, path
'de_CH.UTF-8@euro', 'admin', 'UTF-8', __DIR__ . '/includes/locale/',
// return array
[
'locale' => 'de_CH.UTF-8@euro',
'lang' => 'de_CH',
'domain' => 'admin',
'encoding' => 'UTF-8',
'path' => "/^\/(.*\/)?includes\/locale\/$/",
],
],
// missing session values check
// special parse session check for locales
'session missing encoding, set from parameters' => [
// lang, domain, encoding, path
self::SITE_LOCALE, self::SITE_DOMAIN, self::SITE_ENCODING, self::LOCALE_PATH,
// SESSION SETTINGS: locale, charset, domain, path
'ja', null, 'admin', __DIR__ . '/locale_other/',
// return array
[
'locale' => 'ja',
'lang' => 'ja',
'domain' => 'admin',
'encoding' => 'UTF-8',
'path' => "/^\/(.*\/)?locale_other\/$/",
],
],
// null return check for invalid entries
'no session set, only parameters, all invalid' => [
// lang, domain, encoding, path
'###', '&&&&', '$$$$', 'foo_bar_path',
// SESSION SETTINGS: locale, charset, domain, path
null, null, null, null,
// return array
[
'locale' => null,
'lang' => null,
'domain' => null,
'encoding' => null,
'path' => null,
],
],
// invalid session names, fall backup
'all session vars are invalid, fallback' => [
// lang, domain, encoding, path
self::SITE_LOCALE, self::SITE_DOMAIN, self::SITE_ENCODING, self::LOCALE_PATH,
// SESSION SETTINGS: locale, charset, domain, path
'###', '&&&&', '$$$$', 'foo_bar_path',
// return array
[
'locale' => 'en_US.UTF-8',
'lang' => 'en_US',
'domain' => 'admin',
'encoding' => 'UTF-8',
'path' => "/^\/(.*\/)?includes\/locale\/$/",
],
],
];
}
/**
* Undocumented function
*
* @covers ::setLocale
* @dataProvider setLocaleFromSessionProvider
* @testdox lang settings lang $language, domain $domain, encoding $encoding, path $path; session lang: $SESSION_DEFAULT_LOCALE, session char: $SESSION_DEFAULT_CHARSET [$_dataName]
*
* @param string| $language
* @param string| $domain
* @param string| $encoding
* @param string| $path
* @param string|null $SESSION_DEFAULT_LOCALE
* @param string|null $SESSION_DEFAULT_CHARSET
* @param string|null $SESSION_DEFAULT_DOMAIN
* @param string|null $SESSION_LOCALE_PATH
* @param array<mixed> $expected
* @return void
*/
public function testsetLocaleFromSession(
string $language,
string $domain,
string $encoding,
string $path,
?string $SESSION_DEFAULT_LOCALE,
?string $SESSION_DEFAULT_CHARSET,
?string $SESSION_DEFAULT_DOMAIN,
?string $SESSION_LOCALE_PATH,
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;
}
if ($SESSION_DEFAULT_DOMAIN !== null) {
$_SESSION['DEFAULT_DOMAIN'] = $SESSION_DEFAULT_DOMAIN;
}
if ($SESSION_LOCALE_PATH !== null) {
$_SESSION['LOCALE_PATH'] = $SESSION_LOCALE_PATH;
}
$return_lang_settings = \CoreLibs\Language\GetLocale::setLocaleFromSession(
$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 (
!empty($value) &&
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__

View File

@@ -22,37 +22,16 @@ final class CoreLibsLanguageL10nTest extends TestCase
*/ */
public static function setUpBeforeClass(): void public static function setUpBeforeClass(): void
{ {
// default web page encoding setting // for deprecation test only, will be removed
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')) { if (!defined('BASE')) {
define('BASE', str_replace('/configs', '', __DIR__) . DIRECTORY_SEPARATOR); define('BASE', str_replace(DIRECTORY_SEPARATOR . 'configs', '', __DIR__) . DIRECTORY_SEPARATOR);
} }
if (!defined('INCLUDES')) { if (!defined('INCLUDES')) {
define('INCLUDES', 'includes' . DIRECTORY_SEPARATOR); define('INCLUDES', 'includes' . DIRECTORY_SEPARATOR);
} }
if (!defined('LANG')) {
define('LANG', 'lang' . DIRECTORY_SEPARATOR);
}
if (!defined('LOCALE')) { if (!defined('LOCALE')) {
define('LOCALE', 'locale' . DIRECTORY_SEPARATOR); define('LOCALE', 'locale' . DIRECTORY_SEPARATOR);
} }
if (!defined('CONTENT_PATH')) {
define('CONTENT_PATH', 'frontend' . DIRECTORY_SEPARATOR);
}
} }
/** /**
@@ -105,77 +84,163 @@ final class CoreLibsLanguageL10nTest extends TestCase
{ {
return [ return [
// 0: locale // 0: locale
// 1: domain // 1: encoding
// 2: encoding // 2: domain
// 3: path // 3: path
// 4: locale expected // 4: locale expected
// 5: locale set expected // 5: locale set expected
// 6: domain exepcted // 6: lang expected
// 7: context (null for none) // 7: lang short expected
// 8: test string in // 8: encoding expected
// 9: test translated // 9: domain exepcted
// 10: context (null for none)
// 11: test string in
// 12: test translated
// 13: deprecation message (until removed)
// new style load // new style load
'gettext load en' => [ 'gettext load en' => [
'en_US.UTF-8', 'en_US.UTF-8',
'UTF-8',
'frontend', 'frontend',
__DIR__ . 'includes/locale/', __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// // 4, 5, 6, 7, 8, 9
'en_US.UTF-8', 'en_US.UTF-8',
'en_US', 'en_US',
'en_US',
'en',
'UTF-8',
'frontend', 'frontend',
// 10
null, null,
// 11, 12
'Original', 'Original',
'Translated frontend en_US', 'Translated frontend en_US',
// 13
null,
], ],
'gettext load en' => [ 'gettext load en' => [
'en_US.UTF-8', 'en_US.UTF-8',
'UTF-8',
'frontend', 'frontend',
__DIR__ . 'includes/locale/', __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// //
'en_US.UTF-8', 'en_US.UTF-8',
'en_US', 'en_US',
'en_US',
'en',
'UTF-8',
'frontend', 'frontend',
//
'context', 'context',
//
'Original', 'Original',
'Original context frontend en_US', 'Original context frontend en_US',
//
null,
], ],
'gettext load ja' => [ 'gettext load ja' => [
'ja_JP.UTF-8', 'ja_JP.UTF-8',
'UTF-8',
'admin', 'admin',
__DIR__ . 'includes/locale/', __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// //
'ja_JP.UTF-8', 'ja_JP.UTF-8',
'ja_JP', 'ja_JP',
'ja_JP',
'ja',
'UTF-8',
'admin', 'admin',
//
null, null,
//
'Original', 'Original',
'Translated admin ja_JP', 'Translated admin ja_JP',
//
null,
], ],
// mixed path and domain // load short locale with different encoding
'mixed path and domain' => [ 'gettext load short ja no encoding' => [
'ja',
'SJIS',
'admin',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
//
'ja',
'ja',
'ja',
'ja',
'SJIS',
'admin',
//
null,
//
'Original',
'Translated admin ja_JP',
//
null,
],
// mixed path and domain [DEPRECATED]
'mixed path and domain [DEPRECATED]' => [
'en_US.UTF-8', 'en_US.UTF-8',
__DIR__ . 'includes/locale/', 'UTF-8',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
'frontend', 'frontend',
// //
'en_US.UTF-8', 'en_US.UTF-8',
'en_US', 'en_US',
'en_US',
'en',
'UTF-8',
'frontend', 'frontend',
//
'context', 'context',
//
'Original', 'Original',
'Original context frontend en_US', 'Original context frontend en_US',
//
'L10n constructor parameter switch is no longer supported. domain is 2nd, path is 3rd parameter'
],
// unset path
'unset path with locale and domain [DEPRECATED]' => [
'ja_JP.UTF-8',
'UTF-8',
'admin',
null,
//
'ja_JP.UTF-8',
'ja_JP',
'ja_JP',
'ja',
'UTF-8',
'admin',
//
null,
//
'Original',
'Translated admin ja_JP',
//
'Empty path parameter is no longer allowed if locale and domain are set',
], ],
// null set // null set
'empty load new ' => [ 'empty load new ' => [
'', '',
'', '',
'', '',
'',
// //
'', '',
'', '',
'', '',
'',
'', // unset on empty call
'',
//
null, null,
//
'Original', 'Original',
'Original', 'Original',
//
null,
] ]
]; ];
} }
@@ -188,37 +253,62 @@ final class CoreLibsLanguageL10nTest extends TestCase
* @testdox check l10n init with Locale $locale, Path $path, Domain $domain, Legacy: $legacy with $context [$_dataName] * @testdox check l10n init with Locale $locale, Path $path, Domain $domain, Legacy: $legacy with $context [$_dataName]
* *
* @param string|null $locale * @param string|null $locale
* @param string|null $encoding
* @param string|null $domain * @param string|null $domain
* @param string|null $path * @param string|null $path
* @param string $locale_expected * @param string $locale_expected
* @param string $locale_set_expected * @param string $locale_set_expected
* @param string $lang_expected
* @param string $lang_short_expected
* @param string $encoding_expected
* @param string $domain_expected * @param string $domain_expected
* @param ?string $context * @param string|null $context
* @param string $original * @param string $original
* @param string $translated * @param string $translated
* @param string|null $deprecation_message
* @return void * @return void
*/ */
public function testL10nObject( public function testL10nObject(
?string $locale, ?string $locale,
?string $encoding,
?string $domain, ?string $domain,
?string $path, ?string $path,
string $locale_expected, string $locale_expected,
string $locale_set_expected, string $locale_set_expected,
string $lang_expected,
string $lang_short_expected,
string $encoding_expected,
string $domain_expected, string $domain_expected,
?string $context, ?string $context,
string $original, string $original,
string $translated string $translated,
?string $deprecation_message
): void { ): void {
if ($deprecation_message !== null) {
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);
}
if ($locale === null) { if ($locale === null) {
$l10n = new \CoreLibs\Language\L10n(); $l10n = new \CoreLibs\Language\L10n();
} elseif ($domain === null) { } elseif ($domain === null) {
// deprecated, locale + domain must be set, handled like empty calls
$l10n = new \CoreLibs\Language\L10n($locale); $l10n = new \CoreLibs\Language\L10n($locale);
} elseif ($path === null) { } elseif ($path === null) {
// deprecated, path must be set, will thow DEPRECATION error, handled like empty
$l10n = new \CoreLibs\Language\L10n($locale, $domain); $l10n = new \CoreLibs\Language\L10n($locale, $domain);
} else { } elseif ($encoding === null) {
// if encoding not found will be UTF-8
$l10n = new \CoreLibs\Language\L10n($locale, $domain, $path); $l10n = new \CoreLibs\Language\L10n($locale, $domain, $path);
} else {
$l10n = new \CoreLibs\Language\L10n($locale, $domain, $path, $encoding);
} }
// print "LOC: " . $locale . ", " . $l10n->getLocale() . ", " . $locale_expected . "\n"; restore_error_handler();
// print "MO: " . $l10n->getMoFile() . "\n"; // print "MO: " . $l10n->getMoFile() . "\n";
$this->assertEquals( $this->assertEquals(
$locale_expected, $locale_expected,
@@ -248,6 +338,20 @@ final class CoreLibsLanguageL10nTest extends TestCase
'Translated string assert failed in context: ' . $context 'Translated string assert failed in context: ' . $context
); );
} }
// test get locel as array
$locale = $l10n->getLocaleAsArray();
$this->assertEquals(
[
'locale' => $locale_expected,
'lang' => $lang_expected,
'lang_short' => $lang_short_expected,
'domain' => $domain_expected,
'encoding' => $encoding_expected,
'path' => $path
],
$locale,
'getLocaleAsArray mismatch'
);
} }
// l10nReloadMOfile and getTranslator // l10nReloadMOfile and getTranslator
@@ -283,7 +387,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
// set 0-2 // set 0-2
'en_US.UTF-8', 'en_US.UTF-8',
'frontend', 'frontend',
__DIR__ . 'includes/locale/', __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// status 3 // status 3
false, false,
// to translate 4 // to translate 4
@@ -296,7 +400,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
// set new 8-10 // set new 8-10
'ja_JP.UTF-8', 'ja_JP.UTF-8',
'frontend', 'frontend',
__DIR__ . 'includes/locale/', __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// status new 11 // status new 11
false, false,
// check new setter 12-14 // check new setter 12-14
@@ -322,7 +426,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
// set new 8-10 // set new 8-10
'en_US.UTF-8', 'en_US.UTF-8',
'frontend', 'frontend',
__DIR__ . 'includes/locale/', __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// status new 11 // status new 11
false, false,
// check new setter 12-14 // check new setter 12-14
@@ -387,12 +491,8 @@ final class CoreLibsLanguageL10nTest extends TestCase
string $domain_expected_b, string $domain_expected_b,
string $translated_b string $translated_b
): void { ): void {
if ($locale === null) { if ($locale === null || $domain === null || $path === null) {
$l10n = new \CoreLibs\Language\L10n(); $l10n = new \CoreLibs\Language\L10n();
} elseif ($domain === null) {
$l10n = new \CoreLibs\Language\L10n($locale);
} elseif ($path === null) {
$l10n = new \CoreLibs\Language\L10n($locale, $domain);
} else { } else {
$l10n = new \CoreLibs\Language\L10n($locale, $domain, $path); $l10n = new \CoreLibs\Language\L10n($locale, $domain, $path);
} }
@@ -494,16 +594,16 @@ final class CoreLibsLanguageL10nTest extends TestCase
{ {
return [ return [
// 0: locale // 0: locale
// 1: path // 1: domain
// 2: domain // 2: path
// 3: context (null for none) // 3: context (null for none)
// 4: single string // 4: single string
// 5: plural string // 5: plural string
// 6: array for each n value expected string // 6: array for each n value expected string
'plural text en' => [ 'plural text en' => [
'en_US', 'en_US',
__DIR__ . 'includes/locale/',
'admin', 'admin',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// context // context
null, null,
// text single/multi in // text single/multi in
@@ -518,8 +618,8 @@ final class CoreLibsLanguageL10nTest extends TestCase
], ],
'plural text context en' => [ 'plural text context en' => [
'en_US', 'en_US',
__DIR__ . 'includes/locale/',
'admin', 'admin',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// context // context
'context', 'context',
// text single/multi in // text single/multi in
@@ -544,8 +644,8 @@ final class CoreLibsLanguageL10nTest extends TestCase
* @testdox plural string test for locale $locale and domain $domain with $context [$_dataName] * @testdox plural string test for locale $locale and domain $domain with $context [$_dataName]
* *
* @param string $locale * @param string $locale
* @param string $path
* @param string $domain * @param string $domain
* @param string $path
* @param ?string $context * @param ?string $context
* @param string $original_single * @param string $original_single
* @param string $original_plural * @param string $original_plural
@@ -555,8 +655,8 @@ final class CoreLibsLanguageL10nTest extends TestCase
public function testNgettext( public function testNgettext(
// config 0-3 // config 0-3
string $locale, string $locale,
string $path,
string $domain, string $domain,
string $path,
// context string // context string
?string $context, ?string $context,
// input strings // input strings
@@ -565,7 +665,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
// expected // expected
array $expected_strings array $expected_strings
): void { ): void {
$l10n = new \CoreLibs\Language\L10n($locale, $path, $domain, false); $l10n = new \CoreLibs\Language\L10n($locale, $domain, $path);
foreach ($expected_strings as $n => $expected) { foreach ($expected_strings as $n => $expected) {
if (empty($context)) { if (empty($context)) {
@@ -981,7 +1081,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
'standard en' => [ 'standard en' => [
'en_US.UTF-8', 'en_US.UTF-8',
'frontend', 'frontend',
__DIR__ . 'includes/locale/', __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
'UTF-8', 'UTF-8',
'Original', 'Original',
'Translated frontend en_US', 'Translated frontend en_US',
@@ -989,7 +1089,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
'standard ja' => [ 'standard ja' => [
'ja_JP.UTF-8', 'ja_JP.UTF-8',
'admin', 'admin',
__DIR__ . 'includes/locale/', __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
'UTF-8', 'UTF-8',
'Original', 'Original',
'Translated admin ja_JP', 'Translated admin ja_JP',
@@ -1030,6 +1130,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
_textdomain($domain); _textdomain($domain);
_bindtextdomain($domain, $path); _bindtextdomain($domain, $path);
_bind_textdomain_codeset($domain, $encoding); _bind_textdomain_codeset($domain, $encoding);
$this->assertEquals( $this->assertEquals(
$translated, $translated,
__($original), __($original),

View File

@@ -0,0 +1 @@
ja_JP

Some files were not shown because too many files have changed in this diff Show More