Compare commits
3 Commits
v9.19.0
...
b7935dcb71
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7935dcb71 | ||
|
|
89e8f79cae | ||
|
|
1a027e5c7d |
@@ -156,32 +156,12 @@ final class CoreLibsConvertMathTest extends TestCase
|
|||||||
public function providerMultiplyMatrices(): array
|
public function providerMultiplyMatrices(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'[3] x [3] => [3x1]' => [
|
'single' => [
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
[14]
|
[14]
|
||||||
],
|
],
|
||||||
'[3] x [3x1]' => [
|
'double first' => [
|
||||||
[1, 2, 3],
|
|
||||||
[[1], [2], [3]],
|
|
||||||
[14]
|
|
||||||
],
|
|
||||||
'[3] x [3x1]' => [
|
|
||||||
[1, 2, 3],
|
|
||||||
[[1], [2], [3]],
|
|
||||||
[14]
|
|
||||||
],
|
|
||||||
'[1x3L] x [3x1]' => [
|
|
||||||
[[1, 2, 3]],
|
|
||||||
[[1], [2], [3]],
|
|
||||||
[14]
|
|
||||||
],
|
|
||||||
'[1x3] x [3x1]' => [
|
|
||||||
[[1], [2], [3]],
|
|
||||||
[[1], [2], [3]],
|
|
||||||
[1, 2, 3]
|
|
||||||
],
|
|
||||||
'[2x3] x [3] => [3x1]' => [
|
|
||||||
[
|
[
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
@@ -192,18 +172,7 @@ final class CoreLibsConvertMathTest extends TestCase
|
|||||||
14
|
14
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'[2x3] x [3x1]' => [
|
'double both' => [
|
||||||
[
|
|
||||||
[1, 2, 3],
|
|
||||||
[1, 2, 3]
|
|
||||||
],
|
|
||||||
[[1], [2], [3]],
|
|
||||||
[
|
|
||||||
14,
|
|
||||||
14
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'[2x3] x [2x3] => [3x3]' => [
|
|
||||||
[
|
[
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
@@ -217,37 +186,7 @@ final class CoreLibsConvertMathTest extends TestCase
|
|||||||
[3, 6, 9]
|
[3, 6, 9]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'[2x3] x [3x3]' => [
|
'tripple first, single second' => [
|
||||||
[
|
|
||||||
[1, 2, 3],
|
|
||||||
[1, 2, 3],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[1, 2, 3],
|
|
||||||
[1, 2, 3],
|
|
||||||
[0, 0, 0],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[3, 6, 9],
|
|
||||||
[3, 6, 9]
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'[2x3] x [3x2]' => [
|
|
||||||
'a' => [
|
|
||||||
[1, 2, 3],
|
|
||||||
[1, 2, 3],
|
|
||||||
],
|
|
||||||
'b' => [
|
|
||||||
[1, 1],
|
|
||||||
[2, 2],
|
|
||||||
[3, 3],
|
|
||||||
],
|
|
||||||
'prod' => [
|
|
||||||
[14, 14],
|
|
||||||
[14, 14],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'[3x3] x [3] => [1x3]' => [
|
|
||||||
[
|
[
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
@@ -260,7 +199,7 @@ final class CoreLibsConvertMathTest extends TestCase
|
|||||||
14
|
14
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'[3x3] x [2x3] => [3x3]' => [
|
'tripple first, double second' => [
|
||||||
[
|
[
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
@@ -276,24 +215,7 @@ final class CoreLibsConvertMathTest extends TestCase
|
|||||||
[3, 6, 9],
|
[3, 6, 9],
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'[3x3] x [3x3]' => [
|
'single first, tripple second' => [
|
||||||
[
|
|
||||||
[1, 2, 3],
|
|
||||||
[1, 2, 3],
|
|
||||||
[1, 2, 3],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[1, 2, 3],
|
|
||||||
[1, 2, 3],
|
|
||||||
// [0, 0, 0],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[3, 6, 9],
|
|
||||||
[3, 6, 9],
|
|
||||||
[3, 6, 9],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'[3] x [3x3]' => [
|
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
[
|
[
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
@@ -304,7 +226,7 @@ final class CoreLibsConvertMathTest extends TestCase
|
|||||||
[6, 12, 18],
|
[6, 12, 18],
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'[2x3] x [3x3]' => [
|
'double first, tripple second' => [
|
||||||
[
|
[
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
|
|||||||
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__
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
"phpstan/phpstan": "^1.12",
|
"phpstan/phpstan": "^1.12",
|
||||||
"phan/phan": "^5.4",
|
"phan/phan": "^5.4",
|
||||||
"phpstan/extension-installer": "^1.4",
|
"phpstan/extension-installer": "^1.4",
|
||||||
|
"phpstan/phpstan-strict-rules": "^1.6",
|
||||||
"phpunit/phpunit": "^9",
|
"phpunit/phpunit": "^9",
|
||||||
"phpstan/phpstan-deprecation-rules": "^1.2",
|
"phpstan/phpstan-deprecation-rules": "^1.2",
|
||||||
"yamadashy/phpstan-friendly-formatter": "^1.1"
|
"yamadashy/phpstan-friendly-formatter": "^1.1"
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ function display(string $color, string $text, string $text_add): string
|
|||||||
["{COLOR}", "{TEXT}", "{CSS}"],
|
["{COLOR}", "{TEXT}", "{CSS}"],
|
||||||
[
|
[
|
||||||
$color,
|
$color,
|
||||||
$text . (!empty($text_add) ? '<br>' . $text_add : ''),
|
$text . ($text_add ? '<br>' . $text_add : ''),
|
||||||
$css
|
$css
|
||||||
],
|
],
|
||||||
$template
|
$template
|
||||||
@@ -123,16 +123,22 @@ $hsl_from_hsb = Color::hsbToHsl($hsb);
|
|||||||
print "HSL from HSB: " . DgS::printAr($hsl_from_hsb) . "<br>";
|
print "HSL from HSB: " . DgS::printAr($hsl_from_hsb) . "<br>";
|
||||||
|
|
||||||
print "<hr>";
|
print "<hr>";
|
||||||
|
print "<h2>LEGACY</h2>";
|
||||||
|
|
||||||
// A(out of bounds)
|
// A(out of bounds)
|
||||||
try {
|
try {
|
||||||
print "C::S/COLOR invalid rgb->hex (gray 125): -1, -1, -1: "
|
print "C::S/COLOR invalid rgb->hex (gray 125): -1, -1, -1: "
|
||||||
. (new Coordinates\RGB([-1, -1, -1]))->returnAsHex() . "<br>";
|
. CoreLibs\Convert\Colors::rgb2hex(-1, -1, -1) . "<br>";
|
||||||
} catch (\LengthException $e) {
|
} catch (\LengthException $e) {
|
||||||
print "*Exception: " . $e->getMessage() . "<br><pre>" . print_r($e, true) . "</pre><br>";
|
print "*Exception: " . $e->getMessage() . "<br>" . $e . "<br>";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
print "\$C::S/COLOR invalid rgb->hex (gray 125): -1, -1, -1: "
|
||||||
|
. $color_class::rgb2hex(-1, -1, -1) . "<br>";
|
||||||
|
} catch (\LengthException $e) {
|
||||||
|
print "**Exception: " . $e->getMessage() . "<br><pre>" . print_r($e, true) . "</pre><br>";
|
||||||
}
|
}
|
||||||
print "<hr>";
|
print "<hr>";
|
||||||
print "<h2>LEGACY</h2>";
|
|
||||||
// B(valid)
|
// B(valid)
|
||||||
$rgb = [50, 20, 30];
|
$rgb = [50, 20, 30];
|
||||||
$hex = '#0a141e';
|
$hex = '#0a141e';
|
||||||
@@ -183,16 +189,13 @@ $s = rand(15, 70);
|
|||||||
$b = 100;
|
$b = 100;
|
||||||
$l = 50;
|
$l = 50;
|
||||||
print "RANDOM IN: H: " . $h . ", S: " . $s . ", B/L: " . $b . "/" . $l . "<br>";
|
print "RANDOM IN: H: " . $h . ", S: " . $s . ", B/L: " . $b . "/" . $l . "<br>";
|
||||||
print "RANDOM hsb->rgb: <pre>"
|
print "RANDOM hsb->rgb: <pre>" . DgS::printAr(SetVarType::setArray(Colors::hsb2rgb($h, $s, $b))) . "</pre><br>";
|
||||||
. DgS::printAr(SetVarType::setArray(Color::hsbToRgb(new Coordinates\HSB([$h, $s, $b])))) . "</pre><br>";
|
print "RANDOM hsl->rgb: <pre>" . DgS::printAr(SetVarType::setArray(Colors::hsl2rgb($h, $s, $l))) . "</pre><br>";
|
||||||
print "RANDOM hsl->rgb: <pre>"
|
|
||||||
. DgS::printAr(SetVarType::setArray(Color::hslToRgb(new Coordinates\HSL([$h, $s, $l])))) . "</pre><br>";
|
|
||||||
|
|
||||||
print "<hr>";
|
print "<hr>";
|
||||||
|
|
||||||
$rgb = [0, 0, 0];
|
$rgb = [0, 0, 0];
|
||||||
print "rgb 0,0,0: " . Dgs::printAr($rgb) . " => "
|
print "rgb 0,0,0: " . Dgs::printAr($rgb) . " => " . Dgs::printAr(Colors::rgb2hsb($rgb[0], $rgb[1], $rgb[2])) . "<br>";
|
||||||
. Dgs::printAr(Color::rgbToHsb(new Coordinates\RGB([$rgb[0], $rgb[1], $rgb[2]]))) . "<br>";
|
|
||||||
|
|
||||||
print "<hr>";
|
print "<hr>";
|
||||||
|
|
||||||
|
|||||||
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__
|
||||||
@@ -23,6 +23,7 @@ $log = new CoreLibs\Logging\Logging([
|
|||||||
'log_file_id' => $LOG_FILE_ID,
|
'log_file_id' => $LOG_FILE_ID,
|
||||||
'log_per_date' => true,
|
'log_per_date' => true,
|
||||||
]);
|
]);
|
||||||
|
$_math = new CoreLibs\Convert\Math();
|
||||||
$math_class = 'CoreLibs\Convert\Math';
|
$math_class = 'CoreLibs\Convert\Math';
|
||||||
|
|
||||||
// define a list of from to color sets for conversion test
|
// define a list of from to color sets for conversion test
|
||||||
@@ -34,9 +35,13 @@ print "<body>";
|
|||||||
print '<div><a href="class_test.php">Class Test Master</a></div>';
|
print '<div><a href="class_test.php">Class Test Master</a></div>';
|
||||||
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
||||||
|
|
||||||
|
print "FCEIL: " . $_math->fceil(5.1234567890, 5) . "<br>";
|
||||||
|
print "FLOORP: " . $_math->floorp(5123456, -3) . "<br>";
|
||||||
|
print "FLOORP: " . $_math->floorp(5123456, -10) . "<br>";
|
||||||
|
print "INITNUMERIC: " . $_math->initNumeric('123') . "<br>";
|
||||||
|
|
||||||
print "S-FCEIL: " . $math_class::fceil(5.1234567890, 5) . "<br>";
|
print "S-FCEIL: " . $math_class::fceil(5.1234567890, 5) . "<br>";
|
||||||
print "S-FLOORP: " . $math_class::floorp(5123456, -3) . "<br>";
|
print "S-FLOORP: " . $math_class::floorp(5123456, -3) . "<br>";
|
||||||
print "S-FLOORP: " . $math_class::floorp(5123456, -10) . "<br>";
|
|
||||||
print "S-INITNUMERIC: " . $math_class::initNumeric(123) . "<br>";
|
print "S-INITNUMERIC: " . $math_class::initNumeric(123) . "<br>";
|
||||||
print "S-INITNUMERIC: " . $math_class::initNumeric(123.456) . "<br>";
|
print "S-INITNUMERIC: " . $math_class::initNumeric(123.456) . "<br>";
|
||||||
print "S-INITNUMERIC: " . $math_class::initNumeric('123') . "<br>";
|
print "S-INITNUMERIC: " . $math_class::initNumeric('123') . "<br>";
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ $test_files = [
|
|||||||
'class_test.db.query-placeholder.php' => 'Class Test: DB query placeholder convert',
|
'class_test.db.query-placeholder.php' => 'Class Test: DB query placeholder convert',
|
||||||
'class_test.db.dbReturn.php' => 'Class Test: DB dbReturn',
|
'class_test.db.dbReturn.php' => 'Class Test: DB dbReturn',
|
||||||
'class_test.db.single.php' => 'Class Test: DB single query tests',
|
'class_test.db.single.php' => 'Class Test: DB single query tests',
|
||||||
|
'class_test.db.sqlite.php' => 'Class Test: DB: SqLite',
|
||||||
'class_test.convert.colors.php' => 'Class Test: CONVERT COLORS',
|
'class_test.convert.colors.php' => 'Class Test: CONVERT COLORS',
|
||||||
'class_test.check.colors.php' => 'Class Test: CHECK COLORS',
|
'class_test.check.colors.php' => 'Class Test: CHECK COLORS',
|
||||||
'class_test.mime.php' => 'Class Test: MIME',
|
'class_test.mime.php' => 'Class Test: MIME',
|
||||||
|
|||||||
@@ -1139,6 +1139,118 @@ class Basic
|
|||||||
|
|
||||||
// *** BETTER PASSWORD OPTIONS END ***
|
// *** BETTER PASSWORD OPTIONS END ***
|
||||||
|
|
||||||
|
// *** COLORS ***
|
||||||
|
// [!!! DEPRECATED !!!]
|
||||||
|
// moved to \CoreLibs\Convert\Colors
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converts a hex RGB color to the int numbers
|
||||||
|
* @param string $hexStr RGB hexstring
|
||||||
|
* @param bool $returnAsString flag to return as string
|
||||||
|
* @param string $seperator string seperator: default: ","
|
||||||
|
* @return string|array<mixed>|bool false on error or array with RGB or
|
||||||
|
* a string with the seperator
|
||||||
|
* @deprecated use \CoreLibs\Convert\Colors::hex2rgb() instead
|
||||||
|
*/
|
||||||
|
public static function hex2rgb(string $hexStr, bool $returnAsString = false, string $seperator = ',')
|
||||||
|
{
|
||||||
|
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Convert\Colors::hex2rgb()', E_USER_DEPRECATED);
|
||||||
|
return \CoreLibs\Convert\Colors::hex2rgb($hexStr, $returnAsString, $seperator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converts the rgb values from int data to the valid rgb html hex string
|
||||||
|
* optional can turn of leading #
|
||||||
|
* @param int $red red 0-255
|
||||||
|
* @param int $green green 0-255
|
||||||
|
* @param int $blue blue 0-255
|
||||||
|
* @param bool $hex_prefix default true, prefix with "#"
|
||||||
|
* @return string|bool rgb in hex values with leading # if set
|
||||||
|
* @deprecated use \CoreLibs\Convert\Colors::rgb2hex() instead
|
||||||
|
*/
|
||||||
|
public static function rgb2hex(int $red, int $green, int $blue, bool $hex_prefix = true)
|
||||||
|
{
|
||||||
|
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Convert\Colors::rgb2hex()', E_USER_DEPRECATED);
|
||||||
|
return \CoreLibs\Convert\Colors::rgb2hex($red, $green, $blue, $hex_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converts and int RGB to the HTML color string in hex format
|
||||||
|
* @param int $red red 0-255
|
||||||
|
* @param int $green green 0-255
|
||||||
|
* @param int $blue blue 0-255
|
||||||
|
* @return string|bool hex rgb string
|
||||||
|
* @deprecated use rgb2hex instead
|
||||||
|
*/
|
||||||
|
public static function rgb2html(int $red, int $green, int $blue)
|
||||||
|
{
|
||||||
|
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Convert\Colors::rgb2hex()', E_USER_DEPRECATED);
|
||||||
|
// check that each color is between 0 and 255
|
||||||
|
return \CoreLibs\Convert\Colors::rgb2hex($red, $green, $blue, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converts RGB to HSB/V values
|
||||||
|
* returns:
|
||||||
|
* array with hue (0-360), sat (0-100%), brightness/value (0-100%)
|
||||||
|
* @param int $red red 0-255
|
||||||
|
* @param int $green green 0-255
|
||||||
|
* @param int $blue blue 0-255
|
||||||
|
* @return array<mixed>|bool Hue, Sat, Brightness/Value
|
||||||
|
* @deprecated use \CoreLibs\Convert\Colors::rgb2hsb() instead
|
||||||
|
*/
|
||||||
|
public static function rgb2hsb(int $red, int $green, int $blue)
|
||||||
|
{
|
||||||
|
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Convert\Colors::rgb2hsb()', E_USER_DEPRECATED);
|
||||||
|
return \CoreLibs\Convert\Colors::rgb2hsb($red, $green, $blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converts HSB/V to RGB values RGB is full INT
|
||||||
|
* @param int $H hue 0-360
|
||||||
|
* @param float $S saturation 0-1 (float)
|
||||||
|
* @param float $V brightness/value 0-1 (float)
|
||||||
|
* @return array<mixed>|bool 0 red/1 green/2 blue array
|
||||||
|
* @deprecated use \CoreLibs\Convert\Colors::hsb2rgb() instead
|
||||||
|
*/
|
||||||
|
public static function hsb2rgb(int $H, float $S, float $V)
|
||||||
|
{
|
||||||
|
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Convert\Colors::hsb2rgb()', E_USER_DEPRECATED);
|
||||||
|
return \CoreLibs\Convert\Colors::hsb2rgb($H, (int)round($S * 100), (int)round($V * 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converts a RGB (0-255) to HSL
|
||||||
|
* return:
|
||||||
|
* array with hue (0-360), saturation (0-100%) and luminance (0-100%)
|
||||||
|
* @param int $r red 0-255
|
||||||
|
* @param int $g green 0-255
|
||||||
|
* @param int $b blue 0-255
|
||||||
|
* @return array<mixed>|bool hue/sat/luminance
|
||||||
|
* @deprecated use \CoreLibs\Convert\Colors::rgb2hsl() instead
|
||||||
|
*/
|
||||||
|
public static function rgb2hsl(int $r, int $g, int $b)
|
||||||
|
{
|
||||||
|
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Convert\Colors::rgb2hsl()', E_USER_DEPRECATED);
|
||||||
|
return \CoreLibs\Convert\Colors::rgb2hsb($r, $g, $b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converts an HSL to RGB
|
||||||
|
* @param int $h hue: 0-360 (degrees)
|
||||||
|
* @param float $s saturation: 0-1
|
||||||
|
* @param float $l luminance: 0-1
|
||||||
|
* @return array<mixed>|bool red/blue/green 0-255 each
|
||||||
|
* @deprecated use \CoreLibs\Convert\Colors::hsl2rgb() instead
|
||||||
|
*/
|
||||||
|
public static function hsl2rgb(int $h, float $s, float $l)
|
||||||
|
{
|
||||||
|
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Convert\Colors::hsl2rgb()', E_USER_DEPRECATED);
|
||||||
|
return \CoreLibs\Convert\Colors::hsl2rgb($h, $s * 100, $l * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// *** COLORS END ***
|
||||||
|
|
||||||
// *** EMAIL FUNCTIONS ***
|
// *** EMAIL FUNCTIONS ***
|
||||||
// [!!! DEPRECATED !!!]
|
// [!!! DEPRECATED !!!]
|
||||||
// Moved to \CoreLibs\Check\Email
|
// Moved to \CoreLibs\Check\Email
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ class CieXyz
|
|||||||
private static function linRgbToXyzD65(RGB $rgb): XYZ
|
private static function linRgbToXyzD65(RGB $rgb): XYZ
|
||||||
{
|
{
|
||||||
// if not linear, convert to linear
|
// if not linear, convert to linear
|
||||||
if (!(bool)$rgb->get('linear')) {
|
if (!$rgb->get('linear')) {
|
||||||
$rgb = (new RGB($rgb->returnAsArray()))->toLinear();
|
$rgb = (new RGB($rgb->returnAsArray()))->toLinear();
|
||||||
}
|
}
|
||||||
return new XYZ(self::convertArray(Math::multiplyMatrices(
|
return new XYZ(self::convertArray(Math::multiplyMatrices(
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class Colors
|
|||||||
* @param bool $hex_prefix default true, prefix with "#"
|
* @param bool $hex_prefix default true, prefix with "#"
|
||||||
* @return string rgb in hex values with leading # if set,
|
* @return string rgb in hex values with leading # if set,
|
||||||
* @throws \LengthException If any argument is not in the range of 0~255
|
* @throws \LengthException If any argument is not in the range of 0~255
|
||||||
* @deprecated v9.20.0 use: new Coordinates\RGB([$red, $green, $blue]))->returnAsHex(true/false for #)
|
|
||||||
*/
|
*/
|
||||||
public static function rgb2hex(
|
public static function rgb2hex(
|
||||||
int $red,
|
int $red,
|
||||||
@@ -54,7 +53,6 @@ class Colors
|
|||||||
* or a string with the seperator
|
* or a string with the seperator
|
||||||
* @throws \InvalidArgumentException if hex string is empty
|
* @throws \InvalidArgumentException if hex string is empty
|
||||||
* @throws \UnexpectedValueException if the hex string value is not valid
|
* @throws \UnexpectedValueException if the hex string value is not valid
|
||||||
* @deprecated v9.20.0 use: new Coordinates\RGB($hex_string) (build string/array from return data)
|
|
||||||
*/
|
*/
|
||||||
public static function hex2rgb(
|
public static function hex2rgb(
|
||||||
string $hex_string,
|
string $hex_string,
|
||||||
@@ -93,7 +91,6 @@ class Colors
|
|||||||
* @param int $blue blue 0-255
|
* @param int $blue blue 0-255
|
||||||
* @return array<int|float> Hue, Sat, Brightness/Value
|
* @return array<int|float> Hue, Sat, Brightness/Value
|
||||||
* @throws \LengthException If any argument is not in the range of 0~255
|
* @throws \LengthException If any argument is not in the range of 0~255
|
||||||
* @deprecated v9.20.0 use: Color::rgbToHsb(...)->returnAsArray() will return float unrounded
|
|
||||||
*/
|
*/
|
||||||
public static function rgb2hsb(int $red, int $green, int $blue): array
|
public static function rgb2hsb(int $red, int $green, int $blue): array
|
||||||
{
|
{
|
||||||
@@ -115,7 +112,6 @@ class Colors
|
|||||||
* @param float $V brightness/value 0-100 (int)
|
* @param float $V brightness/value 0-100 (int)
|
||||||
* @return array<int> 0 red/1 green/2 blue array as 0-255
|
* @return array<int> 0 red/1 green/2 blue array as 0-255
|
||||||
* @throws \LengthException If any argument is not in the valid range
|
* @throws \LengthException If any argument is not in the valid range
|
||||||
* @deprecated v9.20.0 use: Color::hsbToRgb(...)->returnAsArray() will return float unrounded
|
|
||||||
*/
|
*/
|
||||||
public static function hsb2rgb(float $H, float $S, float $V): array
|
public static function hsb2rgb(float $H, float $S, float $V): array
|
||||||
{
|
{
|
||||||
@@ -137,7 +133,6 @@ class Colors
|
|||||||
* @param int $blue blue 0-255
|
* @param int $blue blue 0-255
|
||||||
* @return array<float> hue/sat/luminance
|
* @return array<float> hue/sat/luminance
|
||||||
* @throws \LengthException If any argument is not in the range of 0~255
|
* @throws \LengthException If any argument is not in the range of 0~255
|
||||||
* @deprecated v9.20.0 use: Color::rgbToHsl(...)->returnAsArray() will return float unrounded
|
|
||||||
*/
|
*/
|
||||||
public static function rgb2hsl(int $red, int $green, int $blue): array
|
public static function rgb2hsl(int $red, int $green, int $blue): array
|
||||||
{
|
{
|
||||||
@@ -158,7 +153,6 @@ class Colors
|
|||||||
* @param float $lum luminance: 0-100
|
* @param float $lum luminance: 0-100
|
||||||
* @return array<int,float|int> red/blue/green 0-255 each
|
* @return array<int,float|int> red/blue/green 0-255 each
|
||||||
* @throws \LengthException If any argument is not in the valid range
|
* @throws \LengthException If any argument is not in the valid range
|
||||||
* @deprecated v9.20.0 use: Color::hslToRgb(...)->returnAsArray() will return float unrounded
|
|
||||||
*/
|
*/
|
||||||
public static function hsl2rgb(float $hue, float $sat, float $lum): array
|
public static function hsl2rgb(float $hue, float $sat, float $lum): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -136,28 +136,6 @@ class Math
|
|||||||
*
|
*
|
||||||
* It returns an array which is the product of the two number matrices passed as parameters.
|
* It returns an array which is the product of the two number matrices passed as parameters.
|
||||||
*
|
*
|
||||||
* NOTE:
|
|
||||||
* if the right side (B matrix) has a missing row, this row will be fillwed with 0 instead of
|
|
||||||
* throwing an error:
|
|
||||||
* A:
|
|
||||||
* [
|
|
||||||
* [1, 2, 3],
|
|
||||||
* [4, 5, 6],
|
|
||||||
* ]
|
|
||||||
* B:
|
|
||||||
* [
|
|
||||||
* [7, 8, 9],
|
|
||||||
* [10, 11, 12],
|
|
||||||
* ]
|
|
||||||
* The B will get a third row with [0, 0, 0] added to make the multiplication work as it will be
|
|
||||||
* rewritten as
|
|
||||||
* B-rewrite:
|
|
||||||
* [
|
|
||||||
* [7, 10, 0],
|
|
||||||
* [8, 11, 12],
|
|
||||||
* [0, 0, 0] <- automatically added
|
|
||||||
* ]
|
|
||||||
*
|
|
||||||
* @param array<float|int|array<int|float>> $a m x n matrice
|
* @param array<float|int|array<int|float>> $a m x n matrice
|
||||||
* @param array<float|int|array<int|float>> $b n x p matrice
|
* @param array<float|int|array<int|float>> $b n x p matrice
|
||||||
*
|
*
|
||||||
@@ -183,9 +161,8 @@ class Math
|
|||||||
$p = count($b[0]);
|
$p = count($b[0]);
|
||||||
|
|
||||||
// transpose $b:
|
// transpose $b:
|
||||||
// so that we can multiply row by row
|
|
||||||
$bCols = array_map(
|
$bCols = array_map(
|
||||||
callback: fn ($k) => array_map(
|
callback: fn ($k) => \array_map(
|
||||||
(fn ($i) => is_array($i) ? $i[$k] : 0),
|
(fn ($i) => is_array($i) ? $i[$k] : 0),
|
||||||
$b,
|
$b,
|
||||||
),
|
),
|
||||||
@@ -198,8 +175,7 @@ class Math
|
|||||||
array_reduce(
|
array_reduce(
|
||||||
array: $row,
|
array: $row,
|
||||||
callback: fn ($a, $v, $i = null) => $a + $v * (
|
callback: fn ($a, $v, $i = null) => $a + $v * (
|
||||||
// if last entry missing for full copy add a 0 to it
|
$col[$i ?? array_search($v, $row) ?: 0]
|
||||||
$col[$i ?? array_search($v, $row, true)] ?? 0 /** @phpstan-ignore-line */
|
|
||||||
),
|
),
|
||||||
initial: 0,
|
initial: 0,
|
||||||
) :
|
) :
|
||||||
@@ -215,7 +191,7 @@ class Math
|
|||||||
|
|
||||||
if ($m === 1) {
|
if ($m === 1) {
|
||||||
// Avoid [[a, b, c, ...]]:
|
// Avoid [[a, b, c, ...]]:
|
||||||
return $product[0];
|
$product = $product[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($p === 1) {
|
if ($p === 1) {
|
||||||
|
|||||||
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__
|
||||||
Reference in New Issue
Block a user