Compare commits

...

3 Commits

Author SHA1 Message Date
Clemens Schwaighofer
c81b602657 phpunit: redirect error_log message to temp file so they are not printed to console
This is for any logging part that logs to emergency where emergency logging is
set to log to the error_log too
2025-10-09 15:05:00 +09:00
Clemens Schwaighofer
59cc5f2060 phpstan checks and fixes 2025-10-09 11:58:47 +09:00
Clemens Schwaighofer
e072aaf4d6 Add ISO Type datetime format to support, and make this default loggint time format 2025-10-09 11:14:06 +09:00
10 changed files with 81 additions and 18 deletions

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

View File

@@ -332,7 +332,7 @@ print "(kosrt, lower case, reverse): "
print "<hr>"; print "<hr>";
$nested = [ $nested = [
'B' => 'foo', 'a', '0', 9, 'B' => 'foo', 'a', '0', 9, /** @phpstan-ignore-line This is a test for wrong index */
'1' => ['z', 'b', 'a'], '1' => ['z', 'b', 'a'],
'd' => ['zaip', 'bar', 'baz'] 'd' => ['zaip', 'bar', 'baz']
]; ];

View File

@@ -68,6 +68,14 @@ function test2(): array
return DebugSupport::getCallerMethodList(1); return DebugSupport::getCallerMethodList(1);
} }
// date stueff
print "printTime(-1): " . DebugSupport::printTime() . "<br>";
print "printTime(2): " . DebugSupport::printTime(2) . "<br>";
print "printTime(3): " . DebugSupport::printTime(3) . "<br>";
print "printTime(5): " . DebugSupport::printTime(5) . "<br>";
print "printIsoTime(): " . DebugSupport::printIsoTime() . "<br>";
print "printIsoTime(false): " . DebugSupport::printIsoTime(false) . "<br>";
print "S::GETCALLERMETHOD: " . DebugSupport::getCallerMethod(0) . "<br>"; print "S::GETCALLERMETHOD: " . DebugSupport::getCallerMethod(0) . "<br>";
print "S::GETCALLERMETHOD: " . test() . "<br>"; print "S::GETCALLERMETHOD: " . test() . "<br>";
print "S::GETCALLERMETHODLIST: <pre>" . print_r(test2(), true) . "</pre><br>"; print "S::GETCALLERMETHODLIST: <pre>" . print_r(test2(), true) . "</pre><br>";
@@ -146,7 +154,7 @@ print "LOG LEVEL: " . DebugSupport::printAr(\CoreLibs\Convert\SetVarType::setAr
$new_log->getLogLevel('debug', 'on') $new_log->getLogLevel('debug', 'on')
)) . "<br>"; )) . "<br>";
echo "<b>CLASS DEBUG CALL</b><br>"; echo "<b>CLASS DEBUG CALL LEGACY</b><br>";
// @codingStandardsIgnoreLine // @codingStandardsIgnoreLine
class TestL class TestL

View File

@@ -18,7 +18,7 @@ class Email
// 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 @
3 => "@(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\.[a-zA-Z]{2,6}$", // wrong part after @ 3 => "@(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.[A-Za-z0-9-]{1,63}(?<!-))*\.[a-zA-Z]{2,6}$", // wrong part after @
// 4 => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.", // wrong domain name 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 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 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

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

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

@@ -96,6 +96,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
@@ -646,7 +651,11 @@ class Logging
} }
// 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();