Compare commits

...

8 Commits

Author SHA1 Message Date
Clemens Schwaighofer
3b1f8745c2 v9.36.0: Bug for call stack in logging and ErrorMessage class 2025-11-27 18:08:15 +09:00
Clemens Schwaighofer
9079d3120f Release: v9.35.1 2025-10-09 15:11:18 +09:00
Clemens Schwaighofer
e945eac122 v9.35.1: Fix phpunit tests with error_log 2025-10-09 15:10:21 +09:00
Clemens Schwaighofer
352e3dca1f Release: v9.35.0 2025-10-09 12:03:02 +09:00
Clemens Schwaighofer
fb9e04fe55 v9.35.0: Logging datetime to iso date format with time zone, unit checks fixes 2025-10-09 12:01:57 +09:00
Clemens Schwaighofer
1b46b378a3 Update publish script with minor output updates 2025-07-15 14:13:08 +09:00
Clemens Schwaighofer
4dda0937e5 Update pulish script with functions and after publish report 2025-07-15 13:43:01 +09:00
Clemens Schwaighofer
935d5420a1 Release: v9.34.0 2025-06-05 18:15:16 +09:00
17 changed files with 331 additions and 160 deletions

View File

@@ -1 +1 @@
9.33.0 9.35.1

View File

@@ -9,16 +9,85 @@ VERSION=$(git tag --list | sort -V | tail -n1 | sed -e "s/^v//");
file_last_published="${BASE_FOLDER}last.published"; file_last_published="${BASE_FOLDER}last.published";
go_flag="$1"; go_flag="$1";
function gitea_publish
{
_GITEA_PUBLISH="${1}"
_GITEA_UPLOAD_FILENAME="${2}"
_GITEA_URL_DL="${3}"
_GITEA_URL_PUSH="${4}"
_GITEA_USER="${5}"
_GITEA_TOKEN="${6}"
_PACKAGE_DOWNLOAD="${7}"
_VERSION="${8}"
_file_last_published="${9}"
if [ -z "${_GITEA_PUBLISH}" ]; then
return
fi;
if [ -n "${_GITEA_UPLOAD_FILENAME}" ] &&
[ -n "${_GITEA_URL_DL}" ] && [ -n "${_GITEA_URL_PUSH}" ] &&
[ -n "${_GITEA_USER}" ] && [ -n "${_GITEA_TOKEN}" ]; then
echo "> Publish ${_GITEA_UPLOAD_FILENAME} with ${_VERSION} to: ${_GITEA_URL_PUSH}";
if [ ! -f "${_PACKAGE_DOWNLOAD}${_GITEA_UPLOAD_FILENAME}-v${_VERSION}.zip" ]; then
echo "> Download: ${_GITEA_UPLOAD_FILENAME}-v${_VERSION}.zip";
curl -LJO \
--output-dir "${_PACKAGE_DOWNLOAD}" \
"${_GITEA_URL_DL}"/v"${_VERSION}".zip;
fi;
if [ ! -f "${_PACKAGE_DOWNLOAD}${_GITEA_UPLOAD_FILENAME}-v${_VERSION}.zip" ]; then
echo "[!] Package file does not exist for version: ${_VERSION}";
else
response=$(curl --user "${_GITEA_USER}":"${_GITEA_TOKEN}" \
--upload-file "${_PACKAGE_DOWNLOAD}${_GITEA_UPLOAD_FILENAME}-v${_VERSION}.zip" \
"${_GITEA_URL_PUSH}"?version="${_VERSION}");
status=$(echo "${response}" | jq .errors[].status);
message=$(echo "${response}" | jq .errors[].message);
if [ -n "${status}" ]; then
echo "[!] Error ${status}: ${message}";
else
echo "> Publish completed";
fi;
echo "${_VERSION}" > "${_file_last_published}";
fi;
else
echo "[!] Missing either GITEA_UPLOAD_FILENAME, GITEA_URL_DL, GITEA_URL_PUSH, GITEA_USER or GITEA_TOKEN environment variable";
fi;
}
function gitlab_publish
{
_GITLAB_PUBLISH="${1}";
_GITLAB_URL="${2}";
_GITLAB_DEPLOY_TOKEN="${3}";
_PACKAGE_DOWNLOAD="${4}"
_VERSION="${5}"
_file_last_published="${6}"
if [ -z "${GITLAB_PUBLISH}" ]; then
return;
fi;
if [ -n "${_GITLAB_URL}" ] && [ -n "${_GITLAB_DEPLOY_TOKEN}" ]; then
curl --data tag=v"${_VERSION}" \
--header "Deploy-Token: ${_GITLAB_DEPLOY_TOKEN}" \
"${_GITLAB_URL}";
curl --data branch=master \
--header "Deploy-Token: ${_GITLAB_DEPLOY_TOKEN}" \
"${_GITLAB_URL}";
echo "${_VERSION}" > "${_file_last_published}";
else
echo "[!] Missing GITLAB_URL or GITLAB_DEPLOY_TOKEN environment variable";
fi;
}
if [ -z "${VERSION}" ]; then if [ -z "${VERSION}" ]; then
echo "Version must be set in the form x.y.z without any leading characters"; echo "[!] Version must be set in the form x.y.z without any leading characters";
exit; exit;
fi; fi;
# compare version, if different or newer, deploy # compare version, if different or newer, deploy
if [ -f "${file_last_published}" ]; then if [ -f "${file_last_published}" ]; then
LAST_PUBLISHED_VERSION=$(cat "${file_last_published}"); LAST_PUBLISHED_VERSION=$(cat "${file_last_published}");
if dpkg --compare-versions "${VERSION}" le "${LAST_PUBLISHED_VERSION}"; then if dpkg --compare-versions "${VERSION}" le "${LAST_PUBLISHED_VERSION}"; then
echo "git tag version ${VERSION} is not newer than previous published version ${LAST_PUBLISHED_VERSION}"; echo "[!] git tag version ${VERSION} is not newer than previous published version ${LAST_PUBLISHED_VERSION}";
exit;
fi; fi;
fi; fi;
@@ -36,62 +105,30 @@ fi;
# GITLAB_TOKEN # GITLAB_TOKEN
# GITLAB_URL # GITLAB_URL
if [ ! -f "${BASE_FOLDER}.env.deploy" ]; then if [ ! -f "${BASE_FOLDER}.env.deploy" ]; then
echo "Deploy enviroment file .env.deploy is missing"; echo "[!] Deploy enviroment file .env.deploy is missing";
exit; exit;
fi; fi;
set -o allexport; set -o allexport;
cd "${BASE_FOLDER}" || exit; cd "${BASE_FOLDER}" || exit
# shellcheck source=.env.deploy # shellcheck source=.env.deploy
source .env.deploy; source .env.deploy;
cd - || exit; cd - >/dev/null 2>&1 || exit;
set +o allexport; set +o allexport;
if [ "${go_flag}" != "go" ]; then if [ "${go_flag}" != "go" ]; then
echo "No go flag given"; echo "[!] No go flag given";
echo "Would publish ${VERSION}"; echo "> Would publish ${VERSION}";
echo "[END]"; echo "[END]";
exit; exit;
fi; fi;
echo "[START]"; echo "[START]";
# gitea # gitea
# skip iof gitea_publish "${GITEA_PUBLISH}" "${GITEA_UPLOAD_FILENAME}" "${GITEA_URL_DL}" "${GITEA_URL_PUSH}" "${GITEA_USER}" "${GITEA_TOKEN}" "${PACKAGE_DOWNLOAD}" "${VERSION}" "${file_last_published}";
if [ -n "${GITEA_PUBLISH}" ]; then gitea_publish "${PR_GITEA_PUBLISH}" "${PR_GITEA_UPLOAD_FILENAME}" "${PR_GITEA_URL_DL}" "${PR_GITEA_URL_PUSH}" "${PR_GITEA_USER}" "${PR_GITEA_TOKEN}" "${PACKAGE_DOWNLOAD}" "${VERSION}" "${file_last_published}";
if [ -n "${GITEA_UPLOAD_FILENAME}" ] &&
[ -n "${GITEA_URL_DL}" ] && [ -n "${GITEA_URL_PUSH}" ] &&
[ -n "${GITEA_USER}" ] && [ -n "${GITEA_TOKEN}" ]; then
if [ ! -f "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" ]; then
curl -LJO \
--output-dir "${PACKAGE_DOWNLOAD}" \
"${GITEA_URL_DL}"/v"${VERSION}".zip;
fi;
if [ ! -f "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" ]; then
echo "Version file does not exist for ${VERSION}";
else
curl --user "${GITEA_USER}":"${GITEA_TOKEN}" \
--upload-file "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" \
"${GITEA_URL_PUSH}"?version="${VERSION}";
echo "${VERSION}" > "${file_last_published}";
fi;
else
echo "Missing either GITEA_UPLOAD_FILENAME, GITEA_URL_DL, GITEA_URL_PUSH, GITEA_USER or GITEA_TOKEN environment variable";
fi;
fi;
# gitlab # gitlab
if [ -n "${GITLAB_PUBLISH}" ]; then # gitlab_publish "${GITLAB_PUBLISH}" "${GITLAB_URL}" "${GITLAB_DEPLOY_TOKEN}" "${PACKAGE_DOWNLOAD}" "${VERSION}" "${file_last_published}";
if [ -n "${GITLAB_URL}" ] && [ -n "${GITLAB_DEPLOY_TOKEN}" ]; then
curl --data tag=v"${VERSION}" \
--header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
"${GITLAB_URL}";
curl --data branch=master \
--header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
"${GITLAB_URL}";
echo "${VERSION}" > "${file_last_published}";
else
echo "Missing GITLAB_URL or GITLAB_DEPLOY_TOKEN environment variable";
fi;
fi;
echo ""; echo "";
echo "[DONE]"; echo "[DONE]";

