From f410d761ba303773218a69725e6b97e0105bc1f3 Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Thu, 9 Mar 2023 16:41:55 +0900 Subject: [PATCH] Remove deprecated classes and methods, deprecate all named constants All named constants used inside classes have been deprecated and must now be set from method calls, class init, etc --- composer.json | 5 +- src/ACL/Login.php | 339 +++++++++---- src/Admin/Backend.php | 173 +++---- src/Admin/EditBase.php | 91 +++- src/Basic.php | 2 +- src/Create/Hash.php | 27 -- src/DB/Extended/ArrayIO.php | 6 +- src/DB/IO.php | 114 +---- src/Debug/FileWriter.php | 5 + src/Debug/Logging.php | 15 + src/Get/DotEnv.php | 8 + src/Get/ReadEnvFile.php | 42 -- src/Language/Encoding.php | 127 ----- src/Language/GetLocale.php | 31 +- src/Language/L10n.php | 45 +- src/Output/Form/Generate.php | 35 +- src/Output/Image.php | 458 +++++++++--------- src/Template/SmartyExtend.php | 361 ++++++++++++-- test/configs/config.php | 27 +- test/phpunit/ACL/CoreLibsACLLoginTest.php | 82 +++- test/phpunit/ACL/includes | 1 + .../CoreLibsCombinedArrayHandlerTest.php | 2 +- .../Debug/CoreLibsDebugLoggingTest.php | 152 ++++-- test/phpunit/Get/CoreLibsGetDotEnvTest.php | 39 +- .../CoreLibsLanguageGetLocaleTest.php | 71 ++- .../Language/CoreLibsLanguageL10nTest.php | 146 ++++-- 26 files changed, 1449 insertions(+), 955 deletions(-) delete mode 100644 src/Get/ReadEnvFile.php delete mode 100644 src/Language/Encoding.php create mode 120000 test/phpunit/ACL/includes diff --git a/composer.json b/composer.json index 2f0480f..2511145 100644 --- a/composer.json +++ b/composer.json @@ -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": { diff --git a/src/ACL/Login.php b/src/ACL/Login.php index 332692e..b7e490e 100644 --- a/src/ACL/Login.php +++ b/src/ACL/Login.php @@ -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 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,12 @@ class Login /** @var bool */ private $login_is_ajax_page = false; + // settings + /** @var array options */ + private $options = []; + /** @var array locale options: locale, domain, encoding (opt), path */ + private $locale = []; + /** @var \CoreLibs\Debug\Logging logger */ public $log; /** @var \CoreLibs\DB\IO database */ @@ -183,15 +214,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 $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 +232,13 @@ class Login // attach session class $this->session = $session; + // set and check options + if (false === $this->loginSetOptions($options)) { + // on failure, exit + echo "Could not set options"; + $this->loginTerminate(4000); + } + // string key, msg: string, flag: e (error), o (ok) $this->login_error_msg = [ '0' => [ @@ -339,7 +376,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 +421,183 @@ class Login // **** PRIVATE INTERNAL // ************************************************************************* + /** + * Set options + * Current allowed + * target : site target + * debug + * auto_login : self start login process + * db_schema + * password_min_length + * default_acl_level + * logout_target : should default be '' or target path to where + * can_change : can change password (NOT IMPLEMENTED) + * forget_flow : reset password on forget (NOT IMPLEMENTED) + * locale_path : absolue path to the locale folder + * site_locale : what locale to load + * site_domain : what domain (locale file name) to use + * + * @param array $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 or DEFAULT_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; + $_SESSION['DEFAULT_DOMAIN'] = $options['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); + } + } + + // write array to options + $this->options = $options; + return true; + } + /** * Checks for all flags and sets error codes for each * In order: @@ -980,6 +1194,34 @@ class Login // $this->debug('ACL', $this->print_ar($this->acl)); } + /** + * set locale and load mo translator + * + * @return void + */ + private function loginSetLocale(): void + { + // ** LANGUAGE SET AFTER LOGIN ** + // set the locale + if ( + !empty($_SESSION['DEFAULT_LOCALE']) + ) { + $locale = $_SESSION['DEFAULT_LOCALE']; + } else { + $locale = $this->options['site_locale']; + } + $this->locale = [ + 'locale' => $locale, + 'domain' => $this->options['site_domain'], + 'path' => $this->options['locale_path'], + ]; + $this->l = new \CoreLibs\Language\L10n( + $this->locale['locale'], + $this->locale['domain'], + $this->locale['path'] + ); + } + /** * checks if the password is in a valid format * @@ -1513,50 +1755,9 @@ EOM; echo 'No active session found'; $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 +1809,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 +1823,7 @@ 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(); // if the password change flag is okay, run the password change method if ($this->password_change) { $this->loginPasswordChange(); @@ -1669,18 +1839,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 +1975,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; diff --git a/src/Admin/Backend.php b/src/Admin/Backend.php index 97d2da8..3f03a46 100644 --- a/src/Admin/Backend.php +++ b/src/Admin/Backend.php @@ -128,7 +128,8 @@ class Backend \CoreLibs\Debug\Logging $log, \CoreLibs\Create\Session $session, \CoreLibs\Language\L10n $l10n, - array $locale + array $locale, + ?int $set_default_acl_level = null ) { // attach db class $this->db = $db; @@ -156,7 +157,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 +198,34 @@ class Backend * @param string $event any kind of event description, * @param string|array $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 +236,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 +291,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 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 +400,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 +450,6 @@ class Backend }; return $enabled; } - - /** - * creates out of a normal db_return array an assoc array - * - * @param array $db_array input array - * @param string|int|bool $key key - * @param string|int|bool $value value - * @return array 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 +483,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 +502,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) . "', " diff --git a/src/Admin/EditBase.php b/src/Admin/EditBase.php index 7476044..30f71c9 100644 --- a/src/Admin/EditBase.php +++ b/src/Admin/EditBase.php @@ -228,10 +228,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 @@ -334,7 +338,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 +435,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 +538,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_css = $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 +618,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, diff --git a/src/Basic.php b/src/Basic.php index 27d0c3e..a9a70c5 100644 --- a/src/Basic.php +++ b/src/Basic.php @@ -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); } /** diff --git a/src/Create/Hash.php b/src/Create/Hash.php index 1209b96..beadac6 100644 --- a/src/Create/Hash.php +++ b/src/Create/Hash.php @@ -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__ diff --git a/src/DB/Extended/ArrayIO.php b/src/DB/Extended/ArrayIO.php index f972e04..5abeac9 100644 --- a/src/DB/Extended/ArrayIO.php +++ b/src/DB/Extended/ArrayIO.php @@ -57,7 +57,7 @@ class ArrayIO extends \CoreLibs\DB\IO * @param array $db_config db connection config * @param array $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'; diff --git a/src/DB/IO.php b/src/DB/IO.php index 6fc5b99..e593d22 100644 --- a/src/DB/IO.php +++ b/src/DB/IO.php @@ -378,16 +378,16 @@ class IO /** * main DB concstructor with auto connection to DB and failure set on failed connection * @param array $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'] ?? ''; @@ -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|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|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|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|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|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 } diff --git a/src/Debug/FileWriter.php b/src/Debug/FileWriter.php index 8ef07d5..27fe3e1 100644 --- a/src/Debug/FileWriter.php +++ b/src/Debug/FileWriter.php @@ -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)) { diff --git a/src/Debug/Logging.php b/src/Debug/Logging.php index d9ffb34..bae2136 100644 --- a/src/Debug/Logging.php +++ b/src/Debug/Logging.php @@ -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 diff --git a/src/Get/DotEnv.php b/src/Get/DotEnv.php index 73b3f2b..de2dad5 100644 --- a/src/Get/DotEnv.php +++ b/src/Get/DotEnv.php @@ -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; diff --git a/src/Get/ReadEnvFile.php b/src/Get/ReadEnvFile.php deleted file mode 100644 index 77da76c..0000000 --- a/src/Get/ReadEnvFile.php +++ /dev/null @@ -1,42 +0,0 @@ - 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|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__ diff --git a/src/Language/GetLocale.php b/src/Language/GetLocale.php index 1124250..f10dc4d 100644 --- a/src/Language/GetLocale.php +++ b/src/Language/GetLocale.php @@ -14,6 +14,7 @@ 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 @@ -36,6 +37,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 +55,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 +84,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 +102,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 ( diff --git a/src/Language/L10n.php b/src/Language/L10n.php index 9419ae1..09c2cae 100644 --- a/src/Language/L10n.php +++ b/src/Language/L10n.php @@ -82,10 +82,23 @@ class L10n string $path = '' ) { // 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; @@ -122,9 +135,9 @@ 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 * @return GetTextReader the main gettext reader object */ public function getTranslator( @@ -160,6 +173,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 { @@ -240,6 +258,25 @@ class L10n return $this->l10n; } + /** + * 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|null, domain: string, encoding: string|null, path: string} + */ + public function getLocaleAsArray(): array + { + $locale = L10n::parseLocale($this->getLocale()); + return [ + 'locale' => $this->getLocale(), + 'lang' => $locale['lang'] + . (!empty($locale['country']) ? '_' . $locale['country'] : ''), + 'domain' => $this->getDomain(), + 'encoding' => $locale['charset'], + 'path' => $this->getBaseLocalePath(), + ]; + } + /** * parse the locale string for further processing * diff --git a/src/Output/Form/Generate.php b/src/Output/Form/Generate.php index cfbe8ee..9c33aa1 100644 --- a/src/Output/Form/Generate.php +++ b/src/Output/Form/Generate.php @@ -305,37 +305,28 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO /** * construct form generator * - * @param array $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|null $locale locale array from ::setLocale, - * null auto set - * @param array|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 $db_config db config array, mandatory + * @param \CoreLibs\Debug\Logging $log Logging class + * @param \CoreLibs\Language\L10n $l10n l10n language class + * @param array $locale locale array from ::setLocale + * @param array|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 $locale, ?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'], - ); + $this->l = $l10n; // legacy lang vars set $this->encoding = $locale['encoding']; $this->lang = $locale['lang']; diff --git a/src/Output/Image.php b/src/Output/Image.php index 20d2a56..664f3a9 100644 --- a/src/Output/Image.php +++ b/src/Output/Image.php @@ -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; diff --git a/src/Template/SmartyExtend.php b/src/Template/SmartyExtend.php index ffbd028..6e87d9e 100644 --- a/src/Template/SmartyExtend.php +++ b/src/Template/SmartyExtend.php @@ -161,9 +161,31 @@ class SmartyExtend extends \Smarty * * @param \CoreLibs\Language\L10n $l10n l10n language class * @param array $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, + array $locale, + ?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(); @@ -191,8 +213,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 +278,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 +357,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 +386,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 +455,191 @@ class SmartyExtend extends \Smarty * wrapper call for setSmartyVars * this is for frontend type and will not set any only admin needed variables * + * @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_stylesheet STYLESHEET + * @param string|null $set_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( + ?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_stylesheet = null, + ?string $set_javascript = null, + ?\CoreLibs\Admin\Backend $cms = null + ): void { + $this->setSmartyVars( + false, + $cms, + $compile_dir, + $cache_dir, + $set_js, + $set_css, + $set_font, + $set_default_encoding, + $set_g_title, + null, + null, + null, + $set_stylesheet, + $set_javascript + ); } /** * wrapper call for setSmartyVars * this is only for admin interface and will set additional variables + * @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 \CoreLibs\Admin\Backend|null $cms Optinal Admin Backend for + * smarty variables merge + * @return void */ - public function setSmartyVarsAdmin(): void - { - $this->setSmartyVars(true); + public function setSmartyVarsAdmin( + ?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, + ?\CoreLibs\Admin\Backend $cms = null + ): void { + $this->setSmartyVars( + true, + $cms, + $compile_dir, + $cache_dir, + $set_js, + $set_css, + $set_font, + $set_g_title, + $set_default_encoding, + $set_admin_stylesheet, + $set_admin_javascript, + $set_page_width, + 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_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_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 + ) + ) || + ( + $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; + // 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 +670,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 +684,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 +700,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 +715,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 @@ -499,16 +742,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 +767,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, diff --git a/test/configs/config.php b/test/configs/config.php index df7f3b9..93e07ea 100644 --- a/test/configs/config.php +++ b/test/configs/config.php @@ -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__ diff --git a/test/phpunit/ACL/CoreLibsACLLoginTest.php b/test/phpunit/ACL/CoreLibsACLLoginTest.php index 2d01194..361e8ed 100644 --- a/test/phpunit/ACL/CoreLibsACLLoginTest.php +++ b/test/phpunit/ACL/CoreLibsACLLoginTest.php @@ -120,8 +120,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 +1104,21 @@ 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', + 'locale_path' => __DIR__ . DIRECTORY_SEPARATOR + . 'includes' . DIRECTORY_SEPARATOR + . 'locale' . DIRECTORY_SEPARATOR, + ] + ]) ->onlyMethods(['loginTerminate', 'loginReadPageName', 'loginPrintLogin']) ->getMock(); $login_mock->expects($this->any()) @@ -1774,7 +1786,21 @@ 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', + 'locale_path' => __DIR__ . DIRECTORY_SEPARATOR + . 'includes' . DIRECTORY_SEPARATOR + . 'locale' . DIRECTORY_SEPARATOR, + ] + ]) ->onlyMethods(['loginTerminate']) ->getMock(); $login_mock->expects($this->any()) @@ -1873,7 +1899,21 @@ 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', + 'locale_path' => __DIR__ . DIRECTORY_SEPARATOR + . 'includes' . DIRECTORY_SEPARATOR + . 'locale' . DIRECTORY_SEPARATOR, + ] + ]) ->onlyMethods(['loginTerminate']) ->getMock(); $login_mock->expects($this->any()) @@ -1946,7 +1986,21 @@ 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', + 'locale_path' => __DIR__ . DIRECTORY_SEPARATOR + . 'includes' . DIRECTORY_SEPARATOR + . 'locale' . DIRECTORY_SEPARATOR, + ] + ]) ->onlyMethods(['loginTerminate']) ->getMock(); $login_mock->expects($this->any()) @@ -2027,7 +2081,21 @@ 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', + 'locale_path' => __DIR__ . DIRECTORY_SEPARATOR + . 'includes' . DIRECTORY_SEPARATOR + . 'locale' . DIRECTORY_SEPARATOR, + ] + ]) ->onlyMethods(['loginTerminate']) ->getMock(); $login_mock->expects($this->any()) diff --git a/test/phpunit/ACL/includes b/test/phpunit/ACL/includes new file mode 120000 index 0000000..d9cfd76 --- /dev/null +++ b/test/phpunit/ACL/includes @@ -0,0 +1 @@ +../AAASetupData/includes \ No newline at end of file diff --git a/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php b/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php index 689f592..0bc60dd 100644 --- a/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php +++ b/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php @@ -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); diff --git a/test/phpunit/Debug/CoreLibsDebugLoggingTest.php b/test/phpunit/Debug/CoreLibsDebugLoggingTest.php index 03f3c91..6b7daad 100644 --- a/test/phpunit/Debug/CoreLibsDebugLoggingTest.php +++ b/test/phpunit/Debug/CoreLibsDebugLoggingTest.php @@ -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,7 +34,8 @@ final class CoreLibsDebugLoggingTest extends TestCase return [ 'log folder set' => [ [ - 'log_folder' => DIRECTORY_SEPARATOR . 'tmp' + 'log_folder' => DIRECTORY_SEPARATOR . 'tmp', + 'file_id' => 'testClassInit' ], [ 'log_folder' => DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR, @@ -43,7 +45,9 @@ final class CoreLibsDebugLoggingTest extends TestCase [] ], 'nothing set' => [ - null, + [ + 'file_id' => 'testClassInit' + ], [ 'log_folder' => getcwd() . DIRECTORY_SEPARATOR, 'debug_all' => false, @@ -51,8 +55,10 @@ final class CoreLibsDebugLoggingTest extends TestCase ], [] ], - 'no options set, constant set' => [ - null, + 'no options set, constant set [DEPRECATED]' => [ + [ + 'file_id' => 'testClassInit' + ], [ 'log_folder' => str_replace(DIRECTORY_SEPARATOR . 'configs', '', __DIR__) . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR, @@ -70,6 +76,7 @@ final class CoreLibsDebugLoggingTest extends TestCase 'standard test set' => [ [ 'log_folder' => DIRECTORY_SEPARATOR . 'tmp', + 'file_id' => 'testClassInit', 'debug_all' => true, 'print_all' => true, ], @@ -89,12 +96,12 @@ 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) { @@ -116,11 +123,24 @@ final class CoreLibsDebugLoggingTest extends TestCase ); } } - 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'], @@ -152,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', @@ -172,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' ], @@ -194,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' ], @@ -210,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', @@ -225,7 +261,8 @@ final class CoreLibsDebugLoggingTest extends TestCase 'values' => [ 'log_file_id' => './#' ] - ] + ], + null ] ]; } @@ -237,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) { @@ -255,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(), @@ -334,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), @@ -456,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), @@ -535,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), @@ -564,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), @@ -630,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 @@ -691,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); @@ -977,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(); diff --git a/test/phpunit/Get/CoreLibsGetDotEnvTest.php b/test/phpunit/Get/CoreLibsGetDotEnvTest.php index 285e19e..76ba345 100644 --- a/test/phpunit/Get/CoreLibsGetDotEnvTest.php +++ b/test/phpunit/Get/CoreLibsGetDotEnvTest.php @@ -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); } } } diff --git a/test/phpunit/Language/CoreLibsLanguageGetLocaleTest.php b/test/phpunit/Language/CoreLibsLanguageGetLocaleTest.php index 981c3e2..f8c9c45 100644 --- a/test/phpunit/Language/CoreLibsLanguageGetLocaleTest.php +++ b/test/phpunit/Language/CoreLibsLanguageGetLocaleTest.php @@ -60,7 +60,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase /** * all the test data * - * @return array + * @return array */ public function setLocaleProvider(): array { @@ -72,6 +72,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase // 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, @@ -85,6 +86,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase '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 @@ -99,6 +101,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase 'encoding' => 'UTF-8', 'path' => "/^\/(.*\/)?includes\/locale\/$/", ], + 'setLocale: Unset $domain is deprecated' ], 'no params, session charset and lang short' => [ // lang, domain, encoding, path @@ -113,6 +116,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase 'encoding' => 'UTF-8', 'path' => "/^\/(.*\/)?includes\/locale\/$/", ], + 'setLocale: Unset $domain is deprecated', ], // param lang (no sessions) 'locale param only, no sessions' => [ @@ -128,6 +132,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase 'encoding' => 'UTF-8', 'path' => "/^\/(.*\/)?includes\/locale\/$/", ], + 'setLocale: Unset $domain is deprecated', ], // different locale setting 'locale complex param only, no sessions' => [ @@ -143,6 +148,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase 'encoding' => 'SJIS', 'path' => "/^\/(.*\/)?includes\/locale\/$/", ], + 'setLocale: Unset $domain is deprecated', ], // param lang and domain (no override) 'locale, domain params, no sessions' => [ @@ -158,6 +164,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase 'encoding' => 'UTF-8', 'path' => "/^\/(.*\/)?includes\/locale\/$/", ], + 'setLocale: Unset $path is deprecated', ], // param lang and domain (no override) 'locale, domain, encoding params, no sessions' => [ @@ -173,6 +180,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase 'encoding' => 'UTF-8', 'path' => "/^\/(.*\/)?includes\/locale\/$/", ], + 'setLocale: Unset $path is deprecated' ], // lang, domain, path (no override) 'locale, domain and path, no sessions' => [ @@ -188,6 +196,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase 'encoding' => 'UTF-8', 'path' => "/^\/(.*\/)?locale_other\/$/", ], + null ], // all params set (no override) 'all parameter, no sessions' => [ @@ -203,6 +212,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase 'encoding' => 'UTF-8', 'path' => "/^\/(.*\/)?locale_other\/$/", ], + null ], // param lang and domain (no override) 'long locale, domain, encoding params, no sessions' => [ @@ -218,6 +228,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase '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 @@ -225,14 +236,22 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase } /** - * 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 - */ + * 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 $expected + * @param string|null $deprecation_message + * @return void + */ public function testsetLocale( ?string $language, ?string $domain, @@ -240,7 +259,8 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase ?string $path, ?string $SESSION_DEFAULT_LOCALE, ?string $SESSION_DEFAULT_CHARSET, - array $expected + array $expected, + ?string $deprecation_message ): void { $return_lang_settings = []; global $_SESSION; @@ -251,19 +271,41 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase 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) { + 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) { + } 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) { + } 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) { + } elseif ( + $language !== null && $domain !== null && + $encoding !== null && $path === null + ) { $return_lang_settings = \CoreLibs\Language\GetLocale::setLocale( $language, $domain, @@ -277,6 +319,7 @@ final class CoreLibsLanguageGetLocaleTest extends TestCase $path ); } + restore_error_handler(); // print "RETURN: " . print_r($return_lang_settings, true) . "\n"; foreach ( diff --git a/test/phpunit/Language/CoreLibsLanguageL10nTest.php b/test/phpunit/Language/CoreLibsLanguageL10nTest.php index ee5bf0f..453e188 100644 --- a/test/phpunit/Language/CoreLibsLanguageL10nTest.php +++ b/test/phpunit/Language/CoreLibsLanguageL10nTest.php @@ -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); - } } /** @@ -110,59 +89,90 @@ final class CoreLibsLanguageL10nTest extends TestCase // 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: encoding expected + // 8: domain exepcted + // 9: context (null for none) + // 10: test string in + // 11: test translated + // 12: deprecation message (until removed) // new style load 'gettext load en' => [ 'en_US.UTF-8', 'frontend', - __DIR__ . 'includes/locale/', + __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR, // 'en_US.UTF-8', 'en_US', + 'en_US', + 'UTF-8', 'frontend', null, 'Original', 'Translated frontend en_US', + null, ], 'gettext load en' => [ 'en_US.UTF-8', 'frontend', - __DIR__ . 'includes/locale/', + __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR, // 'en_US.UTF-8', 'en_US', + 'en_US', + 'UTF-8', 'frontend', 'context', 'Original', 'Original context frontend en_US', + null, ], 'gettext load ja' => [ 'ja_JP.UTF-8', 'admin', - __DIR__ . 'includes/locale/', + __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR, // 'ja_JP.UTF-8', 'ja_JP', + 'ja_JP', + 'UTF-8', 'admin', null, 'Original', 'Translated admin ja_JP', + null, ], - // mixed path and domain - 'mixed path and domain' => [ + // mixed path and domain [DEPRECATED] + 'mixed path and domain [DEPRECATED]' => [ 'en_US.UTF-8', - __DIR__ . 'includes/locale/', + __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'locale' . DIRECTORY_SEPARATOR, 'frontend', // 'en_US.UTF-8', 'en_US', + 'en_US', + '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', + 'admin', + null, + // + 'ja_JP.UTF-8', + 'ja_JP', + 'ja_JP', + '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 ' => [ @@ -173,9 +183,12 @@ final class CoreLibsLanguageL10nTest extends TestCase '', '', '', + '', + '', null, 'Original', 'Original', + null, ] ]; } @@ -192,10 +205,13 @@ final class CoreLibsLanguageL10nTest extends TestCase * @param string|null $path * @param string $locale_expected * @param string $locale_set_expected + * @param string $lang_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( @@ -204,20 +220,36 @@ final class CoreLibsLanguageL10nTest extends TestCase ?string $path, string $locale_expected, string $locale_set_expected, + string $lang_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) { + // same as if locale is null $l10n = new \CoreLibs\Language\L10n($locale); } elseif ($path === null) { + // deprecated, path must be set $l10n = new \CoreLibs\Language\L10n($locale, $domain); } else { $l10n = new \CoreLibs\Language\L10n($locale, $domain, $path); } + restore_error_handler(); // print "LOC: " . $locale . ", " . $l10n->getLocale() . ", " . $locale_expected . "\n"; // print "MO: " . $l10n->getMoFile() . "\n"; $this->assertEquals( @@ -248,6 +280,19 @@ 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, + 'domain' => $domain_expected, + 'encoding' => $encoding_expected, + 'path' => $path + ], + $locale, + 'getLocaleAsArray mismatch' + ); } // l10nReloadMOfile and getTranslator @@ -283,7 +328,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 +341,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 +367,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 +432,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 +535,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 +559,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 +585,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 +596,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 +606,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 +1022,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 +1030,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 +1071,7 @@ final class CoreLibsLanguageL10nTest extends TestCase _textdomain($domain); _bindtextdomain($domain, $path); _bind_textdomain_codeset($domain, $encoding); + $this->assertEquals( $translated, __($original),