Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfd49947ad | ||
|
|
6985dc4e9d | ||
|
|
5f2668b011 | ||
|
|
eba1ef9c59 | ||
|
|
8497144053 | ||
|
|
2006798388 | ||
|
|
bf63d850ca | ||
|
|
53e267ce24 | ||
|
|
1754ecf2ee | ||
|
|
3c37899a48 | ||
|
|
0436cfe3da | ||
|
|
3606de1a00 | ||
|
|
3081439eda | ||
|
|
7af0e74b85 | ||
|
|
7748b83a6b | ||
|
|
f83293ff1a | ||
|
|
9c3be2942e | ||
|
|
ee62bd98ee | ||
|
|
02e9610fad | ||
|
|
8a41db4649 | ||
|
|
e27ea3dc9f | ||
|
|
ec4bf54d81 | ||
|
|
ec3ca787fa | ||
|
|
86acbbb85b | ||
|
|
8e0af7a5f7 | ||
|
|
b022662dfc | ||
|
|
3039ebf913 |
@@ -458,6 +458,47 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dateRangeHasWeekendProvider(): array
|
||||
{
|
||||
return [
|
||||
'no weekend' => [
|
||||
'2023-07-03',
|
||||
'2023-07-04',
|
||||
false
|
||||
],
|
||||
'start weekend sat' => [
|
||||
'2023-07-01',
|
||||
'2023-07-04',
|
||||
true
|
||||
],
|
||||
'start weekend sun' => [
|
||||
'2023-07-02',
|
||||
'2023-07-04',
|
||||
true
|
||||
],
|
||||
'end weekend sat' => [
|
||||
'2023-07-03',
|
||||
'2023-07-08',
|
||||
true
|
||||
],
|
||||
'end weekend sun' => [
|
||||
'2023-07-03',
|
||||
'2023-07-09',
|
||||
true
|
||||
],
|
||||
'long period > 6 days' => [
|
||||
'2023-07-03',
|
||||
'2023-07-27',
|
||||
true
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* date string convert test
|
||||
*
|
||||
@@ -780,6 +821,29 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
|
||||
$output
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::dateRangeHasWeekend
|
||||
* @dataProvider dateRangeHasWeekendProvider
|
||||
* @testdox dateRangeHasWeekend $start_date and $end_date are expected weekend $expected [$_dataName]
|
||||
*
|
||||
* @param string $start_date
|
||||
* @param string $end_date
|
||||
* @param bool $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testDateRangeHasWeekend(
|
||||
string $start_date,
|
||||
string $end_date,
|
||||
bool $expected
|
||||
): void {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Combined\DateTime::dateRangeHasWeekend($start_date, $end_date)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace tests;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use CoreLibs\Logging\Logger\Level;
|
||||
use CoreLibs\DB\Options\Convert;
|
||||
|
||||
/**
|
||||
* Test class for DB\IO + DB\SQL\PgSQL
|
||||
@@ -4557,6 +4558,176 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
$db->dbClose();
|
||||
}
|
||||
|
||||
// testing auto convert
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::dbSetConvertFlag
|
||||
* @testdox Check convert type works
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConvertType(): void
|
||||
{
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config['valid'],
|
||||
self::$log
|
||||
);
|
||||
$bytea_data = $db->dbEscapeBytea(
|
||||
file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'CoreLibsDBIOTest.php') ?: ''
|
||||
);
|
||||
$query_insert = <<<SQL
|
||||
INSERT INTO table_with_primary_key (
|
||||
uid,
|
||||
row_int, row_numeric, row_varchar, row_varchar_literal,
|
||||
row_json, row_jsonb, row_bytea, row_timestamp,
|
||||
row_date, row_interval, row_array_int, row_array_varchar
|
||||
) VALUES (
|
||||
$1,
|
||||
$2, $3, $4, $5,
|
||||
$6, $7, $8, $9,
|
||||
$10, $11, $12, $13
|
||||
)
|
||||
SQL;
|
||||
$db->dbExecParams(
|
||||
$query_insert,
|
||||
[
|
||||
'CONVERT_TYPE_TEST',
|
||||
1, 1.5, 'varchar', 'varchar literla',
|
||||
json_encode(['json', 'a', 1, true, 'sub' => ['b', 'c']]),
|
||||
json_encode(['jsonb', 'a', 1, true, 'sub' => ['b', 'c']]),
|
||||
$bytea_data, date('Y-m-d H:i:s'), date('Y-m-d'), date('H:m:s'),
|
||||
'{1,2,3}', '{"a","b","c"}'
|
||||
]
|
||||
);
|
||||
$type_layout = [
|
||||
'uid' => 'string',
|
||||
'row_int' => 'int',
|
||||
'row_numeric' => 'float',
|
||||
'row_varchar' => 'string',
|
||||
'row_varchar_literal' => 'string',
|
||||
'row_json' => 'json',
|
||||
'row_jsonb' => 'json',
|
||||
'row_bytea' => 'bytea',
|
||||
'row_timestamp' => 'string',
|
||||
'row_date' => 'string',
|
||||
'row_interval' => 'string',
|
||||
'row_array_int' => 'string',
|
||||
'row_array_varchar' => 'string'
|
||||
];
|
||||
$query_select = <<<SQL
|
||||
SELECT
|
||||
uid,
|
||||
row_int, row_numeric, row_varchar, row_varchar_literal,
|
||||
row_json, row_jsonb, row_bytea, row_timestamp,
|
||||
row_date, row_interval, row_array_int, row_array_varchar
|
||||
FROM
|
||||
table_with_primary_key
|
||||
WHERE
|
||||
uid = $1
|
||||
SQL;
|
||||
$res = $db->dbReturnRowParams($query_select, ['CONVERT_TYPE_TEST']);
|
||||
// all hast to be string
|
||||
foreach ($res as $key => $value) {
|
||||
$this->assertIsString($value, 'Aseert string for column: ' . $key);
|
||||
}
|
||||
// convert base only
|
||||
$db->dbSetConvertFlag(Convert::on);
|
||||
$res = $db->dbReturnRowParams($query_select, ['CONVERT_TYPE_TEST']);
|
||||
foreach ($res as $key => $value) {
|
||||
if (is_numeric($key)) {
|
||||
$name = $db->dbGetFieldName($key);
|
||||
} else {
|
||||
$name = $key;
|
||||
}
|
||||
switch ($type_layout[$name]) {
|
||||
case 'int':
|
||||
$this->assertIsInt($value, 'Aseert int for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
default:
|
||||
$this->assertIsString($value, 'Aseert string for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$db->dbSetConvertFlag(Convert::numeric);
|
||||
$res = $db->dbReturnRowParams($query_select, ['CONVERT_TYPE_TEST']);
|
||||
foreach ($res as $key => $value) {
|
||||
if (is_numeric($key)) {
|
||||
$name = $db->dbGetFieldName($key);
|
||||
} else {
|
||||
$name = $key;
|
||||
}
|
||||
switch ($type_layout[$name]) {
|
||||
case 'int':
|
||||
$this->assertIsInt($value, 'Aseert int for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'float':
|
||||
$this->assertIsFloat($value, 'Aseert float for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
default:
|
||||
$this->assertIsString($value, 'Aseert string for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$db->dbSetConvertFlag(Convert::json);
|
||||
$res = $db->dbReturnRowParams($query_select, ['CONVERT_TYPE_TEST']);
|
||||
foreach ($res as $key => $value) {
|
||||
if (is_numeric($key)) {
|
||||
$name = $db->dbGetFieldName($key);
|
||||
} else {
|
||||
$name = $key;
|
||||
}
|
||||
switch ($type_layout[$name]) {
|
||||
case 'int':
|
||||
$this->assertIsInt($value, 'Aseert int for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'float':
|
||||
$this->assertIsFloat($value, 'Aseert float for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'json':
|
||||
case 'jsonb':
|
||||
$this->assertIsArray($value, 'Aseert array for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
default:
|
||||
$this->assertIsString($value, 'Aseert string for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$db->dbSetConvertFlag(Convert::bytea);
|
||||
$res = $db->dbReturnRowParams($query_select, ['CONVERT_TYPE_TEST']);
|
||||
foreach ($res as $key => $value) {
|
||||
if (is_numeric($key)) {
|
||||
$name = $db->dbGetFieldName($key);
|
||||
} else {
|
||||
$name = $key;
|
||||
}
|
||||
switch ($type_layout[$name]) {
|
||||
case 'int':
|
||||
$this->assertIsInt($value, 'Aseert int for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'float':
|
||||
$this->assertIsFloat($value, 'Aseert float for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'json':
|
||||
case 'jsonb':
|
||||
$this->assertIsArray($value, 'Aseert array for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'bytea':
|
||||
// for hex types it must not start with \x
|
||||
$this->assertStringStartsNotWith(
|
||||
'\x',
|
||||
$value,
|
||||
'Aseert bytes not starts with \x for column: ' . $key . '/' . $name
|
||||
);
|
||||
break;
|
||||
default:
|
||||
$this->assertIsString($value, 'Aseert string for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - internal read data (post exec)
|
||||
// dbGetNumRows, dbGetNumFields, dbGetFieldNames,
|
||||
// dbGetQuery, dbGetQueryHash, dbGetDbh
|
||||
@@ -4588,7 +4759,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
. "('Foxtrott', 'Tango', 789, '1982-10-15') ",
|
||||
null,
|
||||
//
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
['row_varchar', 'row_varchar_literal', 'row_int', 'row_date'],
|
||||
['varchar', 'varchar', 'int4', 'date'],
|
||||
@@ -4705,9 +4876,16 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
$db->dbExecParams($query, $params);
|
||||
}
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'PgSql\Result',
|
||||
$db->dbGetCursor(),
|
||||
'Failed assert dbGetCursor'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$compare_query ?? $query,
|
||||
$db->dbGetQuery()
|
||||
$db->dbGetQuery(),
|
||||
'Failed assert dbGetQuery'
|
||||
);
|
||||
$this->assertEquals(
|
||||
// perhaps move that somewhere else?
|
||||
@@ -4720,7 +4898,8 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
($params === null ?
|
||||
$db->dbGetQueryHash($query) :
|
||||
$db->dbGetQueryHash($query, $params)
|
||||
)
|
||||
),
|
||||
'Failed assertdbGetQueryHash '
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected_rows,
|
||||
@@ -4742,6 +4921,35 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
$db->dbGetFieldTypes(),
|
||||
'Failed assert dbGetFieldTypes'
|
||||
);
|
||||
// check FieldNameTypes matches
|
||||
$this->assertEquals(
|
||||
array_combine(
|
||||
$expected_col_names,
|
||||
$expected_col_types
|
||||
),
|
||||
$db->dbGetFieldNameTypes(),
|
||||
'Failed assert dbGetFieldNameTypes'
|
||||
);
|
||||
// check pos matches name
|
||||
// name matches type
|
||||
// pos matches type
|
||||
foreach ($expected_col_names as $pos => $name) {
|
||||
$this->assertEquals(
|
||||
$name,
|
||||
$db->dbGetFieldName($pos),
|
||||
'Failed assert dbGetFieldName: ' . $pos . ' => ' . $name
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected_col_types[$pos],
|
||||
$db->dbGetFieldType($name),
|
||||
'Failed assert dbGetFieldType: ' . $name . ' => ' . $expected_col_types[$pos]
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected_col_types[$pos],
|
||||
$db->dbGetFieldType($pos),
|
||||
'Failed assert dbGetFieldType: ' . $pos . ' => ' . $expected_col_types[$pos]
|
||||
);
|
||||
}
|
||||
$dbh = $db->dbGetDbh();
|
||||
$this->assertIsObject(
|
||||
$dbh
|
||||
|
||||
@@ -24,6 +24,11 @@ final class CoreLibsLoggingLoggingTest extends TestCase
|
||||
. "\[\w+\]\s{1}" // run id
|
||||
. "{[\w\\\\]+(::\w+)?}\s{1}"; // class
|
||||
|
||||
public static function tearDownAfterClass(): void
|
||||
{
|
||||
array_map('unlink', glob(self::LOG_FOLDER . '*.log'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test set for options BASIC
|
||||
*
|
||||
@@ -686,6 +691,11 @@ final class CoreLibsLoggingLoggingTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function providerLoggingLevelWrite(): array
|
||||
{
|
||||
return [
|
||||
@@ -791,6 +801,46 @@ final class CoreLibsLoggingLoggingTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
// check log level that writer writes in correct level
|
||||
// also that non debug ignores prefix/group
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::log
|
||||
* @testdox log() general call test
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLoggingLog(): void
|
||||
{
|
||||
// init logger
|
||||
$log = new \CoreLibs\Logging\Logging([
|
||||
'log_file_id' => 'testLoggingLog',
|
||||
'log_folder' => self::LOG_FOLDER,
|
||||
'log_per_level' => true,
|
||||
]);
|
||||
$log_ok = $log->log(Level::Debug, 'DEBUG', group_id: 'GROUP_ID', prefix: 'PREFIX:');
|
||||
$this->assertTrue($log_ok, 'assert ::log (debug) OK');
|
||||
$this->assertEquals(
|
||||
$log->getLogFile(),
|
||||
$log->getLogFileId() . '_DEBUG.log'
|
||||
);
|
||||
$log_ok = $log->log(Level::Info, 'INFO', group_id: 'GROUP_ID', prefix: 'PREFIX:');
|
||||
$this->assertTrue($log_ok, 'assert ::log (info) OK');
|
||||
$this->assertEquals(
|
||||
$log->getLogFile(),
|
||||
$log->getLogFileId() . '_INFO.log'
|
||||
);
|
||||
}
|
||||
|
||||
// must test flow:
|
||||
// init normal
|
||||
// log -> check file name
|
||||
// set per date
|
||||
// log -> check file name
|
||||
// and same for per_run
|
||||
|
||||
// deprecated calls check?
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use CoreLibs\Security\SymmetricEncryption;
|
||||
* @coversDefaultClass \CoreLibs\Security\SymmetricEncryption
|
||||
* @testdox \CoreLibs\Security\SymmetricEncryption method tests
|
||||
*/
|
||||
final class CoreLibsSecuritySymmetricEncryption extends TestCase
|
||||
final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Undocumented function
|
||||
34
4dev/tests/Template/CoreLibsTemplateHtmlBuilderBlockTest.php
Normal file
34
4dev/tests/Template/CoreLibsTemplateHtmlBuilderBlockTest.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CoreLibs\Template\HtmlBuilder\Block;
|
||||
|
||||
/**
|
||||
* Test class for Template\HtmlBuilder\Block
|
||||
* @coversDefaultClass \CoreLibs\Template\HtmlBuilder\Block
|
||||
* @testdox \CoreLibs\Template\HtmlBuilder\Block method tests
|
||||
*/
|
||||
final class CoreLibsTemplateHtmlBuilderBlockTest extends TestCase
|
||||
{
|
||||
public function testCreateBlock(): void
|
||||
{
|
||||
$el = Block::cel('div', 'id', 'content', ['css'], ['onclick' => 'foo();']);
|
||||
$this->assertEquals(
|
||||
'<div id="id" class="css" onclick="foo();">content</div>',
|
||||
Block::buildHtml($el)
|
||||
);
|
||||
}
|
||||
|
||||
// ael
|
||||
// aelx|addSub
|
||||
// resetSub
|
||||
// acssel/rcssel/scssel
|
||||
// buildHtml
|
||||
// buildHtmlFromList|printHtmlFromArray
|
||||
}
|
||||
|
||||
// __END__
|
||||
546
4dev/tests/Template/CoreLibsTemplateHtmlBuilderElementTest.php
Normal file
546
4dev/tests/Template/CoreLibsTemplateHtmlBuilderElementTest.php
Normal file
@@ -0,0 +1,546 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CoreLibs\Template\HtmlBuilder\Element;
|
||||
use CoreLibs\Template\HtmlBuilder\General\Error;
|
||||
use CoreLibs\Template\HtmlBuilder\General\HtmlBuilderExcpetion;
|
||||
|
||||
/**
|
||||
* Test class for Template\HtmlBuilder\Element
|
||||
* @coversDefaultClass \CoreLibs\Template\HtmlBuilder\Element
|
||||
* @testdox \CoreLibs\Template\HtmlBuilder\Element method tests
|
||||
*/
|
||||
final class CoreLibsTemplateHtmlBuilderElementTest extends TestCase
|
||||
{
|
||||
public function providerCreateElements(): array
|
||||
{
|
||||
return [
|
||||
'simple div' => [
|
||||
'tag' => 'div',
|
||||
'id' => 'id',
|
||||
'content' => 'content',
|
||||
'css' => ['css'],
|
||||
'options' => ['onclick' => 'foo();'],
|
||||
'expected' => '<div id="id" class="css" onclick="foo();">content</div>'
|
||||
],
|
||||
'simple input' => [
|
||||
'tag' => 'input',
|
||||
'id' => 'id',
|
||||
'content' => null,
|
||||
'css' => ['css'],
|
||||
'options' => ['name' => 'name', 'onclick' => 'foo();'],
|
||||
'expected' => '<input id="id" name="name" class="css" onclick="foo();">'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::Element
|
||||
* @covers ::buildHtml
|
||||
* @covers ::getTag
|
||||
* @covers ::getId
|
||||
* @covers ::getContent
|
||||
* @covers ::getOptions
|
||||
* @covers ::getCss
|
||||
* @dataProvider providerCreateElements
|
||||
* @testdox create single new Element test [$_dataName]
|
||||
*
|
||||
* @param string $tag
|
||||
* @param string|null $id
|
||||
* @param string|null $content
|
||||
* @param array|null $css
|
||||
* @param array|null $options
|
||||
* @param string $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testCreateElement(
|
||||
string $tag,
|
||||
?string $id,
|
||||
?string $content,
|
||||
?array $css,
|
||||
?array $options,
|
||||
string $expected
|
||||
): void {
|
||||
$el = new Element($tag, $id ?? '', $content ?? '', $css ?? [], $options ?? []);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$el->buildHtml(),
|
||||
'element creation failed'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$tag,
|
||||
$el->getTag(),
|
||||
'get tag failed'
|
||||
);
|
||||
|
||||
if ($id !== null) {
|
||||
$this->assertEquals(
|
||||
$id,
|
||||
$el->getId(),
|
||||
'get id failed'
|
||||
);
|
||||
}
|
||||
if ($content !== null) {
|
||||
$this->assertEquals(
|
||||
$content,
|
||||
$el->getContent(),
|
||||
'get content failed'
|
||||
);
|
||||
}
|
||||
if ($css !== null) {
|
||||
$this->assertEquals(
|
||||
$css,
|
||||
$el->getCss(),
|
||||
'get css failed'
|
||||
);
|
||||
}
|
||||
if ($options !== null) {
|
||||
$this->assertEquals(
|
||||
$options,
|
||||
$el->getOptions(),
|
||||
'get options failed'
|
||||
);
|
||||
}
|
||||
if (!empty($options['name'])) {
|
||||
$this->assertEquals(
|
||||
$options['name'],
|
||||
$el->getName(),
|
||||
'get name failed'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* css add/remove
|
||||
*
|
||||
* @cover ::getCss
|
||||
* @cover ::addCss
|
||||
* @cover ::removeCss
|
||||
* @testdox test handling of adding and removing css classes
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCssHandling(): void
|
||||
{
|
||||
$el = new Element('div', 'css-test', 'CSS content');
|
||||
$this->assertEqualsCanonicalizing(
|
||||
[],
|
||||
$el->getCss(),
|
||||
'check empty css'
|
||||
);
|
||||
$el->addCss('foo');
|
||||
$this->assertEqualsCanonicalizing(
|
||||
['foo'],
|
||||
$el->getCss(),
|
||||
'check added one css'
|
||||
);
|
||||
$el->removeCss('foo');
|
||||
$this->assertEqualsCanonicalizing(
|
||||
[],
|
||||
$el->getCss(),
|
||||
'check remove added css'
|
||||
);
|
||||
// add serveral
|
||||
// remove some of them
|
||||
$el->addCss('a', 'b', 'c');
|
||||
$this->assertEqualsCanonicalizing(
|
||||
['a', 'b', 'c'],
|
||||
$el->getCss(),
|
||||
'check added some css'
|
||||
);
|
||||
$el->removeCss('a', 'c');
|
||||
// $this->assertArray
|
||||
$this->assertEqualsCanonicalizing(
|
||||
['b'],
|
||||
$el->getCss(),
|
||||
'check remove some css'
|
||||
);
|
||||
// chained add and remove
|
||||
$el->addCss('a', 'b', 'c', 'd')->removeCss('b', 'd');
|
||||
$this->assertEqualsCanonicalizing(
|
||||
['a', 'c'],
|
||||
$el->getCss(),
|
||||
'check chain add remove some css'
|
||||
);
|
||||
$el->resetCss();
|
||||
$this->assertEqualsCanonicalizing(
|
||||
[],
|
||||
$el->getCss(),
|
||||
'check reset css'
|
||||
);
|
||||
// remove something that does not eixst
|
||||
$el->addCss('exists');
|
||||
$el->removeCss('not');
|
||||
$this->assertEqualsCanonicalizing(
|
||||
['exists'],
|
||||
$el->getCss(),
|
||||
'check remove not exitsing'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* nested test
|
||||
*
|
||||
* @testdox nested test and loop assign detection
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBuildNested(): void
|
||||
{
|
||||
Error::resetMessages();
|
||||
$el = new Element('div', 'build-test');
|
||||
$el_sub = new Element('div', 'sub-1');
|
||||
$el->addSub($el_sub);
|
||||
$this->assertEquals(
|
||||
'<div id="build-test"><div id="sub-1"></div></div>',
|
||||
$el->buildHtml(),
|
||||
'nested build failed'
|
||||
);
|
||||
// this would create a loop, throws error
|
||||
$this->expectException(HtmlBuilderExcpetion::class);
|
||||
$this->expectExceptionMessage("Cannot assign Element to itself, this would create an infinite loop");
|
||||
$el_sub->addSub($el_sub);
|
||||
$this->assertEquals(
|
||||
'<div id="sub-1"></div>',
|
||||
$el_sub->buildHtml(),
|
||||
'loop detection failed'
|
||||
);
|
||||
$this->assertTrue(
|
||||
Error::hasError(),
|
||||
'failed to throw error post loop detection'
|
||||
);
|
||||
$this->assertEquals(
|
||||
[[
|
||||
'level' => 'Error',
|
||||
'id' => '100',
|
||||
'message' => 'Cannot assign Element to itself, this would create an infinite loop',
|
||||
'context' => ['tag' => 'div', 'id' => 'sub-1']
|
||||
]],
|
||||
Error::getMessages(),
|
||||
'check error is 100 failed'
|
||||
);
|
||||
// get sub
|
||||
$this->assertEquals(
|
||||
[$el_sub],
|
||||
$el->getSub(),
|
||||
'get sub failed'
|
||||
);
|
||||
// reset sub
|
||||
$el->resetSub();
|
||||
$this->assertEquals(
|
||||
[],
|
||||
$el->getSub(),
|
||||
'reset sub failed'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @testdox updated nested connection
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNestedChangeContent(): void
|
||||
{
|
||||
$el = new Element('div', 'build-test');
|
||||
$el_s_1 = new Element('div', 'sub-1');
|
||||
$el_s_2 = new Element('div', 'sub-2');
|
||||
$el_s_3 = new Element('div', 'sub-3');
|
||||
$el_s_4 = new Element('div', 'sub-4');
|
||||
|
||||
$el->addSub($el_s_1, $el_s_2);
|
||||
// only sub -1, -2
|
||||
$this->assertEquals(
|
||||
'<div id="build-test"><div id="sub-1"></div><div id="sub-2"></div></div>',
|
||||
$el->buildHtml(),
|
||||
'check basic nested'
|
||||
);
|
||||
|
||||
// now add -3, -4 to both -1 and -2
|
||||
$el_s_1->addSub($el_s_3, $el_s_4);
|
||||
$el_s_2->addSub($el_s_3, $el_s_4);
|
||||
$this->assertEquals(
|
||||
'<div id="build-test"><div id="sub-1"><div id="sub-3"></div><div id="sub-4">'
|
||||
. '</div></div><div id="sub-2"><div id="sub-3"></div><div id="sub-4"></div>'
|
||||
. '</div></div>',
|
||||
$el->buildHtml(),
|
||||
'check nested added'
|
||||
);
|
||||
|
||||
// now add some css to el_s_3, will update in both sets
|
||||
$el_s_3->addCss('red');
|
||||
$this->assertEquals(
|
||||
'<div id="build-test"><div id="sub-1"><div id="sub-3" class="red"></div><div id="sub-4">'
|
||||
. '</div></div><div id="sub-2"><div id="sub-3" class="red"></div><div id="sub-4"></div>'
|
||||
. '</div></div>',
|
||||
$el->buildHtml(),
|
||||
'check nested u@dated'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @testdox test change tag/id/content
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testChangeElementData(): void
|
||||
{
|
||||
$el = new Element('div', 'id', 'Content');
|
||||
// content change
|
||||
$this->assertEquals(
|
||||
'Content',
|
||||
$el->getContent(),
|
||||
'set content'
|
||||
);
|
||||
$el->setContent('New Content');
|
||||
$this->assertEquals(
|
||||
'New Content',
|
||||
$el->getContent(),
|
||||
'changed content'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'div',
|
||||
$el->getTag(),
|
||||
'set tag'
|
||||
);
|
||||
$el->setTag('span');
|
||||
$this->assertEquals(
|
||||
'span',
|
||||
$el->getTag(),
|
||||
'changed tag'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'id',
|
||||
$el->getId(),
|
||||
'set id'
|
||||
);
|
||||
$el->setId('id-2');
|
||||
$this->assertEquals(
|
||||
'id-2',
|
||||
$el->getId(),
|
||||
'changed id'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @testdox test change options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testChangeOptions(): void
|
||||
{
|
||||
$el = new Element('button', 'id', 'Action', ['css'], ['value' => '3']);
|
||||
$this->assertEquals(
|
||||
['value' => '3'],
|
||||
$el->getOptions(),
|
||||
'set option'
|
||||
);
|
||||
$el->setOptions([
|
||||
'value' => '2'
|
||||
]);
|
||||
$this->assertEquals(
|
||||
['value' => '2'],
|
||||
$el->getOptions(),
|
||||
'changed option'
|
||||
);
|
||||
// add a new one
|
||||
$el->setOptions([
|
||||
'Foo' => 'bar',
|
||||
'Moo' => 'cow'
|
||||
]);
|
||||
$this->assertEquals(
|
||||
[
|
||||
'value' => '2',
|
||||
'Foo' => 'bar',
|
||||
'Moo' => 'cow'
|
||||
],
|
||||
$el->getOptions(),
|
||||
'changed option'
|
||||
);
|
||||
}
|
||||
|
||||
// build output
|
||||
// build from array list
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @testdox build element tree from object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBuildHtmlObject(): void
|
||||
{
|
||||
// build a simple block
|
||||
// div -> div -> button
|
||||
// -> div -> span
|
||||
// -> div -> input
|
||||
$el = new Element('div', 'master', '', ['master']);
|
||||
$el->addSub(
|
||||
Element::addElement(
|
||||
new Element('div', 'div-button', '', ['dv-bt']),
|
||||
new Element('button', 'button-id', 'Click me', ['bt-red'], [
|
||||
'OnClick' => 'action();',
|
||||
'value' => 'click',
|
||||
'type' => 'button'
|
||||
]),
|
||||
),
|
||||
Element::addElement(
|
||||
new Element('div', 'div-span', '', ['dv-sp']),
|
||||
new Element('span', 'span-id', 'Big important message<br>other', ['red']),
|
||||
),
|
||||
Element::addElement(
|
||||
new Element('div', 'div-input', '', ['dv-in']),
|
||||
new Element('input', 'input-id', '', ['in-blue'], [
|
||||
'OnClick' => 'otherAction();',
|
||||
'value' => 'Touch',
|
||||
'type' => 'button'
|
||||
]),
|
||||
),
|
||||
);
|
||||
$this->assertEquals(
|
||||
'<div id="master" class="master">'
|
||||
. '<div id="div-button" class="dv-bt">'
|
||||
. '<button id="button-id" name="button-id" class="bt-red" OnClick="action();" '
|
||||
. 'value="click" type="button">Click me</button>'
|
||||
. '</div>'
|
||||
. '<div id="div-span" class="dv-sp">'
|
||||
. '<span id="span-id" class="red">Big important message<br>other</span>'
|
||||
. '</div>'
|
||||
. '<div id="div-input" class="dv-in">'
|
||||
. '<input id="input-id" name="input-id" '
|
||||
. 'class="in-blue" OnClick="otherAction();" value="Touch" type="button">'
|
||||
. '</div>'
|
||||
. '</div>',
|
||||
$el->buildHtml()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @testdox build elements from array list
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testbuildHtmlArray(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
'<div id="id-1">A</div>'
|
||||
. '<div id="id-2">B</div>'
|
||||
. '<div id="id-3">C</div>',
|
||||
Element::buildHtmlFromList([
|
||||
new Element('div', 'id-1', 'A'),
|
||||
new Element('div', 'id-2', 'B'),
|
||||
new Element('div', 'id-3', 'C'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @testdox check for invalid tag detection, possible invalid id, possible invalid css
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInvalidElement(): void
|
||||
{
|
||||
Error::resetMessages();
|
||||
$this->expectException(HtmlBuilderExcpetion::class);
|
||||
$this->expectExceptionMessage("Could not create Element");
|
||||
$el = new Element('');
|
||||
$this->assertTrue(
|
||||
Error::hasError(),
|
||||
'failed to set error invalid tag detection'
|
||||
);
|
||||
$this->assertEquals(
|
||||
[[
|
||||
'level' => 'Error',
|
||||
'id' => '201',
|
||||
'message' => 'invalid or empty tag',
|
||||
'context' => ['tag' => '']
|
||||
]],
|
||||
Error::getMessages(),
|
||||
'check error message failed'
|
||||
);
|
||||
|
||||
// if we set invalid tag
|
||||
$el = new Element('div');
|
||||
$this->expectException(HtmlBuilderExcpetion::class);
|
||||
$this->expectExceptionMessageMatches("/^Invalid or empty tag: /");
|
||||
$this->expectExceptionMessage("Invalid or empty tag: 123123");
|
||||
$el->setTag('123123');
|
||||
$this->assertTrue(
|
||||
Error::hasError(),
|
||||
'failed to set error invalid tag detection'
|
||||
);
|
||||
$this->assertEquals(
|
||||
[[
|
||||
'level' => 'Error',
|
||||
'id' => '201',
|
||||
'message' => 'invalid or empty tag',
|
||||
'context' => ['tag' => '']
|
||||
]],
|
||||
Error::getMessages(),
|
||||
'check error message failed'
|
||||
);
|
||||
|
||||
|
||||
// invalid id (warning)
|
||||
Error::resetMessages();
|
||||
$el = new Element('div', '-$a15');
|
||||
$this->assertTrue(
|
||||
Error::hasWarning(),
|
||||
'failed to set warning invalid id detection'
|
||||
);
|
||||
$this->assertEquals(
|
||||
[[
|
||||
'level' => 'Warning',
|
||||
'id' => '202',
|
||||
'message' => 'possible invalid id',
|
||||
'context' => ['id' => '-$a15', 'tag' => 'div']
|
||||
]],
|
||||
Error::getMessages(),
|
||||
'check error message failed'
|
||||
);
|
||||
|
||||
// invalid name
|
||||
Error::resetMessages();
|
||||
$el = new Element('div', 'valid', '', [], ['name' => '-$asdf&']);
|
||||
$this->assertTrue(
|
||||
Error::hasWarning(),
|
||||
'failed to set warning invalid name detection'
|
||||
);
|
||||
$this->assertEquals(
|
||||
[[
|
||||
'level' => 'Warning',
|
||||
'id' => '203',
|
||||
'message' => 'possible invalid name',
|
||||
'context' => ['name' => '-$asdf&', 'id' => 'valid', 'tag' => 'div']
|
||||
]],
|
||||
Error::getMessages(),
|
||||
'check error message failed'
|
||||
);
|
||||
}
|
||||
|
||||
// static add element
|
||||
// print object/array
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CoreLibs\Template\HtmlBuilder\StringReplace;
|
||||
|
||||
/**
|
||||
* Test class for Template\HtmlBuilder\StringReplace
|
||||
* @coversDefaultClass \CoreLibs\Template\HtmlBuilder\StringReplace
|
||||
* @testdox \CoreLibs\Template\HtmlBuilder\StringReplace method tests
|
||||
*/
|
||||
final class CoreLibsTemplateHtmlBuilderStringReplaceTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::replaceData
|
||||
* @testdox test basic replaceData
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testReplaceData(): void
|
||||
{
|
||||
$html_block = <<<HTML
|
||||
<div id="{ID}" class="{CSS}">
|
||||
{CONTENT}
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEquals(
|
||||
<<<HTML
|
||||
<div id="block-id" class="blue,red">
|
||||
Some content here<br>with bla bla inside
|
||||
</div>
|
||||
HTML,
|
||||
StringReplace::replaceData(
|
||||
$html_block,
|
||||
[
|
||||
'ID' => 'block-id',
|
||||
'CSS' => join(',', ['blue', 'red']),
|
||||
'{CONTENT}' => 'Some content here<br>with bla bla inside',
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @testdox replaceData error
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
/* public function testReplaceDataErrors(): void
|
||||
{
|
||||
$this->expectException(HtmlBuilderExcpetion::class);
|
||||
$this->expectExceptionMessage("Replace and content array count differ");
|
||||
StringReplace::replaceData('<span>{FOO}</span>', ['{FOO}', '{BAR}'], ['foo']);
|
||||
} */
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -143,6 +143,26 @@ print "DATE-dow[$date];invalid: " . DateTime::setWeekdayNameFromDate($date) . "<
|
||||
print "DATE-dow[$date],long;invalid: " . DateTime::setWeekdayNameFromDate($date, true) . "<br>";
|
||||
print "DOW-date[$date];invalid: " . DateTime::setWeekdayNumberFromDate($date) . "<br>";
|
||||
|
||||
// check date range includes a weekend
|
||||
// does not:
|
||||
$start_date = '2023-07-03';
|
||||
$end_date = '2023-07-05';
|
||||
print "Has Weekend: " . $start_date . " ~ " . $end_date . ": "
|
||||
. Dgs::prBl(DateTime::dateRangeHasWeekend($start_date, $end_date)) . "<br>";
|
||||
$start_date = '2023-07-03';
|
||||
$end_date = '2023-07-10';
|
||||
print "Has Weekend: " . $start_date . " ~ " . $end_date . ": "
|
||||
. Dgs::prBl(DateTime::dateRangeHasWeekend($start_date, $end_date)) . "<br>";
|
||||
$start_date = '2023-07-03';
|
||||
$end_date = '2023-07-31';
|
||||
print "Has Weekend: " . $start_date . " ~ " . $end_date . ": "
|
||||
. Dgs::prBl(DateTime::dateRangeHasWeekend($start_date, $end_date)) . "<br>";
|
||||
$start_date = '2023-07-01';
|
||||
$end_date = '2023-07-03';
|
||||
print "Has Weekend: " . $start_date . " ~ " . $end_date . ": "
|
||||
. Dgs::prBl(DateTime::dateRangeHasWeekend($start_date, $end_date)) . "<br>";
|
||||
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -38,7 +38,9 @@ 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 '<div><a href="class_test.db.type.php">Class Test DB Types</a></div>';
|
||||
print '<div><a href="class_test.db.dbReturn.php">Class Test DB dbReturn</a></div>';
|
||||
print '<div><a href="class_test.db.single.php">Class Test DB Single Aciont</a></div>';
|
||||
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
||||
|
||||
print "LOGFILE NAME: " . $db->log->getLogFile() . "<br>";
|
||||
@@ -170,10 +172,10 @@ print "EOM READ OF PREVIOUS INSERTED: " . print_r($db->dbReturnRow($query), true
|
||||
print "LAST ERROR: " . $db->dbGetLastError() . "<br>";
|
||||
print "<br>";
|
||||
$query = <<<SQL
|
||||
SELECT
|
||||
test_foo_id, test
|
||||
FROM test_foo
|
||||
WHERE test_foo_id = $1;
|
||||
SELECT
|
||||
test_foo_id, test
|
||||
FROM test_foo
|
||||
WHERE test_foo_id = $1;
|
||||
SQL;
|
||||
print "RETURN ROW PARAMS: " . print_r(
|
||||
$db->dbReturnRowParams(
|
||||
@@ -334,10 +336,10 @@ $status = $db->dbExecParams($query_insert, $query_params);
|
||||
echo "<b>*</b><br>";
|
||||
echo "EOM STRING WITH MORE THAN 10 PARAMETERS: "
|
||||
. Support::printToString($query_params) . " |<br>"
|
||||
. " |<br>"
|
||||
. "PRIMARY KEY: " . Support::printToString($db->dbGetInsertPK()) . " | "
|
||||
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
|
||||
. "RETURNING RETURN: " . print_r($db->dbGetReturningArray(), true)
|
||||
. "QUERY: " . $db->dbGetQuery() . " |<br>"
|
||||
. "PRIMARY KEY: " . Support::printToString($db->dbGetInsertPK()) . " |<br>"
|
||||
. "RETURNING EXT: <pre>" . print_r($db->dbGetReturningExt(), true) . "</pre> |<br>"
|
||||
. "RETURNING RETURN: <pre>" . print_r($db->dbGetReturningArray(), true) . "</pre> |<br>"
|
||||
. "ERROR: " . $db->dbGetLastError(true) . "<br>";
|
||||
echo "<hr>";
|
||||
// binary insert tests
|
||||
@@ -355,10 +357,10 @@ $status = $db->dbExec($query);
|
||||
$__last_insert_id = $db->dbGetInsertPK();
|
||||
print "BINARY DATA INSERT: "
|
||||
. Support::printToString($status) . " |<br>"
|
||||
. " |<br>"
|
||||
. "PRIMARY KEY: " . Support::printToString($db->dbGetInsertPK()) . " | "
|
||||
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
|
||||
. "RETURNING RETURN: " . print_r($db->dbGetReturningArray(), true)
|
||||
. "QUERY: " . $db->dbGetQuery() . " |<br>"
|
||||
. "PRIMARY KEY: " . Support::printToString($db->dbGetInsertPK()) . " |<br>"
|
||||
. "RETURNING EXT: <pre>" . print_r($db->dbGetReturningExt(), true) . "</pre> |<br>"
|
||||
. "RETURNING RETURN: <pre>" . print_r($db->dbGetReturningArray(), true) . "</pre> |<br>"
|
||||
. "ERROR: " . $db->dbGetLastError(true) . "<br>";
|
||||
|
||||
echo "<b>*</b><br>";
|
||||
@@ -369,7 +371,11 @@ INSERT INTO binary_test (
|
||||
$1, $2, $3
|
||||
)
|
||||
SQL;
|
||||
$status = $db->dbExecParams($query, [$filename, $rand_bin_uid, $binary_data]);
|
||||
// $binary_data is dbEscapedBytea!
|
||||
$uniqid = \CoreLibs\Create\Uids::uniqIdShort();
|
||||
$status = $db->dbExecParams($query, [
|
||||
'class_test.db.php', $uniqid, $binary_data
|
||||
]);
|
||||
$__last_insert_id = $db->dbGetInsertPK();
|
||||
print "BINARY DATA INSERT PARAMS: "
|
||||
. Support::printToString($status) . " |<br>"
|
||||
@@ -378,7 +384,23 @@ print "BINARY DATA INSERT PARAMS: "
|
||||
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
|
||||
. "RETURNING RETURN: " . print_r($db->dbGetReturningArray(), true)
|
||||
. "ERROR: " . $db->dbGetLastError(true) . "<br>";
|
||||
|
||||
print "BINARY READER: ";
|
||||
$query = <<<SQL
|
||||
SELECT
|
||||
filename, uid, binary_data
|
||||
FROM
|
||||
binary_test
|
||||
WHERE
|
||||
uid = $1
|
||||
SQL;
|
||||
$res = $db->dbReturnRowParams($query, [$uniqid]);
|
||||
if (is_array($res)) {
|
||||
var_dump($res);
|
||||
$file = $db->dbUnescapeBytea($res['binary_data']);
|
||||
// var_dump($file);
|
||||
} else {
|
||||
print "Execute error";
|
||||
}
|
||||
echo "<hr>";
|
||||
|
||||
// returning test with multiple entries
|
||||
@@ -578,6 +600,44 @@ while (
|
||||
}
|
||||
echo "<hr>";
|
||||
|
||||
print "DB RETURN PARAMS LIKE<br>";
|
||||
$q = <<<SQL
|
||||
SELECT
|
||||
test_foo_id, test, some_bool, string_a, number_a, number_a_numeric
|
||||
FROM test_foo
|
||||
WHERE string_a LIKE $1;
|
||||
SQL;
|
||||
while (
|
||||
is_array($res = $db->dbReturnParams($q, ['%string%']))
|
||||
) {
|
||||
print "ROW: <pre>" . print_r($res, true) . "</pre><br>";
|
||||
}
|
||||
echo "<hr>";
|
||||
|
||||
print "DB RETURN PARAMS ANY<br>";
|
||||
$q = <<<SQL
|
||||
SELECT
|
||||
test_foo_id, test, some_bool, string_a, number_a, number_a_numeric
|
||||
FROM test_foo
|
||||
WHERE string_a = ANY($1);
|
||||
SQL;
|
||||
$query_value = '{'
|
||||
. join(',', ['string a'])
|
||||
. '}';
|
||||
while (
|
||||
is_array($res = $db->dbReturnParams($q, [$query_value]))
|
||||
) {
|
||||
print "ROW: <pre>" . print_r($res, true) . "</pre><br>";
|
||||
}
|
||||
echo "<hr>";
|
||||
|
||||
print "COMPOSITE ELEMENT READ<br>";
|
||||
$res = $db->dbReturnRow("SELECT item, count, (item).name, (item).price, (item).supplier_id FROM on_hand");
|
||||
print "ROW: <pre>" . print_r($res) . "</pre>";
|
||||
var_dump($res);
|
||||
print "Field Name/Types: <pre>" . print_r($db->dbGetFieldNameTypes(), true) . "</pre>";
|
||||
echo "<hr>";
|
||||
|
||||
// NOTE: try to replacate connection still exists if script is run a second time
|
||||
// open pg bouncer connection
|
||||
$db_pgb = new CoreLibs\DB\IO($DB_CONFIG['test_pgbouncer'] ?? [], $log);
|
||||
|
||||
@@ -35,7 +35,6 @@ 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 '<div><a href="class_test.db.dbReturn.php">Class Test DB dbReturn</a></div>';
|
||||
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
||||
|
||||
print "LOGFILE NAME: " . $db->log->getLogFile() . "<br>";
|
||||
@@ -54,38 +53,76 @@ if (($dbh = $db->dbGetDbh()) instanceof \PgSql\Connection) {
|
||||
print "NO DB HANDLER<br>";
|
||||
}
|
||||
|
||||
// params > 10 for debug
|
||||
// error catcher
|
||||
$query_insert = <<<SQL
|
||||
INSERT INTO many_columns (
|
||||
col_01_int,
|
||||
col_01, col_02, col_03, col_04, col_05, col_06, col_07, col_08, col_09,
|
||||
col_10, col_11, col_12, col_02_int
|
||||
) VALUES (
|
||||
1,
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9,
|
||||
$10, $11, $12, $13
|
||||
)
|
||||
RETURNING
|
||||
many_columns_id,
|
||||
col_01_int,
|
||||
col_01, col_02, col_03, col_04, col_05, col_06, col_07, col_08, col_09,
|
||||
col_10, col_11, col_12, col_02_int
|
||||
SQL;
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param \CoreLibs\DB\IO $dbc
|
||||
* @return void
|
||||
*/
|
||||
function testDBS(\CoreLibs\DB\IO $dbc): void
|
||||
{
|
||||
echo "Int call<br>";
|
||||
$dbc->dbReturnRow("SELECT test FROM test_foo LIMIT 1");
|
||||
}
|
||||
|
||||
$uniqid = \CoreLibs\Create\Uids::uniqIdShort();
|
||||
$binary_data = $db->dbEscapeBytea(file_get_contents('class_test.db.php') ?: '');
|
||||
$query_params = [
|
||||
'col 1', 'col 2', 'col 3', 'col 4', 'col 5', 'col 6', 'col 7', 'col 8',
|
||||
'col 9', 'col 10', 'col 11', 'col 12', null
|
||||
$uniqid,
|
||||
true,
|
||||
'STRING A',
|
||||
2,
|
||||
2.5,
|
||||
1,
|
||||
date('H:m:s'),
|
||||
date('Y-m-d H:m:s'),
|
||||
json_encode(['a' => 'string', 'b' => 1, 'c' => 1.5, 'f' => true, 'g' => ['a', 1, 1.5]]),
|
||||
null,
|
||||
'{"a", "b"}',
|
||||
'{1,2}',
|
||||
'{"(array Text A, 5, 8.8)","(array Text B, 10, 15.2)"}',
|
||||
'("Text", 4, 6.3)',
|
||||
$binary_data
|
||||
];
|
||||
|
||||
$query_insert = <<<SQL
|
||||
INSERT INTO test_foo (
|
||||
test, some_bool, string_a, number_a, number_a_numeric, smallint_a,
|
||||
some_time, some_timestamp, json_string, null_var,
|
||||
array_char_1, array_int_1,
|
||||
array_composite,
|
||||
composite_item,
|
||||
some_binary
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6,
|
||||
$7, $8, $9, $10,
|
||||
$11, $12,
|
||||
$13,
|
||||
$14,
|
||||
$15
|
||||
)
|
||||
SQL;
|
||||
$status = $db->dbExecParams($query_insert, $query_params);
|
||||
echo "<b>*</b><br>";
|
||||
echo "EOM STRING WITH MORE THAN 10 PARAMETERS: "
|
||||
. Support::printToString($query_params) . " |<br>"
|
||||
. " |<br>"
|
||||
. "PRIMARY KEY: " . Support::printToString($db->dbGetInsertPK()) . " | "
|
||||
// . "RETURNING EXT: " . Support::printToString($db->dbGetReturningExt()) . " | "
|
||||
. "RETURNING RETURN: " . Support::printToString($db->dbGetReturningArray())
|
||||
. "ERROR: " . $db->dbGetLastError(true) . "<br>";
|
||||
echo "<hr>";
|
||||
$query_select = <<<SQL
|
||||
SELECT
|
||||
test_foo_id,
|
||||
test, some_bool, string_a, number_a, number_a_numeric, smallint_a,
|
||||
number_real, number_double, number_serial,
|
||||
some_time, some_timestamp, json_string, null_var,
|
||||
array_char_1, array_char_2, array_int_1, array_int_2, array_composite,
|
||||
composite_item, (composite_item).*
|
||||
some_binary
|
||||
FROM
|
||||
test_foo
|
||||
WHERE
|
||||
test = $1;
|
||||
SQL;
|
||||
$res = $db->dbReturnRowParams($query_select, [$uniqid]);
|
||||
if (is_array($res)) {
|
||||
var_dump($res);
|
||||
}
|
||||
|
||||
testDBS($db);
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
|
||||
171
www/admin/class_test.db.types.php
Normal file
171
www/admin/class_test.db.types.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?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);
|
||||
// sample config
|
||||
require 'config.php';
|
||||
// define log file id
|
||||
$LOG_FILE_ID = 'classTest-db-types';
|
||||
ob_end_flush();
|
||||
|
||||
use CoreLibs\Debug\Support;
|
||||
use CoreLibs\DB\Options\Convert;
|
||||
|
||||
$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\IO(DB_CONFIG, $log);
|
||||
$db->log->debug('START', '=============================>');
|
||||
|
||||
$PAGE_NAME = 'TEST CLASS: DB COLUMN TYPES';
|
||||
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 '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
||||
|
||||
print "LOGFILE NAME: " . $db->log->getLogFile() . "<br>";
|
||||
print "LOGFILE ID: " . $db->log->getLogFileId() . "<br>";
|
||||
print "DBINFO: " . $db->dbInfo() . "<br>";
|
||||
// DB client encoding
|
||||
print "DB client encoding: " . $db->dbGetEncoding() . "<br>";
|
||||
print "DB search path: " . $db->dbGetSchema() . "<br>";
|
||||
|
||||
$to_db_version = '15.2';
|
||||
print "VERSION DB: " . $db->dbVersion() . "<br>";
|
||||
print "SERVER ENCODING: " . $db->dbVersionInfo('server_encoding') . "<br>";
|
||||
if (($dbh = $db->dbGetDbh()) instanceof \PgSql\Connection) {
|
||||
print "ALL OUTPUT [TEST]: <pre>" . print_r(pg_version($dbh), true) . "</pre><br>";
|
||||
} else {
|
||||
print "NO DB HANDLER<br>";
|
||||
}
|
||||
|
||||
print "<b>TRUNCATE test_foo</b><br>";
|
||||
$db->dbExec("TRUNCATE test_foo");
|
||||
|
||||
/* $q = <<<SQL
|
||||
INSERT INTO test_foo (test, array_composite) VALUES ('C', '{"(a,1,1.5)","(b,2,2.5)"}')
|
||||
SQL;
|
||||
$db->dbExecParams($q);
|
||||
pg_query($db->dbGetDbh(), $q);
|
||||
$q = <<<SQL
|
||||
INSERT INTO test_foo (test, array_composite) VALUES ($1, $2)
|
||||
SQL;
|
||||
// $db->dbExecParams($q, ['D', '{"(a b,1,1.5)","(c,3,4.5)"}']);
|
||||
$db->dbExecParams($q, ['D', '{"(array Text A, 5, 8.8)","(array Text B, 10, 15.2)"}']);
|
||||
*/
|
||||
$uniqid = \CoreLibs\Create\Uids::uniqIdShort();
|
||||
$binary_data = $db->dbEscapeBytea(file_get_contents('class_test.db.php') ?: '');
|
||||
$query_params = [
|
||||
$uniqid,
|
||||
true,
|
||||
'STRING A',
|
||||
2,
|
||||
2.5,
|
||||
1,
|
||||
date('H:m:s'),
|
||||
date('Y-m-d H:i:s'),
|
||||
json_encode(['a' => 'string', 'b' => 1, 'c' => 1.5, 'f' => true, 'g' => ['a', 1, 1.5]]),
|
||||
null,
|
||||
'{"a", "b"}',
|
||||
'{1,2}',
|
||||
'{"(array Text A, 5, 8.8)","(array Text B, 10, 15.2)"}',
|
||||
'("Text", 4, 6.3)',
|
||||
$binary_data
|
||||
];
|
||||
|
||||
$query_insert = <<<SQL
|
||||
INSERT INTO test_foo (
|
||||
test, some_bool, string_a, number_a, number_a_numeric, smallint_a,
|
||||
some_time, some_timestamp, json_string, null_var,
|
||||
array_char_1, array_int_1,
|
||||
array_composite,
|
||||
composite_item,
|
||||
some_binary
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6,
|
||||
$7, $8, $9, $10,
|
||||
$11, $12,
|
||||
$13,
|
||||
$14,
|
||||
$15
|
||||
)
|
||||
RETURNING
|
||||
test_foo_id,
|
||||
test, some_bool, string_a, number_a, number_a_numeric, smallint_a,
|
||||
some_time, some_timestamp, json_string, null_var,
|
||||
array_char_1, array_int_1,
|
||||
array_composite,
|
||||
composite_item,
|
||||
some_binary
|
||||
SQL;
|
||||
$status = $db->dbExecParams($query_insert, $query_params);
|
||||
echo "<b>*</b><br>";
|
||||
echo "INSERT ALL COLUMN TYPES: "
|
||||
. Support::printToString($query_params) . " |<br>"
|
||||
. "QUERY: " . $db->dbGetQuery() . " |<br>"
|
||||
. "PRIMARY KEY: " . Support::printToString($db->dbGetInsertPK()) . " |<br>"
|
||||
. "RETURNING EXT: <pre>" . print_r($db->dbGetReturningExt(), true) . "</pre> |<br>"
|
||||
. "RETURNING RETURN: <pre>" . print_r($db->dbGetReturningArray(), true) . "<pre> |<br>"
|
||||
. "ERROR: " . $db->dbGetLastError(true) . "<br>";
|
||||
echo "<hr>";
|
||||
|
||||
$query_select = <<<SQL
|
||||
SELECT
|
||||
test_foo_id,
|
||||
test, some_bool, string_a, number_a, number_a_numeric, smallint_a,
|
||||
number_real, number_double, number_numeric_3, number_serial,
|
||||
some_time, some_timestamp, json_string, null_var,
|
||||
array_char_1, array_char_2, array_int_1, array_int_2, array_composite,
|
||||
composite_item, (composite_item).*,
|
||||
some_binary
|
||||
FROM
|
||||
test_foo
|
||||
WHERE
|
||||
test = $1;
|
||||
SQL;
|
||||
$res = $db->dbReturnRowParams($query_select, [$uniqid]);
|
||||
// auto switch:
|
||||
// ^int
|
||||
// bool
|
||||
// with flags:
|
||||
// json(b) => array
|
||||
// bytes => string? or resource?
|
||||
// numeric => float (can have precision cut)
|
||||
$pos = 0;
|
||||
$name = '';
|
||||
if (is_array($res)) {
|
||||
$cursor = $db->dbGetCursor();
|
||||
var_dump($res);
|
||||
print "Field Name/Types: <pre>" . print_r($db->dbGetFieldNameTypes(), true) . "</pre>";
|
||||
print "Get type for: 'number_a':" . $db->dbGetFieldType('number_a') . "<br>";
|
||||
print "Get type for: 0: " . $db->dbGetFieldType(0) . "<br>";
|
||||
print "Get name for: 0: " . $db->dbGetFieldName(0) . "<br>";
|
||||
}
|
||||
|
||||
$db->dbSetConvertFlag(Convert::on);
|
||||
$db->dbSetConvertFlag(Convert::json);
|
||||
$db->dbSetConvertFlag(Convert::numeric);
|
||||
$db->dbSetConvertFlag(Convert::bytea);
|
||||
$res = $db->dbReturnRowParams($query_select, [$uniqid]);
|
||||
if (is_array($res)) {
|
||||
var_dump($res);
|
||||
}
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
// __END__
|
||||
83
www/admin/class_test.html_build.block.php
Normal file
83
www/admin/class_test.html_build.block.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php // phpcs:ignore warning
|
||||
|
||||
/**
|
||||
* @phan-file-suppress PhanTypeSuspiciousStringExpression
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
|
||||
|
||||
ob_start();
|
||||
|
||||
// basic class test file
|
||||
define('USE_DATABASE', false);
|
||||
// sample config
|
||||
require 'config.php';
|
||||
// define log file id
|
||||
$LOG_FILE_ID = 'classTest-html_build-block';
|
||||
ob_end_flush();
|
||||
|
||||
use CoreLibs\Template\HtmlBuilder\Block;
|
||||
|
||||
$log = new CoreLibs\Logging\Logging([
|
||||
'log_folder' => BASE . LOG,
|
||||
'log_file_id' => $LOG_FILE_ID,
|
||||
'log_per_date' => true,
|
||||
]);
|
||||
|
||||
// define a list of from to color sets for conversion test
|
||||
|
||||
$PAGE_NAME = 'TEST CLASS: HTML BUILD: BLOCK';
|
||||
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 '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
||||
|
||||
$el = Block::cel('div', 'el-1', 'Content', ['red'], ['onClick' => 'javascript:alert(\'JS alert\');']);
|
||||
|
||||
print "<pre>" . htmlentities(Block::buildHtml($el)) . "</pre>";
|
||||
|
||||
$el_a = Block::cel('div', 'u-id', '', ['base', 'cool']);
|
||||
$el_a_1 = Block::cel('span', 's-id-1', 'Span A', ['bold']);
|
||||
$el_a_2 = Block::cel('span', 's-id-2', 'Span B');
|
||||
$el_a_3 = Block::cel('a', 'link-a', 'Title', ['l-highlight'], ['OnClick' => 'Foo();']);
|
||||
$el_a_2 = Block::aelx($el_a_2, $el_a_3);
|
||||
// css changes before added to array
|
||||
$el_a_1 = Block::acssel($el_a_1, 'italic', 'green', 'italic', 'font-large');
|
||||
$el_a_1 = Block::rcssel($el_a_1, 'green');
|
||||
// switch
|
||||
$el_a_1 = Block::scssel($el_a_1, ['one', 'two', 'three'], ['three']);
|
||||
// this will add el_a_2 to the el_a block
|
||||
$el_a_1 = Block::aelx($el_a_1, $el_a_2);
|
||||
$el_a = Block::aelx($el_a, $el_a_1, $el_a_2);
|
||||
|
||||
// this will not update el_a
|
||||
// $el_a_1 = Block::aelx($el_a_1, $el_a_2);
|
||||
|
||||
$el_a_list = [];
|
||||
$el_a_list[] = Block::cel('foo', 'foo-A');
|
||||
$el_a_list[] = Block::cel('bar', 'foo-B');
|
||||
$el_a_list[] = Block::cel('baz', 'foo-C');
|
||||
$el_a_list[] = Block::cel('br');
|
||||
$el_a_list[] = Block::cel('input');
|
||||
|
||||
echo "<hr>";
|
||||
print "EL_A: <pre>" . print_r($el_a, true) . "</pre>";
|
||||
|
||||
echo "<hr>";
|
||||
print "phfo(\$el_o): <pre>" . htmlentities(Block::buildHtml($el_a, true)) . "</pre>";
|
||||
echo "<hr>";
|
||||
print "phfa(\$el_list): <pre>" . htmlentities(Block::buildHtmlFromList($el_a_list, true)) . "</pre>";
|
||||
|
||||
echo "<hr>";
|
||||
// self loop test (will not trigger, are arrays)
|
||||
$el_s = Block::cel('div', 'id-s', 'Self', []);
|
||||
$el_s = Block::aelx($el_s, $el_s);
|
||||
|
||||
print "phfo(\$el_): <pre>" . htmlentities(Block::buildHtml($el_s, true)) . "</pre>";
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
// __END__
|
||||
142
www/admin/class_test.html_build.element.php
Normal file
142
www/admin/class_test.html_build.element.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php // phpcs:ignore warning
|
||||
|
||||
/**
|
||||
* @phan-file-suppress PhanTypeSuspiciousStringExpression
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
|
||||
|
||||
ob_start();
|
||||
|
||||
// basic class test file
|
||||
define('USE_DATABASE', false);
|
||||
// sample config
|
||||
require 'config.php';
|
||||
// define log file id
|
||||
$LOG_FILE_ID = 'classTest-html_build';
|
||||
ob_end_flush();
|
||||
|
||||
use CoreLibs\Template\HtmlBuilder\Element;
|
||||
use CoreLibs\Template\HtmlBuilder\General\Error;
|
||||
use CoreLibs\Template\HtmlBuilder\General\HtmlBuilderExcpetion;
|
||||
use CoreLibs\Debug\Support;
|
||||
|
||||
$log = new CoreLibs\Logging\Logging([
|
||||
'log_folder' => BASE . LOG,
|
||||
'log_file_id' => $LOG_FILE_ID,
|
||||
'log_per_date' => true,
|
||||
]);
|
||||
|
||||
// define a list of from to color sets for conversion test
|
||||
|
||||
$PAGE_NAME = 'TEST CLASS: HTML BUILD';
|
||||
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 '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
||||
|
||||
$el = new Element('div', 'el-1', 'Content', ['red'], ['onClick' => 'javascript:alert(\'JS alert\');']);
|
||||
|
||||
print "<pre>" . htmlentities($el->buildHtml()) . "</pre>";
|
||||
|
||||
$el_o = new Element('div', 'u-id', '', ['base', 'cool']);
|
||||
$el_o_1 = new Element('span', 's-id-1', 'Span A', ['bold']);
|
||||
$el_o_2 = new Element('span', 's-id-2', 'Span B');
|
||||
$el_o_3 = new Element('a', 'link-a', 'Title', ['l-highlight'], ['OnClick' => 'Foo();']);
|
||||
$el_o_2->addSub($el_o_3);
|
||||
$el_o->addSub($el_o_1, $el_o_2);
|
||||
|
||||
$el_o_1->addCss('italic', 'green', 'italic', 'font-large')
|
||||
->removeCss('green');
|
||||
|
||||
$el_o_2->addCss('wrong-css')
|
||||
->removeCss('wrong-css', 'correct-css');
|
||||
$el_o_2->addCss('a', 'b')->removeCss('correct-css');
|
||||
|
||||
$el_o_1->addSub($el_o_2);
|
||||
|
||||
// var_dump($el2);
|
||||
|
||||
$el_o_list = [];
|
||||
$el_o_list[] = new Element('foo', 'foo-A');
|
||||
$el_o_list[] = new Element('bar', 'foo-B');
|
||||
$el_o_list[] = new Element('baz', 'foo-C');
|
||||
$el_o_list[] = new Element('br');
|
||||
$el_o_list[] = new Element('input', 'tag', '', [], ['name' => 'foo', 'value' => 'ABC']);
|
||||
|
||||
// $el2->resetSub();
|
||||
// var_dump($el2);
|
||||
echo "<hr>";
|
||||
print "EL_O: <pre>" . print_r($el_o, true) . "</pre>";
|
||||
|
||||
echo "<hr>";
|
||||
print "buildHtml(): <pre>" . htmlentities($el_o->buildHtml()) . "</pre>";
|
||||
echo "<hr>";
|
||||
print "phfo(\$el_o): <pre>" . htmlentities($el_o::printHtmlFromObject($el_o, true)) . "</pre>";
|
||||
echo "<hr>";
|
||||
print "phfa(\$el_list): <pre>" . htmlentities($el_o::buildHtmlFromList($el_o_list, true)) . "</pre>";
|
||||
|
||||
echo "<hr>";
|
||||
|
||||
// self loop
|
||||
|
||||
$el_s = new Element('div', 'id-s', 'Self');
|
||||
try {
|
||||
$el_s->addSub($el_s, new Element('span', '', 'Span'));
|
||||
} catch (HtmlBuilderExcpetion $e) {
|
||||
print "E: " . $e->getMessage() . " | " . $e->getTraceAsString() . "<br>";
|
||||
}
|
||||
|
||||
// var_dump($el_s);
|
||||
print "el_s, buildHtml(): <pre>" . htmlentities($el_s->buildHtml()) . "</pre>";
|
||||
|
||||
$el_s_2 = new Element('div', 'id-s', 'Self', []);
|
||||
$el_s_2->addSub(
|
||||
new Element('span', 's-1', 's 1'),
|
||||
new Element('span', 's-2', 's 2'),
|
||||
);
|
||||
|
||||
$el_s_3 = new Element('div', 'id-3', 'ID 3');
|
||||
try {
|
||||
$el_s_3->addSub($el_s_2);
|
||||
$el_s_2->addSub($el_s_2);
|
||||
} catch (HtmlBuilderExcpetion $e) {
|
||||
print "E: " . $e->getMessage() . " | " . $e->getTraceAsString() . "<br>";
|
||||
}
|
||||
|
||||
// print "<pre>" . var_export($el_s_3, true) . "</pre>";
|
||||
|
||||
print "el_s_3, buildHtml(): <pre>" . htmlentities($el_s_3->buildHtml()) . "</pre>";
|
||||
|
||||
echo "<hr>";
|
||||
Error::resetMessages();
|
||||
try {
|
||||
$el_er = new Element('');
|
||||
} catch (HtmlBuilderExcpetion $e) {
|
||||
print "E: " . $e->getMessage() . " | " . $e->getTraceAsString() . "<br>";
|
||||
if ($e->getPrevious() !== null) {
|
||||
print "E: " . $e->getPrevious()->getMessage() . " | " . $e->getPrevious()->getTraceAsString() . "<br>";
|
||||
}
|
||||
}
|
||||
print "Errors: <pre>" . print_r(Error::getMessages(), true) . "</pre>";
|
||||
print "Warning: " . Support::printToString(Error::hasWarning()) . "<br>";
|
||||
print "Error: " . Support::printToString(Error::hasError()) . "<br>";
|
||||
Error::resetMessages();
|
||||
try {
|
||||
$el_er = new Element('123123');
|
||||
} catch (HtmlBuilderExcpetion $e) {
|
||||
print "E: " . $e->getMessage() . " | " . $e->getTraceAsString() . "<br>";
|
||||
if ($e->getPrevious() !== null) {
|
||||
print "E: " . $e->getPrevious()->getMessage() . " | " . $e->getPrevious()->getTraceAsString() . "<br>";
|
||||
}
|
||||
}
|
||||
print "Errors: <pre>" . print_r(Error::getMessages(), true) . "</pre>";
|
||||
print "Warning: " . Support::printToString(Error::hasWarning()) . "<br>";
|
||||
print "Error: " . Support::printToString(Error::hasError()) . "<br>";
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
// __END__
|
||||
83
www/admin/class_test.html_build.replace.php
Normal file
83
www/admin/class_test.html_build.replace.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php // phpcs:ignore warning
|
||||
|
||||
/**
|
||||
* @phan-file-suppress PhanTypeSuspiciousStringExpression
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
|
||||
|
||||
ob_start();
|
||||
|
||||
// basic class test file
|
||||
define('USE_DATABASE', false);
|
||||
// sample config
|
||||
require 'config.php';
|
||||
// define log file id
|
||||
$LOG_FILE_ID = 'classTest-html_build-string-replace';
|
||||
ob_end_flush();
|
||||
|
||||
use CoreLibs\Template\HtmlBuilder\StringReplace;
|
||||
|
||||
$log = new CoreLibs\Logging\Logging([
|
||||
'log_folder' => BASE . LOG,
|
||||
'log_file_id' => $LOG_FILE_ID,
|
||||
'log_per_date' => true,
|
||||
]);
|
||||
|
||||
// define a list of from to color sets for conversion test
|
||||
|
||||
$PAGE_NAME = 'TEST CLASS: HTML BUILD: STRING REPLACE';
|
||||
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 '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
||||
|
||||
$html_block = <<<HTML
|
||||
<div id="{ID}" class="{CSS}">
|
||||
{CONTENT}
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
print "<pre>" . htmlentities(StringReplace::replaceData(
|
||||
$html_block,
|
||||
[
|
||||
'ID' => 'block-id',
|
||||
'CSS' => join(',', ['blue', 'red']),
|
||||
'{CONTENT}' => 'Some content here<br>with bla bla inside'
|
||||
]
|
||||
)) . "</pre>";
|
||||
|
||||
StringReplace::loadElements(
|
||||
['foo', $html_block],
|
||||
['bar', <<<HTML
|
||||
<span id="{ID}">{CONTENT}</span>
|
||||
HTML]
|
||||
);
|
||||
|
||||
print "Get: <pre>" . htmlentities(StringReplace::getElement('bar') ?: '') . '</pre>';
|
||||
|
||||
print "Build element: <pre>" . htmlentities(StringReplace::buildElement(
|
||||
'bar',
|
||||
[
|
||||
'ID}' => 'new-id',
|
||||
'{CONTENT' => 'Test cow 日本語'
|
||||
]
|
||||
)) . '</pre>' ;
|
||||
|
||||
print "Build element as replace: <pre>" . htmlentities(StringReplace::buildElement(
|
||||
'bar',
|
||||
['
|
||||
ID}' => 'diff-id',
|
||||
'{CONTENT' => 'Test cow 日本語. More text plus'
|
||||
],
|
||||
'rpl-1'
|
||||
)) . '</pre>' ;
|
||||
|
||||
print "Get replacement: <pre>" . htmlentities(StringReplace::getReplaceBlock('rpl-1')) . "</pre>";
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
// __END__
|
||||
@@ -36,7 +36,7 @@ $log = new CoreLibs\Logging\Logging([
|
||||
'log_per_date' => true,
|
||||
]);
|
||||
|
||||
$PAGE_NAME = 'TEST CLASS: DEBUG LOGGING';
|
||||
$PAGE_NAME = 'TEST CLASS: LOGGING';
|
||||
print "<!DOCTYPE html>";
|
||||
print "<html><head><title>" . $PAGE_NAME . "</title><head>";
|
||||
print "<body>";
|
||||
@@ -44,12 +44,12 @@ print '<div><a href="class_test.php">Class Test Master</a></div>';
|
||||
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
||||
|
||||
$log->logger2Debug();
|
||||
|
||||
echo "<hr>";
|
||||
print "Level 250: " . Level::fromValue(250)->getName() . "<br>";
|
||||
print "Flag: per_run (from int): " . Flag::fromValue(2)->getName() . "<br>";
|
||||
print "Flag: per_run getName(): " . Flag::per_class->getName() . "<br>";
|
||||
print "Flag: per_run ->name: " . Flag::per_class->name . "<br>";
|
||||
print "Flag: per_run ->value: " . Flag::per_class->value . "<br>";
|
||||
print "Flag: per_class (16) (from int): " . Flag::fromValue(16)->getName() . "<br>";
|
||||
print "Flag: per_class getName(): " . Flag::per_class->getName() . "<br>";
|
||||
print "Flag: per_class ->name: " . Flag::per_class->name . "<br>";
|
||||
print "Flag: per_class ->value: " . Flag::per_class->value . "<br>";
|
||||
$log->setLogUniqueId();
|
||||
print "LogUniqId: " . $log->getLogUniqueId() . "<br>";
|
||||
|
||||
@@ -76,10 +76,19 @@ with
|
||||
and > and <
|
||||
EOM));
|
||||
$log->info('Info message', ['info' => 'log']);
|
||||
$log->notice('Notice message', ['notice' => 'log']);
|
||||
$log->warning('Warning message', ['warning' => 'log']);
|
||||
$log->error('Cannot process data', ['error' => 'log']);
|
||||
|
||||
$log->critical('Critical message', ['critical' => 'log']);
|
||||
$log->alert('Alert message', ['Alert' => 'log']);
|
||||
$log->emergency('Emergency message', ['Emergency' => 'log']);
|
||||
print "Log File: " . $log->getLogFile() . "<br>";
|
||||
|
||||
$log->setLogFlag(Flag::per_run);
|
||||
$log->debug('PER RUN', 'per run logging');
|
||||
print "Log File: " . $log->getLogFile() . "<br>";
|
||||
$log->unsetLogFlag(Flag::per_run);
|
||||
|
||||
// init empty
|
||||
unset($LOG_FILE_ID);
|
||||
$ll = new CoreLibs\Logging\Logging([
|
||||
|
||||
@@ -69,6 +69,7 @@ print "<body>";
|
||||
// key: file name, value; name
|
||||
$test_files = [
|
||||
'class_test.db.php' => 'Class Test: DB',
|
||||
'class_test.db.types.php' => 'Class Test: DB COLUMN TYPES',
|
||||
'class_test.db.single.php' => 'Class Test: DB SINGLE',
|
||||
'class_test.db.dbReturn.php' => 'Class Test: DB dbReturn',
|
||||
'class_test.convert.colors.php' => 'Class Test: CONVERT COLORS',
|
||||
@@ -80,6 +81,9 @@ $test_files = [
|
||||
'class_test.encryption.php' => 'Class Test: ENCRYPTION',
|
||||
'class_test.math.php' => 'Class Test: MATH',
|
||||
'class_test.html.php' => 'Class Test: HTML/ELEMENTS',
|
||||
'class_test.html_build.element.php' => 'Class Test: HTML BUILDER: ELEMENT',
|
||||
'class_test.html_build.block.php' => 'Class Test: HTML BUILDER: BLOCK',
|
||||
'class_test.html_build.replace.php' => 'Class Test: HTML BUILDER: STRING REPLACE',
|
||||
'class_test.email.php' => 'Class Test: EMAIL',
|
||||
'class_test.create_email.php' => 'Class Test: CREATE EMAIL',
|
||||
'class_test.uids.php' => 'Class Test: UIDS',
|
||||
|
||||
@@ -22,6 +22,7 @@ $DB_CONFIG = [
|
||||
'db_type' => 'pgsql',
|
||||
'db_encoding' => '',
|
||||
'db_ssl' => 'allow', // allow, disable, require, prefer
|
||||
// 'db_convert_type' => ['json'] // on, json, numeric, bytea
|
||||
],
|
||||
// same as above, but uses pg bouncer
|
||||
'test_pgbouncer' => [
|
||||
|
||||
@@ -222,7 +222,17 @@ if ($is_secure) {
|
||||
}
|
||||
// define the db config set name, the db config and the db schema
|
||||
define('DB_CONFIG_NAME', $SITE_CONFIG[HOST_NAME]['db_host'] ?? '');
|
||||
define('DB_CONFIG', $DB_CONFIG[DB_CONFIG_NAME] ?? []);
|
||||
define('DB_CONFIG', $DB_CONFIG[DB_CONFIG_NAME] ?? [
|
||||
'db_name' => '',
|
||||
'db_user' => '',
|
||||
'db_pass' => '',
|
||||
'db_host' => '',
|
||||
'db_port' => 5432,
|
||||
'db_schema' => '',
|
||||
'db_encoding' => '',
|
||||
'db_type' => '',
|
||||
'db_ssl' => ''
|
||||
]);
|
||||
// because we can't change constant, but we want to for db debug flag
|
||||
$GLOBALS['DB_CONFIG_SET'] = DB_CONFIG;
|
||||
// define('DB_CONFIG_TARGET', SITE_CONFIG[$HOST_NAME]['db_host_target']);
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// style sheet for the edit base interface
|
||||
define('EDIT_BASE_STYLESHEET', 'edit.css');
|
||||
|
||||
// define('SOME_ID', <SOME VALUE>);
|
||||
|
||||
/************* CONVERT *******************/
|
||||
|
||||
@@ -87,7 +87,7 @@ $l10n = new \CoreLibs\Language\L10n(
|
||||
$locale['locale'],
|
||||
$locale['domain'],
|
||||
$locale['path'],
|
||||
$locale['encoding']
|
||||
$locale['encoding'],
|
||||
);
|
||||
|
||||
// create smarty object
|
||||
|
||||
@@ -86,7 +86,7 @@ $edit_base->editBaseRun(
|
||||
BASE . INCLUDES . TEMPLATES . CONTENT_PATH,
|
||||
BASE . TEMPLATES_C,
|
||||
BASE . CACHE,
|
||||
ADMIN_STYLESHEET,
|
||||
EDIT_BASE_STYLESHEET,
|
||||
DEFAULT_ENCODING,
|
||||
LAYOUT . CSS,
|
||||
LAYOUT . JS,
|
||||
|
||||
@@ -85,6 +85,21 @@ function getScrollOffset()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper to get the correct scroll offset for opener page (from popup)
|
||||
* @return {Object} object with x/y px
|
||||
*/
|
||||
function getScrollOffsetOpener() // eslint-disable-line no-unused-vars
|
||||
{
|
||||
var left, top;
|
||||
left = opener.window.pageXOffset || (opener.document.documentElement.scrollLeft || opener.document.body.scrollLeft);
|
||||
top = opener.window.pageYOffset || (opener.document.documentElement.scrollTop || opener.document.body.scrollTop);
|
||||
return {
|
||||
left: left,
|
||||
top: top
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* centers div to current window size middle
|
||||
* @param {String} id element to center
|
||||
@@ -575,7 +590,7 @@ function actionIndicator(loc, overlay = true) // eslint-disable-line no-unused-v
|
||||
*/
|
||||
function actionIndicatorShow(loc, overlay = true)
|
||||
{
|
||||
// console.log('Indicator: SHOW [%s]', loc);
|
||||
// console.log('{Indicator}: SHOW [%s]', loc);
|
||||
if (!$('#indicator').is(':visible')) {
|
||||
if (!$('#indicator').hasClass('progress')) {
|
||||
$('#indicator').addClass('progress');
|
||||
@@ -597,7 +612,7 @@ function actionIndicatorShow(loc, overlay = true)
|
||||
*/
|
||||
function actionIndicatorHide(loc, overlay = true)
|
||||
{
|
||||
// console.log('Indicator: HIDE [%s]', loc);
|
||||
// console.log('{Indicator}: HIDE [%s]', loc);
|
||||
$('#indicator').hide();
|
||||
if (overlay === true) {
|
||||
overlayBoxHide();
|
||||
@@ -677,7 +692,7 @@ function ClearCall() // eslint-disable-line no-unused-vars
|
||||
*/
|
||||
function showActionIndicator(loc) // eslint-disable-line no-unused-vars
|
||||
{
|
||||
// console.log('Indicator: SHOW [%s]', loc);
|
||||
// console.log('{Indicator}: SHOW [%s]', loc);
|
||||
// check if indicator element exists
|
||||
if ($('#indicator').length == 0) {
|
||||
var el = document.createElement('div');
|
||||
@@ -715,7 +730,7 @@ function showActionIndicator(loc) // eslint-disable-line no-unused-vars
|
||||
*/
|
||||
function hideActionIndicator(loc) // eslint-disable-line no-unused-vars
|
||||
{
|
||||
// console.log('Indicator: HIDE [%s]', loc);
|
||||
// console.log('{Indicator}: HIDE [%s]', loc);
|
||||
// check if indicator is visible
|
||||
if ($('#indicator').is(':visible')) {
|
||||
// hide indicator
|
||||
@@ -965,6 +980,44 @@ function scssel(_element, rcss, acss) // eslint-disable-line no-unused-vars
|
||||
*/
|
||||
function phfo(tree)
|
||||
{
|
||||
let name_elements = [
|
||||
'button',
|
||||
'fieldset',
|
||||
'form',
|
||||
'iframe',
|
||||
'input',
|
||||
'map',
|
||||
'meta',
|
||||
'object',
|
||||
'output',
|
||||
'param',
|
||||
'select',
|
||||
'textarea',
|
||||
];
|
||||
let skip_options = [
|
||||
'id',
|
||||
'name',
|
||||
'class',
|
||||
];
|
||||
let no_close = [
|
||||
'input',
|
||||
'br',
|
||||
'img',
|
||||
'hr',
|
||||
'area',
|
||||
'col',
|
||||
'keygen',
|
||||
'wbr',
|
||||
'track',
|
||||
'source',
|
||||
'param',
|
||||
'command',
|
||||
// only in header
|
||||
'base',
|
||||
'meta',
|
||||
'link',
|
||||
'embed',
|
||||
];
|
||||
// holds the elements
|
||||
var content = [];
|
||||
// main part line
|
||||
@@ -974,7 +1027,7 @@ function phfo(tree)
|
||||
if (tree.id) {
|
||||
line += ' id="' + tree.id + '"';
|
||||
// if anything input (input, textarea, select then add name too)
|
||||
if (['input', 'textarea', 'select', 'button'].includes(tree.tag)) {
|
||||
if (name_elements.includes(tree.tag)) {
|
||||
line += ' name="' + (tree.name ? tree.name : tree.id) + '"';
|
||||
}
|
||||
}
|
||||
@@ -992,7 +1045,7 @@ function phfo(tree)
|
||||
if (isObject(tree.options)) {
|
||||
// ignores id, name, class as key
|
||||
for (const [key, item] of Object.entries(tree.options)) {
|
||||
if (!['id', 'name', 'class'].includes(key)) {
|
||||
if (!skip_options.includes(key)) {
|
||||
line += ' ' + key + '="' + item + '"';
|
||||
}
|
||||
}
|
||||
@@ -1016,9 +1069,7 @@ function phfo(tree)
|
||||
}
|
||||
// if not input, image or br, then close
|
||||
if (
|
||||
tree.tag != 'input' ||
|
||||
tree.tag != 'img' ||
|
||||
tree.tag != 'br'
|
||||
!no_close.includes(tree.tag)
|
||||
) {
|
||||
content.push('</' + tree.tag + '>');
|
||||
}
|
||||
|
||||
@@ -231,8 +231,6 @@ class Login
|
||||
) {
|
||||
// attach db class
|
||||
$this->db = $db;
|
||||
// log login data for this class only
|
||||
$log->setLogFlag(\CoreLibs\Logging\Logger\Flag::per_class);
|
||||
// attach logger
|
||||
$this->log = $log;
|
||||
// attach session class
|
||||
@@ -1060,9 +1058,9 @@ class Login
|
||||
];
|
||||
// set the default unit
|
||||
if ($res['edit_default']) {
|
||||
$_SESSION['UNIT_DEFAULT'] = $res['edit_access_id'];
|
||||
$_SESSION['UNIT_DEFAULT'] = (int)$res['edit_access_id'];
|
||||
}
|
||||
$_SESSION['UNIT_UID'][$res['uid']] = $res['edit_access_id'];
|
||||
$_SESSION['UNIT_UID'][$res['uid']] = (int)$res['edit_access_id'];
|
||||
// sub arrays for simple access
|
||||
array_push($eauid, $res['edit_access_id']);
|
||||
$unit_acl[$res['edit_access_id']] = $res['level'];
|
||||
@@ -1148,18 +1146,18 @@ class Login
|
||||
// user > page > group
|
||||
// group ACL 0
|
||||
if ($_SESSION['GROUP_ACL_LEVEL'] != -1) {
|
||||
$this->acl['base'] = $_SESSION['GROUP_ACL_LEVEL'];
|
||||
$this->acl['base'] = (int)$_SESSION['GROUP_ACL_LEVEL'];
|
||||
}
|
||||
// page ACL 1
|
||||
if (
|
||||
isset($_SESSION['PAGES_ACL_LEVEL'][$this->page_name]) &&
|
||||
$_SESSION['PAGES_ACL_LEVEL'][$this->page_name] != -1
|
||||
) {
|
||||
$this->acl['base'] = $_SESSION['PAGES_ACL_LEVEL'][$this->page_name];
|
||||
$this->acl['base'] = (int)$_SESSION['PAGES_ACL_LEVEL'][$this->page_name];
|
||||
}
|
||||
// user ACL 2
|
||||
if ($_SESSION['USER_ACL_LEVEL'] != -1) {
|
||||
$this->acl['base'] = $_SESSION['USER_ACL_LEVEL'];
|
||||
$this->acl['base'] = (int)$_SESSION['USER_ACL_LEVEL'];
|
||||
}
|
||||
}
|
||||
$_SESSION['BASE_ACL_LEVEL'] = $this->acl['base'];
|
||||
@@ -2347,7 +2345,10 @@ HTML;
|
||||
is_array($_SESSION['UNIT']) &&
|
||||
!array_key_exists($edit_access_id, $_SESSION['UNIT'])
|
||||
) {
|
||||
return $_SESSION['UNIT_DEFAULT'] ?? null;
|
||||
$edit_access_id = null;
|
||||
if (is_numeric($_SESSION['UNIT_DEFAULT'])) {
|
||||
$edit_access_id = (int)$_SESSION['UNIT_DEFAULT'];
|
||||
}
|
||||
}
|
||||
return $edit_access_id;
|
||||
}
|
||||
|
||||
@@ -164,6 +164,10 @@ class Backend
|
||||
);
|
||||
}
|
||||
$this->default_acl = $set_default_acl_level ?? DEFAULT_ACL_LEVEL;
|
||||
// if negative or larger than 100, reset to 0
|
||||
if ($this->default_acl < 0 || $this->default_acl > 100) {
|
||||
$this->default_acl = 0;
|
||||
}
|
||||
|
||||
// queue key
|
||||
if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action)) {
|
||||
|
||||
@@ -41,7 +41,8 @@ class EditBase
|
||||
/**
|
||||
* construct form generator
|
||||
*
|
||||
* @param array<mixed> $db_config db config array, mandatory
|
||||
* phpcs:ignore
|
||||
* @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[]} $db_config db config array, mandatory
|
||||
* @param \CoreLibs\Logging\Logging $log Logging class, null auto set
|
||||
* @param \CoreLibs\Language\L10n $l10n l10n language class, null auto set
|
||||
* @param \CoreLibs\ACL\Login $login login class for ACL settings
|
||||
|
||||
@@ -452,6 +452,31 @@ class DateTime
|
||||
return $days;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a weekend day (sat/sun) is in the given date range
|
||||
* Can have time too, but is not needed
|
||||
*
|
||||
* @param string $start_date Y-m-d
|
||||
* @param string $end_date Y-m-d
|
||||
* @return bool True for has weekend, False for has not
|
||||
*/
|
||||
public static function dateRangeHasWeekend(
|
||||
string $start_date,
|
||||
string $end_date,
|
||||
): bool {
|
||||
$dd_start = new \DateTime($start_date);
|
||||
$dd_end = new \DateTime($end_date);
|
||||
if (
|
||||
// starts with a weekend
|
||||
$dd_start->format('N') >= 6 ||
|
||||
// start day plus diff will be 6 and so fall into a weekend
|
||||
((int)$dd_start->format('w') + $dd_start->diff($dd_end)->days) >= 6
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -54,7 +54,8 @@ class ArrayIO extends \CoreLibs\DB\IO
|
||||
* constructor for the array io class, set the
|
||||
* primary key name automatically (from array)
|
||||
*
|
||||
* @param array<mixed> $db_config db connection config
|
||||
* phpcs:ignore
|
||||
* @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[]} $db_config db connection config
|
||||
* @param array<mixed> $table_array table array config
|
||||
* @param string $table_name table name string
|
||||
* @param \CoreLibs\Logging\Logging $log Logging class
|
||||
@@ -587,7 +588,7 @@ class ArrayIO extends \CoreLibs\DB\IO
|
||||
// get it at the end, cause now we can be more sure of no double IDs, etc
|
||||
reset($this->table_array);
|
||||
// create select part & addition FK part
|
||||
foreach ($this->table_array as $column => $data_array) {
|
||||
foreach (array_keys($this->table_array) as $column) {
|
||||
// check FK ...
|
||||
if (
|
||||
isset($this->table_array[$column]['fk']) &&
|
||||
|
||||
@@ -259,6 +259,8 @@ namespace CoreLibs\DB;
|
||||
use CoreLibs\Create\Hash;
|
||||
use CoreLibs\Debug\Support;
|
||||
use CoreLibs\Create\Uids;
|
||||
use CoreLibs\Convert\Json;
|
||||
use CoreLibs\DB\Options\Convert;
|
||||
|
||||
// below no ignore is needed if we want to use PgSql interface checks with PHP 8.0
|
||||
// as main system. Currently all @var sets are written as object
|
||||
@@ -307,7 +309,7 @@ class IO
|
||||
// basic vars
|
||||
// the dbh handler, if disconnected by command is null, bool:false on error,
|
||||
/** @var \PgSql\Connection|false|null */
|
||||
private \PgSql\Connection|false|null $dbh;
|
||||
private \PgSql\Connection|false|null $dbh = null;
|
||||
/** @var bool DB_DEBUG ... (if set prints out debug msgs) */
|
||||
private bool $db_debug = false;
|
||||
/** @var string the DB connected to */
|
||||
@@ -328,6 +330,17 @@ class IO
|
||||
private string $db_type;
|
||||
/** @var string ssl flag (for postgres only), disable, allow, prefer, require */
|
||||
private string $db_ssl;
|
||||
/** @var array<string> flag for converting types from settings */
|
||||
private array $db_convert_type = [];
|
||||
// convert type settings
|
||||
// 0: OFF (CONVERT_OFF)
|
||||
// >0: ON
|
||||
// 1: convert intN/bool (CONVERT_ON)
|
||||
// 2: convert json/jsonb to array (CONVERT_JSON)
|
||||
// 4: convert numeric/floatN to float (CONVERT_NUMERIC)
|
||||
// 8: convert bytea to string data (CONVERT_BYTEA)
|
||||
/** @var int type settings as bit mask, 0 for off, anything >2 will aways set 1 too */
|
||||
private int $convert_type = Convert::off->value;
|
||||
// FOR BELOW: (This should be private and only readable through some method)
|
||||
// cursor array for cached readings
|
||||
/** @var array<string,mixed> extended cursoers string index with content */
|
||||
@@ -343,6 +356,8 @@ class IO
|
||||
private array $field_names = [];
|
||||
/** @var array<string> field type names */
|
||||
private array $field_types = [];
|
||||
/** @var array<string,string> field name to type */
|
||||
private array $field_name_types = [];
|
||||
/** @var array<mixed> always return as array, even if only one */
|
||||
private array $insert_id_arr = [];
|
||||
/** @var string primary key name for insert recovery from insert_id_arr */
|
||||
@@ -392,8 +407,11 @@ class IO
|
||||
public \CoreLibs\Logging\Logging $log;
|
||||
|
||||
/**
|
||||
* main DB concstructor with auto connection to DB and failure set on failed connection
|
||||
* @param array<mixed> $db_config DB configuration array
|
||||
* main DB concstructor with auto connection to DB
|
||||
* and failure set on failed connection
|
||||
*
|
||||
* phpcs:ignore
|
||||
* @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[]} $db_config DB configuration array
|
||||
* @param \CoreLibs\Logging\Logging $log Logging class
|
||||
*/
|
||||
public function __construct(
|
||||
@@ -402,17 +420,8 @@ class IO
|
||||
) {
|
||||
// attach logger
|
||||
$this->log = $log;
|
||||
// sets the names (for connect/reconnect)
|
||||
$this->db_name = $db_config['db_name'] ?? '';
|
||||
$this->db_user = $db_config['db_user'] ?? '';
|
||||
$this->db_pwd = $db_config['db_pass'] ?? '';
|
||||
$this->db_host = $db_config['db_host'] ?? '';
|
||||
$this->db_port = !empty($db_config['db_port']) ? (int)$db_config['db_port'] : 5432;
|
||||
// do not set to 'public' if not set, because the default is already public
|
||||
$this->db_schema = !empty($db_config['db_schema']) ? $db_config['db_schema'] : '';
|
||||
$this->db_encoding = !empty($db_config['db_encoding']) ? $db_config['db_encoding'] : '';
|
||||
$this->db_type = $db_config['db_type'] ?? '';
|
||||
$this->db_ssl = !empty($db_config['db_ssl']) ? $db_config['db_ssl'] : 'allow';
|
||||
// set the config options
|
||||
$this->__setConfigOptions($db_config);
|
||||
// set debug, either via global var, or from config, else set to false
|
||||
$this->dbSetDebug(
|
||||
// set if logging level is Debug
|
||||
@@ -497,6 +506,84 @@ class IO
|
||||
// PRIVATE METHODS
|
||||
// *************************************************************
|
||||
|
||||
/**
|
||||
* Setup DB config and options
|
||||
*
|
||||
* phpcs:ignore
|
||||
* @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[]} $db_config
|
||||
* @return bool
|
||||
*/
|
||||
private function __setConfigOptions(array $db_config): bool
|
||||
{
|
||||
// sets the names (for connect/reconnect)
|
||||
$this->db_name = $db_config['db_name'] ?? '';
|
||||
$this->db_user = $db_config['db_user'] ?? '';
|
||||
$this->db_pwd = $db_config['db_pass'] ?? '';
|
||||
$this->db_host = $db_config['db_host'] ?? '';
|
||||
// port
|
||||
$this->db_port = !empty($db_config['db_port']) ?
|
||||
(int)$db_config['db_port'] : 5432;
|
||||
if ($this->db_port < 0 || $this->db_port > 65535) {
|
||||
$this->db_port = 5432;
|
||||
}
|
||||
// do not set to 'public' if not set, because the default is already public
|
||||
$this->db_schema = !empty($db_config['db_schema']) ?
|
||||
$db_config['db_schema'] : '';
|
||||
$this->db_encoding = !empty($db_config['db_encoding']) ?
|
||||
$db_config['db_encoding'] : '';
|
||||
// db type
|
||||
$this->db_type = $db_config['db_type'] ?? '';
|
||||
if (!in_array($this->db_type, ['pgsql'])) {
|
||||
$this->db_type = 'pgsql';
|
||||
}
|
||||
// ssl setting
|
||||
$this->db_ssl = !empty($db_config['db_ssl']) ?
|
||||
$db_config['db_ssl'] : 'allow';
|
||||
if (!in_array($this->db_ssl, ['allow', 'disable', 'require', 'prefer'])) {
|
||||
$this->db_ssl = 'allow';
|
||||
}
|
||||
// trigger convert type
|
||||
// ['on', 'json', 'numeric', 'bytea'] allowed
|
||||
// if on is not set but other valid than on is assumed
|
||||
foreach ($db_config['db_convert_type'] ?? [] as $db_convert_type) {
|
||||
if (!in_array($db_convert_type, ['on', 'json', 'numeric', 'bytea'])) {
|
||||
continue;
|
||||
}
|
||||
$this->db_convert_type[] = $db_convert_type;
|
||||
$this->__setConvertType($db_convert_type);
|
||||
}
|
||||
|
||||
// return status true: ok, false: options error
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the convert bit flags
|
||||
*
|
||||
* @param string $db_convert_type One of 'on', 'json', 'numeric', 'bytea'
|
||||
* @return void
|
||||
*/
|
||||
private function __setConvertType(string $db_convert_type): void
|
||||
{
|
||||
switch ($db_convert_type) {
|
||||
case 'on':
|
||||
$this->convert_type |= Convert::on->value;
|
||||
break;
|
||||
case 'json':
|
||||
$this->convert_type |= Convert::on->value;
|
||||
$this->convert_type |= Convert::json->value;
|
||||
break;
|
||||
case 'numeric':
|
||||
$this->convert_type |= Convert::on->value;
|
||||
$this->convert_type |= Convert::numeric->value;
|
||||
break;
|
||||
case 'bytea':
|
||||
$this->convert_type |= Convert::on->value;
|
||||
$this->convert_type |= Convert::bytea->value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* based on $this->db_type
|
||||
* here we need to load the db pgsql include one
|
||||
@@ -525,8 +612,10 @@ class IO
|
||||
}
|
||||
|
||||
/**
|
||||
* internal connection function. Used to connect to the DB if there is no connection done yet.
|
||||
* internal connection function.
|
||||
* Used to connect to the DB if there is no connection done yet.
|
||||
* Called before any execute
|
||||
*
|
||||
* @return bool true on successfull connect, false if failed
|
||||
*/
|
||||
private function __connectToDB(): bool
|
||||
@@ -571,6 +660,7 @@ class IO
|
||||
/**
|
||||
* close db connection
|
||||
* only used by the deconstructor
|
||||
*
|
||||
* @return void has no return
|
||||
*/
|
||||
private function __closeDB(): void
|
||||
@@ -585,6 +675,7 @@ class IO
|
||||
* checks if query is a SELECT, SHOW or WITH, if not error, 0 return
|
||||
* NOTE:
|
||||
* Query needs to start with SELECT, SHOW or WITH
|
||||
*
|
||||
* @param string $query query to check
|
||||
* @return bool true if matching, false if not
|
||||
*/
|
||||
@@ -602,6 +693,7 @@ class IO
|
||||
* if pure is set to true, only when INSERT is set will return true
|
||||
* NOTE:
|
||||
* Queries need to start with INSERT, UPDATE, DELETE. Anything else is ignored
|
||||
*
|
||||
* @param string $query query to check
|
||||
* @param bool $pure pure check (only insert), default false
|
||||
* @return bool true if matching, false if not
|
||||
@@ -620,6 +712,7 @@ class IO
|
||||
/**
|
||||
* returns true if the query starts with UPDATE
|
||||
* query NEEDS to start with UPDATE
|
||||
*
|
||||
* @param string $query query to check
|
||||
* @return bool returns true if the query starts with UPDATE
|
||||
*/
|
||||
@@ -635,6 +728,7 @@ class IO
|
||||
* internal funktion that creates the array
|
||||
* NOTE:
|
||||
* used in db_dump_data only
|
||||
*
|
||||
* @param array<mixed> $array array to print
|
||||
* @return string string with printed and formated array
|
||||
*/
|
||||
@@ -698,15 +792,46 @@ class IO
|
||||
. \CoreLibs\Debug\Support::prAr($error_data)
|
||||
. ']';
|
||||
}
|
||||
// we need to trace back where the first non class call was done
|
||||
// add this stack trace to the context
|
||||
$call_stack = [];
|
||||
foreach (array_reverse(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)) as $call_trace) {
|
||||
if (
|
||||
!empty($call_trace['file']) &&
|
||||
str_ends_with($call_trace['file'], '/DB/IO.php')
|
||||
) {
|
||||
break;
|
||||
}
|
||||
$call_stack[] =
|
||||
($call_trace['file'] ?? 'n/f') . ':'
|
||||
. ($call_trace['line'] ?? '-') . ':'
|
||||
. (!empty($call_trace['class']) ? $call_trace['class'] . '->' : '')
|
||||
. $call_trace['function'];
|
||||
}
|
||||
$context = [
|
||||
'call_trace' => array_reverse($call_stack)
|
||||
];
|
||||
switch ($id) {
|
||||
case 'DB_ERROR':
|
||||
$this->log->error($debug_id . ' :' . $prefix . $error_string);
|
||||
$this->log->error(
|
||||
$prefix . $error_string,
|
||||
$context
|
||||
);
|
||||
break;
|
||||
case 'DB_WARNING':
|
||||
$this->log->warning($debug_id . ' :' . $prefix . $error_string);
|
||||
$this->log->warning(
|
||||
$prefix . $error_string,
|
||||
$context
|
||||
);
|
||||
break;
|
||||
default:
|
||||
$this->log->debug($debug_id, $error_string, $prefix);
|
||||
// used named arguments so we can easy change the order of debug
|
||||
$this->log->debug(
|
||||
group_id: $debug_id,
|
||||
message: $error_string,
|
||||
prefix: $prefix,
|
||||
context: $context
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -740,6 +865,7 @@ class IO
|
||||
* Is called on base queries to reset error before each run
|
||||
* Recent error history can be checked with
|
||||
* dbGetErrorHistory or dbGetWarningHistory
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function __dbErrorReset(): void
|
||||
@@ -751,6 +877,7 @@ class IO
|
||||
|
||||
/**
|
||||
* Check if there is a cursor and write this cursors error info
|
||||
*
|
||||
* @param \PgSql\Result|false $cursor current cursor for pg_result_error,
|
||||
* pg_last_error too, but pg_result_error
|
||||
* is more accurate (PgSql\Result)
|
||||
@@ -811,6 +938,7 @@ class IO
|
||||
* error level, source as :: separated string
|
||||
* additional pg error message if exists and optional msg given on error call
|
||||
* all error messages are grouped by error_history_id set when errors are reset
|
||||
*
|
||||
* @param string $level
|
||||
* @param string $error_id
|
||||
* @param string $where_called
|
||||
@@ -841,6 +969,7 @@ class IO
|
||||
|
||||
/**
|
||||
* write an error
|
||||
*
|
||||
* @param integer $error_id Any Error ID, used in debug message string
|
||||
* @param \PgSql\Result|false $cursor Optional cursor, passed on to preprocessor
|
||||
* @param string $msg optional message added to debug
|
||||
@@ -868,6 +997,7 @@ class IO
|
||||
|
||||
/**
|
||||
* write a warning
|
||||
*
|
||||
* @param integer $warning_id Integer warning id added to debug
|
||||
* @param \PgSql\Result|false $cursor Optional cursor, passed on to preprocessor
|
||||
* @param string $msg optional message added to debug
|
||||
@@ -895,6 +1025,7 @@ class IO
|
||||
/**
|
||||
* if there is the 'to_encoding' var set,
|
||||
* and the field is in the wrong encoding converts it to the target
|
||||
*
|
||||
* @param array<mixed>|false $row Array from fetch_row
|
||||
* @return array<mixed>|false Convert fetch_row array, or false
|
||||
*/
|
||||
@@ -903,11 +1034,8 @@ class IO
|
||||
if (is_bool($row)) {
|
||||
return false;
|
||||
}
|
||||
// only do if array, else pass through row (can be false)
|
||||
if (
|
||||
!is_array($row) ||
|
||||
empty($this->to_encoding)
|
||||
) {
|
||||
// do not do anything if no to encoding is set
|
||||
if (empty($this->to_encoding)) {
|
||||
return $row;
|
||||
}
|
||||
// go through each row and convert the encoding if needed
|
||||
@@ -929,8 +1057,70 @@ class IO
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert column content to the type in the name/pos field
|
||||
* Note that on default it will only convert types that 100% map to PHP
|
||||
* - intN
|
||||
* - bool
|
||||
* everything else will stay string.
|
||||
* Fruther flags in the conert_type allow to convert:
|
||||
* - json/jsonb to array
|
||||
* - bytea to string
|
||||
* Dangerous convert:
|
||||
* - numeric/float to float (precision can be lost)
|
||||
*
|
||||
* @param array<mixed>|false $row
|
||||
* @return array<mixed>|false
|
||||
*/
|
||||
private function __dbConvertType(array|false $row): array|false
|
||||
{
|
||||
if (is_bool($row)) {
|
||||
return false;
|
||||
}
|
||||
// if convert type is not turned on
|
||||
if (!$this->convert_type) {
|
||||
return $row;
|
||||
}
|
||||
foreach ($row as $key => $value) {
|
||||
// always bool/int
|
||||
if (
|
||||
$this->dbGetFieldType($key) != 'interval' &&
|
||||
str_starts_with($this->dbGetFieldType($key) ?: '', 'int')
|
||||
) {
|
||||
$row[$key] = (int)$value;
|
||||
}
|
||||
if ($this->dbGetFieldType($key) == 'bool') {
|
||||
$row[$key] = $this->dbBoolean($value);
|
||||
}
|
||||
if (
|
||||
$this->convert_type & Convert::json->value &&
|
||||
str_starts_with($this->dbGetFieldType($key) ?: '', 'json')
|
||||
) {
|
||||
$row[$key] = Json::jsonConvertToArray($value);
|
||||
}
|
||||
if (
|
||||
$this->convert_type & Convert::numeric->value &&
|
||||
(
|
||||
str_starts_with($this->dbGetFieldType($key) ?: '', 'numeric') ||
|
||||
str_starts_with($this->dbGetFieldType($key) ?: '', 'float')
|
||||
// $this->dbGetFieldType($key) == 'real'
|
||||
)
|
||||
) {
|
||||
$row[$key] = (float)$value;
|
||||
}
|
||||
if (
|
||||
$this->convert_type & Convert::bytea->value &&
|
||||
$this->dbGetFieldType($key) == 'bytea'
|
||||
) {
|
||||
$row[$key] = $this->dbUnescapeBytea($value);
|
||||
}
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* for debug purpose replaces $1, $2, etc with actual data
|
||||
*
|
||||
* @param string $query Query to replace values in
|
||||
* @param array<mixed> $data The data array
|
||||
* @return string string of query with data inside
|
||||
@@ -964,7 +1154,9 @@ class IO
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts schema and table from the query, if no schema returns just empty string
|
||||
* extracts schema and table from the query,
|
||||
* if no schema returns just empty string
|
||||
*
|
||||
* @param string $query insert/select/update/delete query
|
||||
* @return array<mixed> array with schema and table
|
||||
*/
|
||||
@@ -1003,6 +1195,7 @@ class IO
|
||||
/**
|
||||
* check if there is another query running, or do we hang after a
|
||||
* PHP error
|
||||
*
|
||||
* @param integer $timeout_seconds For complex timeout waits, default 3 seconds
|
||||
* @return bool True for connection OK, else false
|
||||
*/
|
||||
@@ -1021,6 +1214,7 @@ class IO
|
||||
/**
|
||||
* dbReturn
|
||||
* Read data from previous written data cache
|
||||
*
|
||||
* @param string $query_hash The hash for the current query
|
||||
* @param bool $assoc_only Only return assoc value (key named)
|
||||
* @return array<mixed> Current position query data from cache
|
||||
@@ -1099,6 +1293,7 @@ class IO
|
||||
* - checks for insert if returning is set/pk name
|
||||
* - sets internal hash for query
|
||||
* - checks multiple call count
|
||||
*
|
||||
* @param string $query Query string
|
||||
* @param array<mixed> $params Query params, needed for hash creation
|
||||
* @param string $pk_name primary key
|
||||
@@ -1183,7 +1378,7 @@ class IO
|
||||
) {
|
||||
$this->returning_id = true;
|
||||
}
|
||||
// $this->debug('DB IO', 'Q: '.$this->query.', RETURN: '.$this->returning_id);
|
||||
// $this->debug('DB IO', 'Q: ' . $this->query . ', RETURN: ' . $this->returning_id);
|
||||
// for DEBUG, only on first time ;)
|
||||
$this->__dbDebug(
|
||||
'db',
|
||||
@@ -1229,6 +1424,7 @@ class IO
|
||||
|
||||
/**
|
||||
* runs post execute for rows affected, field names, inserted primary key, etc
|
||||
*
|
||||
* @return bool true on success or false if an error occured
|
||||
*/
|
||||
private function __dbPostExec(): bool
|
||||
@@ -1254,11 +1450,18 @@ class IO
|
||||
$this->field_names = [];
|
||||
for ($i = 0; $i < $this->num_fields; $i++) {
|
||||
$this->field_names[] = $this->db_functions->__dbFieldName($this->cursor, $i) ?: '';
|
||||
// if (!empty($this->field_names[$i]))
|
||||
// $this->field_name_types[$this->field_names[$i]] = null;
|
||||
}
|
||||
$this->field_types = [];
|
||||
for ($i = 0; $i < $this->num_fields; $i++) {
|
||||
$this->field_types[] = $this->db_functions->__dbFieldType($this->cursor, $i) ?: '';
|
||||
}
|
||||
// combined array
|
||||
$this->field_name_types = array_combine(
|
||||
$this->field_names,
|
||||
$this->field_types
|
||||
);
|
||||
} elseif ($this->__checkQueryForInsert($this->query)) {
|
||||
// if not select do here
|
||||
// count affected rows
|
||||
@@ -1292,6 +1495,7 @@ class IO
|
||||
* insert_id_ext [DEPRECATED, all in insert_id_arr]
|
||||
* - holds all returning as array
|
||||
* TODO: Only use insert_id_arr and use functions to get ok array or single
|
||||
*
|
||||
* @param bool $returning_id
|
||||
* @param string $query
|
||||
* @param string|null $pk_name
|
||||
@@ -1384,6 +1588,7 @@ class IO
|
||||
* closes the db_connection
|
||||
* normally this is not used, as the class deconstructor closes
|
||||
* the connection down
|
||||
*
|
||||
* @return void has no return
|
||||
*/
|
||||
public function dbClose(): void
|
||||
@@ -1405,6 +1610,7 @@ class IO
|
||||
* returns the db init error
|
||||
* if failed to connect it is set to false
|
||||
* else true
|
||||
*
|
||||
* @return bool Connection status
|
||||
*/
|
||||
public function dbGetConnectionStatus(): bool
|
||||
@@ -1414,6 +1620,7 @@ class IO
|
||||
|
||||
/**
|
||||
* get certain settings like username, db name
|
||||
*
|
||||
* @param string $name what setting to query
|
||||
* @return int|string|bool setting value, if not allowed name return false
|
||||
*/
|
||||
@@ -1458,6 +1665,7 @@ class IO
|
||||
|
||||
/**
|
||||
* prints out status info from the connected DB (might be usefull for debug stuff)
|
||||
*
|
||||
* @param bool $log Show db connection info, default true
|
||||
* if set to false won't write to error_msg var
|
||||
* @param bool $strip Strip all HTML
|
||||
@@ -1497,6 +1705,7 @@ class IO
|
||||
|
||||
/**
|
||||
* Server version as integer value
|
||||
*
|
||||
* @return integer Version as integer
|
||||
*/
|
||||
public function dbVersionNumeric(): int
|
||||
@@ -1506,6 +1715,7 @@ class IO
|
||||
|
||||
/**
|
||||
* return current database version (server side) as string
|
||||
*
|
||||
* @return string database version as string
|
||||
*/
|
||||
public function dbVersion(): string
|
||||
@@ -1515,6 +1725,7 @@ class IO
|
||||
|
||||
/**
|
||||
* extended version info, can access all additional information data
|
||||
*
|
||||
* @param string $parameter Array parameter name, if not valid returns
|
||||
* empty string
|
||||
* @param bool $strip Strip extended server info string, default true
|
||||
@@ -1528,6 +1739,7 @@ class IO
|
||||
|
||||
/**
|
||||
* All possible parameter names for dbVersionInfo
|
||||
*
|
||||
* @return array<mixed> List of all parameter names
|
||||
*/
|
||||
public function dbVersionInfoParameters(): array
|
||||
@@ -1537,6 +1749,7 @@ class IO
|
||||
|
||||
/**
|
||||
* returns bool true or false if the string matches the database version
|
||||
*
|
||||
* @param string $compare string to match in type =X.Y, >X.Y, <X.Y, <=X.Y, >=X.Y
|
||||
* @return bool true for ok, false on not ok
|
||||
*/
|
||||
@@ -1605,6 +1818,7 @@ class IO
|
||||
|
||||
/**
|
||||
* dumps ALL data for this query, OR if no query given all in cursor_ext array
|
||||
*
|
||||
* @param string $query Query, if given, only from this quey (if found)
|
||||
* else current cursor
|
||||
* @return string Formated string with all the data in the array
|
||||
@@ -1632,6 +1846,7 @@ class IO
|
||||
|
||||
/**
|
||||
* neutral function to escape a string for DB writing
|
||||
*
|
||||
* @param string|int|float|bool $string string to escape
|
||||
* @return string escaped string
|
||||
*/
|
||||
@@ -1643,6 +1858,7 @@ class IO
|
||||
/**
|
||||
* neutral function to escape a string for DB writing
|
||||
* this one adds '' quotes around the string
|
||||
*
|
||||
* @param string|int|float|bool $string string to escape
|
||||
* @return string escaped string
|
||||
*/
|
||||
@@ -1653,6 +1869,7 @@ class IO
|
||||
|
||||
/**
|
||||
* string escape for column and table names
|
||||
*
|
||||
* @param string $string string to escape
|
||||
* @return string escaped string
|
||||
*/
|
||||
@@ -1663,6 +1880,7 @@ class IO
|
||||
|
||||
/**
|
||||
* escape data for writing to bytea type column field
|
||||
*
|
||||
* @param string $data data to escape to bytea
|
||||
* @return string escaped bytea string
|
||||
*/
|
||||
@@ -1673,6 +1891,7 @@ class IO
|
||||
|
||||
/**
|
||||
* unescape bytea data back to normal binrary data
|
||||
*
|
||||
* @param string $bytea bytea data stream
|
||||
* @return string binary data string
|
||||
*/
|
||||
@@ -1683,6 +1902,7 @@ class IO
|
||||
|
||||
/**
|
||||
* clear up any data for valid DB insert
|
||||
*
|
||||
* @param int|float|string|bool|null $value to escape data
|
||||
* @param string $kbn escape trigger type
|
||||
* @return string escaped value
|
||||
@@ -1749,10 +1969,11 @@ class IO
|
||||
* if the input is a single char 't' or 'f
|
||||
* it will return the bool value instead
|
||||
* also converts smallint 1/0 to true false
|
||||
*
|
||||
* @param string|bool|int $string 't' / 'f' or any string, or bool true/false
|
||||
* @param bool $rev do reverse (bool to string)
|
||||
* @return bool|string correct php bool true/false
|
||||
* or postgresql 't'/'f'
|
||||
* @return bool|string [default=false]: corretc postgresql -> php,
|
||||
* true: convert php to postgresql
|
||||
*/
|
||||
public function dbBoolean(string|bool|int $string, bool $rev = false): bool|string
|
||||
{
|
||||
@@ -1784,6 +2005,7 @@ class IO
|
||||
|
||||
/**
|
||||
* only for postgres. pretty formats an age or datetime difference string
|
||||
*
|
||||
* @param string $interval Age or interval/datetime difference
|
||||
* @param bool $show_micro micro on off (default false)
|
||||
* @return string Y/M/D/h/m/s formatted string (like timeStringFormat)
|
||||
@@ -1835,9 +2057,11 @@ class IO
|
||||
/**
|
||||
* this is only needed for Postgresql. Converts postgresql arrays to PHP
|
||||
* Recommended to rather user 'array_to_json' instead and convet JSON in PHP
|
||||
* or if ARRAY_AGG -> JSONB_AGG
|
||||
*
|
||||
* @param string $text input text to parse to an array
|
||||
* @return array<mixed> PHP array of the parsed data
|
||||
* @deprecated Recommended to use 'array_to_json' in PostgreSQL instead
|
||||
* @deprecated Recommended to use 'array_to_json/jsonb_agg' in PostgreSQL instead
|
||||
*/
|
||||
public function dbArrayParse(string $text): array
|
||||
{
|
||||
@@ -1851,6 +2075,7 @@ class IO
|
||||
|
||||
/**
|
||||
* returns an array of the table with columns and values. FALSE on no table found
|
||||
*
|
||||
* @param string $table table name
|
||||
* @param string $schema optional schema name
|
||||
* @return array<mixed>|false array of table data, false on error (table not found)
|
||||
@@ -1954,6 +2179,10 @@ class IO
|
||||
'data' => [],
|
||||
// field names as array
|
||||
'field_names' => [],
|
||||
// field types as array (pos in field names is pos here)
|
||||
'field_types' => [],
|
||||
// name to type assoc array (from field names and field types)
|
||||
'field_name_types' => [],
|
||||
// number of fields (field names)
|
||||
'num_fields' => 0,
|
||||
// number of rows that will be maximum returned
|
||||
@@ -2117,6 +2346,12 @@ class IO
|
||||
);
|
||||
}
|
||||
$this->field_types = $this->cursor_ext[$query_hash]['field_types'];
|
||||
// combined name => type
|
||||
$this->cursor_ext[$query_hash]['field_name_types'] = array_combine(
|
||||
$this->field_names,
|
||||
$this->field_types
|
||||
);
|
||||
$this->field_name_types = $this->cursor_ext[$query_hash]['field_name_types'];
|
||||
// reset first call var
|
||||
$first_call = false;
|
||||
// reset the internal pos counter
|
||||
@@ -2139,9 +2374,11 @@ class IO
|
||||
!is_int($this->cursor_ext[$query_hash]['cursor'])
|
||||
) {
|
||||
$return = $this->__dbConvertEncoding(
|
||||
$this->db_functions->__dbFetchArray(
|
||||
$this->cursor_ext[$query_hash]['cursor'],
|
||||
$this->db_functions->__dbResultType($assoc_only)
|
||||
$this->__dbConvertType(
|
||||
$this->db_functions->__dbFetchArray(
|
||||
$this->cursor_ext[$query_hash]['cursor'],
|
||||
$this->db_functions->__dbResultType($assoc_only)
|
||||
)
|
||||
)
|
||||
);
|
||||
$this->cursor_ext[$query_hash]['log'][] = 'DB Reading data: '
|
||||
@@ -2238,6 +2475,7 @@ class IO
|
||||
* for INSERT INTO queries it is highly recommended to set the pk_name to avoid an
|
||||
* additional read from the database for the PK NAME
|
||||
* Wrapper for dbExecParams without params
|
||||
*
|
||||
* @param string $query the query, if not given,
|
||||
* the query class var will be used
|
||||
* if this was not set, method will quit with false
|
||||
@@ -2307,10 +2545,9 @@ class IO
|
||||
}
|
||||
}
|
||||
|
||||
// add adbExecParams(string $query = '', array $params = [], string $pk_name = ')
|
||||
|
||||
/**
|
||||
* executes a cursor and returns the data, if no more data 0 will be returned
|
||||
*
|
||||
* @param \PgSql\Result|false $cursor the cursor from db_exec or
|
||||
* pg_query/pg_exec/mysql_query
|
||||
* if not set will use internal cursor,
|
||||
@@ -2333,9 +2570,11 @@ class IO
|
||||
return false;
|
||||
}
|
||||
return $this->__dbConvertEncoding(
|
||||
$this->db_functions->__dbFetchArray(
|
||||
$cursor,
|
||||
$this->db_functions->__dbResultType($assoc_only)
|
||||
$this->__dbConvertType(
|
||||
$this->db_functions->__dbFetchArray(
|
||||
$cursor,
|
||||
$this->db_functions->__dbResultType($assoc_only)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -2343,6 +2582,7 @@ class IO
|
||||
/**
|
||||
* returns the FIRST row of the given query
|
||||
* wrapper for dbReturnRowParms
|
||||
*
|
||||
* @param string $query the query to be executed
|
||||
* @param bool $assoc_only if true, only return assoc entry (default false)
|
||||
* @return array<mixed>|false row array or false on error
|
||||
@@ -2388,6 +2628,7 @@ class IO
|
||||
/**
|
||||
* creates an array of hashes of the query (all data)
|
||||
* Wrapper for dbReturnArrayParams
|
||||
*
|
||||
* @param string $query the query to be executed
|
||||
* @param bool $assoc_only if true, only name ref are returned (default true)
|
||||
* @return array<mixed>|false array of hashes (row -> fields), false on error
|
||||
@@ -2432,6 +2673,20 @@ class IO
|
||||
return $rows;
|
||||
}
|
||||
|
||||
// ***************************
|
||||
// CURSOR RETURN
|
||||
// ***************************
|
||||
|
||||
/**
|
||||
* Get current set cursor or false if not set or error
|
||||
*
|
||||
* @return \PgSql\Result|false
|
||||
*/
|
||||
public function dbGetCursor(): \PgSql\Result|false
|
||||
{
|
||||
return $this->cursor;
|
||||
}
|
||||
|
||||
// ***************************
|
||||
// CURSOR EXT CACHE RESET
|
||||
// ***************************
|
||||
@@ -2557,6 +2812,7 @@ class IO
|
||||
|
||||
/**
|
||||
* gets how often a query was called already
|
||||
*
|
||||
* @param string $query query string
|
||||
* @param array<mixed> $params If the query is params type we need params
|
||||
* data to create a unique call one, optional
|
||||
@@ -2581,6 +2837,7 @@ class IO
|
||||
* for INSERT INTO queries it is highly recommended
|
||||
* to set the pk_name to avoid an additional
|
||||
* read from the database for the PK NAME
|
||||
*
|
||||
* @param string $stm_name statement name
|
||||
* @param string $query queryt string to run
|
||||
* @param string $pk_name optional primary key
|
||||
@@ -2693,6 +2950,7 @@ class IO
|
||||
|
||||
/**
|
||||
* runs a prepare query
|
||||
*
|
||||
* @param string $stm_name statement name for the query to run
|
||||
* @param array<mixed> $data data to run for this query, empty array for none
|
||||
* @return \PgSql\Result|false false on error, or result on OK
|
||||
@@ -2791,6 +3049,7 @@ class IO
|
||||
* executes the query async so other methods can be run at the same time
|
||||
* Wrapper for dbExecParamsAsync
|
||||
* NEEDS : dbCheckAsync
|
||||
*
|
||||
* @param string $query query to run
|
||||
* @param string $pk_name optional primary key name, only used with
|
||||
* insert for returning call
|
||||
@@ -2890,6 +3149,7 @@ class IO
|
||||
/**
|
||||
* checks a previous async query and returns data if finished
|
||||
* NEEDS : dbExecAsync
|
||||
*
|
||||
* @return \PgSql\Result|bool cursor resource if the query is still running,
|
||||
* false if an error occured or cursor of that query
|
||||
*/
|
||||
@@ -2930,6 +3190,7 @@ class IO
|
||||
|
||||
/**
|
||||
* Returns the current async running query hash
|
||||
*
|
||||
* @return string Current async running query hash
|
||||
*/
|
||||
public function dbGetAsyncRunning(): string
|
||||
@@ -2948,6 +3209,7 @@ class IO
|
||||
|
||||
/**
|
||||
* writes into one table based on array of table columns
|
||||
*
|
||||
* @param array<mixed> $write_array list of elements to write
|
||||
* @param array<mixed> $not_write_array list of elements not to write
|
||||
* @param int $primary_key id key to decide if we write insert or update
|
||||
@@ -3163,6 +3425,54 @@ class IO
|
||||
return $this->db_debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Convert $convert
|
||||
* @return void
|
||||
*/
|
||||
public function dbSetConvertFlag(Convert $convert): void
|
||||
{
|
||||
$this->convert_type |= $convert->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Convert $convert
|
||||
* @return void
|
||||
*/
|
||||
public function dbUnsetConvertFlag(Convert $convert): void
|
||||
{
|
||||
$this->convert_type &= ~$convert->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset to origincal config file set
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dbResetConvertFlag(): void
|
||||
{
|
||||
foreach ($this->db_convert_type as $db_convert_type) {
|
||||
$this->__setConvertType($db_convert_type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Convert $convert
|
||||
* @return bool
|
||||
*/
|
||||
public function dbGetConvertFlag(Convert $convert): bool
|
||||
{
|
||||
if ($this->convert_type & $convert->value) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* set max query calls, set to -1 to disable loop
|
||||
* protection. this will generate a warning
|
||||
@@ -3314,12 +3624,11 @@ class IO
|
||||
* Alternative use dbSetEcnoding to trigger encoding change on the DB side
|
||||
* Set to empty string to turn off
|
||||
* @param string $encoding PHP Valid encoding to set
|
||||
* @return string Current set encoding
|
||||
* @return void
|
||||
*/
|
||||
public function dbSetToEncoding(string $encoding): string
|
||||
public function dbSetToEncoding(string $encoding): void
|
||||
{
|
||||
$this->to_encoding = $encoding;
|
||||
return $this->to_encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3555,6 +3864,45 @@ class IO
|
||||
return $this->field_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field name to type connection list
|
||||
*
|
||||
* @return array<string,string>
|
||||
*/
|
||||
public function dbGetFieldNameTypes(): array
|
||||
{
|
||||
return $this->field_name_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field name for a position
|
||||
*
|
||||
* @param int $pos Position number in query
|
||||
* @return false|string Field name or false for not found
|
||||
*/
|
||||
public function dbGetFieldName(int $pos): false|string
|
||||
{
|
||||
return $this->field_names[$pos] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a field type for a field name or pos,
|
||||
* will return false if field is not found in list
|
||||
*
|
||||
* @param string|int $name_pos Field name or pos to get the type for
|
||||
* @return false|string Either the field type or
|
||||
* false for not found in list
|
||||
*/
|
||||
public function dbGetFieldType(int|string $name_pos): false|string
|
||||
{
|
||||
if (is_numeric($name_pos)) {
|
||||
$field_type = $this->field_types[$name_pos] ?? false;
|
||||
} else {
|
||||
$field_type = $this->field_name_types[$name_pos] ?? false;
|
||||
}
|
||||
return $field_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for given key in statement
|
||||
* Will write error if statemen id does not exist
|
||||
|
||||
63
www/lib/CoreLibs/DB/Options/Convert.php
Normal file
63
www/lib/CoreLibs/DB/Options/Convert.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AUTOR: Clemens Schwaighofer
|
||||
* CREATED: 2023/6/9
|
||||
* DESCRIPTION:
|
||||
* DB Options for convert type
|
||||
*
|
||||
* off: no conversion (all string)
|
||||
* on: int/bool only
|
||||
* json: json/jsonb to array
|
||||
* numeric: any numeric or float to float
|
||||
* bytes: decode bytea to string
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\DB\Options;
|
||||
|
||||
enum Convert: int
|
||||
{
|
||||
/** do not convert */
|
||||
case off = 0;
|
||||
/** convert only int/bool */
|
||||
case on = 1;
|
||||
/** also convert json to php array */
|
||||
case json = 2;
|
||||
/** also convert any float/real/numeric to php float */
|
||||
case numeric = 4;
|
||||
/** also decode bytea string to php string */
|
||||
case bytea = 8;
|
||||
|
||||
/**
|
||||
* get internal name from string value
|
||||
*
|
||||
* @param non-empty-string $name
|
||||
* @return self
|
||||
*/
|
||||
public static function fromName(string $name): self
|
||||
{
|
||||
return match ($name) {
|
||||
'Off', 'off', 'OFF', 'convert_off', 'CONVERT_OFF' => self::off,
|
||||
'On', 'on', 'ON', 'convert_on', 'CONVERT_ON' => self::on,
|
||||
'Json', 'json', 'JSON', 'convert_json', 'CONVERT_JSON' => self::json,
|
||||
'Numeric', 'numeric', 'NUMERIC', 'convert_numeric', 'CONVERT_NUMERIC' => self::numeric,
|
||||
'Bytea', 'bytea', 'BYTEA', 'convert_bytea', 'CONVERT_BYTEA' => self::bytea,
|
||||
default => self::off,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get internal name from int value
|
||||
*
|
||||
* @param int $value
|
||||
* @return self
|
||||
*/
|
||||
public static function fromValue(int $value): self
|
||||
{
|
||||
return self::from($value);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -34,29 +34,29 @@ class Support
|
||||
}
|
||||
|
||||
/**
|
||||
* prints a html formatted (pre) array
|
||||
* prints a html formatted (pre) data
|
||||
*
|
||||
* @param array<mixed> $array any array
|
||||
* @param bool $no_html default add <pre>
|
||||
* @return string formatted array for output with <pre> tag added
|
||||
* @param mixed $data any data
|
||||
* @param bool $no_html default add <pre>
|
||||
* @return string formatted array for output with <pre> tag added
|
||||
*/
|
||||
public static function printAr(array $array, bool $no_html = false): string
|
||||
public static function printAr(mixed $data, bool $no_html = false): string
|
||||
{
|
||||
return $no_html ?
|
||||
print_r($array, true) :
|
||||
'<pre>' . print_r($array, true) . '</pre>';
|
||||
print_r($data, true) :
|
||||
'<pre>' . print_r($data, true) . '</pre>';
|
||||
}
|
||||
|
||||
/**
|
||||
* alternate name for printAr function
|
||||
*
|
||||
* @param array<mixed> $array any array
|
||||
* @param bool $no_html default add <pre>
|
||||
* @return string formatted array for output with <pre> tag added
|
||||
* @param mixed $data any array
|
||||
* @param bool $no_html default add <pre>
|
||||
* @return string formatted array for output with <pre> tag added
|
||||
*/
|
||||
public static function printArray(array $array, bool $no_html = false): string
|
||||
public static function printArray(mixed $data, bool $no_html = false): string
|
||||
{
|
||||
return self::printAr($array, $no_html);
|
||||
return self::printAr($data, $no_html);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,12 +65,12 @@ class Support
|
||||
* Do not use this without using it in a string in debug function
|
||||
* Note: for full data debug dumps use Support::dumpVar()
|
||||
*
|
||||
* @param array<mixed> $a Array to format
|
||||
* @return string print_r formated
|
||||
* @param mixed $data Data to print
|
||||
* @return string print_r formated
|
||||
*/
|
||||
public static function prAr(array $a): string
|
||||
public static function prAr(mixed $data): string
|
||||
{
|
||||
return self::printAr($a, true);
|
||||
return self::printAr($data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -407,13 +407,6 @@ class Logging
|
||||
}
|
||||
$this->setLogFlag($log_flag_key);
|
||||
}
|
||||
// init per run uid
|
||||
if ($this->getLogFlag(Flag::per_run)) {
|
||||
$this->setLogUniqueId();
|
||||
} elseif ($this->getLogFlag(Flag::per_date)) {
|
||||
// init file date
|
||||
$this->log_file_date = date('Y-m-d');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -535,7 +528,7 @@ class Logging
|
||||
* Prepare the log message with all needed info blocks:
|
||||
* [timestamp] [host name] [file path + file] [running uid] {class} <debug level/group id> - message
|
||||
*
|
||||
* @param string $level_str Log level we will write to
|
||||
* @param Level $level Log level we will write to
|
||||
* @param string|Stringable $message The message to write
|
||||
* @param mixed[] $context Any additional info we want to attach in any format
|
||||
* @param string $group_id A group id, only used in DEBUG level,
|
||||
@@ -543,11 +536,15 @@ class Logging
|
||||
* @return string
|
||||
*/
|
||||
private function prepareLog(
|
||||
string $level_str,
|
||||
Level $level,
|
||||
string|\Stringable $message,
|
||||
array $context = [],
|
||||
string $group_id = '',
|
||||
): string {
|
||||
// only prepare if to write log level is in set log level
|
||||
if (!$this->checkLogLevel($level)) {
|
||||
return '';
|
||||
}
|
||||
// file + line: call not this but one before (the one that calls this)
|
||||
$file_line = Support::getCallerFileLine(2) ??
|
||||
System::getPageName(System::FULL_PATH);
|
||||
@@ -562,7 +559,7 @@ class Logging
|
||||
$timestamp = Support::printTime();
|
||||
|
||||
// if group id is empty replace it with current level
|
||||
$group_str = $level_str;
|
||||
$group_str = $level->getName();
|
||||
if (!empty($group_id)) {
|
||||
$group_str .= ':' . $group_id;
|
||||
}
|
||||
@@ -570,7 +567,7 @@ class Logging
|
||||
$context_str = '';
|
||||
if ($context != []) {
|
||||
// TODO this here has to be changed to something better
|
||||
$context_str = ' ' . print_r($context, true);
|
||||
$context_str = ' :' . print_r($context, true);
|
||||
}
|
||||
// build log string
|
||||
return '[' . $timestamp . '] '
|
||||
@@ -776,6 +773,13 @@ class Logging
|
||||
public function setLogFlag(Flag $flag): void
|
||||
{
|
||||
$this->log_flags |= $flag->value;
|
||||
// init per run uid
|
||||
if ($this->getLogFlag(Flag::per_run)) {
|
||||
$this->setLogUniqueId();
|
||||
} elseif ($this->getLogFlag(Flag::per_date)) {
|
||||
// init file date
|
||||
$this->setLogDate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -906,6 +910,42 @@ class Logging
|
||||
// MAIN CALLS
|
||||
// *********************************************************************
|
||||
|
||||
/**
|
||||
* Commong log interface
|
||||
*
|
||||
* extended with group_id, prefix that are ONLY used for debug level
|
||||
*
|
||||
* @param Level $level
|
||||
* @param string|\Stringable $message
|
||||
* @param mixed[] $context
|
||||
* @param string $group_id
|
||||
* @param string $prefix
|
||||
* @return bool
|
||||
*/
|
||||
public function log(
|
||||
Level $level,
|
||||
string|\Stringable $message,
|
||||
array $context = [],
|
||||
string $group_id = '',
|
||||
string $prefix = '',
|
||||
): bool {
|
||||
// if we are not debug, ignore group_id and prefix
|
||||
if ($level != Level::Debug) {
|
||||
$group_id = '';
|
||||
$prefix = '';
|
||||
}
|
||||
return $this->writeErrorMsg(
|
||||
$level,
|
||||
$this->prepareLog(
|
||||
$level,
|
||||
$prefix . $message,
|
||||
$context,
|
||||
$group_id
|
||||
),
|
||||
$group_id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEBUG: 100
|
||||
*
|
||||
@@ -913,23 +953,23 @@ class Logging
|
||||
*
|
||||
* @param string $group_id id for error message, groups messages together
|
||||
* @param string|Stringable $message the actual error message
|
||||
* @param mixed[] $context
|
||||
* @param string $prefix Attach some block before $string.
|
||||
* Will not be stripped even
|
||||
* when strip is true
|
||||
* if strip is false, recommended to add that to $string
|
||||
* @param mixed[] $context
|
||||
* @return bool True if logged, false if not logged
|
||||
*/
|
||||
public function debug(
|
||||
string $group_id,
|
||||
string|\Stringable $message,
|
||||
string $prefix = '',
|
||||
array $context = []
|
||||
array $context = [],
|
||||
string $prefix = ''
|
||||
): bool {
|
||||
return $this->writeErrorMsg(
|
||||
$this->log_level,
|
||||
Level::Debug,
|
||||
$this->prepareLog(
|
||||
Level::Debug->getName(),
|
||||
Level::Debug,
|
||||
$prefix . $message,
|
||||
$context,
|
||||
$group_id
|
||||
@@ -950,7 +990,7 @@ class Logging
|
||||
return $this->writeErrorMsg(
|
||||
Level::Info,
|
||||
$this->prepareLog(
|
||||
Level::Info->getName(),
|
||||
Level::Info,
|
||||
$message,
|
||||
$context,
|
||||
)
|
||||
@@ -969,7 +1009,7 @@ class Logging
|
||||
return $this->writeErrorMsg(
|
||||
Level::Notice,
|
||||
$this->prepareLog(
|
||||
Level::Notice->getName(),
|
||||
Level::Notice,
|
||||
$message,
|
||||
$context,
|
||||
)
|
||||
@@ -988,7 +1028,7 @@ class Logging
|
||||
return $this->writeErrorMsg(
|
||||
Level::Warning,
|
||||
$this->prepareLog(
|
||||
Level::Warning->getName(),
|
||||
Level::Warning,
|
||||
$message,
|
||||
$context,
|
||||
)
|
||||
@@ -1007,7 +1047,7 @@ class Logging
|
||||
return $this->writeErrorMsg(
|
||||
Level::Error,
|
||||
$this->prepareLog(
|
||||
Level::Error->getName(),
|
||||
Level::Error,
|
||||
$message,
|
||||
$context,
|
||||
)
|
||||
@@ -1026,7 +1066,7 @@ class Logging
|
||||
return $this->writeErrorMsg(
|
||||
Level::Critical,
|
||||
$this->prepareLog(
|
||||
Level::Critical->getName(),
|
||||
Level::Critical,
|
||||
$message,
|
||||
$context,
|
||||
)
|
||||
@@ -1045,7 +1085,7 @@ class Logging
|
||||
return $this->writeErrorMsg(
|
||||
Level::Alert,
|
||||
$this->prepareLog(
|
||||
Level::Alert->getName(),
|
||||
Level::Alert,
|
||||
$message,
|
||||
$context,
|
||||
)
|
||||
@@ -1064,7 +1104,7 @@ class Logging
|
||||
return $this->writeErrorMsg(
|
||||
Level::Emergency,
|
||||
$this->prepareLog(
|
||||
Level::Emergency->getName(),
|
||||
Level::Emergency,
|
||||
$message,
|
||||
$context,
|
||||
)
|
||||
@@ -1082,12 +1122,12 @@ class Logging
|
||||
* But this does not wrap it in <pre></pre>
|
||||
* Do not use this without using it in a string in debug function
|
||||
*
|
||||
* @param array<mixed> $a Array to format
|
||||
* @return string print_r formated
|
||||
* @param mixed $data Data to format
|
||||
* @return string print_r formated
|
||||
*/
|
||||
public function prAr(array $a): string
|
||||
public function prAr(mixed $data): string
|
||||
{
|
||||
return Support::printArray($a, true);
|
||||
return Support::printArray($data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -232,13 +232,13 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
|
||||
/** @var string */
|
||||
public string $col_name; // the name of the columen (before _<type>) [used for order button]
|
||||
/** @var int */
|
||||
public int $yes; // the yes flag that triggers the template to show ALL and not only new/load
|
||||
public int $yes = 0; // the yes flag that triggers the template to show ALL and not only new/load
|
||||
/** @var string */
|
||||
public string $msg; // the error msg
|
||||
public string $msg = ''; // the error msg
|
||||
/** @var int */
|
||||
public int $error; // the error flag set for printing red error msg
|
||||
public int $error = 0; // the error flag set for printing red error msg
|
||||
/** @var int */
|
||||
public int $warning; // warning flag, for information (saved, loaded, etc)
|
||||
public int $warning = 0; // warning flag, for information (saved, loaded, etc)
|
||||
/** @var string */
|
||||
public string $archive_pk_name; // the pk name for the load select form
|
||||
/** @var string */
|
||||
@@ -282,7 +282,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
|
||||
public array $login_acl = [];
|
||||
// layout publics
|
||||
/** @var int */
|
||||
public int $table_width;
|
||||
public int $table_width = 0;
|
||||
// internal lang & encoding vars
|
||||
/** @var string */
|
||||
public string $lang_dir = '';
|
||||
@@ -308,7 +308,8 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
|
||||
/**
|
||||
* construct form generator
|
||||
*
|
||||
* @param array<mixed> $db_config db config array, mandatory
|
||||
* phpcs:ignore
|
||||
* @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[]} $db_config db config array, mandatory
|
||||
* @param \CoreLibs\Logging\Logging $log Logging class
|
||||
* @param \CoreLibs\Language\L10n $l10n l10n language class
|
||||
* @param array<string,mixed> $login_acl Login ACL array,
|
||||
|
||||
@@ -36,6 +36,7 @@ class Image
|
||||
): string|false {
|
||||
// get image type flags
|
||||
$image_types = [
|
||||
0 => 'UNKOWN-IMAGE',
|
||||
1 => 'gif',
|
||||
2 => 'jpg',
|
||||
3 => 'png'
|
||||
@@ -69,7 +70,7 @@ class Image
|
||||
}
|
||||
// does this picture exist and is it a picture
|
||||
if (file_exists($filename) && is_file($filename)) {
|
||||
[$width, $height, $type] = getimagesize($filename) ?: [];
|
||||
[$width, $height, $type] = getimagesize($filename) ?: [0, 0, 0];
|
||||
$convert_prefix = '';
|
||||
$create_file = false;
|
||||
$delete_filename = '';
|
||||
@@ -98,7 +99,7 @@ class Image
|
||||
if (!is_file($filename)) {
|
||||
$filename .= '-0';
|
||||
}
|
||||
[$width, $height, $type] = getimagesize($filename) ?: [];
|
||||
[$width, $height, $type] = getimagesize($filename) ?: [0, 0, 0];
|
||||
}
|
||||
// if no size given, set size to original
|
||||
if (!$size_x || $size_x < 1) {
|
||||
@@ -117,7 +118,7 @@ class Image
|
||||
$status = exec($convert_string, $output, $return);
|
||||
// get the size of the converted data, if converted
|
||||
if (is_file($thumbnail)) {
|
||||
[$width, $height, $type] = getimagesize($thumbnail) ?: [];
|
||||
[$width, $height, $type] = getimagesize($thumbnail) ?: [0, 0, 0];
|
||||
}
|
||||
}
|
||||
if ($height > $size_y) {
|
||||
@@ -217,7 +218,7 @@ class Image
|
||||
return $thumbnail;
|
||||
}
|
||||
// $this->debug('IMAGE PREPARE', "FILENAME OK, THUMB WIDTH/HEIGHT OK");
|
||||
[$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [];
|
||||
[$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [0, 0, null];
|
||||
$thumbnail_write_path = null;
|
||||
$thumbnail_web_path = null;
|
||||
// path set first
|
||||
@@ -447,7 +448,7 @@ class Image
|
||||
if (!function_exists('exif_read_data') || !is_writeable($filename)) {
|
||||
return;
|
||||
}
|
||||
[$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [];
|
||||
[$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [0, 0, null];
|
||||
// add @ to avoid "file not supported error"
|
||||
$exif = @exif_read_data($filename);
|
||||
$orientation = null;
|
||||
|
||||
264
www/lib/CoreLibs/Template/HtmlBuilder/Block.php
Normal file
264
www/lib/CoreLibs/Template/HtmlBuilder/Block.php
Normal file
@@ -0,0 +1,264 @@
|
||||
<?php // phpcs:disable Generic.Files.LineLength
|
||||
|
||||
/**
|
||||
* AUTOR: Clemens Schwaighofer
|
||||
* CREATED: 2023/6/1
|
||||
* DESCRIPTION:
|
||||
* html builder: array
|
||||
* static build for array lists (not objects)
|
||||
*
|
||||
* Recommended to use the Object one or for speed the String Replace
|
||||
*/
|
||||
|
||||
namespace CoreLibs\Template\HtmlBuilder;
|
||||
|
||||
use CoreLibs\Template\HtmlBuilder\General\Settings;
|
||||
use CoreLibs\Template\HtmlBuilder\General\Error;
|
||||
use CoreLibs\Template\HtmlBuilder\General\HtmlBuilderExcpetion;
|
||||
|
||||
class Block
|
||||
{
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param string $tag
|
||||
* @param string $id
|
||||
* @param string $content
|
||||
* @param array<string> $css,
|
||||
* @param array<string,string> $options
|
||||
* @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}
|
||||
* @throws HtmlBuilderExcpetion
|
||||
*/
|
||||
public static function cel(
|
||||
string $tag,
|
||||
string $id = '',
|
||||
string $content = '',
|
||||
array $css = [],
|
||||
array $options = []
|
||||
): array {
|
||||
if (!preg_match("/^[A-Za-z]+$/", $tag)) {
|
||||
Error::setError(
|
||||
'201',
|
||||
'invalid or empty tag',
|
||||
['tag' => $tag]
|
||||
);
|
||||
throw new HtmlBuilderExcpetion('Invalid or empty tag');
|
||||
}
|
||||
return [
|
||||
'tag' => $tag,
|
||||
'id' => $id,
|
||||
'name' => $options['name'] ?? '',
|
||||
'content' => $content,
|
||||
'css' => $css,
|
||||
'options' => $options,
|
||||
'sub' => [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search element tree for id and add
|
||||
* if id is empty add at current
|
||||
*
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $base
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $attach
|
||||
* @param string $id
|
||||
* @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}
|
||||
*/
|
||||
public static function ael(
|
||||
array $base,
|
||||
array $attach,
|
||||
string $id = ''
|
||||
): array {
|
||||
// no id or matching id
|
||||
if (
|
||||
empty($id) ||
|
||||
$base['id'] == $id
|
||||
) {
|
||||
self::addSub($base, $attach);
|
||||
return $base;
|
||||
}
|
||||
// find id in 'id' in all 'sub'
|
||||
foreach ($base['sub'] as $el) {
|
||||
$el = self::ael($el, $attach, $id);
|
||||
}
|
||||
|
||||
return $base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $base
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} ...$attach
|
||||
* @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}
|
||||
*/
|
||||
public static function aelx(
|
||||
array $base,
|
||||
array ...$attach
|
||||
): array {
|
||||
$base = self::addSub($base, ...$attach);
|
||||
return $base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $sub
|
||||
* @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}
|
||||
*/
|
||||
public static function addSub(array $element, array ...$sub): array
|
||||
{
|
||||
if (!isset($element['sub'])) {
|
||||
$element['sub'] = [];
|
||||
}
|
||||
array_push($element['sub'], ...$sub);
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
|
||||
* @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}
|
||||
*/
|
||||
public static function resetSub(array $element): array
|
||||
{
|
||||
$element['sub'] = [];
|
||||
return $element;
|
||||
}
|
||||
|
||||
// CSS Elements
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
|
||||
* @param string ...$css
|
||||
* @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}
|
||||
*/
|
||||
public static function acssel(array $element, string ...$css): array
|
||||
{
|
||||
$element['css'] = array_unique(array_merge($element['css'] ?? [], $css));
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
|
||||
* @param string ...$css
|
||||
* @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}
|
||||
*/
|
||||
public static function rcssel(array $element, string ...$css): array
|
||||
{
|
||||
$element['css'] = array_diff($element['css'] ?? [], $css);
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
* scssel (switch) is not supported
|
||||
* use rcssel -> acssel
|
||||
*
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
|
||||
* @param array<string> $rcss
|
||||
* @param array<string> $acss
|
||||
* @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}
|
||||
*/
|
||||
public static function scssel(array $element, array $rcss, array $acss): array
|
||||
{
|
||||
return self::acssel(
|
||||
self::rcssel($element, ...$rcss),
|
||||
...$acss
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
* alias phfo
|
||||
*
|
||||
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $tree
|
||||
* @param bool $add_nl [default=false]
|
||||
* @return string
|
||||
*/
|
||||
public static function buildHtml(array $tree, bool $add_nl = false): string
|
||||
{
|
||||
if (empty($tree['tag'])) {
|
||||
return '';
|
||||
}
|
||||
// print "D01: " . microtime(true) . "<br>";
|
||||
$line = '<' . $tree['tag'];
|
||||
|
||||
if (!empty($tree['id'])) {
|
||||
$line .= ' id="' . $tree['id'] . '"';
|
||||
if (in_array($tree['tag'], Settings::NAME_ELEMENTS)) {
|
||||
$line .= ' name="'
|
||||
. (!empty($tree['name']) ? $tree['name'] : $tree['id'])
|
||||
. '"';
|
||||
}
|
||||
}
|
||||
if (count($tree['css'])) {
|
||||
$line .= ' class="' . join(' ', $tree['css']) . '"';
|
||||
}
|
||||
foreach ($tree['options'] ?? [] as $key => $item) {
|
||||
if (in_array($key, Settings::SKIP_OPTIONS)) {
|
||||
continue;
|
||||
}
|
||||
$line .= ' ' . $key . '="' . $item . '"';
|
||||
}
|
||||
$line .= '>';
|
||||
if (!empty($tree['content'])) {
|
||||
$line .= $tree['content'];
|
||||
}
|
||||
// sub nodes
|
||||
foreach ($tree['sub'] ?? [] as $sub) {
|
||||
if ($add_nl === true) {
|
||||
$line .= "\n";
|
||||
}
|
||||
$line .= self::buildHtml($sub, $add_nl);
|
||||
if ($add_nl === true) {
|
||||
$line .= "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// close line if needed
|
||||
if (!in_array($tree['tag'], Settings::NO_CLOSE)) {
|
||||
$line .= '</' . $tree['tag'] . '>';
|
||||
}
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
* alias phfa
|
||||
*
|
||||
* @param array<array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}> $list
|
||||
* @param bool $add_nl [default=false]
|
||||
* @return string
|
||||
*/
|
||||
public static function buildHtmlFromList(array $list, bool $add_nl = false): string
|
||||
{
|
||||
$output = '';
|
||||
foreach ($list as $el) {
|
||||
$output .= self::buildHtml($el, $add_nl);
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
* wrapper for buildHtmlFromList
|
||||
*
|
||||
* @param array<array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}> $list array of Elements to build string from
|
||||
* @param bool $add_nl [default=false] Optional output string line break
|
||||
* @return string build html as string
|
||||
*/
|
||||
public static function printHtmlFromArray(array $list, bool $add_nl = false): string
|
||||
{
|
||||
return self::buildHtmlFromList($list, $add_nl);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
559
www/lib/CoreLibs/Template/HtmlBuilder/Element.php
Normal file
559
www/lib/CoreLibs/Template/HtmlBuilder/Element.php
Normal file
@@ -0,0 +1,559 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AUTOR: Clemens Schwaighofer
|
||||
* CREATED: 2023/6/1
|
||||
* DESCRIPTION:
|
||||
* html builder: element
|
||||
* nested and connected objects
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Template\HtmlBuilder;
|
||||
|
||||
use CoreLibs\Template\HtmlBuilder\General\Settings;
|
||||
use CoreLibs\Template\HtmlBuilder\General\Error;
|
||||
use CoreLibs\Template\HtmlBuilder\General\HtmlBuilderExcpetion;
|
||||
|
||||
class Element
|
||||
{
|
||||
/** @var string */
|
||||
private string $tag = '';
|
||||
/** @var string */
|
||||
private string $id = '';
|
||||
/** @var string */
|
||||
private string $name = '';
|
||||
/** @var string */
|
||||
private string $content = '';
|
||||
/** @var array<string> */
|
||||
private array $css = [];
|
||||
/** @var array<string,mixed> */
|
||||
private array $options = [];
|
||||
/** @var array<Element> list of elements */
|
||||
private array $sub = [];
|
||||
|
||||
/**
|
||||
* create new html element
|
||||
*
|
||||
* @param string $tag html tag (eg div, button, etc)
|
||||
* @param string $id html tag id, used also for name if name
|
||||
* not set in $options
|
||||
* @param string $content content text inside, eg <div>Content</div>
|
||||
* if sub elements exist, they are added after content
|
||||
* @param array<string> $css array of css names, put style in $options
|
||||
* @param array<string,string> $options Additional element options in
|
||||
* key = value format
|
||||
* eg: onClick => 'something();'
|
||||
* id, css are skipped
|
||||
* name only set on input/button
|
||||
* @throws HtmlBuilderExcpetion
|
||||
*/
|
||||
public function __construct(
|
||||
string $tag,
|
||||
string $id = '',
|
||||
string $content = '',
|
||||
array $css = [],
|
||||
array $options = []
|
||||
) {
|
||||
// exit if not valid tag
|
||||
try {
|
||||
$this->setTag($tag);
|
||||
} catch (HtmlBuilderExcpetion $e) {
|
||||
throw new HtmlBuilderExcpetion('Could not create Element', 0, $e);
|
||||
}
|
||||
$this->setId($id);
|
||||
$this->setName($options['name'] ?? '');
|
||||
$this->setContent($content);
|
||||
$this->addCss(...$css);
|
||||
$this->setOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* set tag
|
||||
*
|
||||
* @param string $tag
|
||||
* @return void
|
||||
* @throws HtmlBuilderExcpetion
|
||||
*/
|
||||
public function setTag(string $tag): void
|
||||
{
|
||||
// tag must be letters only
|
||||
if (!preg_match("/^[A-Za-z]+$/", $tag)) {
|
||||
Error::setError(
|
||||
'201',
|
||||
'invalid or empty tag',
|
||||
['tag' => $tag]
|
||||
);
|
||||
throw new HtmlBuilderExcpetion('Invalid or empty tag: ' . $tag);
|
||||
}
|
||||
$this->tag = $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the tag name
|
||||
*
|
||||
* @return string HTML element tag
|
||||
*/
|
||||
public function getTag(): string
|
||||
{
|
||||
return $this->tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the element id
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function setId(string $id): void
|
||||
{
|
||||
// invalid id and name check too
|
||||
// be strict: [a-zA-Z0-9], -, _
|
||||
// cannot start with digit, two hyphens or a hyphen with a digit:
|
||||
// 0abc
|
||||
// __abc
|
||||
// _0abc
|
||||
if (
|
||||
!empty($id) &&
|
||||
!preg_match("/^[A-Za-z][\w-]*$/", $id)
|
||||
) {
|
||||
Error::setWarning(
|
||||
'202',
|
||||
'possible invalid id',
|
||||
['id' => $id, 'tag' => $this->getTag()]
|
||||
);
|
||||
// TODO: shoud throw error
|
||||
}
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the html tag id
|
||||
*
|
||||
* @return string HTML element id
|
||||
*/
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name for elements
|
||||
* only for elements that need it (input/button/form)
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setName(string $name): void
|
||||
{
|
||||
if (
|
||||
!empty($name) &&
|
||||
!preg_match("/^[A-Za-z][\w-]*$/", $name)
|
||||
) {
|
||||
Error::setWarning(
|
||||
'203',
|
||||
'possible invalid name',
|
||||
['name' => $name, 'id' => $this->getId(), 'tag' => $this->getTag()]
|
||||
);
|
||||
// TODO: shoud throw error
|
||||
}
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the name if set
|
||||
*
|
||||
* @return string Optional HTML name (eg for input)
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new content for element
|
||||
*
|
||||
* @param string $content
|
||||
* @return void
|
||||
*/
|
||||
public function setContent(string $content): void
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the elment text content (not sub elements)
|
||||
*
|
||||
* @return string HTML content text as is
|
||||
*/
|
||||
public function getContent(): string
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* set or update options
|
||||
*
|
||||
* @param array<string,mixed> $options
|
||||
* @return void
|
||||
*/
|
||||
public function setOptions(array $options): void
|
||||
{
|
||||
foreach ($options as $key => $value) {
|
||||
if (empty($key)) {
|
||||
Error::setError(
|
||||
'110',
|
||||
'Cannot set option with empty key',
|
||||
['id' => $this->getId(), 'tag' => $this->getTag()]
|
||||
);
|
||||
// TODO: shoud throw error
|
||||
continue;
|
||||
}
|
||||
// if data is null
|
||||
if ($value === null) {
|
||||
if (isset($this->options[$key])) {
|
||||
unset($this->options[$key]);
|
||||
} else {
|
||||
Error::setError(
|
||||
'210',
|
||||
'Cannot set option with null value',
|
||||
['id' => $this->getId(), 'tag' => $this->getTag()]
|
||||
);
|
||||
}
|
||||
// TODO: shoud throw error
|
||||
continue;
|
||||
}
|
||||
$this->options[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the options array
|
||||
* also holds "name" option
|
||||
* anything like: style, javascript, value or any other html tag option
|
||||
* right side can be empty but not null
|
||||
*
|
||||
* @return array<string,string> get options as list html option name and value
|
||||
*/
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
// Sub Elements
|
||||
|
||||
/**
|
||||
* get the sub elements (array of Elements)
|
||||
*
|
||||
* @return array<Element> Array of Elements (that can have sub elements)
|
||||
*/
|
||||
public function getSub(): array
|
||||
{
|
||||
return $this->sub;
|
||||
}
|
||||
|
||||
/**
|
||||
* add one or many sub elements (add at the end)
|
||||
*
|
||||
* @param Element $sub One or many elements to add
|
||||
* @return void
|
||||
* @throws HtmlBuilderExcpetion
|
||||
*/
|
||||
public function addSub(Element ...$sub): void
|
||||
{
|
||||
foreach ($sub as $_sub) {
|
||||
// if one of the elements is the same as this class, ignore it
|
||||
// with this we avoid self reference loop
|
||||
if ($_sub == $this) {
|
||||
Error::setError(
|
||||
'100',
|
||||
'Cannot assign Element to itself, this would create an infinite loop',
|
||||
['id' => $this->getId(), 'tag' => $this->getTag()]
|
||||
);
|
||||
throw new HtmlBuilderExcpetion('Cannot assign Element to itself, this would create an infinite loop');
|
||||
}
|
||||
array_push($this->sub, $_sub);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element from the sub array
|
||||
* By pos in array or id set on first level
|
||||
*
|
||||
* @param int|string $id String id name or int pos number in array
|
||||
* @return void
|
||||
*/
|
||||
public function removeSub(int|string $id): void
|
||||
{
|
||||
// find element with id and remove it
|
||||
// or when number find pos in sub and remove it
|
||||
if (is_int($id)) {
|
||||
if (!isset($this->sub[$id])) {
|
||||
return;
|
||||
}
|
||||
unset($this->sub[$id]);
|
||||
return;
|
||||
}
|
||||
// only on first level
|
||||
foreach ($this->sub as $pos => $el) {
|
||||
if (
|
||||
$el->getId() === $id
|
||||
) {
|
||||
unset($this->sub[$pos]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove all sub elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetSub(): void
|
||||
{
|
||||
$this->sub = [];
|
||||
}
|
||||
|
||||
// CSS Elements
|
||||
|
||||
/**
|
||||
* get the current set css elements
|
||||
*
|
||||
* @return array<string> list of css element entries
|
||||
*/
|
||||
public function getCss(): array
|
||||
{
|
||||
return $this->css;
|
||||
}
|
||||
|
||||
/**
|
||||
* add one or many new css elements
|
||||
* Note that we can chain: add/remove/reset
|
||||
*
|
||||
* @param string ...$css one or more css strings to add
|
||||
* @return Element Current element for chaining
|
||||
*/
|
||||
public function addCss(string ...$css): Element
|
||||
{
|
||||
// should do check for empty/invalid css
|
||||
$_set_css = [];
|
||||
foreach ($css as $_css) {
|
||||
if (empty($_css)) {
|
||||
Error::setError(
|
||||
'204',
|
||||
'cannot have empty css string',
|
||||
);
|
||||
// TODO: shoud throw error
|
||||
continue;
|
||||
}
|
||||
// -?[_A-Za-z][_A-Za-z0-9-]*
|
||||
if (!preg_match("/^-?[_A-Za-z][_A-Za-z0-9-]*$/", $_css)) {
|
||||
Error::setWarning(
|
||||
'205',
|
||||
'possible invalid css string',
|
||||
['css' => $_css, 'id' => $this->id, 'tag' => $this->tag]
|
||||
);
|
||||
// TODO: shoud throw error
|
||||
}
|
||||
$_set_css[] = $_css;
|
||||
}
|
||||
$this->css = array_unique(array_merge($this->css, $_set_css));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove one or more css elements
|
||||
* Note that we can chain: add/remove/reset
|
||||
*
|
||||
* @param string ...$css one or more css strings to remove
|
||||
* @return Element Current element for chaining
|
||||
*/
|
||||
public function removeCss(string ...$css): Element
|
||||
{
|
||||
$this->css = array_diff($this->css, $css);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* unset all css elements
|
||||
* Note that we can chain: add/remove/reset
|
||||
*
|
||||
* @return Element
|
||||
*/
|
||||
public function resetCss(): Element
|
||||
{
|
||||
$this->css = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
// build output from tree
|
||||
|
||||
/**
|
||||
* build html string from the current element tree (self)
|
||||
* or from the Element tree given as parameter
|
||||
* if $add_nl is set then new lines are added before each sub element added
|
||||
* no indet is done (tab or other)
|
||||
*
|
||||
* @param Element|null $tree Different Element tree to build
|
||||
* if not set (null), self is used
|
||||
* @param bool $add_nl [default=false] Optional output string line breaks
|
||||
* @return string HTML as string
|
||||
*/
|
||||
public function buildHtml(Element $tree = null, bool $add_nl = false): string
|
||||
{
|
||||
// print "D01: " . microtime(true) . "<br>";
|
||||
if ($tree === null) {
|
||||
$tree = $this;
|
||||
}
|
||||
$line = '<' . $tree->getTag();
|
||||
|
||||
if ($tree->getId()) {
|
||||
$line .= ' id="' . $tree->getId() . '"';
|
||||
if (in_array($tree->getTag(), Settings::NAME_ELEMENTS)) {
|
||||
$line .= ' name="'
|
||||
. (!empty($tree->getName()) ? $tree->getName() : $tree->getId())
|
||||
. '"';
|
||||
}
|
||||
}
|
||||
if (count($tree->getCss())) {
|
||||
$line .= ' class="' . join(' ', $tree->getCss()) . '"';
|
||||
}
|
||||
foreach ($tree->getOptions() as $key => $item) {
|
||||
// skip
|
||||
if (in_array($key, Settings::SKIP_OPTIONS)) {
|
||||
continue;
|
||||
}
|
||||
$line .= ' ' . $key . '="' . $item . '"';
|
||||
}
|
||||
$line .= '>';
|
||||
if (strlen($tree->getContent()) > 0) {
|
||||
$line .= $tree->getContent();
|
||||
}
|
||||
// sub nodes
|
||||
foreach ($tree->getSub() as $sub) {
|
||||
if ($add_nl === true) {
|
||||
$line .= "\n";
|
||||
}
|
||||
$line .= $tree->buildHtml($sub, $add_nl);
|
||||
if ($add_nl === true) {
|
||||
$line .= "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// close line if needed
|
||||
if (!in_array($tree->getTag(), Settings::NO_CLOSE)) {
|
||||
$line .= '</' . $tree->getTag() . '>';
|
||||
}
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
// this is static
|
||||
|
||||
/**
|
||||
* Builds a single string from an array of elements
|
||||
* a new line can be added before each new element if $add_nl is set to true
|
||||
*
|
||||
* @param array<Element> $list array of Elements, uses buildHtml internal
|
||||
* @param bool $add_nl [default=false] Optional output string line breaks
|
||||
* @return string HTML as string
|
||||
*/
|
||||
public static function buildHtmlFromList(array $list, bool $add_nl = false): string
|
||||
{
|
||||
$output = '';
|
||||
foreach ($list as $el) {
|
||||
if (!empty($output) && $add_nl === true) {
|
||||
$output .= "\n";
|
||||
}
|
||||
$output .= $el->buildHtml();
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
// so we can call builder statically
|
||||
|
||||
/**
|
||||
* Search element tree for id and add
|
||||
* if id is empty add at element given in parameter $base
|
||||
*
|
||||
* @param Element $base Element to attach to
|
||||
* @param Element $attach Element to attach (single)
|
||||
* @param string $id Optional id, if empty then attached at the end
|
||||
* If set will loop through ALL sub elements until
|
||||
* matching id found. if not found, not added
|
||||
* @return Element Element with attached sub element
|
||||
*/
|
||||
public static function addElementWithId(
|
||||
Element $base,
|
||||
Element $attach,
|
||||
string $id = ''
|
||||
): Element {
|
||||
// no id or matching id
|
||||
if (
|
||||
empty($id) ||
|
||||
$base->getId() == $id
|
||||
) {
|
||||
$base->addSub($attach);
|
||||
return $base;
|
||||
}
|
||||
// find id in 'id' in all 'sub'
|
||||
foreach ($base->getSub() as $el) {
|
||||
self::addElementWithId($el, $attach, $id);
|
||||
}
|
||||
|
||||
return $base;
|
||||
}
|
||||
|
||||
/**
|
||||
* add one or more elemens to $base
|
||||
*
|
||||
* @param Element $base Element to attach to
|
||||
* @param Element ...$attach Element or Elements to attach
|
||||
* @return Element Element with attached sub elements
|
||||
*/
|
||||
public static function addElement(
|
||||
Element $base,
|
||||
Element ...$attach
|
||||
): Element {
|
||||
// we must make sure we do not self attach
|
||||
$base->addSub(...$attach);
|
||||
return $base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static call version for building
|
||||
* not recommended to be used, rather use "Element->buildHtml()"
|
||||
* wrapper for buildHtml
|
||||
*
|
||||
* @param ?Element $tree Element tree to build
|
||||
* if not set returns empty string
|
||||
* @param bool $add_nl [default=false] Optional output string line break
|
||||
* @return string build html as string
|
||||
* @deprecated Do not use, use Element->buildHtml() instead
|
||||
*/
|
||||
public static function printHtmlFromObject(Element $tree = null, bool $add_nl = false): string
|
||||
{
|
||||
// nothing ->bad
|
||||
if ($tree === null) {
|
||||
return '';
|
||||
}
|
||||
return $tree->buildHtml(add_nl: $add_nl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
* wrapper for buildHtmlFromList
|
||||
*
|
||||
* @param array<Element> $list array of Elements to build string from
|
||||
* @param bool $add_nl [default=false] Optional output string line break
|
||||
* @return string build html as string
|
||||
*/
|
||||
public static function printHtmlFromArray(array $list, bool $add_nl = false): string
|
||||
{
|
||||
return self::buildHtmlFromList($list, $add_nl);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
127
www/lib/CoreLibs/Template/HtmlBuilder/General/Error.php
Normal file
127
www/lib/CoreLibs/Template/HtmlBuilder/General/Error.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AUTOR: Clemens Schwaighofer
|
||||
* CREATED: 2023/6/27
|
||||
* DESCRIPTION:
|
||||
* Error logging for the HtmlBuilder systs
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Template\HtmlBuilder\General;
|
||||
|
||||
class Error
|
||||
{
|
||||
/** @var array<array{level:string,id:string,message:string,context:array<mixed>}> */
|
||||
private static array $messages = [];
|
||||
|
||||
/**
|
||||
* internal writer for messages
|
||||
*
|
||||
* @param string $level
|
||||
* @param string $id
|
||||
* @param string $message
|
||||
* @param array<mixed> $context
|
||||
* @return void
|
||||
*/
|
||||
private static function writeContent(
|
||||
string $level,
|
||||
string $id,
|
||||
string $message,
|
||||
array $context
|
||||
): void {
|
||||
self::$messages[] = [
|
||||
'level' => $level,
|
||||
'id' => $id,
|
||||
'message' => $message,
|
||||
'context' => $context,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* warning collector for all internal string errors
|
||||
* builds an warning with warning id, message text and array with optional content
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $message
|
||||
* @param array<mixed> $context
|
||||
* @return void
|
||||
*/
|
||||
public static function setWarning(string $id, string $message, array $context = []): void
|
||||
{
|
||||
self::writeContent('Warning', $id, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* error collector for all internal string errors
|
||||
* builds an error with error id, message text and array with optional content
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $message
|
||||
* @param array<mixed> $context
|
||||
* @return void
|
||||
*/
|
||||
public static function setError(string $id, string $message, array $context = []): void
|
||||
{
|
||||
self::writeContent('Error', $id, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all set errors
|
||||
*
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function getMessages(): array
|
||||
{
|
||||
return self::$messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all errors
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function resetMessages(): void
|
||||
{
|
||||
self::$messages = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* internal level in message array exists check
|
||||
*
|
||||
* @param string $level
|
||||
* @return bool
|
||||
*/
|
||||
private static function hasLevel(string $level): bool
|
||||
{
|
||||
return array_filter(
|
||||
self::$messages,
|
||||
function ($var) use ($level) {
|
||||
return $var['level'] == $level ? true : false;
|
||||
}
|
||||
) === [] ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if any error is set
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasError(): bool
|
||||
{
|
||||
return self::hasLevel('Error');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if any warning is set
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasWarning(): bool
|
||||
{
|
||||
return self::hasLevel('Warning');
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AUTOR: Clemens Schwaighofer
|
||||
* CREATED: 2023/6/28
|
||||
* DESCRIPTION:
|
||||
* Exception class for the HtmlBuilder blocks
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Template\HtmlBuilder\General;
|
||||
|
||||
/**
|
||||
* Exception class for HtmlBuilder
|
||||
*/
|
||||
class HtmlBuilderExcpetion extends \Exception
|
||||
{
|
||||
}
|
||||
|
||||
// __END__
|
||||
69
www/lib/CoreLibs/Template/HtmlBuilder/General/Settings.php
Normal file
69
www/lib/CoreLibs/Template/HtmlBuilder/General/Settings.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AUTOR: Clemens Schwaighofer
|
||||
* CREATED: 2023/7/22
|
||||
* DESCRIPTION:
|
||||
* General settings for html elements
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Template\HtmlBuilder\General;
|
||||
|
||||
class Settings
|
||||
{
|
||||
/** @var array<string> list of html elements that can have the name tag */
|
||||
public const NAME_ELEMENTS = [
|
||||
'button',
|
||||
'fieldset',
|
||||
'form',
|
||||
'iframe',
|
||||
'input',
|
||||
'map',
|
||||
'meta',
|
||||
'object',
|
||||
'output',
|
||||
'param',
|
||||
'select',
|
||||
'textarea',
|
||||
];
|
||||
|
||||
/** @var array<string> options key entries to be skipped in build */
|
||||
public const SKIP_OPTIONS = [
|
||||
'id',
|
||||
'name',
|
||||
'class',
|
||||
];
|
||||
|
||||
/** @var array<string> html elements that don't need to be closed */
|
||||
public const NO_CLOSE = [
|
||||
'input',
|
||||
'br',
|
||||
'img',
|
||||
'hr',
|
||||
'area',
|
||||
'col',
|
||||
'keygen',
|
||||
'wbr',
|
||||
'track',
|
||||
'source',
|
||||
'param',
|
||||
'command',
|
||||
// only in header
|
||||
'base',
|
||||
'meta',
|
||||
'link',
|
||||
'embed',
|
||||
];
|
||||
|
||||
/** @var array<string> invalid tags, not allowed in body */
|
||||
public const NOT_IN_BODY_ALLOWED = [
|
||||
'base',
|
||||
'meta',
|
||||
'link',
|
||||
'embed', // not sure
|
||||
];
|
||||
}
|
||||
|
||||
// __END__
|
||||
194
www/lib/CoreLibs/Template/HtmlBuilder/StringReplace.php
Normal file
194
www/lib/CoreLibs/Template/HtmlBuilder/StringReplace.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AUTOR: Clemens Schwaighofer
|
||||
* CREATED: 2023/6/23
|
||||
* DESCRIPTION:
|
||||
* Simeple string replace calls for elements
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Template\HtmlBuilder;
|
||||
|
||||
use CoreLibs\Template\HtmlBuilder\General\Error;
|
||||
use CoreLibs\Template\HtmlBuilder\General\HtmlBuilderExcpetion;
|
||||
|
||||
class StringReplace
|
||||
{
|
||||
/** @var array<string,string> */
|
||||
private static array $elements = [];
|
||||
/** @var array<string,string> */
|
||||
private static array $replace = [];
|
||||
|
||||
/**
|
||||
* load html blocks into array for repeated usage
|
||||
* each array group parameter has 0: index, 1: content
|
||||
* There is no content check done.
|
||||
* index must be non empty (but has no fixed format)
|
||||
* if same index is tried twice it will set an error and skip
|
||||
*
|
||||
* @param array{0:string,1:string} ...$element Elements to load
|
||||
* @return void
|
||||
* @throws HtmlBuilderExcpetion
|
||||
*/
|
||||
public static function loadElements(array ...$element): void
|
||||
{
|
||||
foreach ($element as $el) {
|
||||
$index = $el[0] ?? '';
|
||||
if (empty($index)) {
|
||||
Error::setError(
|
||||
'310',
|
||||
'Index cannot be an empty string',
|
||||
[
|
||||
'element' => $index
|
||||
]
|
||||
);
|
||||
throw new HtmlBuilderExcpetion('Index cannot be an empty string');
|
||||
}
|
||||
if (isset(self::$elements[$index])) {
|
||||
Error::setError(
|
||||
'311',
|
||||
'Index already exists',
|
||||
[
|
||||
'element' => $index
|
||||
]
|
||||
);
|
||||
throw new HtmlBuilderExcpetion('Index already exists: ' . $index);
|
||||
}
|
||||
// content check?
|
||||
self::$elements[$index] = $el[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update an element at index
|
||||
* can also be used to reset (empty string)
|
||||
*
|
||||
* @param string $index
|
||||
* @param string $element
|
||||
* @return void
|
||||
*/
|
||||
public static function updateElement(string $index, string $element): void
|
||||
{
|
||||
if (!isset(self::$elements[$index])) {
|
||||
Error::setError(
|
||||
'312',
|
||||
'Index does not exists',
|
||||
[
|
||||
'element' => $index
|
||||
]
|
||||
);
|
||||
throw new HtmlBuilderExcpetion('Index does not exists: ' . $index);
|
||||
}
|
||||
// allow empty reset
|
||||
self::$elements[$index] = $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* get an element block at index
|
||||
* if not found will return false
|
||||
*
|
||||
* @param string $index
|
||||
* @return string
|
||||
* @throws HtmlBuilderExcpetion
|
||||
*/
|
||||
public static function getElement(string $index): string
|
||||
{
|
||||
if (!isset(self::$elements[$index])) {
|
||||
Error::setError('321', 'Index not found in elements', ['element' => $index]);
|
||||
throw new HtmlBuilderExcpetion('Index not found in elements array: ' . $index);
|
||||
}
|
||||
return self::$elements[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* set a replacement block at index
|
||||
* can be used for setting one block and using it agai
|
||||
*
|
||||
* @param string $index
|
||||
* @param string $content
|
||||
* @return void
|
||||
*/
|
||||
public static function setReplaceBlock(string $index, string $content): void
|
||||
{
|
||||
self::$replace[$index] = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* get replacement block at index, if not found return empty and set error
|
||||
*
|
||||
* @param string $index
|
||||
* @return string
|
||||
* @throws HtmlBuilderExcpetion
|
||||
*/
|
||||
public static function getReplaceBlock(string $index): string
|
||||
{
|
||||
if (!isset(self::$replace[$index])) {
|
||||
Error::setError('331', 'Index not found in replace block', ['replace' => $index]);
|
||||
throw new HtmlBuilderExcpetion('Index not found in replace block array: ' . $index);
|
||||
}
|
||||
return self::$replace[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* build and element on an index and either returns it or also sets it
|
||||
* into the replace block array
|
||||
* if index not found in relement list will return false
|
||||
*
|
||||
* @param string $index index of set element
|
||||
* @param array<string,string> $replace array of text to search (key) and replace (value) for
|
||||
* @return string
|
||||
* @throws HtmlBuilderExcpetion
|
||||
*/
|
||||
public static function buildElement(
|
||||
string $index,
|
||||
array $replace,
|
||||
string $replace_index = ''
|
||||
): string {
|
||||
try {
|
||||
self::getElement($index);
|
||||
} catch (HtmlBuilderExcpetion $e) {
|
||||
throw new HtmlBuilderExcpetion('Cannot fetch element with index: ' . $index, 0, $e);
|
||||
}
|
||||
if ($replace_index) {
|
||||
self::setReplaceBlock(
|
||||
$replace_index,
|
||||
self::replaceData(self::$elements[$index], $replace)
|
||||
);
|
||||
return self::getReplaceBlock($replace_index);
|
||||
} else {
|
||||
return self::replaceData(self::$elements[$index], $replace);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* main replace entries in text string
|
||||
* elements to be replaced are in {} brackets. if they are missing in the
|
||||
* replace array they will be added.
|
||||
* if the replace and content count is not the same then an error will be thrown
|
||||
*
|
||||
* @param string $data
|
||||
* @param array<string,string> $replace
|
||||
* @return string
|
||||
* @throws HtmlBuilderExcpetion
|
||||
*/
|
||||
public static function replaceData(string $data, array $replace): string
|
||||
{
|
||||
$to_replace = array_keys($replace);
|
||||
// all replace data must have {} around
|
||||
array_walk($to_replace, function (&$entry) {
|
||||
if (!str_starts_with($entry, '{')) {
|
||||
$entry = '{' . $entry;
|
||||
}
|
||||
if (!str_ends_with($entry, '}')) {
|
||||
$entry .= '}';
|
||||
}
|
||||
// do some validation?
|
||||
});
|
||||
// replace content
|
||||
return str_replace($to_replace, array_values($replace), $data);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -77,79 +77,79 @@ class SmartyExtend extends \Smarty
|
||||
public string $COMPILE_ID = '';
|
||||
// template vars
|
||||
/** @var string */
|
||||
public string $MASTER_TEMPLATE_NAME;
|
||||
public string $MASTER_TEMPLATE_NAME = '';
|
||||
/** @var string */
|
||||
public string $PAGE_FILE_NAME;
|
||||
public string $PAGE_FILE_NAME = '';
|
||||
/** @var string */
|
||||
public string $CONTENT_INCLUDE;
|
||||
public string $CONTENT_INCLUDE = '';
|
||||
/** @var string */
|
||||
public string $FORM_NAME;
|
||||
public string $FORM_NAME = '';
|
||||
/** @var string */
|
||||
public string $FORM_ACTION;
|
||||
public string $FORM_ACTION = '';
|
||||
/** @var string */
|
||||
public string $L_TITLE;
|
||||
public string $L_TITLE = '';
|
||||
/** @var string|int */
|
||||
public string|int $PAGE_WIDTH;
|
||||
// smarty include/set var
|
||||
/** @var string */
|
||||
public string $TEMPLATE_PATH;
|
||||
public string $TEMPLATE_PATH = '';
|
||||
/** @var string */
|
||||
public string $TEMPLATE_NAME;
|
||||
public string $TEMPLATE_NAME = '';
|
||||
/** @var string */
|
||||
public string $INC_TEMPLATE_NAME;
|
||||
public string $INC_TEMPLATE_NAME = '';
|
||||
/** @var string */
|
||||
public string $JS_TEMPLATE_NAME;
|
||||
public string $JS_TEMPLATE_NAME = '';
|
||||
/** @var string */
|
||||
public string $CSS_TEMPLATE_NAME;
|
||||
public string $CSS_TEMPLATE_NAME = '';
|
||||
/** @var string|null */
|
||||
public string|null $TEMPLATE_TRANSLATE;
|
||||
/** @var string|null */
|
||||
public string|null $JS_TRANSLATE;
|
||||
// core group
|
||||
/** @var string */
|
||||
public string $JS_CORE_TEMPLATE_NAME;
|
||||
public string $JS_CORE_TEMPLATE_NAME = '';
|
||||
/** @var string */
|
||||
public string $CSS_CORE_TEMPLATE_NAME;
|
||||
public string $CSS_CORE_TEMPLATE_NAME = '';
|
||||
/** @var string */
|
||||
public string $JS_CORE_INCLUDE;
|
||||
public string $JS_CORE_INCLUDE = '';
|
||||
/** @var string */
|
||||
public string $CSS_CORE_INCLUDE;
|
||||
public string $CSS_CORE_INCLUDE = '';
|
||||
// local names
|
||||
/** @var string */
|
||||
public string $JS_SPECIAL_TEMPLATE_NAME = '';
|
||||
/** @var string */
|
||||
public string $CSS_SPECIAL_TEMPLATE_NAME = '';
|
||||
/** @var string */
|
||||
public string $JS_INCLUDE;
|
||||
public string $JS_INCLUDE = '';
|
||||
/** @var string */
|
||||
public string $CSS_INCLUDE;
|
||||
public string $CSS_INCLUDE = '';
|
||||
/** @var string */
|
||||
public string $JS_SPECIAL_INCLUDE;
|
||||
public string $JS_SPECIAL_INCLUDE = '';
|
||||
/** @var string */
|
||||
public string $CSS_SPECIAL_INCLUDE;
|
||||
public string $CSS_SPECIAL_INCLUDE = '';
|
||||
/** @var string */
|
||||
public string $ADMIN_JAVASCRIPT;
|
||||
public string $ADMIN_JAVASCRIPT = '';
|
||||
/** @var string */
|
||||
public string $ADMIN_STYLESHEET;
|
||||
public string $ADMIN_STYLESHEET = '';
|
||||
/** @var string */
|
||||
public string $FRONTEND_JAVASCRIPT;
|
||||
public string $FRONTEND_JAVASCRIPT = '';
|
||||
/** @var string */
|
||||
public string $FRONTEND_STYLESHEET;
|
||||
public string $FRONTEND_STYLESHEET = '';
|
||||
// other smarty folder vars
|
||||
/** @var string */
|
||||
public string $INCLUDES;
|
||||
public string $INCLUDES = '';
|
||||
/** @var string */
|
||||
public string $JAVASCRIPT;
|
||||
public string $JAVASCRIPT = '';
|
||||
/** @var string */
|
||||
public string $CSS;
|
||||
public string $CSS = '';
|
||||
/** @var string */
|
||||
public string $FONT;
|
||||
public string $FONT = '';
|
||||
/** @var string */
|
||||
public string $PICTURES;
|
||||
public string $PICTURES = '';
|
||||
/** @var string */
|
||||
public string $CACHE_PICTURES;
|
||||
public string $CACHE_PICTURES = '';
|
||||
/** @var string */
|
||||
public string $CACHE_PICTURES_ROOT;
|
||||
public string $CACHE_PICTURES_ROOT = '';
|
||||
|
||||
// constructor class, just sets the language stuff
|
||||
/**
|
||||
@@ -373,7 +373,7 @@ class SmartyExtend extends \Smarty
|
||||
// check for template include
|
||||
if (
|
||||
$this->USE_INCLUDE_TEMPLATE === true &&
|
||||
!$this->TEMPLATE_NAME
|
||||
empty($this->TEMPLATE_NAME)
|
||||
) {
|
||||
$this->TEMPLATE_NAME = $this->CONTENT_INCLUDE;
|
||||
// add to cache & compile id
|
||||
@@ -390,7 +390,7 @@ class SmartyExtend extends \Smarty
|
||||
exit('MASTER TEMPLATE: ' . $this->MASTER_TEMPLATE_NAME . ' could not be found');
|
||||
}
|
||||
if (
|
||||
$this->TEMPLATE_NAME &&
|
||||
!empty($this->TEMPLATE_NAME) &&
|
||||
!file_exists($this->getTemplateDir()[0] . DIRECTORY_SEPARATOR . $this->TEMPLATE_NAME)
|
||||
) {
|
||||
exit('INCLUDE TEMPLATE: ' . $this->TEMPLATE_NAME . ' could not be found');
|
||||
@@ -418,7 +418,12 @@ class SmartyExtend extends \Smarty
|
||||
}
|
||||
}
|
||||
// if we can't find it, dump it
|
||||
if (!file_exists($this->getTemplateDir()[0] . DIRECTORY_SEPARATOR . $this->TEMPLATE_TRANSLATE)) {
|
||||
if (
|
||||
!file_exists(
|
||||
$this->getTemplateDir()[0] . DIRECTORY_SEPARATOR
|
||||
. $this->TEMPLATE_TRANSLATE
|
||||
)
|
||||
) {
|
||||
$this->TEMPLATE_TRANSLATE = null;
|
||||
}
|
||||
if (empty($this->JS_TRANSLATE)) {
|
||||
|
||||
7
www/vendor/composer/autoload_classmap.php
vendored
7
www/vendor/composer/autoload_classmap.php
vendored
@@ -39,6 +39,7 @@ return array(
|
||||
'CoreLibs\\Create\\Uids' => $baseDir . '/lib/CoreLibs/Create/Uids.php',
|
||||
'CoreLibs\\DB\\Extended\\ArrayIO' => $baseDir . '/lib/CoreLibs/DB/Extended/ArrayIO.php',
|
||||
'CoreLibs\\DB\\IO' => $baseDir . '/lib/CoreLibs/DB/IO.php',
|
||||
'CoreLibs\\DB\\Options\\Convert' => $baseDir . '/lib/CoreLibs/DB/Options/Convert.php',
|
||||
'CoreLibs\\DB\\SQL\\Interface\\SqlFunctions' => $baseDir . '/lib/CoreLibs/DB/SQL/Interface/SqlFunctions.php',
|
||||
'CoreLibs\\DB\\SQL\\PgSQL' => $baseDir . '/lib/CoreLibs/DB/SQL/PgSQL.php',
|
||||
'CoreLibs\\Debug\\FileWriter' => $baseDir . '/lib/CoreLibs/Debug/FileWriter.php',
|
||||
@@ -76,6 +77,12 @@ return array(
|
||||
'CoreLibs\\Security\\CreateKey' => $baseDir . '/lib/CoreLibs/Security/CreateKey.php',
|
||||
'CoreLibs\\Security\\Password' => $baseDir . '/lib/CoreLibs/Security/Password.php',
|
||||
'CoreLibs\\Security\\SymmetricEncryption' => $baseDir . '/lib/CoreLibs/Security/SymmetricEncryption.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\Block' => $baseDir . '/lib/CoreLibs/Template/HtmlBuilder/Block.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\Element' => $baseDir . '/lib/CoreLibs/Template/HtmlBuilder/Element.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\General\\Error' => $baseDir . '/lib/CoreLibs/Template/HtmlBuilder/General/Error.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\General\\HtmlBuilderExcpetion' => $baseDir . '/lib/CoreLibs/Template/HtmlBuilder/General/HtmlBuilderExcpetion.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\General\\Settings' => $baseDir . '/lib/CoreLibs/Template/HtmlBuilder/General/Settings.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\StringReplace' => $baseDir . '/lib/CoreLibs/Template/HtmlBuilder/StringReplace.php',
|
||||
'CoreLibs\\Template\\SmartyExtend' => $baseDir . '/lib/CoreLibs/Template/SmartyExtend.php',
|
||||
'FileUpload\\Core\\qqUploadedFile' => $baseDir . '/lib/FileUpload/Core/qqUploadedFile.php',
|
||||
'FileUpload\\Core\\qqUploadedFileForm' => $baseDir . '/lib/FileUpload/Core/qqUploadedFileForm.php',
|
||||
|
||||
7
www/vendor/composer/autoload_static.php
vendored
7
www/vendor/composer/autoload_static.php
vendored
@@ -90,6 +90,7 @@ class ComposerStaticInit10fe8fe2ec4017b8644d2b64bcf398b9
|
||||
'CoreLibs\\Create\\Uids' => __DIR__ . '/../..' . '/lib/CoreLibs/Create/Uids.php',
|
||||
'CoreLibs\\DB\\Extended\\ArrayIO' => __DIR__ . '/../..' . '/lib/CoreLibs/DB/Extended/ArrayIO.php',
|
||||
'CoreLibs\\DB\\IO' => __DIR__ . '/../..' . '/lib/CoreLibs/DB/IO.php',
|
||||
'CoreLibs\\DB\\Options\\Convert' => __DIR__ . '/../..' . '/lib/CoreLibs/DB/Options/Convert.php',
|
||||
'CoreLibs\\DB\\SQL\\Interface\\SqlFunctions' => __DIR__ . '/../..' . '/lib/CoreLibs/DB/SQL/Interface/SqlFunctions.php',
|
||||
'CoreLibs\\DB\\SQL\\PgSQL' => __DIR__ . '/../..' . '/lib/CoreLibs/DB/SQL/PgSQL.php',
|
||||
'CoreLibs\\Debug\\FileWriter' => __DIR__ . '/../..' . '/lib/CoreLibs/Debug/FileWriter.php',
|
||||
@@ -127,6 +128,12 @@ class ComposerStaticInit10fe8fe2ec4017b8644d2b64bcf398b9
|
||||
'CoreLibs\\Security\\CreateKey' => __DIR__ . '/../..' . '/lib/CoreLibs/Security/CreateKey.php',
|
||||
'CoreLibs\\Security\\Password' => __DIR__ . '/../..' . '/lib/CoreLibs/Security/Password.php',
|
||||
'CoreLibs\\Security\\SymmetricEncryption' => __DIR__ . '/../..' . '/lib/CoreLibs/Security/SymmetricEncryption.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\Block' => __DIR__ . '/../..' . '/lib/CoreLibs/Template/HtmlBuilder/Block.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\Element' => __DIR__ . '/../..' . '/lib/CoreLibs/Template/HtmlBuilder/Element.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\General\\Error' => __DIR__ . '/../..' . '/lib/CoreLibs/Template/HtmlBuilder/General/Error.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\General\\HtmlBuilderExcpetion' => __DIR__ . '/../..' . '/lib/CoreLibs/Template/HtmlBuilder/General/HtmlBuilderExcpetion.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\General\\Settings' => __DIR__ . '/../..' . '/lib/CoreLibs/Template/HtmlBuilder/General/Settings.php',
|
||||
'CoreLibs\\Template\\HtmlBuilder\\StringReplace' => __DIR__ . '/../..' . '/lib/CoreLibs/Template/HtmlBuilder/StringReplace.php',
|
||||
'CoreLibs\\Template\\SmartyExtend' => __DIR__ . '/../..' . '/lib/CoreLibs/Template/SmartyExtend.php',
|
||||
'FileUpload\\Core\\qqUploadedFile' => __DIR__ . '/../..' . '/lib/FileUpload/Core/qqUploadedFile.php',
|
||||
'FileUpload\\Core\\qqUploadedFileForm' => __DIR__ . '/../..' . '/lib/FileUpload/Core/qqUploadedFileForm.php',
|
||||
|
||||
Reference in New Issue
Block a user