View File

@@ -10,12 +10,16 @@ class Email
/** @var array<int,string> */ /** @var array<int,string> */
private static array $email_regex_check = [ private static array $email_regex_check = [
0 => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@" 0 => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@"
. "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$", // MASTER // . "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$", // MASTER
// fixed pattern matching for domain
. "(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\.[a-zA-Z]{2,6}$", // MASTER
1 => "@(.*)@(.*)", // double @ 1 => "@(.*)@(.*)", // double @
2 => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@", // wrong part before @ 2 => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@", // wrong part before @
3 => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.([a-zA-Z]{2,}){1}$", // wrong part after @ // 3 => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.([a-zA-Z]{2,}){1}$", // wrong part after @
4 => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.", // wrong domain name part 3 => "@(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\.[a-zA-Z]{2,6}$", // wrong part after @
5 => "\.([a-zA-Z]{2,6}){1}$", // wrong top level part // 4 => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.", // wrong domain name part
4 => "@(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\.", // wrong domain name part
5 => "\.[a-zA-Z]{2,6}$", // wrong top level part
6 => "@(.*)\.{2,}", // double .. in domain name part 6 => "@(.*)\.{2,}", // double .. in domain name part
7 => "@.*\.$" // ends with a dot, top level, domain missing 7 => "@.*\.$" // ends with a dot, top level, domain missing
]; ];

View File

@@ -150,14 +150,14 @@ class ArrayHandler
* array search simple. looks for key, value combination, if found, returns true * array search simple. looks for key, value combination, if found, returns true
* on default does not strict check, so string '4' will match int 4 and vica versa * on default does not strict check, so string '4' will match int 4 and vica versa
* *
* @param array<mixed> $array search in as array * @param array<mixed> $in_array search in as array
* @param string|int $key key (key to search in) * @param string|int $key key (key to search in)
* @param string|int|bool|array<string|int|bool> $value values list (what to find) * @param string|int|bool|array<string|int|bool> $value values list (what to find)
* @param bool $strict [false], if set to true, will strict check key/value * @param bool $strict [false], if set to true, will strict check key/value
* @return bool true on found, false on not found * @return bool true on found, false on not found
*/ */
public static function arraySearchSimple( public static function arraySearchSimple(
array $array, array $in_array,
string|int $key, string|int $key,
string|int|bool|array $value, string|int|bool|array $value,
bool $strict = false bool $strict = false
@@ -166,7 +166,7 @@ class ArrayHandler
if (!is_array($value)) { if (!is_array($value)) {
$value = [$value]; $value = [$value];
} }
foreach ($array as $_key => $_value) { foreach ($in_array as $_key => $_value) {
// if value is an array, we search // if value is an array, we search
if (is_array($_value)) { if (is_array($_value)) {
// call recursive, and return result if it is true, else continue // call recursive, and return result if it is true, else continue
@@ -189,19 +189,19 @@ class ArrayHandler
* If prefix is turned on each found group will be prefixed with the * If prefix is turned on each found group will be prefixed with the
* search key * search key
* *
* @param array<mixed> $array array to search in * @param array<mixed> $in_array array to search in
* @param array<mixed> $needles keys to find in array * @param array<mixed> $needles keys to find in array
* @param bool $flat [false] Turn on flat output * @param bool $flat [false] Turn on flat output
* @param bool $prefix [false] Prefix found with needle key * @param bool $prefix [false] Prefix found with needle key
* @return array<mixed> Found values * @return array<mixed> Found values
*/ */
public static function arraySearchKey( public static function arraySearchKey(
array $array, array $in_array,
array $needles, array $needles,
bool $flat = false, bool $flat = false,
bool $prefix = false bool $prefix = false
): array { ): array {
$iterator = new \RecursiveArrayIterator($array); $iterator = new \RecursiveArrayIterator($in_array);
$recursive = new \RecursiveIteratorIterator( $recursive = new \RecursiveIteratorIterator(
$iterator, $iterator,
\RecursiveIteratorIterator::SELF_FIRST \RecursiveIteratorIterator::SELF_FIRST
@@ -248,7 +248,7 @@ class ArrayHandler
* If not found return an array with the array block there the required key is missing, * If not found return an array with the array block there the required key is missing,
* the path as string with seperator block set and the missing key entry * the path as string with seperator block set and the missing key entry
* *
* @param array<mixed> $array * @param array<mixed> $in_array
* @param string|int|float|bool $search_value * @param string|int|float|bool $search_value
* @param string|array<string> $required_key * @param string|array<string> $required_key
* @param ?string $search_key [null] * @param ?string $search_key [null]
@@ -257,7 +257,7 @@ class ArrayHandler
* @return array<array{content?:array<mixed>,path?:string,missing_key?:array<string>}> * @return array<array{content?:array<mixed>,path?:string,missing_key?:array<string>}>
*/ */
public static function findArraysMissingKey( public static function findArraysMissingKey(
array $array, array $in_array,
string|int|float|bool $search_value, string|int|float|bool $search_value,
string|array $required_key, string|array $required_key,
?string $search_key = null, ?string $search_key = null,
@@ -265,7 +265,7 @@ class ArrayHandler
string $current_path = '' string $current_path = ''
): array { ): array {
$results = []; $results = [];
foreach ($array as $key => $value) { foreach ($in_array as $key => $value) {
$path = $current_path ? $current_path . $path_separator . $key : $key; $path = $current_path ? $current_path . $path_separator . $key : $key;
if (is_array($value)) { if (is_array($value)) {
@@ -321,7 +321,7 @@ class ArrayHandler
* Find key => value entry and return set with key for all matching * Find key => value entry and return set with key for all matching
* Can search recursively through nested arrays if recursive flag is set * Can search recursively through nested arrays if recursive flag is set
* *
* @param array<mixed> $array * @param array<mixed> $in_array
* @param string $lookup * @param string $lookup
* @param int|string|float|bool $search * @param int|string|float|bool $search
* @param bool $strict [false] * @param bool $strict [false]
@@ -332,7 +332,7 @@ class ArrayHandler
* @return array<mixed> * @return array<mixed>
*/ */
public static function selectArrayFromOption( public static function selectArrayFromOption(
array $array, array $in_array,
string $lookup, string $lookup,
int|string|float|bool $search, int|string|float|bool $search,
bool $strict = false, bool $strict = false,
@@ -342,7 +342,7 @@ class ArrayHandler
string $flat_separator = self::DATA_SEPARATOR string $flat_separator = self::DATA_SEPARATOR
): array { ): array {
// skip on empty // skip on empty
if ($array == []) { if ($in_array == []) {
return []; return [];
} }
// init return result // init return result
@@ -352,7 +352,7 @@ class ArrayHandler
$search = strtolower($search); $search = strtolower($search);
} }
foreach ($array as $key => $value) { foreach ($in_array as $key => $value) {
// Handle current level search // Handle current level search
if (isset($value[$lookup])) { if (isset($value[$lookup])) {
$compareValue = $value[$lookup]; $compareValue = $value[$lookup];
@@ -399,14 +399,14 @@ class ArrayHandler
/** /**
* main wrapper function for next/prev key * main wrapper function for next/prev key
* *
* @param array<mixed> $array array to search in * @param array<mixed> $in_array array to search in
* @param int|string $key key for next/prev * @param int|string $key key for next/prev
* @param bool $next [=true] if to search next or prev * @param bool $next [=true] if to search next or prev
* @return int|string|null Next/prev key or null for end/first * @return int|string|null Next/prev key or null for end/first
*/ */
private static function arrayGetKey(array $array, int|string $key, bool $next = true): int|string|null private static function arrayGetKey(array $in_array, int|string $key, bool $next = true): int|string|null
{ {
$keys = array_keys($array); $keys = array_keys($in_array);
if (($position = array_search($key, $keys, true)) === false) { if (($position = array_search($key, $keys, true)) === false) {
return null; return null;
} }
@@ -422,26 +422,26 @@ class ArrayHandler
* Get previous array key from an array * Get previous array key from an array
* null on not found * null on not found
* *
* @param array<mixed> $array * @param array<mixed> $in_array
* @param int|string $key * @param int|string $key
* @return int|string|null Next key, or null for not found * @return int|string|null Next key, or null for not found
*/ */
public static function arrayGetPrevKey(array $array, int|string $key): int|string|null public static function arrayGetPrevKey(array $in_array, int|string $key): int|string|null
{ {
return self::arrayGetKey($array, $key, false); return self::arrayGetKey($in_array, $key, false);
} }
/** /**
* Get next array key from an array * Get next array key from an array
* null on not found * null on not found
* *
* @param array<mixed> $array * @param array<mixed> $in_array
* @param int|string $key * @param int|string $key
* @return int|string|null Next key, or null for not found * @return int|string|null Next key, or null for not found
*/ */
public static function arrayGetNextKey(array $array, int|string $key): int|string|null public static function arrayGetNextKey(array $in_array, int|string $key): int|string|null
{ {
return self::arrayGetKey($array, $key, true); return self::arrayGetKey($in_array, $key, true);
} }
/** /**
@@ -463,27 +463,27 @@ class ArrayHandler
} }
// default key is not string // default key is not string
$key_is_string = false; $key_is_string = false;
$arrays = func_get_args(); $in_arrays = func_get_args();
// if last is not array, then assume it is trigger for key is always string // if last is not array, then assume it is trigger for key is always string
if (!is_array(end($arrays))) { if (!is_array(end($in_arrays))) {
if (array_pop($arrays)) { if (array_pop($in_arrays)) {
$key_is_string = true; $key_is_string = true;
} }
} }
// check that arrays count is at least two, else we don't have enough to do anything // check that arrays count is at least two, else we don't have enough to do anything
if (count($arrays) < 2) { if (count($in_arrays) < 2) {
throw new \ArgumentCountError(__FUNCTION__ . ' needs two or more array arguments'); throw new \ArgumentCountError(__FUNCTION__ . ' needs two or more array arguments');
} }
$merged = []; $merged = [];
while ($arrays) { while ($in_arrays) {
$array = array_shift($arrays); $in_array = array_shift($in_arrays);
if (!is_array($array)) { if (!is_array($in_array)) {
throw new \TypeError(__FUNCTION__ . ' encountered a non array argument'); throw new \TypeError(__FUNCTION__ . ' encountered a non array argument');
} }
if (!$array) { if (!$in_array) {
continue; continue;
} }
foreach ($array as $key => $value) { foreach ($in_array as $key => $value) {
// if string or if key is assumed to be string do key match // if string or if key is assumed to be string do key match
// else add new entry // else add new entry
if (is_string($key) || $key_is_string === false) { if (is_string($key) || $key_is_string === false) {
@@ -589,14 +589,14 @@ class ArrayHandler
* converts multi dimensional array to a flat array * converts multi dimensional array to a flat array
* does NOT preserve keys * does NOT preserve keys
* *
* @param array<mixed> $array multi dimensionial array * @param array<mixed> $in_array multi dimensionial array
* @return array<mixed> flattened array * @return array<mixed> flattened array
*/ */
public static function flattenArray(array $array): array public static function flattenArray(array $in_array): array
{ {
$return = []; $return = [];
array_walk_recursive( array_walk_recursive(
$array, $in_array,
function ($value) use (&$return) { function ($value) use (&$return) {
$return[] = $value; $return[] = $value;
} }
@@ -607,13 +607,13 @@ class ArrayHandler
/** /**
* will loop through an array recursivly and write the array keys back * will loop through an array recursivly and write the array keys back
* *
* @param array<mixed> $array multidemnsional array to flatten * @param array<mixed> $in_array multidemnsional array to flatten
* @param array<mixed> $return recoursive pass on array of keys * @param array<mixed> $return recoursive pass on array of keys
* @return array<mixed> flattened keys array * @return array<mixed> flattened keys array
*/ */
public static function flattenArrayKey(array $array, array $return = []): array public static function flattenArrayKey(array $in_array, array $return = []): array
{ {
foreach ($array as $key => $sub) { foreach ($in_array as $key => $sub) {
$return[] = $key; $return[] = $key;
if (is_array($sub) && count($sub) > 0) { if (is_array($sub) && count($sub) > 0) {
$return = self::flattenArrayKey($sub, $return); $return = self::flattenArrayKey($sub, $return);
@@ -626,14 +626,14 @@ class ArrayHandler
* as above will flatten an array, but in this case only the outmost * as above will flatten an array, but in this case only the outmost
* leave nodes, all other keyswill be skipped * leave nodes, all other keyswill be skipped
* *
* @param array<mixed> $array multidemnsional array to flatten * @param array<mixed> $in_array multidemnsional array to flatten
* @return array<mixed> flattened keys array * @return array<mixed> flattened keys array
*/ */
public static function flattenArrayKeyLeavesOnly(array $array): array public static function flattenArrayKeyLeavesOnly(array $in_array): array
{ {
$return = []; $return = [];
array_walk_recursive( array_walk_recursive(
$array, $in_array,
function ($value, $key) use (&$return) { function ($value, $key) use (&$return) {
$return[] = $key; $return[] = $key;
} }
@@ -645,14 +645,14 @@ class ArrayHandler
* searches for key -> value in an array tree and writes the value one level up * searches for key -> value in an array tree and writes the value one level up
* this will remove this leaf will all other values * this will remove this leaf will all other values
* *
* @param array<mixed> $array nested array * @param array<mixed> $in_array nested array
* @param string|int $search key to find that has no sub leaf * @param string|int $search key to find that has no sub leaf
* and will be pushed up * and will be pushed up
* @return array<mixed> modified, flattened array * @return array<mixed> modified, flattened array
*/ */
public static function arrayFlatForKey(array $array, string|int $search): array public static function arrayFlatForKey(array $in_array, string|int $search): array
{ {
foreach ($array as $key => $value) { foreach ($in_array as $key => $value) {
// if it is not an array do just nothing // if it is not an array do just nothing
if (!is_array($value)) { if (!is_array($value)) {
continue; continue;
@@ -660,14 +660,14 @@ class ArrayHandler
// probe it has search key // probe it has search key
if (isset($value[$search])) { if (isset($value[$search])) {
// set as current // set as current
$array[$key] = $value[$search]; $in_array[$key] = $value[$search];
} else { } else {
// call up next node down // call up next node down
// $array[$key] = call_user_func(__METHOD__, $value, $search); // $in_array[$key] = call_user_func(__METHOD__, $value, $search);
$array[$key] = self::arrayFlatForKey($value, $search); $in_array[$key] = self::arrayFlatForKey($value, $search);
} }
} }
return $array; return $in_array;
} }
/** /**
@@ -677,13 +677,13 @@ class ArrayHandler
* *
* https://stackoverflow.com/a/369608 * https://stackoverflow.com/a/369608
* *
* @param array<mixed> $array Array where elements are located * @param array<mixed> $in_array Array where elements are located
* @param array<mixed> $remove Elements to remove * @param array<mixed> $remove Elements to remove
* @return array<mixed> Array with $remove elements removed * @return array<mixed> Array with $remove elements removed
*/ */
public static function arrayRemoveEntry(array $array, array $remove): array public static function arrayRemoveEntry(array $in_array, array $remove): array
{ {
return array_diff($array, $remove); return array_diff($in_array, $remove);
} }
/** /**
@@ -693,20 +693,20 @@ class ArrayHandler
* key list is a list[string] * key list is a list[string]
* if key list is empty, return array as is * if key list is empty, return array as is
* *
* @param array<string,mixed> $array * @param array<string,mixed> $in_array
* @param array<string> $key_list * @param array<string> $key_list
* @return array<string,mixed> * @return array<string,mixed>
*/ */
public static function arrayReturnMatchingKeyOnly( public static function arrayReturnMatchingKeyOnly(
array $array, array $in_array,
array $key_list array $key_list
): array { ): array {
// on empty return as is // on empty return as is
if (empty($key_list)) { if (empty($key_list)) {
return $array; return $in_array;
} }
return array_filter( return array_filter(
$array, $in_array,
fn($key) => in_array($key, $key_list), fn($key) => in_array($key, $key_list),
ARRAY_FILTER_USE_KEY ARRAY_FILTER_USE_KEY
); );
@@ -748,16 +748,19 @@ class ArrayHandler
* sort ascending or descending with or without lower case convert * sort ascending or descending with or without lower case convert
* value only, will loose key connections unless preserve_keys is set to true * value only, will loose key connections unless preserve_keys is set to true
* *
* @param array<mixed> $array array to sort by values * @param array<mixed> $in_array Array to sort by values
* @param int $params sort flags * @param bool $case_insensitive [false] Sort case insensitive
* @param bool $reverse [false] Reverse sort
* @param bool $maintain_keys [false] Maintain keys
* @param int $flag [SORT_REGULAR] Sort flags
* @return array<mixed> * @return array<mixed>
*/ */
public static function sortArray( public static function sortArray(
array $array, array $in_array,
bool $case_insensitive = false, bool $case_insensitive = false,
bool $reverse = false, bool $reverse = false,
bool $maintain_keys = false, bool $maintain_keys = false,
int $params = SORT_REGULAR int $flag = SORT_REGULAR
): array { ): array {
$fk_sort_lower_case = function (string $a, string $b): int { $fk_sort_lower_case = function (string $a, string $b): int {
return strtolower($a) <=> strtolower($b); return strtolower($a) <=> strtolower($b);
@@ -767,26 +770,26 @@ class ArrayHandler
}; };
$case_insensitive ? ( $case_insensitive ? (
$maintain_keys ? $maintain_keys ?
(uasort($array, $reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case)) : (uasort($in_array, $reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case)) :
(usort($array, $reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case)) (usort($in_array, $reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case))
) : ) :
( (
$maintain_keys ? $maintain_keys ?
($reverse ? arsort($array, $params) : asort($array, $params)) : ($reverse ? arsort($in_array, $flag) : asort($in_array, $flag)) :
($reverse ? rsort($array, $params) : sort($array, $params)) ($reverse ? rsort($in_array, $flag) : sort($in_array, $flag))
); );
return $array; return $in_array;
} }
/** /**
* sort by key ascending or descending and return * sort by key ascending or descending and return
* *
* @param array<mixed> $array * @param array<mixed> $in_array Array to srt
* @param bool $case_insensitive [false] * @param bool $case_insensitive [false] Sort keys case insenstive
* @param bool $reverse [false] * @param bool $reverse [false] Reverse key sort
* @return array<mixed> * @return array<mixed>
*/ */
public static function ksortArray(array $array, bool $case_insensitive = false, bool $reverse = false): array public static function ksortArray(array $in_array, bool $case_insensitive = false, bool $reverse = false): array
{ {
$fk_sort_lower_case = function (string $a, string $b): int { $fk_sort_lower_case = function (string $a, string $b): int {
return strtolower($a) <=> strtolower($b); return strtolower($a) <=> strtolower($b);
@@ -801,12 +804,12 @@ class ArrayHandler
return $b <=> $a; return $b <=> $a;
}; };
uksort( uksort(
$array, $in_array,
$case_insensitive ? $case_insensitive ?
($reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case) : ($reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case) :
($reverse ? $fk_sort_reverse : $fk_sort) ($reverse ? $fk_sort_reverse : $fk_sort)
); );
return $array; return $in_array;
} }
} }

View File

@@ -77,7 +77,7 @@ class Byte
// labels in order of size [Y, Z] // labels in order of size [Y, Z]
$labels = ['', 'K', 'M', 'G', 'T', 'P', 'E']; $labels = ['', 'K', 'M', 'G', 'T', 'P', 'E'];
// exp position calculation // exp position calculation
$exp = floor(log($abs_bytes, $unit)); $exp = (int)floor(log($abs_bytes, $unit));
// avoid printing out anything larger than max labels // avoid printing out anything larger than max labels
if ($exp >= count($labels)) { if ($exp >= count($labels)) {
$exp = count($labels) - 1; $exp = count($labels) - 1;

View File

@@ -55,10 +55,10 @@ class Json
* Deos not throw errors * Deos not throw errors
* *
* @param array<mixed> $data * @param array<mixed> $data
* @param int $flags json_encode flags as is * @param int $flags [JSON_UNESCAPED_UNICODE] json_encode flags as is
* @return string JSON string or '{}' if false * @return string JSON string or '{}' if false
*/ */
public static function jsonConvertArrayTo(array $data, int $flags = 0): string public static function jsonConvertArrayTo(array $data, int $flags = JSON_UNESCAPED_UNICODE): string
{ {
$json_string = json_encode($data, $flags) ?: '{}'; $json_string = json_encode($data, $flags) ?: '{}';
self::$json_last_error = json_last_error(); self::$json_last_error = json_last_error();

View File

@@ -199,15 +199,17 @@ class Math
callback: fn ($col) => is_array($row) ? callback: fn ($col) => is_array($row) ?
array_reduce( array_reduce(
array: $row, array: $row,
callback: fn ($a, $v, $i = null) => $a + $v * ( // TODO check that v is not an array
callback: fn ($a, $v, $i = null) => $a + $v * ( /** @phpstan-ignore-line Possible array + int */
// if last entry missing for full copy add a 0 to it // if last entry missing for full copy add a 0 to it
$col[$i ?? array_search($v, $row, true)] ?? 0 /** @phpstan-ignore-line */ $col[$i ?? array_search($v, $row, true)] ?? 0
), ),
initial: 0, initial: 0,
) : ) :
array_reduce( array_reduce(
array: $col, array: $col,
callback: fn ($a, $v) => $a + $v * $row, // TODO check that v is not an array
callback: fn ($a, $v) => $a + $v * $row, /** @phpstan-ignore-line Possible array + int */
initial: 0, initial: 0,
), ),
array: $bCols, array: $bCols,

View File

@@ -81,7 +81,7 @@ class Uids
*/ */
public static function validateUuuidv4(string $uuidv4): bool public static function validateUuuidv4(string $uuidv4): bool
{ {
if (!preg_match("/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/", $uuidv4)) { if (!preg_match("/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i", $uuidv4)) {
return false; return false;
} }
return true; return true;

View File

@@ -263,11 +263,11 @@ class ConvertPlaceholder
} }
} }
// add the connectors back (1), and the data sets only if no replacement will be done // add the connectors back (1), and the data sets only if no replacement will be done
return $params_lookup[$match] ?? return $params_lookup[$match]/* ??
throw new \RuntimeException( throw new \RuntimeException(
'Cannot lookup ' . $match . ' in params lookup list', 'Cannot lookup ' . $match . ' in params lookup list',
211 211
); )*/;
}, },
$converted_placeholders['original']['query'] $converted_placeholders['original']['query']
); );
@@ -327,11 +327,11 @@ class ConvertPlaceholder
} }
} }
// add the connectors back (1), and the data sets only if no replacement will be done // add the connectors back (1), and the data sets only if no replacement will be done
return $params_lookup[$match] ?? return $params_lookup[$match]/* ??
throw new \RuntimeException( throw new \RuntimeException(
'Cannot lookup ' . $match . ' in params lookup list', 'Cannot lookup ' . $match . ' in params lookup list',
231 231
); )*/;
}, },
$converted_placeholders['original']['query'] $converted_placeholders['original']['query']
); );

View File

@@ -33,6 +33,36 @@ class Support
return $string; return $string;
} }
/**
* print ISO type datetime with microseconds and timezone
* Y-m-dTH:i:s.uP
* if no micro time the ".u" part is omitted
*
* @param bool $set_micro_time
* @return string
*/
public static function printIsoTime(bool $set_micro_time = true): string
{
$datetime = new \DateTime();
// Format the DateTime object to ISO 8601 with microseconds
// 'Y-m-d\TH:i:s.uP' is the format string:
// Y: Full year (e.g., 2025)
// m: Month (01-12)
// d: Day of the month (01-31)
// T: Literal 'T' to separate date and time (escaped with a backslash)
// H: Hour (00-23)
// i: Minute (00-59)
// s: Second (00-59)
// u: Microseconds (e.g., 654321)
// P: Difference to Greenwich time (GMT) with colon (e.g., +09:00)
if ($set_micro_time) {
return $datetime->format('Y-m-d\TH:i:s.uP');
} else {
return $datetime->format('Y-m-d\TH:i:sP');
}
}
/** /**
* prints a html formatted (pre) data * prints a html formatted (pre) data
* *

View File

@@ -131,6 +131,7 @@ class ErrorMessage
// set a jump target // set a jump target
$this->setJumpTarget($jump_target['target'] ?? null, $jump_target['info'] ?? null, $level); $this->setJumpTarget($jump_target['target'] ?? null, $jump_target['info'] ?? null, $level);
// write to log for abort/crash // write to log for abort/crash
$this->log->setErrorMessageCallSetErrorMsg();
switch ($level) { switch ($level) {
case 'notice': case 'notice':
$this->log->notice($message ?? $str, array_merge([ $this->log->notice($message ?? $str, array_merge([
@@ -210,6 +211,7 @@ class ErrorMessage
?bool $log_error = null, ?bool $log_error = null,
?bool $log_warning = null, ?bool $log_warning = null,
): void { ): void {
$this->log->setErrorMessageCallSetMessage();
$this->setErrorMsg( $this->setErrorMsg(
$error_id ?? '', $error_id ?? '',
$level, $level,

View File

@@ -112,7 +112,7 @@ enum Level: int
} }
/** /**
* Returns true if the passed $level is higher or equal to $this * Returns true if the passed $level is included in set level
* *
* @param Level $level * @param Level $level
* @return bool * @return bool

View File

@@ -13,6 +13,7 @@ namespace CoreLibs\Logging\Logger;
enum MessageLevel: int enum MessageLevel: int
{ {
case noset = 0;
case ok = 100; case ok = 100;
case success = 150; // special for file uploads case success = 150; // special for file uploads
case info = 200; case info = 200;

View File

@@ -29,11 +29,19 @@ use Stringable;
class Logging class Logging
{ {
/** @var int minimum size for a max file size, so we don't set 1 byte, 10kb */ /** @var int minimum size for a max file size, so we don't set 1 byte, 10kb */
public const MIN_LOG_MAX_FILESIZE = 10 * 1024; public const int MIN_LOG_MAX_FILESIZE = 10 * 1024;
/** @var string log file extension, not changeable */ /** @var string log file extension, not changeable */
private const LOG_FILE_NAME_EXT = "log"; private const string LOG_FILE_NAME_EXT = "log";
/** @var string log file block separator, not changeable */ /** @var string log file block separator, not changeable */
private const LOG_FILE_BLOCK_SEPARATOR = '.'; private const string LOG_FILE_BLOCK_SEPARATOR = '.';
/** @var int the base stack trace level for the line number */
private const int DEFAULT_STACK_TRACE_LEVEL_LINE = 1;
/** @var array<string,int> */
private const array STACK_OVERRIDE_CHECK = [
'setErrorMsg' => 2,
'setMessage' => 3,
];
// MARK: OPTION array // MARK: OPTION array
// NOTE: the second party array{} hs some errors // NOTE: the second party array{} hs some errors
@@ -96,6 +104,11 @@ class Logging
'type' => 'bool', 'mandatory' => false, 'type' => 'bool', 'mandatory' => false,
'default' => false, 'deprecated' => true, 'use' => 'log_per_date' 'default' => false, 'deprecated' => true, 'use' => 'log_per_date'
], ],
// if turned off uses old time format without time zone
'log_time_format_iso' => [
'type' => 'bool', 'mandatory' => false,
'default' => true, 'deprecated' => false
]
]; ];
// options // options
@@ -133,6 +146,12 @@ class Logging
/** @var string Y-m-d file in file name */ /** @var string Y-m-d file in file name */
private string $log_file_date = ''; private string $log_file_date = '';
// speical flags for ErrorMessage calls
/** @var bool Flag to set if called from ErrorMessage::setErrorMsg */
private bool $error_message_call_set_error_msg = false;
/** @var bool Flag to set if called from ErrorMessage::setMessage */
private bool $error_message_call_set_message = false;
/** /**
* 1: create a new log file per run (time stamp + unique ID) * 1: create a new log file per run (time stamp + unique ID)
* 2: add Y-m-d and do automatic daily rotation * 2: add Y-m-d and do automatic daily rotation
@@ -622,31 +641,65 @@ class Logging
$file_line = ''; $file_line = '';
$caller_class_method = '-'; $caller_class_method = '-';
$traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); $traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
// print "[" . $level->getName() . "] [$message] prepareLog:<br>" . Support::printAr($traces); $stack_trace_start_level_line = self::DEFAULT_STACK_TRACE_LEVEL_LINE;
// file + line: call not this but one before (the one that calls this) // set stack trace level +1 if called from ErrorMessage::setMessage
// start from this level, if unset fall down until we are at null if ($this->error_message_call_set_message) {
$start_trace_level = 2; $stack_trace_start_level_line = 3;
for ($trace_level = $start_trace_level; $trace_level >= 0; $trace_level--) { } elseif ($this->error_message_call_set_error_msg) {
if (isset($traces[$trace_level])) { $stack_trace_start_level_line = 2;
$file_line = ($traces[$trace_level]['file'] ?? $traces[$trace_level]['function']) }
. ':' . ($traces[$trace_level]['line'] ?? '-'); // if we have line > default, then check if valid, else reset to default
// as namespace\class->method if ($stack_trace_start_level_line > self::DEFAULT_STACK_TRACE_LEVEL_LINE) {
$caller_class_method = // check if function at level is one of the override checks
// get the last call before we are in the Logging class $fn_check = $traces[$stack_trace_start_level_line]['function'] ?? '';
($traces[$trace_level]['class'] ?? '') if (
// connector, if unkown use == !isset(self::STACK_OVERRIDE_CHECK[$fn_check]) ||
. ($traces[$trace_level]['type'] ?? '') self::STACK_OVERRIDE_CHECK[$fn_check] != $stack_trace_start_level_line
// method/function: prepareLog->(debug|info|...)->[THIS] ) {
. $traces[$trace_level]['function']; $stack_trace_start_level_line = self::DEFAULT_STACK_TRACE_LEVEL_LINE;
break;
} }
} }
$this->error_message_call_set_message = false;
$this->error_message_call_set_error_msg = false;
// set stack trace level +1 if called from ErrorMessage::setMessage
// print "[" . $level->getName() . "] [$message] [" . $stack_trace_start_level_line . "] "
// . "prepareLog:<br>" . Support::printAr($traces);
// file + line: call not this but one before (the one that calls this)
// start from this level, if unset fall down until we are at null
// NOTE this has to be pushed to 3 for setMessage wrap calls
for ($trace_level = $stack_trace_start_level_line; $trace_level >= 0; $trace_level--) {
if (!isset($traces[$trace_level])) {
continue;
}
$file_line = ($traces[$trace_level]['file'] ?? $traces[$trace_level]['function'])
. ':' . ($traces[$trace_level]['line'] ?? '-');
// call function is one stack level above
$trace_level++;
// skip setting if we are in the top level already
if (!isset($traces[$trace_level])) {
break;
}
// as namespace\class->method
$caller_class_method =
// get the last call before we are in the Logging class
($traces[$trace_level]['class'] ?? '')
// connector, if unkown use ==
. ($traces[$trace_level]['type'] ?? '')
// method/function: prepareLog->(debug|info|...)->[THIS]
. $traces[$trace_level]['function'];
break;
}
// if not line is set
if (empty($file_line)) { if (empty($file_line)) {
$file_line = System::getPageName(System::FULL_PATH); $file_line = System::getPageName(System::FULL_PATH);
} }
// print "CLASS: " . $class . "<br>"; // print "CLASS: " . $class . "<br>";
// get timestamp // get timestamp
$timestamp = Support::printTime(); if (!empty($this->options['log_time_format_iso'])) {
$timestamp = Support::printIsoTime();
} else {
$timestamp = Support::printTime();
}
// if group id is empty replace it with current level // if group id is empty replace it with current level
$group_str = $level->getName(); $group_str = $level->getName();
@@ -1008,6 +1061,30 @@ class Logging
return $this->log_max_filesize; return $this->log_max_filesize;
} }
// *********************************************************************
// MARK: ErrorMessage class overrides
// *********************************************************************
/**
* call if called from Error Message setMessage wrapper
*
* @return void
*/
public function setErrorMessageCallSetMessage(): void
{
$this->error_message_call_set_message = true;
}
/**
* call if called from Error Message setMessage wrapper
*
* @return void
*/
public function setErrorMessageCallSetErrorMsg(): void
{
$this->error_message_call_set_error_msg = true;
}
// ********************************************************************* // *********************************************************************
// MARK: OPTIONS CALLS // MARK: OPTIONS CALLS
// ********************************************************************* // *********************************************************************
@@ -1475,14 +1552,15 @@ class Logging
Level::Error, Level::Critical, Level::Alert, Level::Emergency Level::Error, Level::Critical, Level::Alert, Level::Emergency
] as $l ] as $l
) { ) {
print "Check: " . $this->log_level->getName() . " | " . $l->getName() . "<br>";
if ($this->log_level->isHigherThan($l)) { if ($this->log_level->isHigherThan($l)) {
print "L: " . $this->log_level->getName() . " > " . $l->getName() . "<br>"; print "L(gt): " . $this->log_level->getName() . " > " . $l->getName() . "<br>";
} }
if ($this->log_level->includes($l)) { if ($this->log_level->includes($l)) {
print "L: " . $this->log_level->getName() . " <= " . $l->getName() . "<br>"; print "L(le): " . $this->log_level->getName() . " <= " . $l->getName() . "<br>";
} }
if ($this->log_level->isLowerThan($l)) { if ($this->log_level->isLowerThan($l)) {
print "L: " . $this->log_level->getName() . " < " . $l->getName() . "<br>"; print "L(lt): " . $this->log_level->getName() . " < " . $l->getName() . "<br>";
} }
echo "<br>"; echo "<br>";
} }

View File

@@ -24,12 +24,12 @@ final class CoreLibsCheckEmailTest extends TestCase
'get email regex invalid -1, will be 0' => [ 'get email regex invalid -1, will be 0' => [
-1, -1,
"^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@" "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@"
. "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$" . "(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\.[a-zA-Z]{2,6}$"
], ],
'get email regex invalid 10, will be 0' => [ 'get email regex invalid 10, will be 0' => [
10, 10,
"^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@" "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@"
. "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$" . "(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\.[a-zA-Z]{2,6}$"
], ],
'get email regex valid 1, will be 1' => [ 'get email regex valid 1, will be 1' => [
1, 1,
@@ -157,7 +157,7 @@ final class CoreLibsCheckEmailTest extends TestCase
'error' => 0, 'error' => 0,
'message' => 'Invalid email address', 'message' => 'Invalid email address',
'regex' => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@" 'regex' => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@"
. "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$" . "(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\.[a-zA-Z]{2,6}$"
] ]
], ],
'error 1 will return double @ error' => [ 'error 1 will return double @ error' => [
@@ -181,7 +181,7 @@ final class CoreLibsCheckEmailTest extends TestCase
[ [
'error' => 3, 'error' => 3,
'message' => 'Invalid domain part after @ sign', 'message' => 'Invalid domain part after @ sign',
'regex' => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.([a-zA-Z]{2,}){1}$" 'regex' => "@(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\.[a-zA-Z]{2,6}$"
] ]
], ],
'error 4 will be invalid domain' => [ 'error 4 will be invalid domain' => [
@@ -189,7 +189,7 @@ final class CoreLibsCheckEmailTest extends TestCase
[ [
'error' => 4, 'error' => 4,
'message' => 'Invalid domain name part', 'message' => 'Invalid domain name part',
'regex' => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\." 'regex' => "@(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\."
] ]
], ],
'error 5 will be invalid domain top level only' => [ 'error 5 will be invalid domain top level only' => [
@@ -197,7 +197,7 @@ final class CoreLibsCheckEmailTest extends TestCase
[ [
'error' => 5, 'error' => 5,
'message' => 'Wrong domain top level part', 'message' => 'Wrong domain top level part',
'regex' => "\.([a-zA-Z]{2,6}){1}$" 'regex' => "\.[a-zA-Z]{2,6}$"
] ]
], ],
'error 6 will be domain double dot' => [ 'error 6 will be domain double dot' => [

View File

@@ -105,11 +105,15 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'log_folder' => self::LOG_FOLDER, 'log_folder' => self::LOG_FOLDER,
'log_level' => Level::Error, 'log_level' => Level::Error,
]); ]);
$errorLogTmpfile = tmpfile();
$errorLogLocationBackup = ini_set('error_log', stream_get_meta_data($errorLogTmpfile)['uri']);
$em = new \CoreLibs\Logging\ErrorMessage($log); $em = new \CoreLibs\Logging\ErrorMessage($log);
$em->setMessage( $em->setMessage(
$level, $level,
$str $str
); );
// for exceptions if log level is set to catch them
$error_log_content = stream_get_contents($errorLogTmpfile);
$this->assertEquals( $this->assertEquals(
[ [
'level' => $expected, 'level' => $expected,
@@ -377,6 +381,8 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
?bool $log_warning, ?bool $log_warning,
string $expected string $expected
): void { ): void {
$errorLogTmpfile = tmpfile();
$errorLogLocationBackup = ini_set('error_log', stream_get_meta_data($errorLogTmpfile)['uri']);
$log = new \CoreLibs\Logging\Logging([ $log = new \CoreLibs\Logging\Logging([
'log_file_id' => 'testErrorMessagesLogError', 'log_file_id' => 'testErrorMessagesLogError',
'log_folder' => self::LOG_FOLDER, 'log_folder' => self::LOG_FOLDER,
@@ -392,6 +398,9 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
log_error: $log_error, log_error: $log_error,
log_warning: $log_warning log_warning: $log_warning
); );
ini_set('error_log', $errorLogLocationBackup);
// for exceptions if log level is set to catch them
$error_log_content = stream_get_contents($errorLogTmpfile);
$file_content = ''; $file_content = '';
if (is_file($log->getLogFolder() . $log->getLogFile())) { if (is_file($log->getLogFolder() . $log->getLogFile())) {
$file_content = file_get_contents( $file_content = file_get_contents(
@@ -447,6 +456,8 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'log_level' => Level::Debug, 'log_level' => Level::Debug,
'log_per_run' => true 'log_per_run' => true
]); ]);
$errorLogTmpfile = tmpfile();
$errorLogLocationBackup = ini_set('error_log', stream_get_meta_data($errorLogTmpfile)['uri']);
$em = new \CoreLibs\Logging\ErrorMessage($log); $em = new \CoreLibs\Logging\ErrorMessage($log);
$em->setErrorMsg( $em->setErrorMsg(
$id, $id,
@@ -456,6 +467,9 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
log_error: $log_error, log_error: $log_error,
log_warning: $log_warning log_warning: $log_warning
); );
ini_set('error_log', $errorLogLocationBackup);
// for exceptions if log level is set to catch them
$error_log_content = stream_get_contents($errorLogTmpfile);
$file_content = ''; $file_content = '';
if (is_file($log->getLogFolder() . $log->getLogFile())) { if (is_file($log->getLogFolder() . $log->getLogFile())) {
$file_content = file_get_contents( $file_content = file_get_contents(

View File

@@ -18,7 +18,7 @@ use CoreLibs\Logging\Logger\Flag;
final class CoreLibsLoggingLoggingTest extends TestCase final class CoreLibsLoggingLoggingTest extends TestCase
{ {
private const LOG_FOLDER = __DIR__ . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR; private const LOG_FOLDER = __DIR__ . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR;
private const REGEX_BASE = "\[[\d\-\s\.:]+\]\s{1}" // date private const REGEX_BASE = "\[[\d\-\s\.:+T]+\]\s{1}" // date, just basic checks
. "\[[\w\.]+(:\d+)?\]\s{1}" // host:port . "\[[\w\.]+(:\d+)?\]\s{1}" // host:port
. "\[(phar:\/\/)?[\w\-\.\/]+:\d+\]\s{1}" // folder/file [note phar:// is for phpunit] . "\[(phar:\/\/)?[\w\-\.\/]+:\d+\]\s{1}" // folder/file [note phar:// is for phpunit]
. "\[\w+\]\s{1}" // run id . "\[\w+\]\s{1}" // run id