Compare commits
13 Commits
b89238b922
...
feature/TT
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
378d6c7527 | ||
|
|
ad7b59e26a | ||
|
|
c43bb0662d | ||
|
|
c4e83f94e9 | ||
|
|
a292abc2c5 | ||
|
|
6c5af91386 | ||
|
|
73fc74a43a | ||
|
|
5c6a5c2d20 | ||
|
|
b033a718ad | ||
|
|
51e3cc7c7f | ||
|
|
b7935dcb71 | ||
|
|
89e8f79cae | ||
|
|
1a027e5c7d |
@@ -3,7 +3,7 @@
|
|||||||
<phar name="phpunit" version="^10.3.5" installed="10.5.46" location="./tools/phpunit" copy="false"/>
|
<phar name="phpunit" version="^10.3.5" installed="10.5.46" location="./tools/phpunit" copy="false"/>
|
||||||
<phar name="phpcbf" version="^3.7.2" installed="3.13.0" location="./tools/phpcbf" copy="false"/>
|
<phar name="phpcbf" version="^3.7.2" installed="3.13.0" location="./tools/phpcbf" copy="false"/>
|
||||||
<phar name="phpcs" version="^3.10.3" installed="3.13.0" location="./tools/phpcs" copy="false"/>
|
<phar name="phpcs" version="^3.10.3" installed="3.13.0" location="./tools/phpcs" copy="false"/>
|
||||||
<phar name="phpstan" version="^2.0" installed="2.1.16" location="./tools/phpstan" copy="false"/>
|
<phar name="phpstan" version="^2.0" installed="2.1.17" location="./tools/phpstan" copy="false"/>
|
||||||
<phar name="phan" version="^5.4.3" installed="5.4.3" location="./tools/phan" copy="false"/>
|
<phar name="phan" version="^5.4.3" installed="5.4.3" location="./tools/phan" copy="false"/>
|
||||||
<phar name="psalm" version="^5.15.0" installed="5.24.0" location="./tools/psalm" copy="false"/>
|
<phar name="psalm" version="^5.15.0" installed="5.24.0" location="./tools/psalm" copy="false"/>
|
||||||
<phar name="phpdox" version="^0.12.0" installed="0.12.0" location="./tools/phpdox" copy="false"/>
|
<phar name="phpdox" version="^0.12.0" installed="0.12.0" location="./tools/phpdox" copy="false"/>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
|
base=$(pwd)"/";
|
||||||
# must be run in ${base}
|
# must be run in ${base}
|
||||||
cd $base || exit;
|
cd $base || exit;
|
||||||
${base}tools/phan --progress-bar -C --analyze-twice;
|
#PHAN_DISABLE_XDEBUG_WARN=1;${base}tools/phan --progress-bar -C --analyze-twice
|
||||||
|
PHAN_DISABLE_XDEBUG_WARN=1;${base}vendor/bin/phan --progress-bar -C --analyze-twice
|
||||||
cd ~ || exit;
|
cd ~ || exit;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
|
base=$(pwd)"/";
|
||||||
# must be run in ${base}
|
# must be run in ${base}
|
||||||
cd $base || exit;
|
cd $base || exit;
|
||||||
${base}tools/phpstan;
|
${base}tools/phpstan;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
# set base variables
|
# set base variables
|
||||||
BASE_PATH="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
|
BASE_PATH=$(pwd)"/";
|
||||||
PHPUNIT_CONFIG="${BASE_PATH}phpunit.xml";
|
PHPUNIT_CONFIG="${BASE_PATH}phpunit.xml";
|
||||||
PHP_BIN_PATH=$(which php);
|
PHP_BIN_PATH=$(which php);
|
||||||
if [ -z "${PHP_BIN_PATH}" ]; then
|
if [ -z "${PHP_BIN_PATH}" ]; then
|
||||||
|
|||||||
46
4dev/tests/DB/CoreLibsDBSqLiteTest.php
Normal file
46
4dev/tests/DB/CoreLibsDBSqLiteTest.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for DB\SqLite
|
||||||
|
* This will only test the SqLite parts
|
||||||
|
* @coversDefaultClass \CoreLibs\DB\SqLite
|
||||||
|
* @testdox \CoreLibs\SqLite method tests for extended DB interface
|
||||||
|
*/
|
||||||
|
final class CoreLibsDBESqLiteTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Undocumented function
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
if (!extension_loaded('sqlite')) {
|
||||||
|
$this->markTestSkipped(
|
||||||
|
'The SqLite extension is not available.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented function
|
||||||
|
*
|
||||||
|
* @testdox DB\SqLite Class tests
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testSqLite()
|
||||||
|
{
|
||||||
|
$this->markTestIncomplete(
|
||||||
|
'DB\SqLite Tests have not yet been implemented'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// __END__
|
||||||
@@ -249,7 +249,7 @@ final class CoreLibsLoggingLoggingTest extends TestCase
|
|||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
$log->loggingLevelIsDebug()
|
$log->loggingLevelIsDebug()
|
||||||
);
|
);
|
||||||
// not set, should be debug]
|
// not set, should be debug
|
||||||
$log = new \CoreLibs\Logging\Logging([
|
$log = new \CoreLibs\Logging\Logging([
|
||||||
'log_file_id' => 'testSetLoggingLevel',
|
'log_file_id' => 'testSetLoggingLevel',
|
||||||
'log_folder' => self::LOG_FOLDER,
|
'log_folder' => self::LOG_FOLDER,
|
||||||
@@ -297,6 +297,71 @@ final class CoreLibsLoggingLoggingTest extends TestCase
|
|||||||
$log->setLoggingLevel('NotGood');
|
$log->setLoggingLevel('NotGood');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented function
|
||||||
|
*
|
||||||
|
* @covers ::setErrorLogWriteLevel
|
||||||
|
* @covers ::getErrorLogWriteLevel
|
||||||
|
* @testdox setErrorLogWriteLevel set/get checks
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testSetErrorLogWriteLevel(): void
|
||||||
|
{
|
||||||
|
// valid that is not Debug
|
||||||
|
$log = new \CoreLibs\Logging\Logging([
|
||||||
|
'log_file_id' => 'testSetErrorLogWriteLevel',
|
||||||
|
'log_folder' => self::LOG_FOLDER,
|
||||||
|
'error_log_write_level' => Level::Error
|
||||||
|
]);
|
||||||
|
$this->assertEquals(
|
||||||
|
Level::Error,
|
||||||
|
$log->getErrorLogWriteLevel()
|
||||||
|
);
|
||||||
|
// not set on init
|
||||||
|
$log = new \CoreLibs\Logging\Logging([
|
||||||
|
'log_file_id' => 'testSetErrorLogWriteLevel',
|
||||||
|
'log_folder' => self::LOG_FOLDER,
|
||||||
|
]);
|
||||||
|
$this->assertEquals(
|
||||||
|
Level::Emergency,
|
||||||
|
$log->getErrorLogWriteLevel()
|
||||||
|
);
|
||||||
|
// invalid, should be Emergency, will throw excpetion too
|
||||||
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage(
|
||||||
|
'Option: "error_log_write_level" is not of instance \CoreLibs\Logging\Logger\Level'
|
||||||
|
);
|
||||||
|
$log = new \CoreLibs\Logging\Logging([
|
||||||
|
'log_file_id' => 'testSetLoggingLevel',
|
||||||
|
'log_folder' => self::LOG_FOLDER,
|
||||||
|
'error_log_write_level' => 'I'
|
||||||
|
]);
|
||||||
|
$this->assertEquals(
|
||||||
|
Level::Emergency,
|
||||||
|
$log->getErrorLogWriteLevel()
|
||||||
|
);
|
||||||
|
// set valid then change
|
||||||
|
$log = new \CoreLibs\Logging\Logging([
|
||||||
|
'log_file_id' => 'testSetErrorLogWriteLevel',
|
||||||
|
'log_folder' => self::LOG_FOLDER,
|
||||||
|
'error_log_write_level' => Level::Error
|
||||||
|
]);
|
||||||
|
$this->assertEquals(
|
||||||
|
Level::Error,
|
||||||
|
$log->getErrorLogWriteLevel()
|
||||||
|
);
|
||||||
|
$log->setErrorLogWriteLevel(Level::Notice);
|
||||||
|
$this->assertEquals(
|
||||||
|
Level::Notice,
|
||||||
|
$log->getErrorLogWriteLevel()
|
||||||
|
);
|
||||||
|
// illegal logging level
|
||||||
|
$this->expectException(\Psr\Log\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessageMatches("/^Level \"NotGood\" is not defined, use one of: /");
|
||||||
|
$log->setErrorLogWriteLevel('NotGood');
|
||||||
|
}
|
||||||
|
|
||||||
// setLogFileId
|
// setLogFileId
|
||||||
// getLogFileId
|
// getLogFileId
|
||||||
|
|
||||||
|
|||||||
157
www/admin/class_test.db.sqlite.php
Normal file
157
www/admin/class_test.db.sqlite.php
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<?php // phpcs:ignore warning
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phan-file-suppress PhanTypeSuspiciousStringExpression
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
// turn on all error reporting
|
||||||
|
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
// basic class test file
|
||||||
|
define('USE_DATABASE', true);
|
||||||
|
define('DATABASE', 'sqlite' . DIRECTORY_SEPARATOR);
|
||||||
|
// sample config
|
||||||
|
require 'config.php';
|
||||||
|
// define log file id
|
||||||
|
$LOG_FILE_ID = 'classTest-db';
|
||||||
|
ob_end_flush();
|
||||||
|
|
||||||
|
$sql_file = BASE . MEDIA . DATABASE . "class_test.db.sqlite.sq3";
|
||||||
|
|
||||||
|
use CoreLibs\DB\SqLite;
|
||||||
|
use CoreLibs\Debug\Support;
|
||||||
|
use CoreLibs\Convert\SetVarType;
|
||||||
|
|
||||||
|
$log = new CoreLibs\Logging\Logging([
|
||||||
|
'log_folder' => BASE . LOG,
|
||||||
|
'log_file_id' => $LOG_FILE_ID,
|
||||||
|
'log_per_date' => true,
|
||||||
|
]);
|
||||||
|
// db connection and attach logger
|
||||||
|
$db = new CoreLibs\DB\SqLite($log, "sqlite:" . $sql_file);
|
||||||
|
$db->log->debug('START', '=============================>');
|
||||||
|
|
||||||
|
$PAGE_NAME = 'TEST CLASS: DB: SqLite';
|
||||||
|
print "<!DOCTYPE html>";
|
||||||
|
print "<html><head><title>" . $PAGE_NAME . "</title></head>";
|
||||||
|
print "<body>";
|
||||||
|
print '<div><a href="class_test.php">Class Test Master</a></div>';
|
||||||
|
|
||||||
|
print "<hr>";
|
||||||
|
|
||||||
|
echo "Create Tables on demand<br>";
|
||||||
|
|
||||||
|
$query = <<<SQL
|
||||||
|
CREATE TABLE IF NOT EXISTS test (
|
||||||
|
test_id INTEGER PRIMARY KEY,
|
||||||
|
c_text TEXT,
|
||||||
|
c_integer INTEGER,
|
||||||
|
c_integer_default INTEGER DEFAULT -1,
|
||||||
|
c_bool BOOLEAN,
|
||||||
|
c_datetime TEXT,
|
||||||
|
c_datetime_microseconds TEXT,
|
||||||
|
c_datetime_default TEXT DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
c_date TEXT,
|
||||||
|
c_julian REAL,
|
||||||
|
c_unixtime DATETIME,
|
||||||
|
c_unixtime_alt DATETIME,
|
||||||
|
c_numeric NUMERIC,
|
||||||
|
c_real REAL,
|
||||||
|
c_blob
|
||||||
|
)
|
||||||
|
SQL;
|
||||||
|
$db->dbExec($query);
|
||||||
|
// **********************
|
||||||
|
$query = <<<SQL
|
||||||
|
CREATE TABLE IF NOT EXISTS test_no_pk (
|
||||||
|
c_text TEXT,
|
||||||
|
c_integer INTEGER
|
||||||
|
)
|
||||||
|
SQL;
|
||||||
|
$db->dbExec($query);
|
||||||
|
|
||||||
|
print "<hr>";
|
||||||
|
|
||||||
|
$table = 'test';
|
||||||
|
echo "Table info for: " . $table . "<br>";
|
||||||
|
|
||||||
|
if (($table_info = $db->dbShowTableMetaData($table)) === false) {
|
||||||
|
print "Read problem for: $table<br>";
|
||||||
|
} else {
|
||||||
|
print "TABLE INFO: <pre>" . print_r($table_info, true) . "</pre><br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "<hr>";
|
||||||
|
|
||||||
|
echo "Insert into 'test'<br>";
|
||||||
|
|
||||||
|
$query = <<<SQL
|
||||||
|
INSERT INTO test (
|
||||||
|
c_text, c_integer, c_bool,
|
||||||
|
c_datetime, c_datetime_microseconds, c_date,
|
||||||
|
c_julian, c_unixtime, c_unixtime_alt,
|
||||||
|
c_numeric, c_real, c_blob
|
||||||
|
) VALUES (
|
||||||
|
?, ?, ?,
|
||||||
|
?, ?, ?,
|
||||||
|
julianday(?), ?, unixepoch(?),
|
||||||
|
?, ?, ?
|
||||||
|
)
|
||||||
|
SQL;
|
||||||
|
$db->dbExecParams($query, [
|
||||||
|
'test', rand(1, 100), true,
|
||||||
|
date('Y-m-d H:i:s'), date_format(date_create("now"), 'Y-m-d H:i:s.u'), date('Y-m-d'),
|
||||||
|
// julianday pass through
|
||||||
|
date('Y-m-d H:i:s'),
|
||||||
|
// use "U" if no unixepoch in query
|
||||||
|
date('U'), date('Y-m-d H:i:s'),
|
||||||
|
1.5, 10.5, 'Anything'
|
||||||
|
]);
|
||||||
|
|
||||||
|
print "<hr>";
|
||||||
|
|
||||||
|
echo "Insert into 'test_no_pk'<br>";
|
||||||
|
|
||||||
|
$query = <<<SQL
|
||||||
|
INSERT INTO test_no_pk (
|
||||||
|
c_text, c_integer
|
||||||
|
) VALUES (
|
||||||
|
?, ?
|
||||||
|
)
|
||||||
|
SQL;
|
||||||
|
$db->dbExecParams($query, ['test no pk', rand(100, 200)]);
|
||||||
|
|
||||||
|
print "<hr>";
|
||||||
|
|
||||||
|
$query = <<<SQL
|
||||||
|
SELECT test_id, c_text, c_integer, c_integer_default, c_datetime_default
|
||||||
|
FROM test
|
||||||
|
SQL;
|
||||||
|
while (is_array($row = $db->dbReturnArray($query))) {
|
||||||
|
print "ROW: PK(test_id): " . $row["test_id"]
|
||||||
|
. ", Text: " . $row["c_text"] . ", Int: " . $row["c_integer"]
|
||||||
|
. ", Int Default: " . $row["c_integer_default"]
|
||||||
|
. ", Date Default: " . $row["c_datetime_default"]
|
||||||
|
. "<br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "<hr>";
|
||||||
|
|
||||||
|
$query = <<<SQL
|
||||||
|
SELECT rowid, c_text, c_integer
|
||||||
|
FROM test_no_pk
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
while (is_array($row = $db->dbReturnArray($query))) {
|
||||||
|
print "ROW[CURSOR]: PK(rowid): " . $row["rowid"]
|
||||||
|
. ", Text: " . $row["c_text"] . ", Int: " . $row["c_integer"]
|
||||||
|
. "<br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "</body></html>";
|
||||||
|
|
||||||
|
// __END__
|
||||||
@@ -83,6 +83,9 @@ function mtParseCSV(
|
|||||||
'UTF-8',
|
'UTF-8',
|
||||||
$encoding
|
$encoding
|
||||||
);
|
);
|
||||||
|
if ($string === false) {
|
||||||
|
return $lines;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($flag == 'INTERN') {
|
if ($flag == 'INTERN') {
|
||||||
// split with PHP function
|
// split with PHP function
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ $log->error('Cannot process data', ['error' => 'log']);
|
|||||||
$log->critical('Critical message', ['critical' => 'log']);
|
$log->critical('Critical message', ['critical' => 'log']);
|
||||||
$log->alert('Alert message', ['Alert' => 'log']);
|
$log->alert('Alert message', ['Alert' => 'log']);
|
||||||
$log->emergency('Emergency message', ['Emergency' => 'log']);
|
$log->emergency('Emergency message', ['Emergency' => 'log']);
|
||||||
|
error_log('TRIGGER ERROR LOG MANUAL: Emergency');
|
||||||
print "Log File: " . $log->getLogFile() . "<br>";
|
print "Log File: " . $log->getLogFile() . "<br>";
|
||||||
|
|
||||||
$log->setLogFlag(Flag::per_run);
|
$log->setLogFlag(Flag::per_run);
|
||||||
|
|||||||
@@ -383,7 +383,8 @@ class Basic
|
|||||||
public function initRandomKeyLength(int $key_length): bool
|
public function initRandomKeyLength(int $key_length): bool
|
||||||
{
|
{
|
||||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Create\RandomKey::setRandomKeyLength()', E_USER_DEPRECATED);
|
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Create\RandomKey::setRandomKeyLength()', E_USER_DEPRECATED);
|
||||||
return \CoreLibs\Create\RandomKey::setRandomKeyLength($key_length);
|
// no op, we do no longer pre set the random key length
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -988,10 +989,10 @@ class Basic
|
|||||||
* @param bool $auto_check default true, if source encoding is set
|
* @param bool $auto_check default true, if source encoding is set
|
||||||
* check that the source is actually matching
|
* check that the source is actually matching
|
||||||
* to what we sav the source is
|
* to what we sav the source is
|
||||||
* @return string encoding converted string
|
* @return string|false encoding converted string
|
||||||
* @deprecated use \CoreLibs\Convert\Encoding::convertEncoding() instead
|
* @deprecated use \CoreLibs\Convert\Encoding::convertEncoding() instead
|
||||||
*/
|
*/
|
||||||
public static function convertEncoding(string $string, string $to_encoding, string $source_encoding = '', bool $auto_check = true): string
|
public static function convertEncoding(string $string, string $to_encoding, string $source_encoding = '', bool $auto_check = true): string|false
|
||||||
{
|
{
|
||||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Convert\Encoding::convertEncoding()', E_USER_DEPRECATED);
|
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Convert\Encoding::convertEncoding()', E_USER_DEPRECATED);
|
||||||
return \CoreLibs\Convert\Encoding::convertEncoding($string, $to_encoding, $source_encoding, $auto_check);
|
return \CoreLibs\Convert\Encoding::convertEncoding($string, $to_encoding, $source_encoding, $auto_check);
|
||||||
|
|||||||
@@ -56,7 +56,11 @@ class Encoding
|
|||||||
{
|
{
|
||||||
// return mb_substitute_character();
|
// return mb_substitute_character();
|
||||||
if ($return_substitute_func === true) {
|
if ($return_substitute_func === true) {
|
||||||
return mb_substitute_character();
|
// if false abort with error
|
||||||
|
if (($return = mb_substitute_character()) === false) {
|
||||||
|
return self::$mb_error_char;
|
||||||
|
}
|
||||||
|
return $return;
|
||||||
} else {
|
} else {
|
||||||
return self::$mb_error_char;
|
return self::$mb_error_char;
|
||||||
}
|
}
|
||||||
@@ -88,7 +92,13 @@ class Encoding
|
|||||||
): array|false {
|
): array|false {
|
||||||
// convert to target encoding and convert back
|
// convert to target encoding and convert back
|
||||||
$temp = mb_convert_encoding($string, $to_encoding, $from_encoding);
|
$temp = mb_convert_encoding($string, $to_encoding, $from_encoding);
|
||||||
|
if ($temp === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$compare = mb_convert_encoding($temp, $from_encoding, $to_encoding);
|
$compare = mb_convert_encoding($temp, $from_encoding, $to_encoding);
|
||||||
|
if ($compare === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// if string does not match anymore we have a convert problem
|
// if string does not match anymore we have a convert problem
|
||||||
if ($string == $compare) {
|
if ($string == $compare) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ class Encoding
|
|||||||
* @param bool $auto_check default true, if source encoding is set
|
* @param bool $auto_check default true, if source encoding is set
|
||||||
* check that the source is actually matching
|
* check that the source is actually matching
|
||||||
* to what we sav the source is
|
* to what we sav the source is
|
||||||
* @return string encoding converted string
|
* @return string|false encoding converted string or false on error
|
||||||
*/
|
*/
|
||||||
public static function convertEncoding(
|
public static function convertEncoding(
|
||||||
string $string,
|
string $string,
|
||||||
string $to_encoding,
|
string $to_encoding,
|
||||||
string $source_encoding = '',
|
string $source_encoding = '',
|
||||||
bool $auto_check = true
|
bool $auto_check = true
|
||||||
): string {
|
): string|false {
|
||||||
// set if not given
|
// set if not given
|
||||||
if (!$source_encoding) {
|
if (!$source_encoding) {
|
||||||
$source_encoding = mb_detect_encoding($string);
|
$source_encoding = mb_detect_encoding($string);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class Email
|
|||||||
* @param string $encoding Encoding, if not set UTF-8
|
* @param string $encoding Encoding, if not set UTF-8
|
||||||
* @param bool $kv_folding If set to true and a valid encoding, do KV folding
|
* @param bool $kv_folding If set to true and a valid encoding, do KV folding
|
||||||
* @return string Correctly encoded and build email string
|
* @return string Correctly encoded and build email string
|
||||||
|
* @throws \IntlException if email name cannot be converted to UTF-8
|
||||||
*/
|
*/
|
||||||
public static function encodeEmailName(
|
public static function encodeEmailName(
|
||||||
string $email,
|
string $email,
|
||||||
@@ -52,6 +53,10 @@ class Email
|
|||||||
if ($encoding != 'UTF-8') {
|
if ($encoding != 'UTF-8') {
|
||||||
$email_name = mb_convert_encoding($email_name, $encoding, 'UTF-8');
|
$email_name = mb_convert_encoding($email_name, $encoding, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
// if we cannot transcode the name, return just the email
|
||||||
|
if ($email_name === false) {
|
||||||
|
throw new \IntlException('Cannot convert email_name to UTF-8');
|
||||||
|
}
|
||||||
$email_name =
|
$email_name =
|
||||||
mb_encode_mimeheader(
|
mb_encode_mimeheader(
|
||||||
in_array($encoding, self::$encoding_kv_allowed) && $kv_folding ?
|
in_array($encoding, self::$encoding_kv_allowed) && $kv_folding ?
|
||||||
@@ -77,6 +82,8 @@ class Email
|
|||||||
* @param bool $kv_folding If set to true and a valid encoding,
|
* @param bool $kv_folding If set to true and a valid encoding,
|
||||||
* do KV folding
|
* do KV folding
|
||||||
* @return array<string> Pos 0: Subject, Pos 1: Body
|
* @return array<string> Pos 0: Subject, Pos 1: Body
|
||||||
|
* @throws \IntlException if subject cannot be converted to UTF-8
|
||||||
|
* @throws \IntlException if body cannot be converted to UTF-8
|
||||||
*/
|
*/
|
||||||
private static function replaceContent(
|
private static function replaceContent(
|
||||||
string $subject,
|
string $subject,
|
||||||
@@ -102,6 +109,12 @@ class Email
|
|||||||
$subject = mb_convert_encoding($subject, $encoding, 'UTF-8');
|
$subject = mb_convert_encoding($subject, $encoding, 'UTF-8');
|
||||||
$body = mb_convert_encoding($body, $encoding, 'UTF-8');
|
$body = mb_convert_encoding($body, $encoding, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
if ($subject === false) {
|
||||||
|
throw new \IntlException('Cannot convert subject to UTF-8');
|
||||||
|
}
|
||||||
|
if ($body === false) {
|
||||||
|
throw new \IntlException('Cannot convert body to UTF-8');
|
||||||
|
}
|
||||||
// we need to encodde the subject
|
// we need to encodde the subject
|
||||||
$subject = mb_encode_mimeheader(
|
$subject = mb_encode_mimeheader(
|
||||||
in_array($encoding, self::$encoding_kv_allowed) && $kv_folding ?
|
in_array($encoding, self::$encoding_kv_allowed) && $kv_folding ?
|
||||||
|
|||||||
90
www/lib/CoreLibs/DB/Interface/DatabaseInterface.php
Normal file
90
www/lib/CoreLibs/DB/Interface/DatabaseInterface.php
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AUTHOR: Clemens Schwaighofer
|
||||||
|
* CREATED: Ymd
|
||||||
|
* DESCRIPTION:
|
||||||
|
* DescriptionHere
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace CoreLibs\DB\Interface;
|
||||||
|
|
||||||
|
interface DatabaseInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Table meta data
|
||||||
|
* Note that if columns have multi
|
||||||
|
*
|
||||||
|
* @param string $table
|
||||||
|
* @return array<array<string,mixed>>|false
|
||||||
|
*/
|
||||||
|
public function dbShowTableMetaData(string $table): array|false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for reading or simple execution, no return data
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
|
public function dbExec(string $query): int|false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a simple query and return its statement
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @return \PDOStatement|false
|
||||||
|
*/
|
||||||
|
public function dbQuery(string $query): \PDOStatement|false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute one query with params
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @param array<mixed> $params
|
||||||
|
* @return \PDOStatement|false
|
||||||
|
*/
|
||||||
|
public function dbExecParams(string $query, array $params): \PDOStatement|false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare query
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @return \PDOStatement|false
|
||||||
|
*/
|
||||||
|
public function dbPrepare(string $query): \PDOStatement|false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* execute a cursor
|
||||||
|
*
|
||||||
|
* @param \PDOStatement $cursor
|
||||||
|
* @param array<mixed> $params
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function dbCursorExecute(\PDOStatement $cursor, array $params): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return array with data, when finshed return false
|
||||||
|
* also returns false on error
|
||||||
|
*
|
||||||
|
* TODO: This is currently a one time run
|
||||||
|
* if the same query needs to be run again, the cursor_ext must be reest
|
||||||
|
* with dbCacheReset
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @param array<mixed> $params
|
||||||
|
* @return array<mixed>|false
|
||||||
|
*/
|
||||||
|
public function dbReturnArray(string $query, array $params = []): array|false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get current db handler
|
||||||
|
* this is for raw access
|
||||||
|
*
|
||||||
|
* @return \PDO
|
||||||
|
*/
|
||||||
|
public function getDbh(): \PDO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// __END__
|
||||||
432
www/lib/CoreLibs/DB/SqLite.php
Normal file
432
www/lib/CoreLibs/DB/SqLite.php
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AUTHOR: Clemens Schwaighofer
|
||||||
|
* CREATED: 2024/8/21
|
||||||
|
* DESCRIPTION:
|
||||||
|
* SQL Lite interface
|
||||||
|
* Note: This is a very simple library and in future should perhaps merge with the master
|
||||||
|
* CoreLibs SQL interface
|
||||||
|
*
|
||||||
|
* TODO: This should move to the CoreLibs\DB\IO class as a sub type for "sqlite" next to "pgsql"
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace CoreLibs\DB;
|
||||||
|
|
||||||
|
use CoreLibs\Create\Hash;
|
||||||
|
|
||||||
|
class SqLite implements Interface\DatabaseInterface
|
||||||
|
{
|
||||||
|
/** @var \CoreLibs\Logging\Logging logging */
|
||||||
|
public \CoreLibs\Logging\Logging $log;
|
||||||
|
|
||||||
|
/** @var string database connection string */
|
||||||
|
private string $dsn;
|
||||||
|
/** @var \PDO database handler */
|
||||||
|
private \PDO $dbh;
|
||||||
|
/** @var PDOStatement|false one cursor, for internal handling */
|
||||||
|
// private \PDOStatement|false $cursor;
|
||||||
|
/** @var array<string,mixed> extended cursoers string index with content */
|
||||||
|
private array $cursor_ext = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init database system
|
||||||
|
*
|
||||||
|
* @param \CoreLibs\Logging\Logging $log
|
||||||
|
* @param string $dsn
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
\CoreLibs\Logging\Logging $log,
|
||||||
|
string $dsn
|
||||||
|
) {
|
||||||
|
$this->log = $log;
|
||||||
|
// open new connection
|
||||||
|
if ($this->__connectToDB($dsn) === false) {
|
||||||
|
throw new \ErrorException("Cannot load database: " . $dsn, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
// MARK: PRIVATE METHODS
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a cursor dump with all info
|
||||||
|
*
|
||||||
|
* @param \PDOStatement $cursor
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
private function __dbGetCursorDump(\PDOStatement $cursor): string|false
|
||||||
|
{
|
||||||
|
// get the cursor info
|
||||||
|
ob_start();
|
||||||
|
$cursor->debugDumpParams();
|
||||||
|
$cursor_dump = ob_get_contents();
|
||||||
|
ob_end_clean();
|
||||||
|
return $cursor_dump;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fetch rows from a cursor (post execute)
|
||||||
|
*
|
||||||
|
* @param \PDOStatement $cursor
|
||||||
|
* @return array<mixed>|false
|
||||||
|
*/
|
||||||
|
private function __dbFetchArray(\PDOStatement $cursor): array|false
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// on empty array return false
|
||||||
|
// TODO make that more elegant?
|
||||||
|
return empty($row = $cursor->fetch(mode:\PDO::FETCH_NAMED)) ? false : $row;
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
$this->log->error(
|
||||||
|
"Cannot fetch from cursor",
|
||||||
|
[
|
||||||
|
"dsn" => $this->dsn,
|
||||||
|
"DumpParams" => $this->__dbGetCursorDump($cursor),
|
||||||
|
"PDOException" => $e
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: open database
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open database
|
||||||
|
* reports errors for wrong DSN or failed connection
|
||||||
|
*
|
||||||
|
* @param string $dsn
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function __connectToDB(string $dsn): bool
|
||||||
|
{
|
||||||
|
// check if dsn starts with ":"
|
||||||
|
if (!str_starts_with($dsn, "sqlite:")) {
|
||||||
|
$this->log->error(
|
||||||
|
"Invalid dsn string",
|
||||||
|
[
|
||||||
|
"dsn" => $dsn
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TODO: if not ":memory:" check if path to file is writeable by system
|
||||||
|
// avoid double open
|
||||||
|
if (!empty($this->dsn) && $dsn == $this->dsn && $this->dbh instanceof \PDO) {
|
||||||
|
$this->log->info(
|
||||||
|
"Connection already establisehd with this dsn",
|
||||||
|
[
|
||||||
|
"dsn" => $dsn,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// TODO: check that folder is writeable
|
||||||
|
// set DSN and open connection
|
||||||
|
$this->dsn = $dsn;
|
||||||
|
try {
|
||||||
|
$this->dbh = new \PDO($this->dsn);
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
$this->log->error(
|
||||||
|
"Cannot open database",
|
||||||
|
[
|
||||||
|
"dsn" => $this->dsn,
|
||||||
|
"PDOException" => $e
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
// MARK: PUBLIC METHODS
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
// MARK: db meta data (table info)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table meta data
|
||||||
|
* Note that if columns have multi
|
||||||
|
*
|
||||||
|
* @param string $table
|
||||||
|
* @return array<array<string,mixed>>|false
|
||||||
|
*/
|
||||||
|
public function dbShowTableMetaData(string $table): array|false
|
||||||
|
{
|
||||||
|
$table_info = [];
|
||||||
|
$query = <<<SQL
|
||||||
|
SELECT
|
||||||
|
ti.cid, ti.name, ti.type, ti.'notnull', ti.dflt_value, ti.pk,
|
||||||
|
il_ii.idx_name, il_ii.idx_unique, il_ii.idx_origin, il_ii.idx_partial
|
||||||
|
FROM
|
||||||
|
sqlite_schema AS m,
|
||||||
|
pragma_table_info(m.name) AS ti
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT
|
||||||
|
il.name AS idx_name, il.'unique' AS idx_unique, il.origin AS idx_origin, il.partial AS idx_partial,
|
||||||
|
ii.cid AS tbl_cid
|
||||||
|
FROM
|
||||||
|
sqlite_schema AS m,
|
||||||
|
pragma_index_list(m.name) AS il,
|
||||||
|
pragma_index_info(il.name) AS ii
|
||||||
|
WHERE m.name = ?1
|
||||||
|
) AS il_ii ON (ti.cid = il_ii.tbl_cid)
|
||||||
|
WHERE
|
||||||
|
m.name = ?1
|
||||||
|
SQL;
|
||||||
|
while (is_array($row = $this->dbReturnArray($query, [$table]))) {
|
||||||
|
$table_info[] = [
|
||||||
|
'cid' => $row['cid'],
|
||||||
|
'name' => $row['name'],
|
||||||
|
'type' => $row['type'],
|
||||||
|
'notnull' => $row['notnull'],
|
||||||
|
'dflt_value' => $row['dflt_value'],
|
||||||
|
'pk' => $row['pk'],
|
||||||
|
'idx_name' => $row['idx_name'],
|
||||||
|
'idx_unique' => $row['idx_unique'],
|
||||||
|
'idx_origin' => $row['idx_origin'],
|
||||||
|
'idx_partial' => $row['idx_partial'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table_info) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $table_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: db exec
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for reading or simple execution, no return data
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
|
public function dbExec(string $query): int|false
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $this->dbh->exec($query);
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
$this->log->error(
|
||||||
|
"Cannot execute query",
|
||||||
|
[
|
||||||
|
"dsn" => $this->dsn,
|
||||||
|
"query" => $query,
|
||||||
|
"PDOException" => $e
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: db query
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a simple query and return its statement
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @return \PDOStatement|false
|
||||||
|
*/
|
||||||
|
public function dbQuery(string $query): \PDOStatement|false
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $this->dbh->query($query, \PDO::FETCH_NAMED);
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
$this->log->error(
|
||||||
|
"Cannot run query",
|
||||||
|
[
|
||||||
|
"dsn" => $this->dsn,
|
||||||
|
"query" => $query,
|
||||||
|
"PDOException" => $e
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: db prepare & execute calls
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute one query with params
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @param array<mixed> $params
|
||||||
|
* @return \PDOStatement|false
|
||||||
|
*/
|
||||||
|
public function dbExecParams(string $query, array $params): \PDOStatement|false
|
||||||
|
{
|
||||||
|
// prepare query
|
||||||
|
if (($cursor = $this->dbPrepare($query)) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// execute the query, on failure return false
|
||||||
|
if ($this->dbCursorExecute($cursor, $params) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare query
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @return \PDOStatement|false
|
||||||
|
*/
|
||||||
|
public function dbPrepare(string $query): \PDOStatement|false
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// store query with cursor so we can reference?
|
||||||
|
return $this->dbh->prepare($query);
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
$this->log->error(
|
||||||
|
"Cannot open cursor",
|
||||||
|
[
|
||||||
|
"dsn" => $this->dsn,
|
||||||
|
"query" => $query,
|
||||||
|
"PDOException" => $e
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* execute a cursor
|
||||||
|
*
|
||||||
|
* @param \PDOStatement $cursor
|
||||||
|
* @param array<mixed> $params
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function dbCursorExecute(\PDOStatement $cursor, array $params): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $cursor->execute($params);
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
// write error log
|
||||||
|
$this->log->error(
|
||||||
|
"Cannot execute prepared query",
|
||||||
|
[
|
||||||
|
"dsn" => $this->dsn,
|
||||||
|
"params" => $params,
|
||||||
|
"DumpParams" => $this->__dbGetCursorDump($cursor),
|
||||||
|
"PDOException" => $e
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: db return array
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns hash for query
|
||||||
|
* Hash is used in all internal storage systems for return data
|
||||||
|
*
|
||||||
|
* @param string $query The query to create the hash from
|
||||||
|
* @param array<mixed> $params If the query is params type we need params
|
||||||
|
* data to create a unique call one, optional
|
||||||
|
* @return string Hash, as set by hash long
|
||||||
|
*/
|
||||||
|
public function dbGetQueryHash(string $query, array $params = []): string
|
||||||
|
{
|
||||||
|
return Hash::__hashLong(
|
||||||
|
$query . (
|
||||||
|
$params !== [] ?
|
||||||
|
'#' . json_encode($params) : ''
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resets all data stored to this query
|
||||||
|
* @param string $query The Query whose cache should be cleaned
|
||||||
|
* @param array<mixed> $params If the query is params type we need params
|
||||||
|
* data to create a unique call one, optional
|
||||||
|
* @return bool False if query not found, true if success
|
||||||
|
*/
|
||||||
|
public function dbCacheReset(string $query, array $params = []): bool
|
||||||
|
{
|
||||||
|
$query_hash = $this->dbGetQueryHash($query, $params);
|
||||||
|
// clears cache for this query
|
||||||
|
if (empty($this->cursor_ext[$query_hash]['query'])) {
|
||||||
|
$this->log->error('Cannot reset cursor_ext with given query and params', [
|
||||||
|
"query" => $query,
|
||||||
|
"params" => $params,
|
||||||
|
]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unset($this->cursor_ext[$query_hash]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return array with data, when finshed return false
|
||||||
|
* also returns false on error
|
||||||
|
*
|
||||||
|
* TODO: This is currently a one time run
|
||||||
|
* if the same query needs to be run again, the cursor_ext must be reest
|
||||||
|
* with dbCacheReset
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @param array<mixed> $params
|
||||||
|
* @return array<mixed>|false
|
||||||
|
*/
|
||||||
|
public function dbReturnArray(string $query, array $params = []): array|false
|
||||||
|
{
|
||||||
|
$query_hash = $this->dbGetQueryHash($query, $params);
|
||||||
|
if (!isset($this->cursor_ext[$query_hash])) {
|
||||||
|
$this->cursor_ext[$query_hash] = [
|
||||||
|
// cursor null: unset, if set \PDOStatement
|
||||||
|
'cursor' => null,
|
||||||
|
// the query used in this call
|
||||||
|
'query' => $query,
|
||||||
|
// parameter
|
||||||
|
'params' => $params,
|
||||||
|
// how many rows have been read from db
|
||||||
|
'read_rows' => 0,
|
||||||
|
// when fetch array or cache read returns false
|
||||||
|
// in loop read that means dbReturn retuns false without error
|
||||||
|
'finished' => false,
|
||||||
|
];
|
||||||
|
if (!empty($params)) {
|
||||||
|
if (($cursor = $this->dbExecParams($query, $params)) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (($cursor = $this->dbQuery($query)) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->cursor_ext[$query_hash]['cursor'] = $cursor;
|
||||||
|
}
|
||||||
|
// flag finished if row is false
|
||||||
|
$row = $this->__dbFetchArray($this->cursor_ext[$query_hash]['cursor']);
|
||||||
|
if ($row === false) {
|
||||||
|
$this->cursor_ext[$query_hash]['finished'] = true;
|
||||||
|
} else {
|
||||||
|
$this->cursor_ext[$query_hash]['read_rows']++;
|
||||||
|
}
|
||||||
|
return $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK other interface
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get current db handler
|
||||||
|
* this is for raw access
|
||||||
|
*
|
||||||
|
* @return \PDO
|
||||||
|
*/
|
||||||
|
public function getDbh(): \PDO
|
||||||
|
{
|
||||||
|
return $this->dbh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// __END__
|
||||||
@@ -35,6 +35,7 @@ class Logging
|
|||||||
/** @var string log file block separator, not changeable */
|
/** @var string log file block separator, not changeable */
|
||||||
private const LOG_FILE_BLOCK_SEPARATOR = '.';
|
private const LOG_FILE_BLOCK_SEPARATOR = '.';
|
||||||
|
|
||||||
|
// MARK: OPTION array
|
||||||
// NOTE: the second party array{} hs some errors
|
// NOTE: the second party array{} hs some errors
|
||||||
/** @var array<string,array<string,string|bool|Level>>|array{string:array{type:string,type_info?:string,mandatory:true,alias?:string,default:string|bool|Level,deprecated:bool,use?:string}} */
|
/** @var array<string,array<string,string|bool|Level>>|array{string:array{type:string,type_info?:string,mandatory:true,alias?:string,default:string|bool|Level,deprecated:bool,use?:string}} */
|
||||||
private const OPTIONS = [
|
private const OPTIONS = [
|
||||||
@@ -50,6 +51,7 @@ class Logging
|
|||||||
'type' => 'string', 'mandatory' => false,
|
'type' => 'string', 'mandatory' => false,
|
||||||
'default' => '', 'deprecated' => true, 'use' => 'log_file_id'
|
'default' => '', 'deprecated' => true, 'use' => 'log_file_id'
|
||||||
],
|
],
|
||||||
|
// log level
|
||||||
'log_level' => [
|
'log_level' => [
|
||||||
'type' => 'instance',
|
'type' => 'instance',
|
||||||
'type_info' => '\CoreLibs\Logging\Logger\Level',
|
'type_info' => '\CoreLibs\Logging\Logger\Level',
|
||||||
@@ -57,6 +59,14 @@ class Logging
|
|||||||
'default' => Level::Debug,
|
'default' => Level::Debug,
|
||||||
'deprecated' => false
|
'deprecated' => false
|
||||||
],
|
],
|
||||||
|
// level to trigger write to error_log
|
||||||
|
'error_log_write_level' => [
|
||||||
|
'type' => 'instance',
|
||||||
|
'type_info' => '\CoreLibs\Logging\Logger\Level',
|
||||||
|
'mandatory' => false,
|
||||||
|
'default' => Level::Emergency,
|
||||||
|
'deprecated' => false,
|
||||||
|
],
|
||||||
// options
|
// options
|
||||||
'log_per_run' => [
|
'log_per_run' => [
|
||||||
'type' => 'bool', 'mandatory' => false,
|
'type' => 'bool', 'mandatory' => false,
|
||||||
@@ -92,8 +102,10 @@ class Logging
|
|||||||
/** @var array<mixed> */
|
/** @var array<mixed> */
|
||||||
private array $options = [];
|
private array $options = [];
|
||||||
|
|
||||||
/** @var Level set level */
|
/** @var Level set logging level */
|
||||||
private Level $log_level;
|
private Level $log_level;
|
||||||
|
/** @var Level set level for writing to error_log, will not write if log level lower than error log write level */
|
||||||
|
private Level $error_log_write_level;
|
||||||
|
|
||||||
// page and host name
|
// page and host name
|
||||||
/** @var string */
|
/** @var string */
|
||||||
@@ -145,12 +157,13 @@ class Logging
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init logger
|
* MARK: Init logger
|
||||||
*
|
*
|
||||||
* options array layout
|
* options array layout
|
||||||
* - log_folder:
|
* - log_folder:
|
||||||
* - log_file_id / file_id (will be deprecated):
|
* - log_file_id / file_id (will be deprecated):
|
||||||
* - log_level:
|
* - log_level:
|
||||||
|
* - error_log_write_level: at what level we write to error_log
|
||||||
*
|
*
|
||||||
* - log_per_run:
|
* - log_per_run:
|
||||||
* - log_per_date: (was print_file_date)
|
* - log_per_date: (was print_file_date)
|
||||||
@@ -172,6 +185,8 @@ class Logging
|
|||||||
|
|
||||||
// set log level
|
// set log level
|
||||||
$this->initLogLevel();
|
$this->initLogLevel();
|
||||||
|
// set error log write level
|
||||||
|
$this->initErrorLogWriteLevel();
|
||||||
// set log folder from options
|
// set log folder from options
|
||||||
$this->initLogFolder();
|
$this->initLogFolder();
|
||||||
// set per run UID for logging
|
// set per run UID for logging
|
||||||
@@ -190,8 +205,10 @@ class Logging
|
|||||||
// PRIVATE METHODS
|
// PRIVATE METHODS
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
|
|
||||||
|
// MARK: options check
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undocumented function
|
* validate options
|
||||||
*
|
*
|
||||||
* @param array<mixed> $options
|
* @param array<mixed> $options
|
||||||
* @return bool
|
* @return bool
|
||||||
@@ -263,6 +280,8 @@ class Logging
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: init log elvels
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init log level, just a wrapper to auto set from options
|
* init log level, just a wrapper to auto set from options
|
||||||
*
|
*
|
||||||
@@ -280,6 +299,24 @@ class Logging
|
|||||||
$this->setLoggingLevel($this->options['log_level']);
|
$this->setLoggingLevel($this->options['log_level']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init error log write level
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function initErrorLogWriteLevel()
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
empty($this->options['error_log_write_level']) ||
|
||||||
|
!$this->options['error_log_write_level'] instanceof Level
|
||||||
|
) {
|
||||||
|
$this->options['error_log_write_level'] = Level::Emergency;
|
||||||
|
}
|
||||||
|
$this->setErrorLogWriteLevel($this->options['error_log_write_level']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: set log folder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the log folder
|
* Set the log folder
|
||||||
* If folder is not writeable the script will throw an E_USER_ERROR
|
* If folder is not writeable the script will throw an E_USER_ERROR
|
||||||
@@ -321,6 +358,8 @@ class Logging
|
|||||||
return $status;
|
return $status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: set host name
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the hostname and port
|
* Set the hostname and port
|
||||||
* If port is not defaul 80 it will be added to the host name
|
* If port is not defaul 80 it will be added to the host name
|
||||||
@@ -337,6 +376,8 @@ class Logging
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: set log file id (file)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set log file prefix id
|
* set log file prefix id
|
||||||
*
|
*
|
||||||
@@ -395,6 +436,8 @@ class Logging
|
|||||||
return $status;
|
return $status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK init log flags and levels
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set flags from options and option flags connection internal settings
|
* set flags from options and option flags connection internal settings
|
||||||
*
|
*
|
||||||
@@ -423,6 +466,19 @@ class Logging
|
|||||||
return $this->log_level->includes($level);
|
return $this->log_level->includes($level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that given level is matchins error_log write level
|
||||||
|
*
|
||||||
|
* @param Level $level
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkErrorLogWriteLevel(Level $level): bool
|
||||||
|
{
|
||||||
|
return $this->error_log_write_level->includes($level);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: build log ifle name
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the file name for writing
|
* Build the file name for writing
|
||||||
*
|
*
|
||||||
@@ -490,6 +546,8 @@ class Logging
|
|||||||
return $fn;
|
return $fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: master write log to file
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* writes error msg data to file for current level
|
* writes error msg data to file for current level
|
||||||
*
|
*
|
||||||
@@ -507,6 +565,10 @@ class Logging
|
|||||||
if (!$this->checkLogLevel($level)) {
|
if (!$this->checkLogLevel($level)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// if we match level then write to error_log
|
||||||
|
if ($this->checkErrorLogWriteLevel($level)) {
|
||||||
|
error_log((string)$message);
|
||||||
|
}
|
||||||
|
|
||||||
// build logging file name
|
// build logging file name
|
||||||
// fn is log folder + file name
|
// fn is log folder + file name
|
||||||
@@ -531,6 +593,8 @@ class Logging
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: master prepare log
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the log message with all needed info blocks:
|
* Prepare the log message with all needed info blocks:
|
||||||
* [timestamp] [host name] [file path + file::row number] [running uid] {class::/->method}
|
* [timestamp] [host name] [file path + file::row number] [running uid] {class::/->method}
|
||||||
@@ -610,6 +674,7 @@ class Logging
|
|||||||
// PUBLIC STATIC METHJODS
|
// PUBLIC STATIC METHJODS
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
|
|
||||||
|
// MARK: set log level
|
||||||
/**
|
/**
|
||||||
* set the log level
|
* set the log level
|
||||||
*
|
*
|
||||||
@@ -670,7 +735,7 @@ class Logging
|
|||||||
|
|
||||||
// **** GET/SETTER
|
// **** GET/SETTER
|
||||||
|
|
||||||
// log level set and get
|
// MARK: log level
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set new log level
|
* set new log level
|
||||||
@@ -705,7 +770,30 @@ class Logging
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// log file id set (file name prefix)
|
// MARK: error log write level
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the error_log write level
|
||||||
|
*
|
||||||
|
* @param string|int|Level $level
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setErrorLogWriteLevel(string|int|Level $level): void
|
||||||
|
{
|
||||||
|
$this->error_log_write_level = $this->processLogLevel($level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the current level for error_log write
|
||||||
|
*
|
||||||
|
* @return Level
|
||||||
|
*/
|
||||||
|
public function getErrorLogWriteLevel(): Level
|
||||||
|
{
|
||||||
|
return $this->error_log_write_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: log file id set (file name prefix)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the internal log file prefix id
|
* sets the internal log file prefix id
|
||||||
@@ -733,7 +821,7 @@ class Logging
|
|||||||
return $this->log_file_id;
|
return $this->log_file_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// log unique id set (for per run)
|
// MARK: log unique id set (for per run)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a unique id based on current date (y/m/d, h:i:s) and a unique id (8 chars)
|
* Sets a unique id based on current date (y/m/d, h:i:s) and a unique id (8 chars)
|
||||||
@@ -768,7 +856,7 @@ class Logging
|
|||||||
return $this->log_file_unique_id;
|
return $this->log_file_unique_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// general log date
|
// MARK: general log date
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the log file date to Y-m-d
|
* set the log file date to Y-m-d
|
||||||
@@ -791,7 +879,7 @@ class Logging
|
|||||||
return $this->log_file_date;
|
return $this->log_file_date;
|
||||||
}
|
}
|
||||||
|
|
||||||
// general flag set
|
// MARK: general flag set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set one of the basic flags
|
* set one of the basic flags
|
||||||
@@ -846,7 +934,7 @@ class Logging
|
|||||||
return $this->log_flags;
|
return $this->log_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// log folder/file
|
// MARK: log folder/file
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set new log folder, check that folder is writeable
|
* set new log folder, check that folder is writeable
|
||||||
@@ -890,7 +978,7 @@ class Logging
|
|||||||
return $this->log_file_name;
|
return $this->log_file_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
// max log file size
|
// MARK: max log file size
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set mag log file size
|
* set mag log file size
|
||||||
@@ -921,7 +1009,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
// OPTIONS CALLS
|
// MARK: OPTIONS CALLS
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -939,6 +1027,8 @@ class Logging
|
|||||||
// MAIN CALLS
|
// MAIN CALLS
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
|
|
||||||
|
// MARK: main log call
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commong log interface
|
* Commong log interface
|
||||||
*
|
*
|
||||||
@@ -976,7 +1066,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DEBUG: 100
|
* MARK: DEBUG: 100
|
||||||
*
|
*
|
||||||
* write debug data to error_msg array
|
* write debug data to error_msg array
|
||||||
*
|
*
|
||||||
@@ -1008,7 +1098,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INFO: 200
|
* MARK: INFO: 200
|
||||||
*
|
*
|
||||||
* @param string|Stringable $message
|
* @param string|Stringable $message
|
||||||
* @param mixed[] $context
|
* @param mixed[] $context
|
||||||
@@ -1027,7 +1117,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTICE: 250
|
* MARK: NOTICE: 250
|
||||||
*
|
*
|
||||||
* @param string|Stringable $message
|
* @param string|Stringable $message
|
||||||
* @param mixed[] $context
|
* @param mixed[] $context
|
||||||
@@ -1046,7 +1136,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WARNING: 300
|
* MARK: WARNING: 300
|
||||||
*
|
*
|
||||||
* @param string|Stringable $message
|
* @param string|Stringable $message
|
||||||
* @param mixed[] $context
|
* @param mixed[] $context
|
||||||
@@ -1065,7 +1155,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ERROR: 400
|
* MARK: ERROR: 400
|
||||||
*
|
*
|
||||||
* @param string|Stringable $message
|
* @param string|Stringable $message
|
||||||
* @param mixed[] $context
|
* @param mixed[] $context
|
||||||
@@ -1084,7 +1174,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CTRITICAL: 500
|
* MARK: CTRITICAL: 500
|
||||||
*
|
*
|
||||||
* @param string|Stringable $message
|
* @param string|Stringable $message
|
||||||
* @param mixed[] $context
|
* @param mixed[] $context
|
||||||
@@ -1103,7 +1193,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ALERT: 550
|
* MARK: ALERT: 550
|
||||||
*
|
*
|
||||||
* @param string|Stringable $message
|
* @param string|Stringable $message
|
||||||
* @param mixed[] $context
|
* @param mixed[] $context
|
||||||
@@ -1122,7 +1212,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EMERGENCY: 600
|
* MARK: EMERGENCY: 600
|
||||||
*
|
*
|
||||||
* @param string|Stringable $message
|
* @param string|Stringable $message
|
||||||
* @param mixed[] $context
|
* @param mixed[] $context
|
||||||
@@ -1141,7 +1231,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
// DEPRECATED SUPPORT CALLS
|
// MARK: DEPRECATED SUPPORT CALLS
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
|
|
||||||
// legacy, but there are too many implemented
|
// legacy, but there are too many implemented
|
||||||
@@ -1199,7 +1289,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
// DEPRECATED METHODS
|
// MARK: DEPRECATED METHODS
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1365,7 +1455,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
// DEBUG METHODS
|
// MARK: DEBUG METHODS
|
||||||
// *********************************************************************
|
// *********************************************************************
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1398,6 +1488,7 @@ class Logging
|
|||||||
}
|
}
|
||||||
// back to options level
|
// back to options level
|
||||||
$this->initLogLevel();
|
$this->initLogLevel();
|
||||||
|
$this->initErrorLogWriteLevel();
|
||||||
print "OPT set level: " . $this->getLoggingLevel()->getName() . "<br>";
|
print "OPT set level: " . $this->getLoggingLevel()->getName() . "<br>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -599,7 +599,7 @@ class Curl implements Interface\RequestsInterface
|
|||||||
// for post we set POST option
|
// for post we set POST option
|
||||||
if ($type == "post") {
|
if ($type == "post") {
|
||||||
curl_setopt($handle, CURLOPT_POST, true);
|
curl_setopt($handle, CURLOPT_POST, true);
|
||||||
} elseif (!empty($type) && in_array($type, self::CUSTOM_REQUESTS)) {
|
} elseif (in_array($type, self::CUSTOM_REQUESTS)) {
|
||||||
curl_setopt($handle, CURLOPT_CUSTOMREQUEST, strtoupper($type));
|
curl_setopt($handle, CURLOPT_CUSTOMREQUEST, strtoupper($type));
|
||||||
}
|
}
|
||||||
// set body data if not null, will send empty [] for empty data
|
// set body data if not null, will send empty [] for empty data
|
||||||
|
|||||||
Reference in New Issue
Block a user