Compare commits

..

12 Commits

89 changed files with 2481 additions and 1371 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
`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"
},
"require-dev": {
"phpstan/phpstan": "1.10.x-dev",
"phpstan/phpstan": "^1.10",
"phan/phan": "v5.x-dev",
"phpunit/phpunit": "^9",
"egrajp/smarty-extended": "^4.3"
"egrajp/smarty-extended": "^4.3",
"vimeo/psalm": "^5.0@dev"
},
"repositories": {
"git.egplusww.jp.Composer": {

View File

@@ -1 +1 @@
7.12.2
8.0.4

View File

@@ -11,7 +11,6 @@ fi;
# compare version, if different or newer, deploy
if [ -f "${file_last_published}" ]; then
LAST_PUBLISHED_VERSION=$(cat ${file_last_published});
echo "V: ${VERSION} | ${LAST_PUBLISHED_VERSION}";
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;

View File

@@ -131,6 +131,31 @@ class Login
// it will be set back to 255
/** @var int */
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 */
private $password_valid_chars = [
// '^(?=.*\d)(?=.*[A-Za-z])[0-9A-Za-z!@#$%]{8,}$',
@@ -167,6 +192,17 @@ class Login
/** @var bool */
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 */
public $log;
/** @var \CoreLibs\DB\IO database */
@@ -183,15 +219,14 @@ class Login
* @param \CoreLibs\DB\IO $db Database connection class
* @param \CoreLibs\Debug\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class
* @param bool $auto_login [default true] Auto login flag, legacy
* If set to true will run login
* during construction
* @param array<string,mixed> $options Login ACL settings
* $auto_login [default true] DEPRECATED, moved into options
*/
public function __construct(
\CoreLibs\DB\IO $db,
\CoreLibs\Debug\Logging $log,
\CoreLibs\Create\Session $session,
bool $auto_login = true
array $options = []
) {
// attach db class
$this->db = $db;
@@ -202,6 +237,13 @@ class Login
// attach session class
$this->session = $session;
// set and check options
if (false === $this->loginSetOptions($options)) {
// on failure, exit
echo "<b>Could not set options</b>";
$this->loginTerminate(4000);
}
// string key, msg: string, flag: e (error), o (ok)
$this->login_error_msg = [
'0' => [
@@ -339,7 +381,7 @@ class Login
$_SESSION['DEFAULT_ACL_LIST_TYPE'] = $this->default_acl_list_type;
// this will be deprecated
if ($auto_login === true) {
if ($this->options['auto_login'] === true) {
$this->loginMainCall();
}
}
@@ -384,6 +426,192 @@ class Login
// **** PRIVATE INTERNAL
// *************************************************************************
/**
* Set options
* Current allowed
* target <string>: site target
* debug <bool>
* auto_login <bool>: self start login process
* db_schema <string>
* password_min_length <int>
* default_acl_level <int>
* logout_target <string>: should default be '' or target path to where
* can_change <bool>: can change password (NOT IMPLEMENTED)
* forget_flow <boo>: reset password on forget (NOT IMPLEMENTED)
* locale_path <string>: absolue path to the locale folder
* site_locale <string>: what locale to load
* site_domain <string>: what domain (locale file name) to use
*
* @param array<string,mixed> $options Options array from class load
* @return bool True on ok, False on failure
*/
private function loginSetOptions(array $options): bool
{
// target and debug flag
if (
empty($options['target'])
) {
$options['target'] = 'test';
}
if (
empty($options['debug']) ||
!is_bool($options['debug'])
) {
$options['debug'] = false;
}
// AUTO LOGIN
if (
!isset($options['auto_login']) ||
!is_bool($options['auto_login'])
) {
// if set to true will run login call during class construction
$options['auto_login'] = false;
}
// DB SCHEMA
if (
empty($options['db_schema']) ||
// TODO more strict check
is_string($options['db_schema'])
) {
// get scham from db, else fallback to public
if (!empty($this->db->dbGetSchema(true))) {
$options['db_schema'] = $this->db->dbGetSchema(true);
} else {
$options['db_schema'] = 'public';
}
}
if ($this->db->dbGetSchema() != $options['db_schema']) {
$this->db->dbSetSchema($options['db_schema']);
}
// MIN PASSWORD LENGTH
// can only be in length of current defined min/max
if (
!empty($options['password_min_lenght']) &&
!is_numeric($options['password_min_length']) &&
$options['password_min_length'] >= self::PASSWORD_MIN_LENGTH &&
$options['password_min_length'] <= self::PASSWORD_MAX_LENGTH
) {
if (
false === $this->loginSetPasswordMinLength(
(int)$options['password_min_length']
)
) {
$options['password_min_length'] = self::PASSWORD_MIN_LENGTH;
}
}
// DEFAULT ACL LEVEL
if (
!isset($options['default_acl_level']) ||
!is_numeric($options['default_acl_level']) ||
$options['default_acl_level'] < 0 || $options['default_acl_level'] > 100
) {
$options['default_acl_level'] = 0;
if (defined('DEFAULT_ACL_LEVEL')) {
trigger_error(
'loginMainCall: DEFAULT_ACL_LEVEL should not be used',
E_USER_DEPRECATED
);
$options['default_acl_level'] = DEFAULT_ACL_LEVEL;
}
}
$this->default_acl_level = (int)$options['default_acl_level'];
// LOGOUT TARGET
if (!isset($options['logout_target'])) {
if (defined('LOGOUT_TARGET')) {
trigger_error(
'loginMainCall: LOGOUT_TARGET should not be used',
E_USER_DEPRECATED
);
$options['logout_target'] = LOGOUT_TARGET;
$this->logout_target = $options['logout_target'];
}
}
// *** PASSWORD SETTINGS
// User can change password
if (
!isset($options['can_change']) ||
!is_bool($options['can_change'])
) {
$options['can_change'] = false;
}
$this->password_change = $options['can_change'];
// User can trigger a forgot password flow
if (
!isset($options['forgot_flow']) ||
!is_bool($options['forgot_flow'])
) {
$options['forgot_flow'] = false;
}
$this->password_forgot = $options['forgot_flow'];
// *** LANGUAGE
// LANG: LOCALE PATH
if (empty($options['locale_path'])) {
// trigger deprecation error
trigger_error(
'loginSetOptions: misssing locale_path entry is deprecated',
E_USER_DEPRECATED
);
// set path
$options['locale_path'] = BASE . INCLUDES . LOCALE;
}
$_SESSION['LOCALE_PATH'] = $options['locale_path'];
// LANG: LOCALE
if (empty($options['site_locale'])) {
trigger_error(
'loginMainCall: SITE_LOCALE should not be used',
E_USER_DEPRECATED
);
$options['site_locale'] = defined('SITE_LOCALE') && !empty(SITE_LOCALE) ?
SITE_LOCALE : 'en.UTF-8';
}
// LANG: DOMAIN
if (empty($options['site_domain'])) {
// we need to get domain set from outside
$options['site_domain'] = 'admin';
if (
defined('SITE_DOMAIN')
) {
// trigger deprecation error
trigger_error(
'loginSetOptions: misssing site_domain entry is deprecated (SITE_DOMAIN)',
E_USER_DEPRECATED
);
// set domain
$options['site_domain'] = SITE_DOMAIN;
} elseif (
defined('CONTENT_PATH')
) {
// trigger deprecation error
trigger_error(
'loginSetOptions: misssing site_domain entry is deprecated (CONTENT_PATH)',
E_USER_DEPRECATED
);
$options['set_domain'] = str_replace(DIRECTORY_SEPARATOR, '', CONTENT_PATH);
}
}
$_SESSION['DEFAULT_DOMAIN'] = $options['site_domain'];
// LANG: ENCODING
if (empty($options['site_encoding'])) {
trigger_error(
'loginMainCall: SITE_ENCODING should not be used',
E_USER_DEPRECATED
);
$options['site_encoding'] = defined('SITE_ENCODING') && !empty(SITE_ENCODING) ?
SITE_ENCODING : 'UTF-8';
}
// write array to options
$this->options = $options;
return true;
}
/**
* Checks for all flags and sets error codes for each
* In order:
@@ -691,6 +919,7 @@ class Login
// rgb: nnn.n for each
// hsl: nnn.n for first, nnn.n% for 2nd, 3rd
// Check\Colors::validateColor()
// LANGUAGE/LOCALE/ENCODING:
$_SESSION['LANG'] = $res['locale'] ?? 'en';
$_SESSION['DEFAULT_CHARSET'] = $res['encoding'] ?? 'UTF-8';
$_SESSION['DEFAULT_LOCALE'] = $_SESSION['LANG']
@@ -980,6 +1209,65 @@ class Login
// $this->debug('ACL', $this->print_ar($this->acl));
}
/**
* set locale
* if invalid, set to empty string
*
* @return void
*/
private function loginSetLocale(): void
{
// ** LANGUAGE SET AFTER LOGIN **
// set the locale
if (
!empty($_SESSION['DEFAULT_LOCALE']) &&
preg_match("/^[-A-Za-z0-9_.@]+$/", $_SESSION['DEFAULT_LOCALE'])
) {
$locale = $_SESSION['DEFAULT_LOCALE'];
} elseif (
!preg_match("/^[-A-Za-z0-9_.@]+$/", $this->options['site_locale'])
) {
$locale = $this->options['site_locale'];
} else {
$locale = '';
}
// set the charset
preg_match('/(?:\\.(?P<charset>[-A-Za-z0-9_]+))/', $locale, $matches);
$locale_encoding = $matches['charset'] ?? '';
if (!empty($locale_encoding)) {
$encoding = strtoupper($locale_encoding);
} elseif (
!empty($_SESSION['DEFAULT_CHARSET']) &&
preg_match("/^[-A-Za-z0-9_]+$/", $_SESSION['DEFAULT_CHARSET'])
) {
$encoding = $_SESSION['DEFAULT_CHARSET'];
} elseif (
!preg_match("/^[-A-Za-z0-9_]+$/", $this->options['site_encoding'])
) {
$encoding = $this->options['site_encoding'];
} else {
$encoding = '';
}
// check domain
$domain = $this->options['site_domain'];
if (
!preg_match("/^\w+$/", $this->options['site_domain'])
) {
$domain = '';
}
$path = $this->options['locale_path'];
if (!is_dir($path)) {
$path = '';
}
// domain and path are a must set from class options
$this->locale = [
'locale' => $locale,
'domain' => $domain,
'encoding' => $encoding,
'path' => $path,
];
}
/**
* checks if the password is in a valid format
*
@@ -1513,50 +1801,9 @@ EOM;
echo '<b>No active session found</b>';
$this->loginTerminate(2000);
}
// if we have a search path we need to set it, to use the correct DB to login
// check what schema to use. if there is a login schema use this, else check
// if there is a schema set in the config, or fall back to DB_SCHEMA
// if this exists, if this also does not exists use public schema
/** @phpstan-ignore-next-line */
if (defined('LOGIN_DB_SCHEMA') && !empty(LOGIN_DB_SCHEMA)) {
$SCHEMA = LOGIN_DB_SCHEMA;
} elseif (!empty($this->db->dbGetSchema(true))) {
$SCHEMA = $this->db->dbGetSchema(true);
} elseif (defined('PUBLIC_SCHEMA')) {
$SCHEMA = PUBLIC_SCHEMA;
} else {
$SCHEMA = 'public';
}
// set schema if schema differs to schema set in db conneciton
if ($this->db->dbGetSchema() != $SCHEMA) {
$this->db->dbExec("SET search_path TO " . $SCHEMA);
}
// set internal page name
$this->page_name = $this->loginReadPageName();
// set default ACL Level
if (defined('DEFAULT_ACL_LEVEL')) {
$this->default_acl_level = DEFAULT_ACL_LEVEL;
}
if (defined('PASSWORD_MIN_LENGTH')) {
$this->password_min_length = PASSWORD_MIN_LENGTH;
$this->password_min_length_max = PASSWORD_MIN_LENGTH;
}
if (defined('PASSWORD_MIN_LENGTH')) {
$this->password_max_length = PASSWORD_MAX_LENGTH;
}
// pre-check that password min/max lengths are inbetween 1 and 255;
if ($this->password_max_length > 255) {
$this->password_max_length = 255;
}
if ($this->password_min_length < 1) {
$this->password_min_length = 1;
}
// set global is ajax page for if we show the data directly,
// or need to pass it back
// to the continue AJAX class for output back to the user
@@ -1608,20 +1855,8 @@ EOM;
$this->pw_old_password = $_POST['pw_old_password'] ?? '';
$this->pw_new_password = $_POST['pw_new_password'] ?? '';
$this->pw_new_password_confirm = $_POST['pw_new_password_confirm'] ?? '';
// logout target (from config)
if (defined('LOGOUT_TARGET')) {
$this->logout_target = LOGOUT_TARGET;
}
// disallow user list for password change
$this->pw_change_deny_users = ['admin'];
// set flag if password change is okay
if (defined('PASSWORD_CHANGE')) {
$this->password_change = PASSWORD_CHANGE;
}
// NOTE: forgot password flow with email
if (defined('PASSWORD_FORGOT')) {
$this->password_forgot = PASSWORD_FORGOT;
}
// max login counts before error reporting
$this->max_login_error_count = 10;
// users that never get locked, even if they are set strict
@@ -1634,26 +1869,13 @@ EOM;
// logsout user
$this->loginLogoutUser();
// ** LANGUAGE SET AFTER LOGIN **
// set the locale
if (
$this->session->checkActiveSession() === true &&
!empty($_SESSION['DEFAULT_LOCALE'])
) {
$locale = $_SESSION['DEFAULT_LOCALE'];
} else {
$locale = (defined('SITE_LOCALE') && !empty(SITE_LOCALE)) ?
SITE_LOCALE :
/** @phpstan-ignore-next-line DEFAULT_LOCALE could be empty */
((defined('DEFAULT_LOCALE') && !empty(DEFAULT_LOCALE)) ?
DEFAULT_LOCALE : 'en.UTF-8');
}
// set domain
if (defined('CONTENT_PATH')) {
$domain = str_replace('/', '', CONTENT_PATH);
} else {
$domain = 'admin';
}
$this->l = new \CoreLibs\Language\L10n($locale, $domain);
$this->loginSetLocale();
// load translator
$this->l = new \CoreLibs\Language\L10n(
$this->locale['locale'],
$this->locale['domain'],
$this->locale['path']
);
// if the password change flag is okay, run the password change method
if ($this->password_change) {
$this->loginPasswordChange();
@@ -1669,18 +1891,21 @@ EOM;
// if variable AJAX flag is not set, show output
// else pass through for ajax work
if ($this->login_is_ajax_page === false) {
// the login screen if we hav no login permission & login screen html data
// the login screen if we hav no login permission and
// login screen html data
if ($this->login_html !== null) {
// echo $this->login_html;
$this->loginPrintLogin();
}
// do not go anywhere, quit processing here
// do something with possible debug data?
if (TARGET == 'live' || TARGET == 'remote') {
if (
in_array($this->options['target'], ['live', 'remove'])
) {
// login
$this->log->setLogLevelAll('debug', DEBUG ? true : false);
$this->log->setLogLevelAll('debug', $this->options['debug']);
$this->log->setLogLevelAll('echo', false);
$this->log->setLogLevelAll('print', DEBUG ? true : false);
$this->log->setLogLevelAll('print', $this->options['debug']);
}
$status_msg = $this->log->printErrorMsg();
// if ($this->echo_output_all) {
@@ -1802,7 +2027,7 @@ EOM;
if (
$length >= $this->password_min_length_max &&
$length <= $this->password_max_length &&
$length <= 255
$length <= self::PASSWORD_MAX_LENGTH
) {
$this->password_min_length = $length;
return true;
@@ -2223,6 +2448,53 @@ EOM;
): bool|string {
return $this->loginGetEditAccessData($edit_access_id, $data_key);
}
/**
* Return locale settings with
* locale
* domain
* encoding
* path
*
* empty string if not set
*
* @return array<string,string> Locale settings
*/
public function loginGetLocale(): array
{
return $this->locale;
}
/**
* return header color or null for not set
*
* @return string|null Header color in RGB hex with leading sharp
*/
public function loginGetHeaderColor(): ?string
{
return $_SESSION['HEADER_COLOR'] ?? null;
}
/**
* Return the current loaded list of pages the user can access
*
* @return array<mixed>
*/
public function loginGetPages(): array
{
return $_SESSION['PAGES'] ?? [];
}
/**
* Get the current set EUID (edit user id)
*
* @return string EUID as string
*/
public function loginGetEuid(): string
{
return $this->euid;
}
}
// __END__

View File

@@ -121,14 +121,14 @@ class Backend
* @param \CoreLibs\Debug\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class
* @param \CoreLibs\Language\L10n $l10n l10n language class
* @param array<string,string> $locale locale data read from setLocale
* @param int|null $set_default_acl_level Default ACL level
*/
public function __construct(
\CoreLibs\DB\IO $db,
\CoreLibs\Debug\Logging $log,
\CoreLibs\Create\Session $session,
\CoreLibs\Language\L10n $l10n,
array $locale
?int $set_default_acl_level = null
) {
// attach db class
$this->db = $db;
@@ -141,12 +141,12 @@ class Backend
// get the language sub class & init it
$this->l = $l10n;
// parse and read, legacy stuff
$locale = $this->l->getLocaleAsArray();
$this->encoding = $locale['encoding'];
$this->lang = $locale['lang'];
// get first part from lang
$this->lang_short = explode('_', $locale['lang'])[0];
$this->domain = $this->l->getDomain();
$this->lang_dir = $this->l->getBaseLocalePath();
$this->lang_short = $locale['lang_short'];
$this->domain = $locale['domain'];
$this->lang_dir = $locale['path'];
// set the page name
$this->page_name = \CoreLibs\Get\System::getPageName();
@@ -156,7 +156,14 @@ class Backend
$this->$_action = $_POST[$_action] ?? '';
}
$this->default_acl = DEFAULT_ACL_LEVEL;
if ($set_default_acl_level === null) {
/** @deprecated Admin::__construct missing default_acl_level parameter */
trigger_error(
'Calling Admin::__construct without default_acl_level parameter is deprecated',
E_USER_DEPRECATED
);
}
$this->default_acl = $set_default_acl_level ?? DEFAULT_ACL_LEVEL;
// queue key
if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action)) {
@@ -190,35 +197,34 @@ class Backend
* @param string $event any kind of event description,
* @param string|array<mixed> $data any kind of data related to that event
* @param string $write_type write type can bei STRING or BINARY
* @param string|null $db_schema override target schema
* @return void
*/
public function adbEditLog(
string $event = '',
string|array $data = '',
string $write_type = 'STRING'
string $write_type = 'STRING',
?string $db_schema = null
): void {
$data_binary = '';
$data_write = '';
if ($write_type == 'BINARY') {
$data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data)));
$data = 'see bzip compressed data_binary field';
$data_write = 'see bzip compressed data_binary field';
}
if ($write_type == 'STRING') {
$data_binary = '';
$data = $this->db->dbEscapeString(serialize($data));
$data_write = $this->db->dbEscapeString(serialize($data));
}
// check schema
$SCHEMA = 'public';
/** @phpstan-ignore-next-line */
if (defined('LOGIN_DB_SCHEMA') && !empty(LOGIN_DB_SCHEMA)) {
$SCHEMA = LOGIN_DB_SCHEMA;
} elseif ($this->db->dbGetSchema()) {
$SCHEMA = $this->db->dbGetSchema();
} elseif (defined('PUBLIC_SCHEMA')) {
$SCHEMA = PUBLIC_SCHEMA;
/** @var string $DB_SCHEMA check schema */
$DB_SCHEMA = 'public';
if ($db_schema !== null) {
$DB_SCHEMA = $db_schema;
} elseif (!empty($this->db->dbGetSchema())) {
$DB_SCHEMA = $this->db->dbGetSchema();
}
/** @phpstan-ignore-next-line for whatever reason $SCHEMA is seen as possible array */
$q = "INSERT INTO " . $SCHEMA . ".edit_log "
$q = "INSERT INTO " . $DB_SCHEMA . ".edit_log "
. "(euid, event_date, event, data, data_binary, page, "
. "ip, user_agent, referer, script_name, query_string, server_name, http_host, "
. "http_accept, http_accept_charset, http_accept_encoding, session_id, "
@@ -229,10 +235,12 @@ class Backend
'NULL')
. ", "
. "NOW(), "
. "'" . $this->db->dbEscapeString((string)$event) . "', '" . $data . "', "
. "'" . $data_binary . "', '" . $this->db->dbEscapeString((string)$this->page_name) . "', "
. "'" . @$_SERVER["REMOTE_ADDR"] . "', "
. "'" . $this->db->dbEscapeString(@$_SERVER['HTTP_USER_AGENT']) . "', "
. "'" . $this->db->dbEscapeString((string)$event) . "', "
. "'" . $data_write . "', "
. "'" . $data_binary . "', "
. "'" . $this->db->dbEscapeString((string)$this->page_name) . "', "
. "'" . ($_SERVER["REMOTE_ADDR"] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_USER_AGENT'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_REFERER'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['SCRIPT_FILENAME'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['QUERY_STRING'] ?? '') . "', "
@@ -282,11 +290,25 @@ class Backend
/**
* menu creater (from login menu session pages)
*
* @param int $flag visible flag trigger
* @param string|null $set_content_path
* @param int $flag visible flag trigger
* @return array<mixed> menu array for output on page (smarty)
*/
public function adbTopMenu(int $flag = 0): array
{
public function adbTopMenu(
?string $set_content_path = null,
int $flag = 0,
): array {
if (
$set_content_path === null ||
!is_string($set_content_path)
) {
/** @deprecated adbTopMenu missing set_content_path parameter */
trigger_error(
'Calling adbTopMenu without set_content_path parameter is deprecated',
E_USER_DEPRECATED
);
}
$set_content_path = $set_content_path ?? CONTENT_PATH;
if ($this->menu_show_flag) {
$flag = $this->menu_show_flag;
}
@@ -377,7 +399,7 @@ class Backend
\CoreLibs\Get\System::getPageName() == $data['filename'] &&
(!isset($data['hostname']) || (
isset($data['hostname']) &&
(!$data['hostname'] || strstr($data['hostname'], CONTENT_PATH) !== false)
(!$data['hostname'] || strstr($data['hostname'], $set_content_path) !== false)
))
) {
$selected = 1;
@@ -427,69 +449,6 @@ class Backend
};
return $enabled;
}
/**
* creates out of a normal db_return array an assoc array
*
* @param array<mixed> $db_array input array
* @param string|int|bool $key key
* @param string|int|bool $value value
* @return array<mixed> associative array
* @deprecated \CoreLibs\Combined\ArrayHandler::genAssocArray()
*/
public function adbAssocArray(array $db_array, string|int|bool $key, string|int|bool $value): array
{
trigger_error(
'Method ' . __METHOD__ . ' is deprecated: \CoreLibs\Combined\ArrayHandler::genAssocArray',
E_USER_DEPRECATED
);
return \CoreLibs\Combined\ArrayHandler::genAssocArray($db_array, $key, $value);
}
/**
* converts bytes into formated string with KB, MB, etc
*
* @param string|int|float $number string or int or number
* @return string formatted string
* @deprecated \CoreLibs\Convert\Byte::humanReadableByteFormat()
*/
public function adbByteStringFormat(string|int|float $number): string
{
trigger_error(
'Method ' . __METHOD__ . ' is deprecated: \CoreLibs\Convert\Byte::humanReadableByteFormat()',
E_USER_DEPRECATED
);
return \CoreLibs\Convert\Byte::humanReadableByteFormat($number);
}
/**
* converts picture to a thumbnail with max x and max y size
*
* @param string $pic source image file with or without path
* @param int $size_x maximum size width
* @param int $size_y maximum size height
* @param string $dummy empty, or file_type to show an icon
* instead of nothing if file is not found
* @param string $path if source start is not ROOT path
* if empty ROOT is choosen
* @return string|bool thumbnail name, or false for error
* @deprecated \CoreLibs\Output\Image::createThumbnail()
*/
public function adbCreateThumbnail(
string $pic,
int $size_x,
int $size_y,
string $dummy = '',
string $path = '',
string $cache = ''
): string|bool {
trigger_error(
'Method ' . __METHOD__ . ' is deprecated: \CoreLibs\Output\Image::createThumbnail()',
E_USER_DEPRECATED
);
return \CoreLibs\Output\Image::createThumbnail($pic, $size_x, $size_y, $dummy, $path, $cache);
}
/**
* wrapper function to fill up the mssages array
*
@@ -523,15 +482,16 @@ class Backend
/**
* writes live queue
*
* @param string $queue_key string to identfy the queue
* @param string $type [description]
* @param string $target [description]
* @param string $data [description]
* @param string $key_name [description]
* @param string $key_value [description]
* @param ?string $associate [description]
* @param ?string $file [description]
* @return void has no return
* @param string $queue_key string to identfy the queue
* @param string $type [description]
* @param string $target [description]
* @param string $data [description]
* @param string $key_name [description]
* @param string $key_value [description]
* @param string|null $associate [description]
* @param string|null $file [description]
* @param string|null $db_schema override target schema
* @return void
*/
public function adbLiveQueue(
string $queue_key,
@@ -541,19 +501,17 @@ class Backend
string $key_name,
string $key_value,
string $associate = null,
string $file = null
string $file = null,
string $db_schema = null,
): void {
/** @phpstan-ignore-next-line */
if (defined('GLOBAL_DB_SCHEMA') && !empty(GLOBAL_DB_SCHEMA)) {
$SCHEMA = GLOBAL_DB_SCHEMA;
} elseif ($this->db->dbGetSchema()) {
$SCHEMA = $this->db->dbGetSchema();
} elseif (defined('PUBLIC_SCHEMA')) {
$SCHEMA = PUBLIC_SCHEMA;
} else {
$SCHEMA = 'public';
/** @var string $DB_SCHEMA check schema */
$DB_SCHEMA = 'public';
if ($db_schema !== null) {
$DB_SCHEMA = $db_schema;
} elseif (!empty($this->db->dbGetSchema())) {
$DB_SCHEMA = $this->db->dbGetSchema();
}
$q = "INSERT INTO " . $SCHEMA . ".live_queue ("
$q = "INSERT INTO " . $DB_SCHEMA . ".live_queue ("
. "queue_key, key_value, key_name, type, target, data, group_key, action, associate, file"
. ") VALUES ("
. "'" . $this->db->dbEscapeString($queue_key) . "', '" . $this->db->dbEscapeString($key_value) . "', "

View File

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

View File

@@ -989,7 +989,7 @@ class Basic
int $jpeg_quality = 80
) {
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Output\Image::createThumbnailSimple()', E_USER_DEPRECATED);
return \CoreLibs\Output\Image::createThumbnailSimple($filename, $thumb_width, $thumb_height, $thumbnail_path, $create_dummy, $use_cache, $high_quality, $jpeg_quality);
return \CoreLibs\Output\Image::createThumbnailSimple($filename, $thumb_width, $thumb_height, $thumbnail_path, null, $create_dummy, $use_cache, $high_quality, $jpeg_quality);
}
/**

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): int|string
{
return Json::jsonGetLastError($return_string);
}
}
// __END__

View File

@@ -90,33 +90,6 @@ class Hash
{
return hash(self::STANDARD_HASH_LONG, $string);
}
/**
* create a unique id with the standard hash type defined in __hash
*
* @return string Unique ID with fixed length of 8 characters
* @deprecated Use \CoreLibs\Create\Uids::uniqIdShort() instead
*/
public static function __uniqId(): string
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, '
. '\CoreLibs\Create\Uids::uniqIdShort() class', E_USER_DEPRECATED);
return \CoreLibs\Create\Uids::uniqIdShort();
}
/**
* create a unique id with the standard long hash type
* defined in __hashLong
*
* @return string Unique ID with length of current default long hash
* @deprecated Use \CoreLibs\Create\Uids::uniqIdLong() instead
*/
public static function __uniqIdLong(): string
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, '
. '\CoreLibs\Create\Uids::uniqIdLong() class', E_USER_DEPRECATED);
return \CoreLibs\Create\Uids::uniqIdLong();
}
}
// __END__

View File

@@ -57,7 +57,7 @@ class ArrayIO extends \CoreLibs\DB\IO
* @param array<mixed> $db_config db connection config
* @param array<mixed> $table_array table array config
* @param string $table_name table name string
* @param \CoreLibs\Debug\Logging|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 $acl_admin Flag if this is an admin ACL access level
*/
@@ -65,12 +65,12 @@ class ArrayIO extends \CoreLibs\DB\IO
array $db_config,
array $table_array,
string $table_name,
\CoreLibs\Debug\Logging $log = null,
\CoreLibs\Debug\Logging $log,
int $base_acl_level = 0,
int $acl_admin = 0
) {
// instance db_io class
parent::__construct($db_config, $log ?? new \CoreLibs\Debug\Logging());
parent::__construct($db_config, $log);
// more error vars for this class
$this->error_string['1999'] = 'No table array or table name set';
$this->error_string['1021'] = 'No Primary Key given';

View File

@@ -378,16 +378,16 @@ class IO
/**
* main DB concstructor with auto connection to DB and failure set on failed connection
* @param array<mixed> $db_config DB configuration array
* @param \CoreLibs\Debug\Logging|null $log Logging class
* @param \CoreLibs\Debug\Logging $log Logging class
* @param bool|null $db_debug_override Overrides debug settings in db_config
*/
public function __construct(
array $db_config,
?\CoreLibs\Debug\Logging $log = null,
\CoreLibs\Debug\Logging $log,
?bool $db_debug_override = null
) {
// attach logger
$this->log = $log ?? new \CoreLibs\Debug\Logging();
$this->log = $log;
// sets the names (for connect/reconnect)
$this->db_name = $db_config['db_name'] ?? '';
$this->db_user = $db_config['db_user'] ?? '';
@@ -405,9 +405,9 @@ class IO
$db_debug_override ??
// from db config setting
$db_config['db_debug'] ??
// should be handled from outside
// [DEPRECATED] should be handled from outside
$_SESSION['DB_DEBUG'] ??
// globals should be deprecated
// [DEPRECATED] globals should be deprecated
$GLOBALS['DB_DEBUG'] ??
false
);
@@ -3245,114 +3245,6 @@ class IO
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(?string $key = null): array|string|int|bool|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(): array|string|int|bool|null
{
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(): array|string|int|bool|null
{
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(?string $key = null): array|string|int|bool|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|\PgSql\Result|null [DEPRECATED]
* @deprecated use dbGetCursorExt($q = null) instead
*/
public function getCursorExt(?string $q = null): array|string|int|\PgSql\Result|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(): ?int
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use dbGetNumRows()', E_USER_DEPRECATED);
return $this->dbGetNumRows();
}
// end if db class
}

View File

@@ -75,6 +75,11 @@ class FileWriter
empty(self::$debug_folder) &&
defined('BASE') && defined('LOG')
) {
/** @deprecated Do not use this anymore, define path with fsetFolder */
trigger_error(
'fsetFolder must be set first. Setting via LOG_FILE_ID and LOg constants is deprecated',
E_USER_DEPRECATED
);
self::$debug_folder = BASE . LOG;
}
if (!is_writeable(self::$debug_folder)) {

View File

@@ -136,6 +136,11 @@ class Logging
$this->log_folder = $this->options['log_folder'] ?? '';
// legacy flow, check must set constants
if (empty($this->log_folder) && defined('BASE') && defined('LOG')) {
/** @deprecated Do not use this anymore, define path on class load */
trigger_error(
'options: log_folder must be set. Setting via BASE and LOG constants is deprecated',
E_USER_DEPRECATED
);
// make sure this is writeable, else skip
$this->log_folder = BASE . LOG;
}
@@ -175,6 +180,11 @@ class Logging
if (!empty($this->options['file_id'])) {
$this->setLogId($this->options['file_id']);
} elseif (!empty($GLOBALS['LOG_FILE_ID'])) {
/** @deprecated Do not use this anymore, define file_id on class load */
trigger_error(
'options: file_id must be set. Setting via LOG_FILE_ID global variable is deprecated',
E_USER_DEPRECATED
);
// legacy flow, should be removed and only set via options
$this->setLogId($GLOBALS['LOG_FILE_ID']);
// TODO trigger deprecation error
@@ -183,6 +193,11 @@ class Logging
// E_USER_DEPRECATED
// );
} elseif (defined('LOG_FILE_ID')) {
/** @deprecated Do not use this anymore, define file_id on class load */
trigger_error(
'options: file_id must be set. Setting via LOG_FILE_ID constant is deprecated',
E_USER_DEPRECATED
);
// legacy flow, should be removed and only set via options
$this->setLogId(LOG_FILE_ID);
// trigger deprecation error
@@ -236,22 +251,22 @@ class Logging
'debug',
$this->options['debug_all'] ??
// for user login, should be handled outside like globals
$_SESSION['DEBUG_ALL'] ??
$GLOBALS['DEBUG_ALL'] ??
$_SESSION['DEBUG_ALL'] ?? // DEPRECATED
$GLOBALS['DEBUG_ALL'] ?? // DEPRECATED
false
);
$this->setLogLevelAll(
'print',
$this->options['print_all'] ??
// for user login, should be handled outside like globals
$_SESSION['DEBUG_ALL'] ??
$GLOBALS['PRINT_ALL'] ??
$_SESSION['DEBUG_ALL'] ?? // DEPRECATED
$GLOBALS['PRINT_ALL'] ?? // DEPRECATED
false
);
$this->setLogLevelAll(
'echo',
$this->options['echo_all'] ??
$GLOBALS['ECHO_ALL'] ??
$GLOBALS['ECHO_ALL'] ?? // DEPRECATED
false
);
@@ -259,32 +274,32 @@ class Logging
// add file date is default on
$this->setGetLogPrintFileDate(
$this->options['print_file_date'] ??
$GLOBALS['LOG_PRINT_FILE_DATE'] ??
$GLOBALS['LOG_PRINT_FILE_DATE'] ?? // DEPRECATED
true
);
// all other logging file name flags are off
$this->setLogPer(
'level',
$this->options['per_level'] ??
$GLOBALS['LOG_PER_LEVEL'] ??
$GLOBALS['LOG_PER_LEVEL'] ?? // DEPRECATED
false
);
$this->setLogPer(
'class',
$this->options['per_class'] ??
$GLOBALS['LOG_PER_CLASS'] ??
$GLOBALS['LOG_PER_CLASS'] ?? // DEPRECATED
false
);
$this->setLogPer(
'page',
$this->options['per_page'] ??
$GLOBALS['LOG_PER_PAGE'] ??
$GLOBALS['LOG_PER_PAGE'] ?? // DEPRECATED
false
);
$this->setLogPer(
'run',
$this->options['per_run'] ??
$GLOBALS['LOG_PER_RUN'] ??
$GLOBALS['LOG_PER_RUN'] ?? // DEPRECATED
false
);
// set log per date

View File

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

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

@@ -1,127 +0,0 @@
<?php
/*
* deprecated function calls
* Language\Encoding::__mbMimeEncode -> Convert\MimeEncode::__mbMimeEncode
* Langauge\Encoding::checkConvertEncoding -> Check\Encoding::checkConvertEncoding
* Langauge\Encoding::setErrorChar -> Check\Encoding::setErrorChar
* Langauge\Encoding::getErrorChar -> Check\Encoding::getErrorChar
* Langauge\Encoding::convertEncoding -> Convert\Encoding::convertEncoding
*/
declare(strict_types=1);
namespace CoreLibs\Language;
class Encoding
{
/**
* wrapper function for mb mime convert
* for correct conversion with long strings
*
* @param string $string string to encode
* @param string $encoding target encoding
* @param string $line_break default line break is \r\n
* @return string encoded string
* @deprecated Use \CoreLibs\Convert\MimeEncode::__mbMimeEncode();
*/
public static function __mbMimeEncode(
string $string,
string $encoding,
string $line_break = "\r\n"
): string {
return \CoreLibs\Convert\MimeEncode::__mbMimeEncode($string, $encoding, $line_break);
}
/**
* set error char
*
* @param string|int|null $string The character to use to represent
* error chars
* "long" for long, "none" for none
* or a valid code point in int
* like 0x2234 (8756, ∴)
* default character is ? (63)
* if null is set then "none"
* @return void
* @deprecated Use \CoreLibs\Check\Encoding::setErrorChar();
*/
public static function setErrorChar(string|int|null $string): void
{
\CoreLibs\Check\Encoding::setErrorChar($string);
}
/**
* get the current set error character
*
* @param bool $return_substitute_func if set to true return the set
* character from the php function
* directly
* @return string|int Set error character
* @deprecated Use \CoreLibs\Check\Encoding::getErrorChar();
*/
public static function getErrorChar(bool $return_substitute_func = false): string|int
{
return \CoreLibs\Check\Encoding::getErrorChar($return_substitute_func);
}
/**
* test if a string can be safely convert between encodings.
* mostly utf8 to shift jis
* the default compare has a possibility of failure, especially with windows
* it is recommended to the following in the script which uses this method:
* mb_substitute_character(0x2234);
* $class->mb_error_char = '∴';
* if check to Shift JIS
* if check to ISO-2022-JP
* if check to ISO-2022-JP-MS
* set three dots (∴) as wrong character for correct convert error detect
* (this char is used, because it is one of the least used ones)
*
* @param string $string string to test
* @param string $from_encoding encoding of string to test
* @param string $to_encoding target encoding
* @return array<string>|false false if no error or
* array with failed characters
* @deprecated Use \CoreLibs\Check\Encoding::checkConvertEncoding();
*/
public static function checkConvertEncoding(
string $string,
string $from_encoding,
string $to_encoding
): array|false {
return \CoreLibs\Check\Encoding::checkConvertEncoding($string, $from_encoding, $to_encoding);
}
/**
* detects the source encoding of the string and if doesn't match
* to the given target encoding it convert is
* if source encoding is set and auto check is true (default) a second
* check is done so that the source string encoding actually matches
* will be skipped if source encoding detection is ascii
*
* @param string $string string to convert
* @param string $to_encoding target encoding
* @param string $source_encoding optional source encoding, will try to auto detect
* @param bool $auto_check default true, if source encoding is set
* check that the source is actually matching
* to what we sav the source is
* @return string encoding converted string
* @deprecated Use \CoreLibs\Convert\Encoding::convertEncoding();
*/
public static function convertEncoding(
string $string,
string $to_encoding,
string $source_encoding = '',
bool $auto_check = true
): string {
return \CoreLibs\Convert\Encoding::convertEncoding(
$string,
$to_encoding,
$source_encoding,
$auto_check
);
}
}
// __END__

View File

@@ -14,12 +14,14 @@ class GetLocale
/**
* returns locale, lang, domain, encoding, path
* from either parameter set or from sessions/config variables
* NOTE: named constant usage is deprecated and will be removed in future
*
* @param string|null $locale override auto detect
* @param string|null $domain override domain
* @param string|null $encoding override encoding
* @param string|null $path override path
* @return array<string,string> locale, domain, encoding, path
* @deprecated use GetLocale::setLocaleSession(...) instead
*/
public static function setLocale(
?string $locale = null,
@@ -27,6 +29,10 @@ class GetLocale
?string $encoding = null,
?string $path = null
): array {
trigger_error(
'Use \CoreLibs\Language\GetLocale::setLocaleSession(...) instead',
E_USER_DEPRECATED
);
// locale must match at least basic rules
if (
empty($locale) ||
@@ -36,6 +42,10 @@ class GetLocale
// parse from session (logged in)
$locale = $_SESSION['DEFAULT_LOCALE'];
} else {
trigger_error(
'setLocale: Unset $locale or unset SESSION locale is deprecated',
E_USER_DEPRECATED
);
// else parse from site locale
$locale = defined('SITE_LOCALE') && !empty(SITE_LOCALE) ?
SITE_LOCALE :
@@ -50,8 +60,16 @@ class GetLocale
empty($domain) ||
!preg_match("/^\w+$/", $domain)
) {
// if no domain is set, fall back to content path
$domain = str_replace('/', '', CONTENT_PATH);
if (!empty($_SESSION['DEFAULT_DOMAIN'])) {
$domain = $_SESSION['DEFAULT_DOMAIN'];
} else {
trigger_error(
'setLocale: Unset $domain is deprecated',
E_USER_DEPRECATED
);
// if no domain is set, fall back to content path
$domain = str_replace(DIRECTORY_SEPARATOR, '', CONTENT_PATH);
}
}
// check that override encoding matches locale encoding
// if locale encoding is set
@@ -71,6 +89,10 @@ class GetLocale
// else set from session
$encoding = $_SESSION['DEFAULT_CHARSET'];
} else {
trigger_error(
'setLocale: Short $locale with unset $encoding or unset SESSION encoding is deprecated',
E_USER_DEPRECATED
);
// else set from site encoding
$encoding = defined('SITE_ENCODING') && !empty(SITE_ENCODING) ?
SITE_ENCODING :
@@ -85,7 +107,15 @@ class GetLocale
empty($path) ||
!is_dir($path)
) {
$path = BASE . INCLUDES . LOCALE;
if (!empty($_SESSION['LOCALE_PATH'])) {
$path = $_SESSION['LOCALE_PATH'];
} else {
trigger_error(
'setLocale: Unset $path is deprecated',
E_USER_DEPRECATED
);
$path = BASE . INCLUDES . LOCALE;
}
}
// extract lang & country from locale string, else set to en
if (
@@ -112,6 +142,113 @@ class GetLocale
'path' => $path,
];
}
/**
* NOTE: For getting the login info via login class use ->loginGetLocale()
*
* Set locale from session or from override parameters
* This is the prefered version to setLocale
* It usese the following SESSION VARIABLES
* DEFAULT_LOCALE
* DEFAULT_DOMAIN
* DEFAULT_CHARSET (should be set from DEFAULT_LOCALE)
* LOCALE_PATH
* in the return array, null set invalid information
*
* @param string $locale override locale
* @param string $domain override domain
* @param string $encoding override encoding
* @param string $path override path
* @return array<string,string> locale, domain, encoding, path
* @return array<string,string|null> Return list of set locale information
* @deprecated This version will be removed in a future version use ACL\Login->loginGetLocale() instead
*/
public static function setLocaleFromSession(
string $locale,
string $domain,
string $encoding,
string $path
): array {
// locale must match at least basic rules
if (
!empty($_SESSION['DEFAULT_LOCALE']) &&
preg_match("/^[-A-Za-z0-9_.@]+$/", $_SESSION['DEFAULT_LOCALE'])
) {
// parse from session (logged in)
$locale = $_SESSION['DEFAULT_LOCALE'];
} elseif (
empty($locale) ||
!preg_match("/^[-A-Za-z0-9_.@]+$/", $locale)
) {
$locale = null;
}
// if domain is set, must be alphanumeric, if not unset
if (
!empty($_SESSION['DEFAULT_DOMAIN']) &&
preg_match("/^\w+$/", $_SESSION['DEFAULT_DOMAIN'])
) {
$domain = $_SESSION['DEFAULT_DOMAIN'];
} elseif (
empty($domain) ||
!preg_match("/^\w+$/", $domain)
) {
$domain = null;
}
// check that override encoding matches locale encoding
// if locale encoding is set
preg_match('/(?:\\.(?P<charset>[-A-Za-z0-9_]+))/', $locale ?? '', $matches);
$locale_encoding = $matches['charset'] ?? null;
if (!empty($locale_encoding)) {
$encoding = strtoupper($locale_encoding);
} elseif (
!empty($_SESSION['DEFAULT_CHARSET']) &&
preg_match("/^[-A-Za-z0-9_]+$/", $_SESSION['DEFAULT_CHARSET'])
) {
$encoding = $_SESSION['DEFAULT_CHARSET'];
} elseif (
empty($encoding) ||
// not valid encoding
!preg_match("/^[-A-Za-z0-9_]+$/", $encoding)
) {
$encoding = null;
}
// path checks if set, if not valid path unset to default BASE path
if (
!empty($_SESSION['LOCALE_PATH']) &&
is_dir($_SESSION['LOCALE_PATH'])
) {
$path = $_SESSION['LOCALE_PATH'];
} elseif (
empty($path) ||
!is_dir($path)
) {
$path = null;
}
// extract lang & country from locale string, else set to en
if (
preg_match(
// lang
'/^(?P<lang>[a-z]{2,3})'
// country code
. '(?:_(?P<country>[A-Z]{2}))?/',
$locale ?? '',
$matches
)
) {
$lang = ($matches['lang'] ?? 'en')
// add country only if set
. (!empty($matches['country']) ? '_' . $matches['country'] : '');
} else {
$lang = null;
}
return [
'locale' => $locale,
'lang' => $lang,
'domain' => $domain,
'encoding' => $encoding,
'path' => $path,
];
}
}
// __END__

View File

@@ -32,12 +32,18 @@ use CoreLibs\Language\Core\GetTextReader;
class L10n
{
/** @var string the default fallback encoding if nothing is set */
public const DEFAULT_CHARSET = 'UTF-8';
/** @var string the current locale */
private $locale = '';
/** @var string the SET locale as WHERE the domain file is */
private $locale_set = '';
/** @var string the default selected/active 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 */
private $domains = [];
/** @var array<string,string> bound paths for domains */
@@ -71,26 +77,42 @@ class L10n
* if locale is not empty will load translation
* else getTranslator needs to be called
*
* @param string $locale language name, default empty string
* will return self instance
* @param string $domain override CONTENT_PATH . $encoding name for mo file
* @param string $path path, if empty fallback on default internal path
* @param string $locale language name, default empty string
* will return self instance
* @param string $domain override CONTENT_PATH . $encoding name for mo file
* @param string $path path, if empty fallback on default internal path
* @param string $encoding Optional encoding, should be set if locale has
* no encoding, defaults to UTF-8
*/
public function __construct(
string $locale = '',
string $domain = '',
string $path = ''
string $path = '',
string $encoding = ''
) {
// auto load language only if at least locale and domain is set
if (!empty($locale) && !empty($domain)) {
// New: path must be set too, or we fall through
if (!empty($locale) && !empty($domain) && empty($path)) {
/** @deprecated if locale and domain are set, path must be set too */
trigger_error(
'Empty path parameter is no longer allowed if locale and domain are set',
E_USER_DEPRECATED
);
}
if (!empty($locale) && !empty($domain) && !empty($path)) {
// check hack if domain and path is switched
// Note this can be removed in future versions
if (strstr($domain, DIRECTORY_SEPARATOR) !== false) {
/** @deprecated domain must be 2nd and path must be third parameter */
trigger_error(
'L10n constructor parameter switch is no longer supported. domain is 2nd, path is 3rd parameter',
E_USER_DEPRECATED
);
$_domain = $path;
$path = $domain;
$domain = $_domain;
}
$this->getTranslator($locale, $domain, $path);
$this->getTranslator($locale, $domain, $path, $encoding);
}
}
@@ -122,15 +144,17 @@ class L10n
/**
* loads the mo file base on path, locale and domain set
*
* @param string $locale language name (optional), fallback is en
* @param string $domain override CONTENT_PATH . $encoding name for mo file
* @param string $path path, if empty fallback on default internal path
* @param string $locale language name, if not set, try previous set
* @param string $domain set name for mo file, if not set, try previous set
* @param string $path path, if not set try to get from paths array, else self
* @param string $override_encoding if locale does not env encoding set, use this one
* @return GetTextReader the main gettext reader object
*/
public function getTranslator(
string $locale = '',
string $domain = '',
string $path = ''
string $path = '',
string $override_encoding = '',
): GetTextReader {
// set local if not from parameter
if (empty($locale)) {
@@ -140,11 +164,16 @@ class L10n
if (empty($domain)) {
$domain = $this->domain;
}
// override encoding for unset
if (!empty($override_encoding)) {
$this->override_encoding = $override_encoding;
}
// store old settings
$old_mofile = $this->mofile;
$old_lang = $this->locale;
$old_lang_set = $this->locale_set;
$old_domain = $this->domain;
$old_encoding = $this->encoding;
$old_base_locale_path = $this->base_locale_path;
$old_base_content_path = $this->base_content_path;
@@ -160,6 +189,11 @@ class L10n
} elseif (
defined('BASE') && defined('INCLUDES') && defined('LOCALE')
) {
/** @deprecated Do not use this anymore, define path on class load */
trigger_error(
'parameter $path must be set. Setting via BASE, INCLUDES and LOCALE constants is deprecated',
E_USER_DEPRECATED
);
// set fallback base path if constant set
$this->base_locale_path = BASE . INCLUDES . LOCALE;
} else {
@@ -168,6 +202,7 @@ class L10n
// now we loop over lang compositions to get the base path
// then we check
$locales = $this->listLocales($locale);
$encoding = $this->getEncodingFromLocale($locale);
foreach ($locales as $_locale) {
$this->base_content_path = $_locale . DIRECTORY_SEPARATOR
. 'LC_MESSAGES' . DIRECTORY_SEPARATOR;
@@ -184,6 +219,7 @@ class L10n
if (is_readable($this->mofile)) {
// locale and domain current wanted
$this->locale = $locale;
$this->encoding = $encoding;
$this->domain = $domain;
// set empty domains path with current locale
if (empty($this->domains[$locale])) {
@@ -207,6 +243,7 @@ class L10n
$this->mofile = $old_mofile;
$this->locale = $old_lang;
$this->locale_set = $old_lang_set;
$this->encoding = $old_encoding;
$this->domain = $old_domain;
$this->base_locale_path = $old_base_locale_path;
$this->base_content_path = $old_base_content_path;
@@ -240,6 +277,40 @@ class L10n
return $this->l10n;
}
/**
* Extract encoding from Locale, or fallback to override one if not set
*
* @param string $locale
* @return string
*/
private function getEncodingFromLocale(string $locale): string
{
// extract charset from $locale
// if not set get override encoding
preg_match('/(?:\\.(?P<charset>[-A-Za-z0-9_]+))/', $locale, $matches);
return $matches['charset'] ?? $this->override_encoding;
}
/**
* Get the local as array same to the GetLocale::setLocale return
* This does not set from outside, but only what is set in the l10n class
*
* @return array{locale: string, lang: string, lang_short: string, domain: string, encoding: string, path: string}
*/
public function getLocaleAsArray(): array
{
$locale = L10n::parseLocale($this->getLocale());
return [
'locale' => $this->getLocale(),
'lang' => ($locale['lang'] ?? '')
. (!empty($locale['country']) ? '_' . $locale['country'] : ''),
'lang_short' => $locale['lang'] ?? '',
'domain' => $this->getDomain(),
'encoding' => $this->getEncoding(),
'path' => $this->getBaseLocalePath(),
];
}
/**
* parse the locale string for further processing
*
@@ -478,6 +549,37 @@ class L10n
return $this->locale_set;
}
/**
* Set override encoding
*
* @param string $encoding
* @return void
*/
public function setOverrideEncoding(string $encoding): void
{
$this->override_encoding = $encoding;
}
/**
* return current set override encoding
*
* @return string
*/
public function getOverrideEncoding(): string
{
return $this->override_encoding;
}
/**
* Current set encoding
*
* @return string
*/
public function getEncoding(): string
{
return $this->encoding;
}
/**
* get current set language
*

View File

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

View File

@@ -12,6 +12,7 @@ class Image
{
/**
* converts picture to a thumbnail with max x and max y size
* TOOD: needs mandatory options for ImageMagic convert, paths, etc folders
*
* @param string $pic source image file with or without path
* @param int $size_x maximum size width
@@ -158,25 +159,27 @@ class Image
* if both are set, those are the max sizes (aspect ration is always ekpt)
* - if path is not given will cache folder for current path set
*
* @param string $filename source file name with full path
* @param int $thumb_width thumbnail width
* @param int $thumb_height thumbnail height
* @param string|null $thumbnail_path altnerative path for thumbnails
* @param bool $create_dummy if we encounter an invalid file
* create a dummy image file and return it
* @param bool $use_cache default to true, set to false to skip
* creating new image if exists
* @param bool $high_quality default to true, uses sample version,
* set to false to not use (default true)
* to use quick but less nice version
* @param int $jpeg_quality default 80, set image quality for jpeg only
* @return string|false thumbnail with path
* @param string $filename source file name with full path
* @param int $thumb_width thumbnail width
* @param int $thumb_height thumbnail height
* @param string|null $cache_folder path for thumbnail cache
* @param string|null $web_folder frontend path for output
* @param bool $create_dummy if we encounter an invalid file
* create a dummy image file and return it
* @param bool $use_cache default to true, set to false to skip
* creating new image if exists
* @param bool $high_quality default to true, uses sample version,
* set to false to not use (default true)
* to use quick but less nice version
* @param int $jpeg_quality default 80, set image quality for jpeg only
* @return string|false thumbnail with path
*/
public static function createThumbnailSimple(
string $filename,
int $thumb_width = 0,
int $thumb_height = 0,
?string $thumbnail_path = null,
?string $cache_folder = null, // will be not null in future
?string $web_folder = null,
bool $create_dummy = true,
bool $use_cache = true,
bool $high_quality = true,
@@ -185,233 +188,246 @@ class Image
$thumbnail = false;
// $this->debug('IMAGE PREPARE', "FILE: $filename (exists "
// .(string)file_exists($filename)."), WIDTH: $thumb_width, HEIGHT: $thumb_height");
if (
$cache_folder === null ||
$web_folder === null
) {
/** @deprecated Do use cache folder and web folder parameters */
trigger_error(
'params $cache_folder and $web_folder must be set. Setting via constants is deprecated',
E_USER_DEPRECATED
);
// NOTE: we need to depracte this
$cache_folder = BASE . LAYOUT . CONTENT_PATH . CACHE . IMAGES;
$web_folder = LAYOUT . CACHE . IMAGES;
if (!is_dir($cache_folder)) {
if (false === mkdir($cache_folder)) {
$cache_folder = BASE . LAYOUT . CONTENT_PATH . CACHE;
$web_folder = LAYOUT . CACHE;
}
}
}
// check that input image exists and is either jpeg or png
// also fail if the basic CACHE folder does not exist at all
if (
file_exists($filename) &&
is_dir(BASE . LAYOUT . CONTENT_PATH . CACHE) &&
is_writable(BASE . LAYOUT . CONTENT_PATH . CACHE)
!file_exists($filename) ||
!is_dir($cache_folder) ||
!is_writable($cache_folder)
) {
// $this->debug('IMAGE PREPARE', "FILENAME OK, THUMB WIDTH/HEIGHT OK");
[$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [];
$thumbnail_write_path = null;
$thumbnail_web_path = null;
// path set first
if (
$img_type == IMAGETYPE_JPEG ||
$img_type == IMAGETYPE_PNG ||
$create_dummy === true
) {
// $this->debug('IMAGE PREPARE', "IMAGE TYPE OK: ".$inc_width.'x'.$inc_height);
// set thumbnail paths
$thumbnail_write_path = BASE . LAYOUT . CONTENT_PATH . CACHE . IMAGES;
$thumbnail_web_path = LAYOUT . CACHE . IMAGES;
// if images folder in cache does not exist create it, if failed, fall back to base cache folder
if (!is_dir($thumbnail_write_path)) {
if (false === mkdir($thumbnail_write_path)) {
$thumbnail_write_path = BASE . LAYOUT . CONTENT_PATH . CACHE;
$thumbnail_web_path = LAYOUT . CACHE;
}
}
return $thumbnail;
}
// $this->debug('IMAGE PREPARE', "FILENAME OK, THUMB WIDTH/HEIGHT OK");
[$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [];
$thumbnail_write_path = null;
$thumbnail_web_path = null;
// path set first
if (
$img_type == IMAGETYPE_JPEG ||
$img_type == IMAGETYPE_PNG ||
$create_dummy === true
) {
// $this->debug('IMAGE PREPARE', "IMAGE TYPE OK: ".$inc_width.'x'.$inc_height);
// set thumbnail paths
$thumbnail_write_path = $cache_folder;
$thumbnail_web_path = $web_folder;
}
// do resize or fall back on dummy run
if (
$img_type == IMAGETYPE_JPEG ||
$img_type == IMAGETYPE_PNG
) {
// if missing width or height in thumb, use the set one
if ($thumb_width == 0) {
$thumb_width = $inc_width;
}
// do resize or fall back on dummy run
if (
$img_type == IMAGETYPE_JPEG ||
$img_type == IMAGETYPE_PNG
) {
// if missing width or height in thumb, use the set one
if ($thumb_width == 0) {
$thumb_width = $inc_width;
}
if ($thumb_height == 0) {
$thumb_height = $inc_height;
}
// check resize parameters
if ($inc_width > $thumb_width || $inc_height > $thumb_height) {
$thumb_width_r = 0;
$thumb_height_r = 0;
// we need to keep the aspect ration on longest side
if (
($inc_height > $inc_width &&
// and the height is bigger than thumb set
$inc_height > $thumb_height) ||
// or the height is smaller or equal width
// but the width for the thumb is equal to the image height
($inc_height <= $inc_width &&
$inc_width == $thumb_width
)
) {
// $this->debug('IMAGE PREPARE', 'HEIGHT > WIDTH');
$ratio = $inc_height / $thumb_height;
$thumb_width_r = (int)ceil($inc_width / $ratio);
$thumb_height_r = $thumb_height;
} else {
// $this->debug('IMAGE PREPARE', 'WIDTH > HEIGHT');
$ratio = $inc_width / $thumb_width;
$thumb_width_r = $thumb_width;
$thumb_height_r = (int)ceil($inc_height / $ratio);
}
// $this->debug('IMAGE PREPARE', "Ratio: $ratio, Target size $thumb_width_r x $thumb_height_r");
// set output thumbnail name
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-'
. $thumb_width_r . 'x' . $thumb_height_r;
if (
$use_cache === false ||
!file_exists($thumbnail_write_path . $thumbnail)
) {
// image, copy source image, offset in image, source x/y, new size, source image size
$thumb = imagecreatetruecolor($thumb_width_r, $thumb_height_r);
if ($thumb === false) {
return false;
}
if ($img_type == IMAGETYPE_PNG) {
$imagecolorallocatealpha = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
if ($imagecolorallocatealpha === false) {
return false;
}
// preservere transaprency
imagecolortransparent(
$thumb,
$imagecolorallocatealpha
);
imagealphablending($thumb, false);
imagesavealpha($thumb, true);
}
$source = null;
switch ($img_type) {
case IMAGETYPE_JPEG:
$source = imagecreatefromjpeg($filename);
break;
case IMAGETYPE_PNG:
$source = imagecreatefrompng($filename);
break;
}
// check that we have a source image resource
if ($source !== null && $source !== false) {
// resize no shift
if ($high_quality === true) {
imagecopyresized(
$thumb,
$source,
0,
0,
0,
0,
$thumb_width_r,
$thumb_height_r,
$inc_width,
$inc_height
);
} else {
imagecopyresampled(
$thumb,
$source,
0,
0,
0,
0,
$thumb_width_r,
$thumb_height_r,
$inc_width,
$inc_height
);
}
// write file
switch ($img_type) {
case IMAGETYPE_JPEG:
imagejpeg($thumb, $thumbnail_write_path . $thumbnail, $jpeg_quality);
break;
case IMAGETYPE_PNG:
imagepng($thumb, $thumbnail_write_path . $thumbnail);
break;
}
// free up resources (in case we are called in a loop)
imagedestroy($source);
imagedestroy($thumb);
} else {
$thumbnail = false;
}
}
if ($thumb_height == 0) {
$thumb_height = $inc_height;
}
// check resize parameters
if ($inc_width > $thumb_width || $inc_height > $thumb_height) {
$thumb_width_r = 0;
$thumb_height_r = 0;
// we need to keep the aspect ration on longest side
if (
($inc_height > $inc_width &&
// and the height is bigger than thumb set
$inc_height > $thumb_height) ||
// or the height is smaller or equal width
// but the width for the thumb is equal to the image height
($inc_height <= $inc_width &&
$inc_width == $thumb_width
)
) {
// $this->debug('IMAGE PREPARE', 'HEIGHT > WIDTH');
$ratio = $inc_height / $thumb_height;
$thumb_width_r = (int)ceil($inc_width / $ratio);
$thumb_height_r = $thumb_height;
} else {
// we just copy over the image as is, we never upscale
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-' . $inc_width . 'x' . $inc_height;
if (
$use_cache === false ||
!file_exists($thumbnail_write_path . $thumbnail)
) {
copy($filename, $thumbnail_write_path . $thumbnail);
}
// $this->debug('IMAGE PREPARE', 'WIDTH > HEIGHT');
$ratio = $inc_width / $thumb_width;
$thumb_width_r = $thumb_width;
$thumb_height_r = (int)ceil($inc_height / $ratio);
}
// add output path
if ($thumbnail !== false) {
$thumbnail = $thumbnail_web_path . $thumbnail;
}
} elseif ($create_dummy === true) {
// create dummy image in the thumbnail size
// if one side is missing, use the other side to create a square
if (!$thumb_width) {
$thumb_width = $thumb_height;
}
if (!$thumb_height) {
$thumb_height = $thumb_width;
}
// do we have an image already?
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-' . $thumb_width . 'x' . $thumb_height;
// $this->debug('IMAGE PREPARE', "Ratio: $ratio, Target size $thumb_width_r x $thumb_height_r");
// set output thumbnail name
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-'
. $thumb_width_r . 'x' . $thumb_height_r;
if (
$use_cache === false ||
!file_exists($thumbnail_write_path . $thumbnail)
) {
// if both are unset, set to 250
if ($thumb_height == 0) {
$thumb_height = 250;
}
if ($thumb_width == 0) {
$thumb_width = 250;
}
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
// image, copy source image, offset in image, source x/y, new size, source image size
$thumb = imagecreatetruecolor($thumb_width_r, $thumb_height_r);
if ($thumb === false) {
return false;
}
// add outside border px = 5% (rounded up)
// eg 50px -> 2.5px
$gray = imagecolorallocate($thumb, 200, 200, 200);
$white = imagecolorallocate($thumb, 255, 255, 255);
if ($gray === false || $white === false) {
return false;
if ($img_type == IMAGETYPE_PNG) {
$imagecolorallocatealpha = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
if ($imagecolorallocatealpha === false) {
return false;
}
// preservere transaprency
imagecolortransparent(
$thumb,
$imagecolorallocatealpha
);
imagealphablending($thumb, false);
imagesavealpha($thumb, true);
}
// fill gray background
imagefill($thumb, 0, 0, $gray);
// now create rectangle
if (imagesx($thumb) < imagesy($thumb)) {
$width = (int)round(imagesx($thumb) / 100 * 5);
$source = null;
switch ($img_type) {
case IMAGETYPE_JPEG:
$source = imagecreatefromjpeg($filename);
break;
case IMAGETYPE_PNG:
$source = imagecreatefrompng($filename);
break;
}
// check that we have a source image resource
if ($source !== null && $source !== false) {
// resize no shift
if ($high_quality === true) {
imagecopyresized(
$thumb,
$source,
0,
0,
0,
0,
$thumb_width_r,
$thumb_height_r,
$inc_width,
$inc_height
);
} else {
imagecopyresampled(
$thumb,
$source,
0,
0,
0,
0,
$thumb_width_r,
$thumb_height_r,
$inc_width,
$inc_height
);
}
// write file
switch ($img_type) {
case IMAGETYPE_JPEG:
imagejpeg($thumb, $thumbnail_write_path . $thumbnail, $jpeg_quality);
break;
case IMAGETYPE_PNG:
imagepng($thumb, $thumbnail_write_path . $thumbnail);
break;
}
// free up resources (in case we are called in a loop)
imagedestroy($source);
imagedestroy($thumb);
} else {
$width = (int)round(imagesy($thumb) / 100 * 5);
$thumbnail = false;
}
imagefilledrectangle(
$thumb,
0 + $width,
0 + $width,
imagesx($thumb) - $width,
imagesy($thumb) - $width,
$white
);
// add "No valid images source"
// OR add circle
// * find center
// * width/height is 75% of size - border
// smaller size is taken
$base_width = imagesx($thumb) > imagesy($thumb) ? imagesy($thumb) : imagesx($thumb);
// get 75% width
$cross_width = (int)round((($base_width - ($width * 2)) / 100 * 75) / 2);
$center_x = (int)round(imagesx($thumb) / 2);
$center_y = (int)round(imagesy($thumb) / 2);
imagefilledellipse($thumb, $center_x, $center_y, $cross_width, $cross_width, $gray);
// find top left and bottom left for first line
imagepng($thumb, $thumbnail_write_path . $thumbnail);
}
// add web path
} else {
// we just copy over the image as is, we never upscale
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-' . $inc_width . 'x' . $inc_height;
if (
$use_cache === false ||
!file_exists($thumbnail_write_path . $thumbnail)
) {
copy($filename, $thumbnail_write_path . $thumbnail);
}
}
// add output path
if ($thumbnail !== false) {
$thumbnail = $thumbnail_web_path . $thumbnail;
}
} elseif ($create_dummy === true) {
// create dummy image in the thumbnail size
// if one side is missing, use the other side to create a square
if (!$thumb_width) {
$thumb_width = $thumb_height;
}
if (!$thumb_height) {
$thumb_height = $thumb_width;
}
// do we have an image already?
$thumbnail = 'thumb-' . pathinfo($filename)['filename'] . '-' . $thumb_width . 'x' . $thumb_height;
if (
$use_cache === false ||
!file_exists($thumbnail_write_path . $thumbnail)
) {
// if both are unset, set to 250
if ($thumb_height == 0) {
$thumb_height = 250;
}
if ($thumb_width == 0) {
$thumb_width = 250;
}
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
if ($thumb === false) {
return false;
}
// add outside border px = 5% (rounded up)
// eg 50px -> 2.5px
$gray = imagecolorallocate($thumb, 200, 200, 200);
$white = imagecolorallocate($thumb, 255, 255, 255);
if ($gray === false || $white === false) {
return false;
}
// fill gray background
imagefill($thumb, 0, 0, $gray);
// now create rectangle
if (imagesx($thumb) < imagesy($thumb)) {
$width = (int)round(imagesx($thumb) / 100 * 5);
} else {
$width = (int)round(imagesy($thumb) / 100 * 5);
}
imagefilledrectangle(
$thumb,
0 + $width,
0 + $width,
imagesx($thumb) - $width,
imagesy($thumb) - $width,
$white
);
// add "No valid images source"
// OR add circle
// * find center
// * width/height is 75% of size - border
// smaller size is taken
$base_width = imagesx($thumb) > imagesy($thumb) ? imagesy($thumb) : imagesx($thumb);
// get 75% width
$cross_width = (int)round((($base_width - ($width * 2)) / 100 * 75) / 2);
$center_x = (int)round(imagesx($thumb) / 2);
$center_y = (int)round(imagesy($thumb) / 2);
imagefilledellipse($thumb, $center_x, $center_y, $cross_width, $cross_width, $gray);
// find top left and bottom left for first line
imagepng($thumb, $thumbnail_write_path . $thumbnail);
}
// add web path
$thumbnail = $thumbnail_web_path . $thumbnail;
}
// either return false or the thumbnail name + output path web
return $thumbnail;

View File

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

View File

@@ -50,9 +50,22 @@ for (
is_file($__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php')
) {
// load enviorment file if it exists
\CoreLibs\Get\DotEnv::readEnvFile(
\gullevek\dotEnv\DotEnv::readEnvFile(
$__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH
);
// find trigger name "admin/" or "frontend/" in the getcwd() folder
$folder = '';
foreach (['admin', 'frontend'] as $_folder) {
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $_folder)) {
$folder = $_folder;
break;
}
}
// if content path is empty, fallback is default
if (empty($folder)) {
$folder = 'default';
}
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
// load master config file that loads all other config files
require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php';
break;
@@ -62,17 +75,5 @@ for (
if (!defined('DIR')) {
exit('Base config could not be loaded');
}
// find trigger name "admin/" or "frontend/" in the getcwd() folder
foreach (['admin', 'frontend'] as $folder) {
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $folder)) {
break;
}
}
// if content path is empty, fallback is default
/** @phpstan-ignore-next-line can be empty */
if (empty($folder)) {
$folder = 'default';
}
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
// __END__

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\MockObject\MockObject;
/*
Not yet covered tests:
- loginGetLocale
- loginGetHeaderColor
- loginGetPages
- loginGetEuid
*/
/**
* Test class for ACL\Login
* @coversDefaultClass \CoreLibs\ACL\Login
@@ -120,8 +128,6 @@ final class CoreLibsACLLoginTest extends TestCase
// define('LOGIN_DB_SCHEMA', '');
// SHOULD SET
// PASSWORD_MIN_LENGTH (d9)
// PASSWORD_MAX_LENGTH (d255)
// DEFAULT_ACL_LEVEL (d80)
// OPT:
@@ -1106,7 +1112,22 @@ final class CoreLibsACLLoginTest extends TestCase
/** @var \CoreLibs\ACL\Login&MockObject */
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
->setConstructorArgs([self::$db, self::$log, $session_mock, false])
->setConstructorArgs([
self::$db,
self::$log,
$session_mock,
[
'auto_login' => false,
'default_acl_level' => 80,
'logout_target' => '',
'site_locale' => 'en_US.UTF-8',
'site_domain' => 'admin',
'site_encoding' => 'UTF-8',
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
. 'includes' . DIRECTORY_SEPARATOR
. 'locale' . DIRECTORY_SEPARATOR,
]
])
->onlyMethods(['loginTerminate', 'loginReadPageName', 'loginPrintLogin'])
->getMock();
$login_mock->expects($this->any())
@@ -1774,7 +1795,22 @@ final class CoreLibsACLLoginTest extends TestCase
);
/** @var \CoreLibs\ACL\Login&MockObject */
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
->setConstructorArgs([self::$db, self::$log, $session_mock, false])
->setConstructorArgs([
self::$db,
self::$log,
$session_mock,
[
'auto_login' => false,
'default_acl_level' => 80,
'logout_target' => '',
'site_locale' => 'en_US.UTF-8',
'site_domain' => 'admin',
'site_encoding' => 'UTF-8',
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
. 'includes' . DIRECTORY_SEPARATOR
. 'locale' . DIRECTORY_SEPARATOR,
]
])
->onlyMethods(['loginTerminate'])
->getMock();
$login_mock->expects($this->any())
@@ -1873,7 +1909,22 @@ final class CoreLibsACLLoginTest extends TestCase
);
/** @var \CoreLibs\ACL\Login&MockObject */
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
->setConstructorArgs([self::$db, self::$log, $session_mock, false])
->setConstructorArgs([
self::$db,
self::$log,
$session_mock,
[
'auto_login' => false,
'default_acl_level' => 80,
'logout_target' => '',
'site_locale' => 'en_US.UTF-8',
'site_domain' => 'admin',
'site_encoding' => 'UTF-8',
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
. 'includes' . DIRECTORY_SEPARATOR
. 'locale' . DIRECTORY_SEPARATOR,
]
])
->onlyMethods(['loginTerminate'])
->getMock();
$login_mock->expects($this->any())
@@ -1946,7 +1997,22 @@ final class CoreLibsACLLoginTest extends TestCase
);
/** @var \CoreLibs\ACL\Login&MockObject */
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
->setConstructorArgs([self::$db, self::$log, $session_mock, false])
->setConstructorArgs([
self::$db,
self::$log,
$session_mock,
[
'auto_login' => false,
'default_acl_level' => 80,
'logout_target' => '',
'site_locale' => 'en_US.UTF-8',
'site_domain' => 'admin',
'site_encoding' => 'UTF-8',
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
. 'includes' . DIRECTORY_SEPARATOR
. 'locale' . DIRECTORY_SEPARATOR,
]
])
->onlyMethods(['loginTerminate'])
->getMock();
$login_mock->expects($this->any())
@@ -2027,7 +2093,22 @@ final class CoreLibsACLLoginTest extends TestCase
);
/** @var \CoreLibs\ACL\Login&MockObject */
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
->setConstructorArgs([self::$db, self::$log, $session_mock, false])
->setConstructorArgs([
self::$db,
self::$log,
$session_mock,
[
'auto_login' => false,
'default_acl_level' => 80,
'logout_target' => '',
'site_locale' => 'en_US.UTF-8',
'site_domain' => 'admin',
'site_encoding' => 'UTF-8',
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
. 'includes' . DIRECTORY_SEPARATOR
. 'locale' . DIRECTORY_SEPARATOR,
]
])
->onlyMethods(['loginTerminate'])
->getMock();
$login_mock->expects($this->any())

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

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

View File

@@ -738,7 +738,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
$warning = array_shift($arrays);
// phpunit 10.0 compatible
$this->expectExceptionMessage(($warning));
$this->expectExceptionMessage($warning);
\CoreLibs\Combined\ArrayHandler::arrayMergeRecursive(...$arrays);

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

@@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
*/
final class CoreLibsDebugLoggingTest extends TestCase
{
private const LOG_FOLDER = __DIR__ . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR;
/**
* test set for options BASIC
*
@@ -33,17 +34,20 @@ final class CoreLibsDebugLoggingTest extends TestCase
return [
'log folder set' => [
[
'log_folder' => '/tmp'
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
'file_id' => 'testClassInit'
],
[
'log_folder' => '/tmp/',
'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
'debug_all' => false,
'print_all' => false,
],
[]
],
'nothing set' => [
null,
[
'file_id' => 'testClassInit'
],
[
'log_folder' => getcwd() . DIRECTORY_SEPARATOR,
'debug_all' => false,
@@ -51,30 +55,33 @@ final class CoreLibsDebugLoggingTest extends TestCase
],
[]
],
'no options set, constant set' => [
null,
'no options set, constant set [DEPRECATED]' => [
[
'log_folder' => str_replace('/configs', '', __DIR__)
. DIRECTORY_SEPARATOR . 'log/',
'file_id' => 'testClassInit'
],
[
'log_folder' => str_replace(DIRECTORY_SEPARATOR . 'configs', '', __DIR__)
. DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR,
'debug_all' => false,
'print_all' => false,
],
[
'constant' => [
'BASE' => str_replace('/configs', '', __DIR__)
'BASE' => str_replace(DIRECTORY_SEPARATOR . 'configs', '', __DIR__)
. DIRECTORY_SEPARATOR,
'LOG' => 'log/'
'LOG' => 'log' . DIRECTORY_SEPARATOR
]
]
],
'standard test set' => [
[
'log_folder' => '/tmp',
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
'file_id' => 'testClassInit',
'debug_all' => true,
'print_all' => true,
],
[
'log_folder' => '/tmp/',
'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR,
'debug_all' => true,
'print_all' => true,
],
@@ -89,35 +96,66 @@ final class CoreLibsDebugLoggingTest extends TestCase
* @dataProvider optionsProvider
* @testdox init test [$_dataName]
*
* @param array|null $options
* @param array $options
* @param array $expected
* @param array $override
* @return void
*/
public function testClassInit(?array $options, array $expected, array $override): void
public function testClassInit(array $options, array $expected, array $override): void
{
if (!empty($override['constant'])) {
foreach ($override['constant'] as $var => $value) {
define($var, $value);
if (!defined($var)) {
define($var, $value);
}
}
// for deprecated no log_folder set
// if base is defined and it does have AAASetupData set
// change the log_folder "Debug" to "AAASetupData"
if (
defined('BASE') &&
strpos(BASE, DIRECTORY_SEPARATOR . 'AAASetupData') !== false
) {
$expected['log_folder'] = str_replace(
DIRECTORY_SEPARATOR . 'Debug',
DIRECTORY_SEPARATOR . 'AAASetupData',
$expected['log_folder']
);
}
}
if ($options === null) {
$log = new \CoreLibs\Debug\Logging();
} else {
$log = new \CoreLibs\Debug\Logging($options);
// if not log folder and constant set -> expect E_USER_DEPRECATION
if (!empty($override['constant']) && empty($options['log_folder'])) {
// the deprecation message
$deprecation_message = 'options: log_folder must be set. '
. 'Setting via BASE and LOG constants is deprecated';
// convert E_USER_DEPRECATED to a exception
set_error_handler(
static function (int $errno, string $errstr): never {
throw new \Exception($errstr, $errno);
},
E_USER_DEPRECATED
);
// catch this with the message
$this->expectExceptionMessage($deprecation_message);
}
$log = new \CoreLibs\Debug\Logging($options);
// reset error handler
restore_error_handler();
// check that settings match
$this->assertEquals(
$expected['log_folder'],
$log->getSetting('log_folder')
$log->getSetting('log_folder'),
'log folder not matching'
);
$this->assertEquals(
$expected['debug_all'],
$log->getSetting('debug_output_all')
$log->getSetting('debug_output_all'),
'debug all flag not matching'
);
$this->assertEquals(
$expected['print_all'],
$log->getSetting('print_output_all')
$log->getSetting('print_output_all'),
'print all flag not matching'
);
// print "LOG: " . $log->getSetting('log_folder') . "\n";
// print "DEBUG: " . $log->getSetting('debug_output_all') . "\n";
@@ -134,17 +172,23 @@ final class CoreLibsDebugLoggingTest extends TestCase
// 0: options
// 1: expected
// 2: override
// 3: exception message
return [
'no log id set' => [
null,
[
'log_folder' => self::LOG_FOLDER,
],
[
'log_file_id' => ''
],
[]
[],
null
],
// set log id manually afterwards
'set log id manually' => [
null,
[
'log_folder' => self::LOG_FOLDER,
],
[
'log_file_id' => '',
'set_log_file_id' => 'abc123',
@@ -154,21 +198,26 @@ final class CoreLibsDebugLoggingTest extends TestCase
'values' => [
'log_file_id' => 'abc123'
]
]
],
null
],
// set log id from options
'set log id via options' => [
[
'file_id' => 'abc456',
'log_folder' => self::LOG_FOLDER,
],
[
'log_file_id' => 'abc456'
],
[]
[],
null
],
// set log id from GLOBALS [DEPRECATED]
'set log id via globals' => [
null,
'set log id via globals [DEPRECATED]' => [
[
'log_folder' => self::LOG_FOLDER,
],
[
'log_file_id' => 'def123'
],
@@ -176,11 +225,14 @@ final class CoreLibsDebugLoggingTest extends TestCase
'globals' => [
'LOG_FILE_ID' => 'def123'
]
]
],
'options: file_id must be set. Setting via LOG_FILE_ID global variable is deprecated'
],
// set log id from CONSTANT [DEPRECATED]
'set log id via constant' => [
null,
'set log id via constant [DEPRECATED]' => [
[
'log_folder' => self::LOG_FOLDER,
],
[
'log_file_id' => 'ghi123'
],
@@ -192,12 +244,14 @@ final class CoreLibsDebugLoggingTest extends TestCase
'constant' => [
'LOG_FILE_ID' => 'ghi123'
]
]
],
'options: file_id must be set. Setting via LOG_FILE_ID constant is deprecated'
],
// invalid, keep previous set
'invalid log id' => [
[
'file_id' => 'jkl456'
'file_id' => 'jkl456',
'log_folder' => self::LOG_FOLDER,
],
[
'log_file_id' => 'jkl456',
@@ -207,7 +261,8 @@ final class CoreLibsDebugLoggingTest extends TestCase
'values' => [
'log_file_id' => './#'
]
]
],
null
]
];
}
@@ -219,13 +274,18 @@ final class CoreLibsDebugLoggingTest extends TestCase
* @dataProvider logIdOptionsProvider
* @testdox log id set/get tests [$_dataName]
*
* @param array|null $options
* @param array $options
* @param array $expected
* @param array $override
* @param string|null $deprecation_message until we remove the old code
* @return void
*/
public function testLogId(?array $options, array $expected, array $override): void
{
public function testLogId(
array $options,
array $expected,
array $override,
?string $deprecation_message
): void {
// we need to set with file_id option, globals LOG_FILE_ID, constant LOG_FILE_ID
if (!empty($override['constant'])) {
foreach ($override['constant'] as $var => $value) {
@@ -237,11 +297,20 @@ final class CoreLibsDebugLoggingTest extends TestCase
$GLOBALS[$var] = $value;
}
}
if ($options === null) {
$log = new \CoreLibs\Debug\Logging();
} else {
$log = new \CoreLibs\Debug\Logging($options);
if (!empty($override['constant']) || !empty($override['globals'])) {
// convert E_USER_DEPRECATED to a exception
set_error_handler(
static function (int $errno, string $errstr): never {
throw new \Exception($errstr, $errno);
},
E_USER_DEPRECATED
);
// catch this with the message
$this->expectExceptionMessage($deprecation_message);
}
$log = new \CoreLibs\Debug\Logging($options);
// reset error handler
restore_error_handler();
// check current
$this->assertEquals(
$log->getLogId(),
@@ -316,7 +385,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
bool $expected_get
): void {
// 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
$this->assertEquals(
$log->setLogLevelAll($type, $flag),
@@ -438,7 +510,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
$expected_get
): void {
// neutral start with default
$log = new \CoreLibs\Debug\Logging();
$log = new \CoreLibs\Debug\Logging([
'file_id' => 'testSetGetLogLevel',
'log_folder' => self::LOG_FOLDER
]);
// set
$this->assertEquals(
$log->setLogLevel($type, $flag, $debug_on),
@@ -517,7 +592,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
bool $expected_get
): void {
// 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
$this->assertEquals(
$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
{
// 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
$this->assertEquals(
$log->setGetLogPrintFileDate($input),
@@ -612,7 +693,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
*/
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(
$log->prAr($input),
$expected
@@ -673,7 +757,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
*/
public function testPrBl(bool $input, ?string $true, ?string $false, string $expected): void
{
$log = new \CoreLibs\Debug\Logging();
$log = new \CoreLibs\Debug\Logging([
'file_id' => 'testPrBl',
'log_folder' => self::LOG_FOLDER
]);
$return = '';
if ($true === null && $false === null) {
$return = $log->prBl($input);
@@ -959,9 +1046,16 @@ final class CoreLibsDebugLoggingTest extends TestCase
public function testLogUniqueId(bool $option, bool $override): void
{
if ($option === true) {
$log = new \CoreLibs\Debug\Logging(['per_run' => $option]);
$log = new \CoreLibs\Debug\Logging([
'file_id' => 'testLogUniqueId',
'log_folder' => self::LOG_FOLDER,
'per_run' => $option
]);
} else {
$log = new \CoreLibs\Debug\Logging();
$log = new \CoreLibs\Debug\Logging([
'file_id' => 'testLogUniqueId',
'log_folder' => self::LOG_FOLDER
]);
$log->setLogUniqueId();
}
$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',
'status' => 2,
'content' => [],
'chmod' => '000',
// 0000
'chmod' => '100000',
],
'empty file' => [
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
'file' => 'empty.env',
'status' => 1,
'content' => [],
'chmod' => null,
// 0664
'chmod' => '100664',
],
'override all' => [
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
'file' => 'test.env',
'status' => 0,
'content' => $dot_env_content,
'chmod' => null,
// 0664
'chmod' => '100664',
],
'override directory' => [
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
@@ -124,6 +127,16 @@ final class CoreLibsGetDotEnvTest extends TestCase
array $expected_env,
?string $chmod
): void {
if (
!empty($chmod) &&
$chmod == '100000' &&
getmyuid() == 0
) {
$this->markTestSkipped(
"Skip cannot read file test because run user is root"
);
return;
}
// if we have file + chmod set
$old_chmod = null;
if (
@@ -134,6 +147,20 @@ final class CoreLibsGetDotEnvTest extends TestCase
$old_chmod = fileperms($folder . DIRECTORY_SEPARATOR . $file);
chmod($folder . DIRECTORY_SEPARATOR . $file, octdec($chmod));
}
$message = '\CoreLibs\Get\DotEnv is deprecated in favor for '
. 'composer package gullevek\dotenv which is a copy of this';
// convert E_USER_DEPRECATED to a exception
set_error_handler(
static function (int $errno, string $errstr): never {
throw new \Exception($errstr, $errno);
},
E_USER_DEPRECATED
);
// tests are never run -> deprecated
if (is_file($folder . DIRECTORY_SEPARATOR . $file)) {
chmod($folder . DIRECTORY_SEPARATOR . $file, 0664);
}
$this->expectExceptionMessage($message);
if ($folder !== null && $file !== null) {
$status = DotEnv::readEnvFile($folder, $file);
} elseif ($folder !== null) {
@@ -141,6 +168,7 @@ final class CoreLibsGetDotEnvTest extends TestCase
} else {
$status = DotEnv::readEnvFile();
}
restore_error_handler();
$this->assertEquals(
$status,
$expected_status,
@@ -153,8 +181,9 @@ final class CoreLibsGetDotEnvTest extends TestCase
'Assert _ENV correct'
);
// if we have file and chmod unset
if ($old_chmod !== null) {
chmod($folder . DIRECTORY_SEPARATOR . $file, $old_chmod);
print "Write mode: $old_chmod\n";
if ($old_chmod !== null && $chmod == '100000') {
chmod($folder . DIRECTORY_SEPARATOR . $file, 0664);
}
}
}

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
{
// 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
// for deprecation test only, will be removed
if (!defined('BASE')) {
define('BASE', str_replace('/configs', '', __DIR__) . DIRECTORY_SEPARATOR);
define('BASE', str_replace(DIRECTORY_SEPARATOR . '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);
}
}
/**
@@ -105,77 +84,163 @@ final class CoreLibsLanguageL10nTest extends TestCase
{
return [
// 0: locale
// 1: domain
// 2: encoding
// 1: encoding
// 2: domain
// 3: path
// 4: locale expected
// 5: locale set expected
// 6: domain exepcted
// 7: context (null for none)
// 8: test string in
// 9: test translated
// 6: lang expected
// 7: lang short expected
// 8: encoding expected
// 9: domain exepcted
// 10: context (null for none)
// 11: test string in
// 12: test translated
// 13: deprecation message (until removed)
// new style load
'gettext load en' => [
'en_US.UTF-8',
'UTF-8',
'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',
'en_US',
'en',
'UTF-8',
'frontend',
// 10
null,
// 11, 12
'Original',
'Translated frontend en_US',
// 13
null,
],
'gettext load en' => [
'en_US.UTF-8',
'UTF-8',
'frontend',
__DIR__ . 'includes/locale/',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
//
'en_US.UTF-8',
'en_US',
'en_US',
'en',
'UTF-8',
'frontend',
//
'context',
//
'Original',
'Original context frontend en_US',
//
null,
],
'gettext load ja' => [
'ja_JP.UTF-8',
'UTF-8',
'admin',
__DIR__ . 'includes/locale/',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
//
'ja_JP.UTF-8',
'ja_JP',
'ja_JP',
'ja',
'UTF-8',
'admin',
//
null,
//
'Original',
'Translated admin ja_JP',
//
null,
],
// mixed path and domain
'mixed path and domain' => [
// load short locale with different encoding
'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',
__DIR__ . 'includes/locale/',
'UTF-8',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
'frontend',
//
'en_US.UTF-8',
'en_US',
'en_US',
'en',
'UTF-8',
'frontend',
//
'context',
//
'Original',
'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
'empty load new ' => [
'',
'',
'',
'',
//
'',
'',
'',
'',
'', // unset on empty call
'',
//
null,
//
'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]
*
* @param string|null $locale
* @param string|null $encoding
* @param string|null $domain
* @param string|null $path
* @param string $locale_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 $context
* @param string|null $context
* @param string $original
* @param string $translated
* @param string|null $deprecation_message
* @return void
*/
public function testL10nObject(
?string $locale,
?string $encoding,
?string $domain,
?string $path,
string $locale_expected,
string $locale_set_expected,
string $lang_expected,
string $lang_short_expected,
string $encoding_expected,
string $domain_expected,
?string $context,
string $original,
string $translated
string $translated,
?string $deprecation_message
): 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) {
$l10n = new \CoreLibs\Language\L10n();
} elseif ($domain === null) {
// deprecated, locale + domain must be set, handled like empty calls
$l10n = new \CoreLibs\Language\L10n($locale);
} elseif ($path === null) {
// deprecated, path must be set, will thow DEPRECATION error, handled like empty
$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);
} 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";
$this->assertEquals(
$locale_expected,
@@ -248,6 +338,20 @@ final class CoreLibsLanguageL10nTest extends TestCase
'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
@@ -283,7 +387,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
// set 0-2
'en_US.UTF-8',
'frontend',
__DIR__ . 'includes/locale/',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// status 3
false,
// to translate 4
@@ -296,7 +400,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
// set new 8-10
'ja_JP.UTF-8',
'frontend',
__DIR__ . 'includes/locale/',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// status new 11
false,
// check new setter 12-14
@@ -322,7 +426,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
// set new 8-10
'en_US.UTF-8',
'frontend',
__DIR__ . 'includes/locale/',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// status new 11
false,
// check new setter 12-14
@@ -387,12 +491,8 @@ final class CoreLibsLanguageL10nTest extends TestCase
string $domain_expected_b,
string $translated_b
): void {
if ($locale === null) {
if ($locale === null || $domain === null || $path === null) {
$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 {
$l10n = new \CoreLibs\Language\L10n($locale, $domain, $path);
}
@@ -494,16 +594,16 @@ final class CoreLibsLanguageL10nTest extends TestCase
{
return [
// 0: locale
// 1: path
// 2: domain
// 1: domain
// 2: path
// 3: context (null for none)
// 4: single string
// 5: plural string
// 6: array for each n value expected string
'plural text en' => [
'en_US',
__DIR__ . 'includes/locale/',
'admin',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// context
null,
// text single/multi in
@@ -518,8 +618,8 @@ final class CoreLibsLanguageL10nTest extends TestCase
],
'plural text context en' => [
'en_US',
__DIR__ . 'includes/locale/',
'admin',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
// context
'context',
// 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]
*
* @param string $locale
* @param string $path
* @param string $domain
* @param string $path
* @param ?string $context
* @param string $original_single
* @param string $original_plural
@@ -555,8 +655,8 @@ final class CoreLibsLanguageL10nTest extends TestCase
public function testNgettext(
// config 0-3
string $locale,
string $path,
string $domain,
string $path,
// context string
?string $context,
// input strings
@@ -565,7 +665,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
// expected
array $expected_strings
): void {
$l10n = new \CoreLibs\Language\L10n($locale, $path, $domain, false);
$l10n = new \CoreLibs\Language\L10n($locale, $domain, $path);
foreach ($expected_strings as $n => $expected) {
if (empty($context)) {
@@ -981,7 +1081,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
'standard en' => [
'en_US.UTF-8',
'frontend',
__DIR__ . 'includes/locale/',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
'UTF-8',
'Original',
'Translated frontend en_US',
@@ -989,7 +1089,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
'standard ja' => [
'ja_JP.UTF-8',
'admin',
__DIR__ . 'includes/locale/',
__DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR,
'UTF-8',
'Original',
'Translated admin ja_JP',
@@ -1030,6 +1130,7 @@ final class CoreLibsLanguageL10nTest extends TestCase
_textdomain($domain);
_bindtextdomain($domain, $path);
_bind_textdomain_codeset($domain, $encoding);
$this->assertEquals(
$translated,
__($original),

View File

@@ -0,0 +1 @@
ja_JP