Compare commits

...

3 Commits

Author SHA1 Message Date
Clemens Schwaighofer
c1212d8116 Add basic Test run class 2021-10-27 13:25:59 +09:00
Clemens Schwaighofer
5230cbf5d3 Update DB IO classes with better RETURNING data handle
Dropped old insert_id and insert_id_ext and only kepy insert_id_arr.
Added insert_id_pk_name to get the inserted pk name.
Insert RETURNING also works on non set pk name with RETURNING set

Moved the get insert (RETURNING) into method so it can be called from
both dbExec and dbExecute flow.

Error code 31 is only thrown if no returning is set and insert flow
cannot find a primary key for this table

Update all old insert_id calls from other classes
2021-10-27 12:18:28 +09:00
Clemens Schwaighofer
a6b42f243f Update CoreLibs with phpstan level 8, add qqFileUploader implementation base, add base Test class for testing 2021-10-26 16:35:26 +09:00
48 changed files with 1554 additions and 821 deletions

View File

@@ -70,14 +70,14 @@ return [
// Thus, both first-party and third-party code being used by
// your application should be included in this list.
'directory_list' => [
// Change this to include the folders you wish to analyze
// (and the folders of their dependencies)
'www',
// To speed up analysis, we recommend going back later and
// limiting this to only the vendor/ subdirectories your
// project depends on.
// `phan --init` will generate a list of folders for you
//'www/vendor',
// Change this to include the folders you wish to analyze
// (and the folders of their dependencies)
'www',
// To speed up analysis, we recommend going back later and
// limiting this to only the vendor/ subdirectories your
// project depends on.
// `phan --init` will generate a list of folders for you
//'www/vendor',
],

View File

@@ -0,0 +1 @@
phan --progress-bar -C --analyze-twice

View File

@@ -0,0 +1 @@
phpstan

View File

@@ -1,9 +1,11 @@
<?php
<?php // phpcs:ignore PSR1.Files.SideEffects
// Boostrap file for PHPstand
// sets the _SERVER['HTTP_HOST'] var so we can have DB detection
$_SERVER['HTTP_HOST'] = 'soba.tokyo.tequila.jp';
// so www/includes/edit_base.php works
require_once('www/lib/Smarty/SmartyBC.class.php');
// for whatever reason it does not load that from the confing.master.php
define('BASE_NAME', '');
// __END__

View File

@@ -2,7 +2,7 @@
parameters:
tmpDir: /tmp/phpstan-corelibs
level: 5
level: max
paths:
- %currentWorkingDirectory%/www
bootstrapFiles:
@@ -17,24 +17,17 @@ parameters:
- www/lib/Smarty/Autoloader.php
- www/lib/CoreLibs/Template/SmartyExtend.php
excludes_analyse:
# no check admin
- www/admin/qq_file_upload_front.php
- www/admin/qq_file_upload_ajax.php
# do not check old qq file uploader tests
- www/admin/qq_file_upload_*.php
# ignore all test files
- www/admin/class_test*php
- www/admin/error_test.php
# admin synlink files
- www/admin/edit_access.php
- www/admin/edit_groups.php
- www/admin/edit_languages.php
- www/admin/edit_menu_group.php
- www/admin/edit_order.php
- www/admin/edit_pages.php
- www/admin/edit_schemes.php
- www/admin/edit_users.php
- www/admin/edit_visible_group.php
- www/admin/edit_*.php
# ignore admin header stuff
- www/includes/admin_header.php # ignore the admin include stuff
# - www/includes/admin_header.php # ignore the admin include stuff
- www/includes/admin_footer.php # ignore the admin include stuff
# deprecated files
- www/includes/admin_set_paths.php # ignore the admin include stuff
- www/includes/admin_smarty.php # ignore the admin include stuff
# folders with data no check needed
@@ -43,10 +36,9 @@ parameters:
- www/log
- www/media
- www/tmp
- www/lib/pChart
- www/lib/pChart2.1.4
- www/lib/Smarty
- www/lib/smarty-3.1.30
- www/lib/pChart*
- www/lib/Smarty*
- www/lib/smarty*
# ignore composer
- www/vendor
# ignore the smartyextend

View File

@@ -52,83 +52,117 @@ echo "DB_CONFIG_SET constant: <pre>" . print_r(DB_CONFIG, true) . "</pre><br>";
// DB client encoding
print "DB Client encoding: " . $db->dbGetEncoding() . "<br>";
while ($res = $db->dbReturn("SELECT * FROM max_test", 0, true)) {
while (is_array($res = $db->dbReturn("SELECT * FROM max_test", 0, true))) {
print "TIME: " . $res['time'] . "<br>";
}
print "CACHED DATA: <pre>" . print_r($db->cursor_ext, true) . "</pre><br>";
while ($res = $db->dbReturn("SELECT * FROM max_test")) {
while (is_array($res = $db->dbReturn("SELECT * FROM max_test"))) {
print "[CACHED] TIME: " . $res['time'] . "<br>";
}
// alternate check for valid data
// while (($res = $db->dbReturn("SELECT * FROM max_test")) !== false) {
// print "[CACHED] TIME: " . $res['time'] . "<br>";
// }
print "<pre>";
$status = $db->dbExec("INSERT INTO foo (test) VALUES ('FOO TEST " . time() . "') RETURNING test");
// truncate test_foo table before testing
print "<b>TRUNCATE test_foo</b><br>";
$query = "TRUNCATE test_foo";
$db->dbExec($query);
print "<b>TRUNCATE test_foobar</b><br>";
$query = "TRUNCATE test_foobar";
$db->dbExec($query);
$status = $db->dbExec("INSERT INTO test_foo (test) VALUES ('FOO TEST " . time() . "') RETURNING test");
print "DIRECT INSERT STATUS: $status | "
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING EXT[test]: " . print_r($db->dbGetReturningExt('test'), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
// should throw deprecated error
// $db->getReturningExt();
print "DIRECT INSERT PREVIOUS INSERTED: "
. print_r($db->dbReturnRow("SELECT foo_id, test FROM foo WHERE foo_id = " . $db->dbGetInsertPK()), true) . "<br>";
$db->dbPrepare("ins_foo", "INSERT INTO foo (test) VALUES ($1)");
$status = $db->dbExecute("ins_foo", array('BAR TEST ' . time()));
print "PREPARE INSERT STATUS: $status | "
. print_r($db->dbReturnRow("SELECT test_foo_id, test FROM test_foo "
. "WHERE test_foo_id = " . $db->dbGetInsertPK()), true) . "<br>";
// PREPARED INSERT
$db->dbPrepare("ins_test_foo", "INSERT INTO test_foo (test) VALUES ($1) RETURNING test");
$status = $db->dbExecute("ins_test_foo", array('BAR TEST ' . time()));
print "PREPARE INSERT[ins_test_foo] STATUS: $status | "
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING RETURN: " . print_r($db->dbGetReturningArray(), true) . "<br>";
print "PREPARE INSERT PREVIOUS INSERTED: "
. print_r($db->dbReturnRow("SELECT foo_id, test FROM foo WHERE foo_id = " . $db->dbGetInsertPK()), true) . "<br>";
. print_r($db->dbReturnRow("SELECT test_foo_id, test FROM test_foo "
. "WHERE test_foo_id = " . $db->dbGetInsertPK()), true) . "<br>";
// returning test with multiple entries
// $status = $db->db_exec(
// "INSERT INTO foo (test) VALUES "
// "INSERT INTO test_foo (test) VALUES "
// . "('BAR 1 " . time() . "'), "
// . "('BAR 2 " . time() . "'), "
// . "('BAR 3 " . time() . "') "
// . "RETURNING foo_id"
// . "RETURNING test_foo_id"
// );
$status = $db->dbExec(
"INSERT INTO foo (test) VALUES "
"INSERT INTO test_foo (test) VALUES "
. "('BAR 1 " . time() . "'), "
. "('BAR 2 " . time() . "'), "
. "('BAR 3 " . time() . "') "
. "RETURNING foo_id, test"
. "RETURNING test_foo_id, test"
);
print "DIRECT MULTIPLE INSERT STATUS: $status | "
print "DIRECT MULTIPLE INSERT WITH RETURN STATUS: $status | "
. "PRIMARY KEYS: " . print_r($db->dbGetInsertPK(), true) . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING EXT[test]: " . print_r($db->dbGetReturningExt('test'), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
// no returning, but not needed ;
$status = $db->dbExec("INSERT INTO foo (test) VALUES ('FOO; TEST " . time() . "');");
print "DIRECT INSERT STATUS: $status | "
$status = $db->dbExec("INSERT INTO test_foo (test) VALUES ('FOO; TEST " . time() . "');");
print "DIRECT INSERT NO RETURN STATUS: $status | "
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
// UPDATE WITH RETURNING
$status = $db->dbExec("UPDATE foo SET test = 'SOMETHING DIFFERENT' WHERE foo_id = 3688452 RETURNING test");
print "UPDATE STATUS: $status | "
$status = $db->dbExec("UPDATE test_foo SET test = 'SOMETHING DIFFERENT' WHERE test_foo_id = 3688452 RETURNING test");
print "UPDATE WITH RETURN STATUS: $status | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
// INSERT WITH NO RETURNING
$status = $db->dbExec("INSERT INTO test_foobar (type, integer) VALUES ('WITH DATA', 123)");
print "INSERT WITH NO PRIMARY KEY NO RETURNING STATUS: $status | "
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
$status = $db->dbExec("INSERT INTO test_foobar (type, integer) VALUES ('WITH DATA', 123) RETURNING type, integer");
print "INSERT WITH NO PRIMARY KEY WITH RETURNING STATUS: $status | "
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
print "</pre>";
// REEAD PREPARE
// READ PREPARE
if (
$db->dbPrepare(
'sel_foo',
"SELECT foo_id, test, some_bool, string_a, number_a, number_a_numeric, some_time "
. "FROM foo ORDER BY foo_id DESC LIMIT 5"
'sel_test_foo',
"SELECT test_foo_id, test, some_bool, string_a, number_a, number_a_numeric, some_time "
. "FROM test_foo ORDER BY test_foo_id DESC LIMIT 5"
) === false
) {
print "Error in sel_foo prepare<br>";
print "Error in sel_test_foo prepare<br>";
} else {
$max_rows = 6;
// do not run this in dbFetchArray directly as
// dbFetchArray(dbExecute(...))
// this will end in an endless loop
$cursor = $db->dbExecute('sel_foo', []);
$cursor = $db->dbExecute('sel_test_foo', []);
$i = 1;
while (($res = $db->dbFetchArray($cursor, true)) !== false) {
print "DB PREP EXEC FETCH ARR: " . $i . ": <pre>" . print_r($res, true) . "</pre><br>";
@@ -138,14 +172,16 @@ if (
# db write class test
$table = 'foo';
$table = 'test_foo';
print "TABLE META DATA: " . DgS::printAr($db->dbShowTableMetaData($table)) . "<br>";
// insert first, then use primary key to update
$primary_key = ''; # unset
$db_write_table = array('test', 'string_a', 'number_a', 'some_bool');
// $db_write_table = array('test');
$object_fields_not_touch = array();
$object_fields_not_update = array();
$data = array('test' => 'BOOL TEST SOMETHING ' . time(), 'string_a' => 'SOME TEXT', 'number_a' => 5);
$db_write_table = ['test', 'string_a', 'number_a', 'some_bool'];
$object_fields_not_touch = [];
$object_fields_not_update = [];
$data = [
'test' => 'dbWriteDataExt: BOOL TEST SOMETHING ' . time(), 'string_a' => 'SOME TEXT', 'number_a' => 5
];
$primary_key = $db->dbWriteDataExt(
$db_write_table,
$primary_key,
@@ -154,8 +190,10 @@ $primary_key = $db->dbWriteDataExt(
$object_fields_not_update,
$data
);
print "Wrote to DB tabel $table and got primary key $primary_key<br>";
$data = array('test' => 'BOOL TEST ON ' . time(), 'string_a' => '', 'number_a' => 0, 'some_bool' => 1);
print "Wrote to DB tabel $table with data " . print_r($data, true) . " and got primary key $primary_key<br>";
$data = [
'test' => 'dbWriteDataExt: BOOL TEST ON ' . time(), 'string_a' => '', 'number_a' => 0, 'some_bool' => 1
];
$primary_key = $db->dbWriteDataExt(
$db_write_table,
$primary_key,
@@ -164,8 +202,10 @@ $primary_key = $db->dbWriteDataExt(
$object_fields_not_update,
$data
);
print "Wrote to DB tabel $table and got primary key $primary_key<br>";
$data = array('test' => 'BOOL TEST OFF ' . time(), 'string_a' => null, 'number_a' => null, 'some_bool' => 0);
print "Wrote to DB tabel $table with data " . print_r($data, true) . " and got primary key $primary_key<br>";
$data = [
'test' => 'dbWriteDataExt: BOOL TEST OFF ' . time(), 'string_a' => null, 'number_a' => null, 'some_bool' => 0
];
$primary_key = $db->dbWriteDataExt(
$db_write_table,
$primary_key,
@@ -174,8 +214,10 @@ $primary_key = $db->dbWriteDataExt(
$object_fields_not_update,
$data
);
print "Wrote to DB tabel $table and got primary key $primary_key<br>";
$data = array('test' => 'BOOL TEST UNSET ' . time());
print "Wrote to DB tabel $table with data " . print_r($data, true) . " and got primary key $primary_key<br>";
$data = [
'test' => 'dbWriteDataExt: BOOL TEST UNSET ' . time()
];
$primary_key = $db->dbWriteDataExt(
$db_write_table,
$primary_key,
@@ -184,7 +226,7 @@ $primary_key = $db->dbWriteDataExt(
$object_fields_not_update,
$data
);
print "Wrote to DB tabel $table and got primary key $primary_key<br>";
print "Wrote to DB tabel $table with data " . print_r($data, true) . " and got primary key $primary_key<br>";
// return Array Test
$query = "SELECT type, sdate, integer FROM foobar";
@@ -192,7 +234,8 @@ $data = $db->dbReturnArray($query, true);
print "Full foobar list: <br><pre>" . print_r($data, true) . "</pre><br>";
# async test queries
/* $db->dbExecAsync("SELECT test FROM foo, (SELECT pg_sleep(10)) as sub WHERE foo_id IN (27, 50, 67, 44, 10)");
/*
$db->dbExecAsync("SELECT test FROM test_foo, (SELECT pg_sleep(10)) as sub WHERE test_foo_id IN (27, 50, 67, 44, 10)");
echo "WAITING FOR ASYNC: ";
$chars = array('|', '/', '-', '\\');
while (($ret = $db->dbCheckAsync()) === true)
@@ -213,7 +256,7 @@ while ($res = $db->dbFetchArray())
echo "RES: " . $res['test'] . "<br>";
}
# test async insert
$db->dbExecAsync("INSERT INTO foo (Test) VALUES ('ASYNC TEST " . time() . "')");
$db->dbExecAsync("INSERT INTO test_foo (Test) VALUES ('ASYNC TEST " . time() . "')");
echo "WAITING FOR ASYNC INSERT: ";
while (($ret = $db->dbCheckAsync()) === true)
{
@@ -223,7 +266,12 @@ while (($ret = $db->dbCheckAsync()) === true)
}
print "<br>END STATUS: " . $ret . " | PK: " . $db->insert_id . "<br>";
print "ASYNC PREVIOUS INSERTED: "
. print_r($db->dbReturnRow("SELECT foo_id, test FROM foo WHERE foo_id = " . $db->insert_id), true) . "<br>"; */
. print_r(
$db->dbReturnRow("SELECT test_foo_id, test FROM test_foo WHERE test_foo_id = "
. $db->insert_id),
true
) . "<br>";
*/
$to_db_version = '9.1.9';
print "VERSION DB: " . $db->dbVersion() . "<br>";
@@ -233,16 +281,17 @@ print "DB Version equal $to_db_version: " . $db->dbCompareVersion('=' . $to_db_v
print "DB Version bigger than $to_db_version: " . $db->dbCompareVersion('>=' . $to_db_version) . "<br>";
print "DB Version bigger $to_db_version: " . $db->dbCompareVersion('>' . $to_db_version) . "<br>";
/* $q = "SELECT FOO FRO BAR";
// $q = "Select * from foo";
$foo = $db->dbExecAsync($q);
/*
$q = "Select * from test_foo";
$test_foo = $db->dbExecAsync($q);
print "[ERR] Query: " . $q . "<br>";
print "[ERR] RESOURCE: $foo<br>";
print "[ERR] RESOURCE: $test_foo<br>";
while (($ret = $db->dbCheckAsync()) === true)
{
print "[ERR]: $ret<br>";
sleep(5);
} */
}
*/
// search path check
$q = "SHOW search_path";
@@ -256,7 +305,7 @@ $status = $db->dbExec(
. "('TIME: " . time() . "', " . rand(1, 10) . ")"
);
print "OTHER SCHEMA INSERT STATUS: "
. $status . " | PK NAME: " . $db->pk_name . ", PRIMARY KEY: " . $db->insert_id . "<br>";
. $status . " | PK NAME: " . $db->dbGetInsertPKName() . ", PRIMARY KEY: " . $db->dbGetInsertPK() . "<br>";
print "<b>NULL TEST DB READ</b><br>";
$q = "SELECT uid, null_varchar, null_int FROM test_null_data WHERE uid = 'A'";

View File

@@ -33,7 +33,7 @@ if (!defined('DS')) {
}
// find trigger name "admin/" or "frontend/" in the getcwd() folder
foreach (['admin', 'frontend'] as $folder) {
if (strstr(getcwd(), DS . $folder)) {
if (strstr(getcwd() ?: '', DS . $folder)) {
define('CONTENT_PATH', $folder . DS);
break;
}

View File

@@ -3,3 +3,5 @@
declare(strict_types=1);
require 'config.php';
// __END__

View File

@@ -12,7 +12,7 @@ declare(strict_types=1);
//------------------------------ variable init start
// for dev test we set full error reporting; writes everything, except E_ERROR into logs/php_error-<day>.log
if ($DEBUG_ALL && $ENABLE_ERROR_HANDLING) {
if (!empty($DEBUG_ALL) && !empty($ENABLE_ERROR_HANDLING)) {
include BASE . LIBS . "Error.Handling.php";
}
// predefine vars
@@ -82,7 +82,7 @@ if (!$login->login) {
// automatic hide for DEBUG messages on live server
// can be overridden when setting DEBUG_ALL_OVERRIDE on top of the script (for emergency debugging of one page only)
if ((TARGET == 'live' || TARGET == 'remote') && !$DEBUG_ALL_OVERRIDE) {
if ((TARGET == 'live' || TARGET == 'remote') && !empty($DEBUG_ALL_OVERRIDE)) {
foreach (['debug', 'echo', 'print'] as $target) {
$login->log->setLogLevelAll($target, false);
$cms->log->setLogLevelAll($target, false);

View File

@@ -175,7 +175,7 @@ if ($form->my_page_name == 'edit_order') {
$options_name = [];
$options_selected = [];
// DB read data for menu
while ($res = $form->dbReturn($q)) {
while (is_array($res = $form->dbReturn($q))) {
$row_data[] = [
"id" => $res[$table_name . "_id"],
"name" => $res["name"],

View File

@@ -72,44 +72,70 @@ use CoreLibs\Check\Password;
class Login extends \CoreLibs\DB\IO
{
/** @var string */
private $euid; // the user id var
// is set to one if login okay, or EUID is set and user is okay to access this page
/** @var bool */
private $permission_okay = false;
/** @var string */
public $login; // pressed login
/** @var string */
private $action; // master action command
/** @var string */
private $username; // login name
/** @var string */
private $password; // login password
/** @var string */
private $logout; // logout button
// login error code, can be matched to the array login_error_msg, which holds the string
/** @var int */
private $login_error = 0;
/** @var bool */
private $password_change = false; // if this is set to true, the user can change passwords
/** @var bool */
private $password_change_ok = false; // password change was successful
// can we reset password and mail to user with new password set screen
/** @var bool */
private $password_forgot = false;
/** @var bool */
private $password_forgot_ok = false; // password forgot mail send ok
/** @var string */
private $change_password;
/** @var string */
private $pw_username;
/** @var string */
private $pw_old_password;
/** @var string */
private $pw_new_password;
/** @var string */
private $pw_new_password_confirm;
/** @var array<string> */
private $pw_change_deny_users = []; // array of users for which the password change is forbidden
/** @var string */
private $logout_target;
/** @var int */
private $max_login_error_count = -1;
/** @var array<string> */
private $lock_deny_users = [];
// if we have password change we need to define some rules
/** @var int */
private $password_min_length = PASSWORD_MIN_LENGTH;
// max length is fixed as 255 (for input type max), if set highter, it will be set back to 255
/** @var int */
private $password_max_length = PASSWORD_MAX_LENGTH;
// can have several regexes, if nothing set, all is ok
/** @var array<string> */
private $password_valid_chars = [
// '^(?=.*\d)(?=.*[A-Za-z])[0-9A-Za-z!@#$%]{8,}$',
// '^(?.*(\pL)u)(?=.*(\pN)u)(?=.*([^\pL\pN])u).{8,}',
];
// all possible login error conditions
/** @var array<mixed> */
private $login_error_msg = [];
// this is an array holding all strings & templates passed from the outside (translation)
/** @var array<mixed> */
private $login_template = [
'strings' => [],
'password_change' => '',
@@ -117,18 +143,23 @@ class Login extends \CoreLibs\DB\IO
];
// acl vars
/** @var array<mixed> */
public $acl = [];
/** @var array<mixed> */
public $default_acl_list = [];
// login html, if we are on an ajax page
/** @var string|null */
private $login_html = '';
/** @var bool */
private $login_is_ajax_page = false;
// language
/** @var \CoreLibs\Language\L10n */
public $l;
/**
* constructor, does ALL, opens db, works through connection checks, closes itself
* @param array $db_config db config array
* @param array<mixed> $db_config db config array
*/
public function __construct(array $db_config)
{
@@ -225,7 +256,7 @@ class Login extends \CoreLibs\DB\IO
$_SESSION['DEFAULT_ACL_LIST'] = [];
// read the current edit_access_right list into an array
$q = "SELECT level, type, name FROM edit_access_right WHERE level >= 0 ORDER BY level";
while ($res = $this->dbReturn($q)) {
while (is_array($res = $this->dbReturn($q))) {
// level to description format (numeric)
$this->default_acl_list[$res['level']] = [
'type' => $res['type'],
@@ -387,8 +418,11 @@ class Login extends \CoreLibs\DB\IO
// password match is done in script, against old plain or new blowfish encypted
. "(LOWER(username) = '" . $this->dbEscapeString(strtolower($this->username)) . "') ";
$res = $this->dbReturn($q);
// username is wrong, but we throw for wrong username and wrong password the same error
if (!$this->cursor_ext[md5($q)]['num_rows']) {
if (!is_array($res)) {
$this->login_error = 1009;
$this->permission_okay = false;
} elseif (!$this->cursor_ext[md5($q)]['num_rows']) {
// username is wrong, but we throw for wrong username and wrong password the same error
$this->login_error = 1010;
} else {
// if login errors is half of max errors and the last login error
@@ -426,7 +460,7 @@ class Login extends \CoreLibs\DB\IO
$_SESSION['EUID'] = $this->euid = $res['edit_user_id'];
// check if user is okay
$this->loginCheckPermissions();
if (!$this->login_error) {
if ($this->login_error == 0) {
// now set all session vars and read page permissions
$GLOBALS['DEBUG_ALL'] = $_SESSION['DEBUG_ALL'] = $res['debug'];
$GLOBALS['DB_DEBUG'] = $_SESSION['DB_DEBUG'] = $res['db_debug'];
@@ -470,6 +504,9 @@ class Login extends \CoreLibs\DB\IO
. "AND epa.enabled = 1 AND epa.edit_group_id = " . $res["edit_group_id"] . " "
. "ORDER BY ep.order_number";
while ($res = $this->dbReturn($q)) {
if (!is_array($res)) {
break;
}
// page id array for sub data readout
$edit_page_ids[$res['edit_page_id']] = $res['cuid'];
// create the array for pages
@@ -496,22 +533,20 @@ class Login extends \CoreLibs\DB\IO
$pages_acl[$res['filename']] = $res['level'];
} // for each page
// get the visible groups for all pages and write them to the pages
$_edit_page_id = 0;
$q = "SELECT epvg.edit_page_id, name, flag "
. "FROM edit_visible_group evp, edit_page_visible_group epvg "
. "WHERE evp.edit_visible_group_id = epvg.edit_visible_group_id "
. "AND epvg.edit_page_id IN (" . join(', ', array_keys($edit_page_ids)) . ") "
. "ORDER BY epvg.edit_page_id";
while ($res = $this->dbReturn($q)) {
while (is_array($res = $this->dbReturn($q))) {
$pages[$edit_page_ids[$res['edit_page_id']]]['visible'][$res['name']] = $res['flag'];
}
// get the same for the query strings
$_edit_page_id = 0;
$q = "SELECT eqs.edit_page_id, name, value, dynamic FROM edit_query_string eqs "
. "WHERE enabled = 1 AND edit_page_id "
. "IN (" . join(', ', array_keys($edit_page_ids)) . ") "
. "ORDER BY eqs.edit_page_id";
while ($res = $this->dbReturn($q)) {
while (is_array($res = $this->dbReturn($q))) {
$pages[$edit_page_ids[$res['edit_page_id']]]['query'][] = [
'name' => $res['name'],
'value' => $res['value'],
@@ -519,14 +554,13 @@ class Login extends \CoreLibs\DB\IO
];
}
// get the page content and add them to the page
$_edit_page_id = 0;
$q = "SELECT epc.edit_page_id, epc.name, epc.uid, epc.order_number, "
. "epc.online, ear.level, ear.type "
. "FROM edit_page_content epc, edit_access_right ear "
. "WHERE epc.edit_access_right_id = ear.edit_access_right_id AND "
. "epc.edit_page_id IN (" . join(', ', array_keys($edit_page_ids)) . ") "
. "ORDER BY epc.order_number";
while ($res = $this->dbReturn($q)) {
while (is_array($res = $this->dbReturn($q))) {
$pages[$edit_page_ids[$res['edit_page_id']]]['content'][$res['uid']] = [
'name' => $res['name'],
'uid' => $res['uid'],
@@ -550,13 +584,13 @@ class Login extends \CoreLibs\DB\IO
$unit_access = [];
$eauid = [];
$unit_acl = [];
while ($res = $this->dbReturn($q)) {
while (is_array($res = $this->dbReturn($q))) {
// read edit access data fields and drop them into the unit access array
$q_sub = "SELECT name, value "
. "FROM edit_access_data "
. "WHERE enabled = 1 AND edit_access_id = " . $res['edit_access_id'];
$ea_data = [];
while ($res_sub = $this->dbReturn($q_sub)) {
while (is_array($res_sub = $this->dbReturn($q_sub))) {
$ea_data[$res_sub['name']] = $res_sub['value'];
}
// build master unit array
@@ -583,7 +617,7 @@ class Login extends \CoreLibs\DB\IO
$_SESSION['EAID'] = $eauid;
} // user has permission to THIS page
} // user was not enabled or other login error
if ($this->login_error) {
if ($this->login_error && is_array($res)) {
$login_error_date_first = '';
if ($res['login_error_count'] == 0) {
$login_error_date_first = ", login_error_date_first = NOW()";
@@ -633,6 +667,11 @@ class Login extends \CoreLibs\DB\IO
. "AND filename = '" . $this->page_name . "' "
. "AND eg.enabled = 1 AND epa.enabled = 1";
$res = $this->dbReturnRow($q);
if (!is_array($res)) {
$this->login_error = 109;
$this->permission_okay = false;
return $this->permission_okay;
}
// unset mem limit if debug is set to 1
// if (
// ($GLOBALS["DEBUG_ALL"] || $GLOBALS["DB_DEBUG"] ||
@@ -795,10 +834,14 @@ class Login extends \CoreLibs\DB\IO
/**
* checks if this edit access id is valid
* @param int|null $edit_access_id access id pk to check
* @return bool true/false: if the edit access is not in the valid list: false
* @return bool true/false: if the edit access is not
* in the valid list: false
*/
public function loginCheckEditAccess($edit_access_id): bool
{
if ($edit_access_id === null) {
return false;
}
if (array_key_exists($edit_access_id, $this->acl['unit'])) {
return true;
} else {
@@ -943,7 +986,7 @@ class Login extends \CoreLibs\DB\IO
/**
* prints out login html part if no permission (error) is set
* @return ?string html data for login page, or null for nothing
* @return string|null html data for login page, or null for nothing
*/
private function loginPrintLogin()
{
@@ -958,7 +1001,7 @@ class Login extends \CoreLibs\DB\IO
$LOGOUT_TARGET = "";
}
$html_string = $this->login_template['template'];
$html_string = (string)$this->login_template['template'];
// if password change is okay
if ($this->password_change) {
@@ -1099,6 +1142,8 @@ class Login extends \CoreLibs\DB\IO
$error_msgs = [
// actually obsolete
'100' => $this->l->__('Fatal Error: <b>[EUID] came in as GET/POST!</b>'),
// query errors
'1009' => $this->l->__('Fatal Error: <b>Login query reading failed<b>'),
// user not found
'1010' => $this->l->__('Fatal Error: <b>Login Failed - Wrong Username or Password</b>'),
// blowfish password wrong
@@ -1111,6 +1156,7 @@ class Login extends \CoreLibs\DB\IO
'103' => $this->l->__('Fatal Error: <b>You do not have the rights to access this Page</b>'),
'104' => $this->l->__('Fatal Error: <b>Login Failed - User not enabled</b>'),
'105' => $this->l->__('Fatal Error: <b>Login Failed - User is locked</b>'),
'109' => $this->l->__('Fatal Error: <b>Check permission query reading failed</b>'),
// actually this is an illegal user, but I mask it
'220' => $this->l->__('Fatal Error: <b>Password change - The user could not be found</b>'),
'200' => $this->l->__('Fatal Error: <b>Password change - Please enter username and old password</b>'),
@@ -1123,7 +1169,8 @@ class Login extends \CoreLibs\DB\IO
// for OK password change
'300' => $this->l->__('Success: <b>Password change successful</b>'),
// this is bad bad error
'9999' => $this->l->__('Fatal Error: <b>necessary crypt engine could not be found</b>. Login is impossible')
'9999' => $this->l->__('Fatal Error: <b>necessary crypt engine could not be found</b>. '
. 'Login is impossible'),
];
// if password change is okay
@@ -1280,7 +1327,7 @@ EOM;
'_FILES' => $_FILES,
'error' => $this->login_error
];
$data_binary = $this->dbEscapeBytea(bzcompress(serialize($_data_binary)));
$data_binary = $this->dbEscapeBytea((string)bzcompress(serialize($_data_binary)));
// SQL querie for log entry
$q = "INSERT INTO edit_log "
. "(username, password, euid, event_date, event, error, data, data_binary, page, "
@@ -1327,6 +1374,7 @@ EOM;
public function loginCheckEditAccessId(?int $edit_access_id): ?int
{
if (
$edit_access_id !== null &&
isset($_SESSION['UNIT']) &&
is_array($_SESSION['UNIT']) &&
!array_key_exists($edit_access_id, $_SESSION['UNIT'])

View File

@@ -34,51 +34,80 @@ namespace CoreLibs\Admin;
class Backend extends \CoreLibs\DB\IO
{
// page name
/** @var array<mixed> */
public $menu = [];
/** @var int|string */
public $menu_show_flag = 0; // top menu flag (mostly string)
// action ids
/** @var array<string> */
public $action_list = [
'action', 'action_id', 'action_sub_id', 'action_yes', 'action_flag',
'action_menu', 'action_value', 'action_error', 'action_loaded'
];
/** @var string */
public $action;
/** @var string|int */
public $action_id;
/** @var string|int */
public $action_sub_id;
/** @var string|int|bool */
public $action_yes;
/** @var string */
public $action_flag;
/** @var string */
public $action_menu;
/** @var string */
public $action_loaded;
/** @var string */
public $action_value;
/** @var string */
public $action_error;
// ACL array variable if we want to set acl data from outisde
/** @var array<mixed> */
public $acl = [];
/** @var int */
public $default_acl;
// queue key
/** @var string */
public $queue_key;
// the current active edit access id
/** @var int */
public $edit_access_id;
// error/warning/info messages
/** @var array<mixed> */
public $messages = [];
/** @var int */
public $error = 0;
/** @var int */
public $warning = 0;
/** @var int */
public $info = 0;
// internal lang & encoding vars
/** @var string */
public $lang_dir = '';
/** @var string */
public $lang;
/** @var string */
public $lang_short;
/** @var string */
public $encoding;
// language
/** @var \CoreLibs\Language\L10n */
public $l;
// smarty publics [end processing in smarty class]
/** @var array<mixed> */
public $DATA;
/** @var array<mixed> */
public $HEADER;
/** @var array<mixed> */
public $DEBUG_DATA;
/** @var array<mixed> */
public $CONTENT_DATA;
// CONSTRUCTOR / DECONSTRUCTOR |====================================>
/**
* main class constructor
* @param array $db_config db config array
* @param array<mixed> $db_config db config array
*/
public function __construct(array $db_config)
{
@@ -151,7 +180,7 @@ class Backend extends \CoreLibs\DB\IO
/**
* set internal ACL from login ACL
* @param array $acl login acl array
* @param array<mixed> $acl login acl array
*/
public function setACL(array $acl): void
{
@@ -160,16 +189,16 @@ class Backend extends \CoreLibs\DB\IO
/**
* writes all action vars plus other info into edit_log tabl
* @param string $event any kind of event description,
* @param string|array $data any kind of data related to that event
* @param string $write_type write type can bei STRING or BINARY
* @return void has no return
* @param string $event any kind of event description,
* @param string|array<mixed> $data any kind of data related to that event
* @param string $write_type write type can bei STRING or BINARY
* @return void
*/
public function adbEditLog(string $event = '', $data = '', string $write_type = 'STRING'): void
{
$data_binary = '';
if ($write_type == 'BINARY') {
$data_binary = $this->dbEscapeBytea(bzcompress(serialize($data)));
$data_binary = $this->dbEscapeBytea((string)bzcompress(serialize($data)));
$data = 'see bzip compressed data_binary field';
}
if ($write_type == 'STRING') {
@@ -178,16 +207,15 @@ class Backend extends \CoreLibs\DB\IO
}
// check schema
$SCHEMA = 'public';
if (defined('LOGIN_DB_SCHEMA') && !empty(LOGIN_DB_SCHEMA)) {
$SCHEMA = LOGIN_DB_SCHEMA;
} elseif ($this->dbGetSchema()) {
$SCHEMA = $this->dbGetSchema();
} elseif (defined('PUBLIC_SCHEMA')) {
$SCHEMA = PUBLIC_SCHEMA;
} else {
$SCHEMA = 'public';
}
/** @phpstan-ignore-next-line for whatever reason $SCHEMA is seen as possible array */
$q = "INSERT INTO " . $SCHEMA . ".edit_log "
. "(euid, event_date, event, data, data_binary, page, "
. "ip, user_agent, referer, script_name, query_string, server_name, http_host, "
@@ -225,8 +253,8 @@ class Backend extends \CoreLibs\DB\IO
/**
* menu creater (from login menu session pages)
* @param int $flag visible flag trigger
* @return array menu array for output on page (smarty)
* @param int $flag visible flag trigger
* @return array<mixed> menu array for output on page (smarty)
*/
public function adbTopMenu(int $flag = 0): array
{
@@ -373,10 +401,10 @@ class Backend extends \CoreLibs\DB\IO
/**
* @deprecated
* creates out of a normal db_return array an assoc array
* @param array $db_array input array
* @param array<mixed> $db_array input array
* @param string|int|bool $key key
* @param string|int|bool $value value
* @return array associative array
* @return array<mixed> associative array
* @deprecated \CoreLibs\Combined\ArrayHandler::genAssocArray()
*/
public function adbAssocArray(array $db_array, $key, $value): array
@@ -407,16 +435,24 @@ class Backend extends \CoreLibs\DB\IO
/**
* @deprecated
* converts picture to a thumbnail with max x and max y size
* @param string $pic source image file with or without path
* @param int $size_x maximum size width
* @param int $size_y maximum size height
* @param string $dummy empty, or file_type to show an icon instead of nothing if file is not found
* @param string $path if source start is not ROOT path, if empty ROOT is choosen
* @return string|bool thumbnail name, or false for error
* @param string $pic source image file with or without path
* @param int $size_x maximum size width
* @param int $size_y maximum size height
* @param string $dummy empty, or file_type to show an icon
* instead of nothing if file is not found
* @param string $path if source start is not ROOT path
* if empty ROOT is choosen
* @return string|bool thumbnail name, or false for error
* @deprecated \CoreLibs\Output\Image::createThumbnail()
*/
public function adbCreateThumbnail($pic, $size_x, $size_y, $dummy = '', $path = "", $cache = "")
{
public function adbCreateThumbnail(
string $pic,
int $size_x,
int $size_y,
string $dummy = '',
string $path = '',
string $cache = ''
) {
trigger_error(
'Method ' . __METHOD__ . ' is deprecated: \CoreLibs\Output\Image::createThumbnail()',
E_USER_DEPRECATED
@@ -426,10 +462,10 @@ class Backend extends \CoreLibs\DB\IO
/**
* wrapper function to fill up the mssages array
* @param string $level info/warning/error
* @param string $msg string, can be printf formated
* @param array $vars optional data for a possible printf formated msg
* @return void has no return
* @param string $level info/warning/error
* @param string $msg string, can be printf formated
* @param array<mixed> $vars optional data for a possible printf formated msg
* @return void has no return
*/
public function adbMsg(string $level, string $msg, array $vars = []): void
{

View File

@@ -57,24 +57,34 @@ namespace CoreLibs;
class Basic
{
// page and host name
/** @var string */
public $page_name;
/** @var string */
public $host_name;
/** @var int */
public $host_port;
// logging interface, Debug\Logging class
/** @var \CoreLibs\Debug\Logging */
public $log;
// email valid checks
/** @var array<mixed> */
public $email_regex_check = [];
/** @var string */
public $email_regex; // regex var for email check
// data path for files
/** @var array<mixed> */
public $data_path = [];
// session name
/** @var string */
private $session_name = '';
/** @var string */
private $session_id = '';
// ajax flag
/** @var bool */
protected $ajax_page_flag = false;
/**
@@ -154,7 +164,7 @@ class Basic
// start session
session_start();
// set internal session id, we can use that later for protection check
$this->session_id = session_id();
$this->session_id = session_id() ?: '';
}
}
@@ -264,14 +274,14 @@ class Basic
* eg $foo->debugFor('print', 'on', ['LOG', 'DEBUG', 'INFO']);
* @param string $type error, echo, print
* @param string $flag on/off
* array $array of levels to turn on/off debug
* array<mixed> $array of levels to turn on/off debug
* @return void has no return
* @deprecated Use $basic->log->debugFor() instead
*/
public function debugFor(string $type, string $flag): void
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use $basic->log->debugFor() or use \CoreLibs\Debug\Logging() class', E_USER_DEPRECATED);
/** @phan-suppress-next-line PhanTypeMismatchArgumentReal */
/** @phan-suppress-next-line PhanTypeMismatchArgumentReal @phpstan-ignore-next-line */
$this->log->debugFor(...[func_get_args()]);
}
@@ -350,8 +360,8 @@ class Basic
/**
* merges the given error array with the one from this class
* only merges visible ones
* @param array $error_msg error array
* @return void has no return
* @param array<mixed> $error_msg error array
* @return void
* @deprecated Use $basic->log->mergeErrors() instead
*/
public function mergeErrors(array $error_msg = []): void
@@ -391,8 +401,8 @@ class Basic
/**
* prints a html formatted (pre) array
* @param array $array any array
* @return string formatted array for output with <pre> tag added
* @param array<mixed> $array any array
* @return string formatted array for output with <pre> tag added
* @deprecated Use $this->log->prAr() instead
*/
public function printAr(array $array): string
@@ -405,7 +415,8 @@ class Basic
* eg for debugging, this function does this
* call this method in the child method and you get the parent function that called
* @param int $level debug level, default 2
* @return ?string null or the function that called the function where this method is called
* @return ?string null or the function that called the function
* where this method is called
* @deprecated Use \CoreLibs\Debug\Support::getCallerMethod() instead
*/
public static function getCallerMethod(int $level = 2): ?string
@@ -471,7 +482,7 @@ class Basic
* returns 'checked' or 'selected' if okay
* $needle is a var, $haystack an array or a string
* **** THE RETURN: VALUE WILL CHANGE TO A DEFAULT NULL IF NOT FOUND ****
* @param array|string $haystack (search in) haystack can be an array or a string
* @param array<mixed>|string $haystack (search in) haystack can be an array or a string
* @param string $needle needle (search for)
* @param int $type type: 0: returns selected, 1, returns checked
* @return ?string returns checked or selected, else returns null
@@ -504,7 +515,7 @@ class Basic
/**
* get the host name without the port as given by the SELF var
* @return array host name/port name
* @return array<mixed> host name/port name
* @deprecated Use \CoreLibs\Get\System::getHostName() instead
*/
public function getHostName(): array
@@ -563,9 +574,9 @@ class Basic
* searches key = value in an array / array
* only returns the first one found
* @param string|int $needle needle (search for)
* @param array $haystack haystack (search in)
* @param array<mixed> $haystack haystack (search in)
* @param string|null $key_lookin the key to look out for, default empty
* @return array array with the elements where the needle can be
* @return array<mixed> array with the elements where the needle can be
* found in the haystack array
* @deprecated Use \CoreLibs\Combined\ArrayHandler::arraySearchRecursive() instead
*/
@@ -577,11 +588,11 @@ class Basic
/**
* recursive array search function, which returns all found not only the first one
* @param string|int $needle needle (search for)
* @param array $haystack haystack (search in)
* @param string|int $key the key to look for in
* @param array|null $path recursive call for previous path
* @return ?array all array elements paths where the element was found
* @param string|int $needle needle (search for)
* @param array<mixed> $haystack haystack (search in)
* @param string|int $key the key to look for in
* @param array<mixed>|null $path recursive call for previous path
* @return ?array<mixed> all array elements paths where the element was found
* @deprecated Use \CoreLibs\Combined\ArrayHandler::arraySearchRecursiveAll() instead
*/
public static function arraySearchRecursiveAll($needle, array $haystack, $key, ?array $path = null): ?array
@@ -592,7 +603,7 @@ class Basic
/**
* array search simple. looks for key, value Combined, if found, returns true
* @param array $array array (search in)
* @param array<mixed> $array array (search in)
* @param string|int $key key (key to search in)
* @param string|int $value value (what to find)
* @return bool true on found, false on not found
@@ -611,7 +622,7 @@ class Basic
* ... etc
* bool key flag: true: handle keys as string or int
* default false: all keys are string
* @return array|bool merged array
* @return array<mixed>|bool merged array
* @deprecated MUSER BE CONVERTED TO \CoreLibs\Combined\ArrayHandler::arrayMergeRecursive() instead
*/
public static function arrayMergeRecursive()
@@ -625,9 +636,9 @@ class Basic
* array_diff only checks elements from A that are not in B, but not the
* other way around.
* Note that like array_diff this only checks first level values not keys
* @param array $a array to compare a
* @param array $b array to compare b
* @return array array with missing elements from a & b
* @param array<mixed> $a array to compare a
* @param array<mixed> $b array to compare b
* @return array<mixed> array with missing elements from a & b
* @deprecated Use \CoreLibs\Combined\ArrayHandler::arrayDiff() instead
*/
public static function arrayDiff(array $a, array $b): array
@@ -639,9 +650,9 @@ class Basic
/**
* search for the needle array elements in haystack and return the ones found as an array,
* is there nothing found, it returns FALSE (boolean)
* @param array $needle elements to search for
* @param array $haystack array where the $needle elements should be searched int
* @return array|bool either the found elements or false for nothing found or error
* @param array<mixed> $needle elements to search for
* @param array<mixed> $haystack array where the $needle elements should be searched int
* @return array<mixed>|bool either the found elements or false for nothing found or error
* @deprecated Use \CoreLibs\Combined\ArrayHandler::inArrayAny() instead
*/
public static function inArrayAny(array $needle, array $haystack)
@@ -652,11 +663,11 @@ class Basic
/**
* creates out of a normal db_return array an assoc array
* @param array $db_array return array from the database
* @param array<mixed> $db_array return array from the database
* @param string|int|bool $key key set, false for not set
* @param string|int|bool $value value set, false for not set
* @param bool $set_only flag to return all (default), or set only
* @return array associative array
* @return array<mixed> associative array
* @deprecated Use \CoreLibs\Combined\ArrayHandler::genAssocArray() instead
*/
public static function genAssocArray(array $db_array, $key, $value, bool $set_only = false): array
@@ -668,7 +679,7 @@ class Basic
/**
* [NOTE]: This is an old function and is deprecated
* wrapper for join, but checks if input is an array and if not returns null
* @param array $array array to convert
* @param array<mixed> $array array to convert
* @param string $connect_char connection character
* @return string joined string
* @deprecated use join() instead
@@ -685,8 +696,8 @@ class Basic
/**
* converts multi dimensional array to a flat array
* does NOT preserve keys
* @param array $array ulti dimensionial array
* @return array flattened array
* @param array<mixed> $array ulti dimensionial array
* @return array<mixed> flattened array
* @deprecated Use \CoreLibs\Combined\ArrayHandler::flattenArray() instead
*/
public static function flattenArray(array $array): array
@@ -697,8 +708,8 @@ class Basic
/**
* will loop through an array recursivly and write the array keys back
* @param array $array multidemnsional array to flatten
* @return array flattened keys array
* @param array<mixed> $array multidemnsional array to flatten
* @return array<mixed> flattened keys array
* @deprecated Use \CoreLibs\Combined\ArrayHandler::flattenArrayKey() instead
*/
public static function flattenArrayKey(array $array/*, array $return = []*/): array
@@ -710,9 +721,9 @@ class Basic
/**
* searches for key -> value in an array tree and writes the value one level up
* this will remove this leaf will all other values
* @param array $array array (nested)
* @param array<mixed> $array array (nested)
* @param string|int $search key to find that has no sub leaf and will be pushed up
* @return array modified, flattened array
* @return array<mixed> modified, flattened array
* @deprecated Use \CoreLibs\Combined\ArrayHandler::arrayFlatForKey() instead
*/
public static function arrayFlatForKey(array $array, $search): array
@@ -923,7 +934,7 @@ class Basic
* @param string $start_date valid start date (y/m/d)
* @param string $end_date valid end date (y/m/d)
* @param bool $return_named return array type, false (default), true for named
* @return array 0/overall, 1/weekday, 2/weekend
* @return array<mixed> 0/overall, 1/weekday, 2/weekend
* @deprecated Use \CoreLibs\Combined\DateTime::calcDaysInterval() instead
*/
public static function calcDaysInterval($start_date, $end_date, bool $return_named = false): array
@@ -1033,7 +1044,7 @@ class Basic
* @param string $string string to test
* @param string $from_encoding encoding of string to test
* @param string $to_encoding target encoding
* @return bool|array false if no error or array with failed characters
* @return bool|array<mixed> false if no error or array with failed characters
* @deprecated use \CoreLibs\Language\Encoding::checkConvertEncoding() instead
*/
public function checkConvertEncoding(string $string, string $from_encoding, string $to_encoding)
@@ -1228,7 +1239,8 @@ class Basic
* @param string $hexStr RGB hexstring
* @param bool $returnAsString flag to return as string
* @param string $seperator string seperator: default: ","
* @return string|array|bool false on error or array with RGB or a string with the seperator
* @return string|array<mixed>|bool false on error or array with RGB or
* a string with the seperator
* @deprecated use \CoreLibs\Convert\Colors::hex2rgb() instead
*/
public static function hex2rgb(string $hexStr, bool $returnAsString = false, string $seperator = ',')
@@ -1275,7 +1287,7 @@ class Basic
* @param int $red red 0-255
* @param int $green green 0-255
* @param int $blue blue 0-255
* @return array Hue, Sat, Brightness/Value
* @return array<mixed> Hue, Sat, Brightness/Value
* @deprecated use \CoreLibs\Convert\Colors::rgb2hsb() instead
*/
public static function rgb2hsb(int $red, int $green, int $blue): array
@@ -1289,7 +1301,7 @@ class Basic
* @param int $H hue 0-360
* @param float $S saturation 0-1 (float)
* @param float $V brightness/value 0-1 (float)
* @return array 0 red/1 green/2 blue array
* @return array<mixed> 0 red/1 green/2 blue array
* @deprecated use \CoreLibs\Convert\Colors::hsb2rgb() instead
*/
public static function hsb2rgb(int $H, float $S, float $V): array
@@ -1305,7 +1317,7 @@ class Basic
* @param int $r red 0-255
* @param int $g green 0-255
* @param int $b blue 0-255
* @return array hue/sat/luminance
* @return array<mixed> hue/sat/luminance
* @deprecated use \CoreLibs\Convert\Colors::rgb2hsl() instead
*/
public static function rgb2hsl(int $r, int $g, int $b): array
@@ -1319,7 +1331,7 @@ class Basic
* @param int $h hue: 0-360 (degrees)
* @param float $s saturation: 0-1
* @param float $l luminance: 0-1
* @return array red/blue/green 0-255 each
* @return array<mixed> red/blue/green 0-255 each
* @deprecated use \CoreLibs\Convert\Colors::hsl2rgb() instead
*/
public static function hsl2rgb(int $h, float $s, float $l): array
@@ -1538,7 +1550,7 @@ class Basic
* @param string|null $json a json string, or null data
* @param bool $override if set to true, then on json error
* set original value as array
* @return array returns an array from the json values
* @return array<mixed> returns an array from the json values
* @deprecated use \CoreLibs\Check\Jason::jsonConvertToArray() instead
*/
public function jsonConvertToArray(?string $json, bool $override = false): array

View File

@@ -7,6 +7,7 @@ namespace CoreLibs\Check;
class Email
{
// this is for error check parts in where the email regex failed
/** @var array<int,string> */
private static $email_regex_check = [
0 => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@"
. "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$", // MASTER
@@ -19,6 +20,7 @@ class Email
7 => "@.*\.$" // ends with a dot, top level, domain missing
];
// the array with the mobile types that are valid
/** @var array<string,string> */
private static $mobile_email_type = [
'.*@docomo\.ne\.jp$' => 'keitai_docomo',
// correct are a[2-4], b2, c[1-9], e[2-9], h[2-4], t[1-9]
@@ -57,6 +59,7 @@ class Email
'.*@emobile-s\.ne\.jp$' => 'keitai_willcom_emnet' # e-mobile, group will willcom
];
// short list for mobile email types
/** @var array<string,string> */
private static $mobile_email_type_short = [
'keitai_docomo' => 'docomo',
'keitai_kddi_ezweb' => 'kddi',
@@ -116,7 +119,7 @@ class Email
* get the full check array
* this will be deprected at some point
*
* @return array
* @return array<mixed>
*/
public static function getEmailRegexCheck(): array
{
@@ -132,9 +135,11 @@ class Email
/**
* guesses the email type (mostly for mobile) from the domain
* if second is set to true, it will return short naming scheme (only provider)
* @param string $email email string
* @param bool $short default false, if true, returns only short type (pc instead of pc_html)
* @return string|bool email type, eg "pc", "docomo", etc, false for invalid short type
* @param string $email email string
* @param bool $short default false, if true,
* returns only short type (pc instead of pc_html)
* @return string|bool email type, eg "pc", "docomo", etc,
* false for invalid short type
*/
public static function getEmailType(string $email, bool $short = false)
{

View File

@@ -34,9 +34,12 @@ class File
is_readable($file)
) {
$f = fopen($file, 'rb');
if (!is_resource($f)) {
return 0;
}
$lines = 0;
while (!feof($f)) {
$lines += substr_count(fread($f, 8192), "\n");
$lines += substr_count(fread($f, 8192) ?: '', "\n");
}
fclose($f);
} else {

View File

@@ -12,6 +12,7 @@ namespace CoreLibs\Check;
class Jason
{
/** @var int */
private static $json_last_error;
/**
@@ -23,7 +24,7 @@ class Jason
* @param string|null $json a json string, or null data
* @param bool $override if set to true, then on json error
* set original value as array
* @return array returns an array from the json values
* @return array<mixed> returns an array from the json values
*/
public static function jsonConvertToArray(?string $json, bool $override = false): array
{

View File

@@ -35,7 +35,7 @@ class PhpVersion
}
// set the php version id
if (!defined('PHP_VERSION_ID')) {
$version = explode('.', phpversion());
$version = explode('.', phpversion() ?: '');
// creates something like 50107
define('PHP_VERSION_ID', (int)$version[0] * 10000 + (int)$version[1] * 100 + (int)$version[2]);
}

View File

@@ -13,11 +13,11 @@ class ArrayHandler
/**
* searches key = value in an array / array
* only returns the first one found
* @param string|int $needle needle (search for)
* @param array $haystack haystack (search in)
* @param string|null $key_lookin the key to look out for, default empty
* @return array array with the elements where the needle can be
* found in the haystack array
* @param string|int $needle needle (search for)
* @param array<mixed> $haystack haystack (search in)
* @param string|null $key_lookin the key to look out for, default empty
* @return array<mixed> array with the elements where the needle can be
* found in the haystack array
*/
public static function arraySearchRecursive($needle, array $haystack, ?string $key_lookin = null): array
{
@@ -68,11 +68,11 @@ class ArrayHandler
/**
* recursive array search function, which returns all found not only the first one
* @param string|int $needle needle (search for)
* @param array $haystack haystack (search in)
* @param string|int $key the key to look for in
* @param array|null $path recursive call for previous path
* @return ?array all array elements paths where the element was found
* @param string|int $needle needle (search for)
* @param array<mixed> $haystack haystack (search in)
* @param string|int $key the key to look for in
* @param array<mixed>|null $path recursive call for previous path
* @return array<mixed>|null all array elements paths where the element was found
*/
public static function arraySearchRecursiveAll($needle, array $haystack, $key, ?array $path = null): ?array
{
@@ -82,41 +82,40 @@ class ArrayHandler
'level' => 0,
'work' => []
];
}
// init sub sets if not set
if (!isset($path['level'])) {
$path['level'] = 0;
}
if (!isset($path['work'])) {
$path['work'] = [];
} else {
// init sub sets if not set
if (!isset($path['level'])) {
$path['level'] = 0;
}
if (!isset($path['work'])) {
$path['work'] = [];
}
}
// should not be needed because it would trigger a php mehtod error
if (!is_array($haystack)) {
$haystack = [];
}
// @phan HACK
$path['level'] = $path['level'] ?? 0;
// go through the array,
foreach ($haystack as $_key => $_value) {
if (is_scalar($_value) && $_value == $needle && !$key) {
// only value matches
$path['work'][$path['level']] = $_key;
$path['work'][$path['level'] ?? 0] = $_key;
$path['found'][] = $path['work'];
} elseif (is_scalar($_value) && $_value == $needle && $_key == $key) {
// key and value matches
$path['work'][$path['level']] = $_key;
$path['work'][$path['level'] ?? 0] = $_key;
$path['found'][] = $path['work'];
} elseif (is_array($_value)) {
// add position to working
$path['work'][$path['level']] = $_key;
$path['work'][$path['level'] ?? 0] = $_key;
// we will up a level
$path['level'] += 1;
// call recursive
$path = self::arraySearchRecursiveAll($needle, $_value, $key, $path);
}
}
// @phan HACK
// be 100% sure the array elements are set
$path['level'] = $path['level'] ?? 0;
$path['work'] = $path['work'] ?? [];
// cut all that is >= level
@@ -128,10 +127,10 @@ class ArrayHandler
/**
* array search simple. looks for key, value combination, if found, returns true
* @param array $array search in as array
* @param string|int $key key (key to search in)
* @param string|int $value value (what to find)
* @return bool true on found, false on not found
* @param array<mixed> $array search in as array
* @param string|int $key key (key to search in)
* @param string|int $value value (what to find)
* @return bool true on found, false on not found
*/
public static function arraySearchSimple(array $array, $key, $value): bool
{
@@ -160,7 +159,7 @@ class ArrayHandler
* ... etc
* bool key flag: true: handle keys as string or int
* default false: all keys are string
* @return array|bool merged array
* @return array<mixed>|bool merged array
*/
public static function arrayMergeRecursive()
{
@@ -215,9 +214,9 @@ class ArrayHandler
* array_diff only checks elements from A that are not in B, but not the
* other way around.
* Note that like array_diff this only checks first level values not keys
* @param array $a array to compare a
* @param array $b array to compare b
* @return array array with missing elements from a & b
* @param array<mixed> $a array to compare a
* @param array<mixed> $b array to compare b
* @return array<mixed> array with missing elements from a & b
*/
public static function arrayDiff(array $a, array $b): array
{
@@ -228,9 +227,9 @@ class ArrayHandler
/**
* search for the needle array elements in haystack and return the ones found as an array,
* is there nothing found, it returns FALSE (boolean)
* @param array $needle elements to search for
* @param array $haystack array where the $needle elements should be searched int
* @return array|bool either the found elements or false for nothing found or error
* @param array<mixed> $needle elements to search for
* @param array<mixed> $haystack array where the $needle elements should be searched int
* @return array<mixed>|bool either the found elements or false for nothing found or error
*/
public static function inArrayAny(array $needle, array $haystack)
{
@@ -255,11 +254,11 @@ class ArrayHandler
/**
* creates out of a normal db_return array an assoc array
* @param array $db_array return array from the database
* @param array<mixed> $db_array return array from the database
* @param string|int|bool $key key set, false for not set
* @param string|int|bool $value value set, false for not set
* @param bool $set_only flag to return all (default), or set only
* @return array associative array
* @return array<mixed> associative array
*/
public static function genAssocArray(array $db_array, $key, $value, bool $set_only = false): array
{
@@ -285,8 +284,8 @@ class ArrayHandler
/**
* converts multi dimensional array to a flat array
* does NOT preserve keys
* @param array $array ulti dimensionial array
* @return array flattened array
* @param array<mixed> $array ulti dimensionial array
* @return array<mixed> flattened array
*/
public static function flattenArray(array $array): array
{
@@ -302,8 +301,8 @@ class ArrayHandler
/**
* will loop through an array recursivly and write the array keys back
* @param array $array multidemnsional array to flatten
* @return array flattened keys array
* @param array<mixed> $array multidemnsional array to flatten
* @return array<mixed> flattened keys array
*/
public static function flattenArrayKey(array $array): array
{
@@ -320,9 +319,9 @@ class ArrayHandler
/**
* searches for key -> value in an array tree and writes the value one level up
* this will remove this leaf will all other values
* @param array $array nested array
* @param string|int $search key to find that has no sub leaf and will be pushed up
* @return array modified, flattened array
* @param array<mixed> $array nested array
* @param string|int $search key to find that has no sub leaf and will be pushed up
* @return array<mixed> modified, flattened array
*/
public static function arrayFlatForKey(array $array, $search): array
{

View File

@@ -38,7 +38,7 @@ class DateTime
{
// check if the timestamp has any h/m/s/ms inside, if yes skip
if (!preg_match("/(h|m|s|ms)/", (string)$timestamp)) {
list($timestamp, $ms) = array_pad(explode('.', (string)round($timestamp, 4)), 2, null);
list($timestamp, $ms) = array_pad(explode('.', (string)round((float)$timestamp, 4)), 2, null);
// if negative remember
$negative = false;
if ((int)$timestamp < 0) {
@@ -65,11 +65,14 @@ class DateTime
if ($ms !== null) {
// if we have ms and it has leading zeros, remove them, but only if it is nut just 0
$ms = preg_replace("/^0+(\d+)$/", '${1}', $ms);
if (!is_string($ms) || empty($ms)) {
$ms = '0';
}
// add ms if there
if ($show_micro) {
$time_string .= ' ' . (!$ms ? 0 : $ms) . 'ms';
$time_string .= ' ' . $ms . 'ms';
} elseif (!$time_string) {
$time_string .= (!$ms ? 0 : $ms) . 'ms';
$time_string .= $ms . 'ms';
}
}
if ($negative) {
@@ -78,7 +81,7 @@ class DateTime
} else {
$time_string = $timestamp;
}
return $time_string;
return (string)$time_string;
}
/**
@@ -90,7 +93,8 @@ class DateTime
public static function stringToTime($timestring)
{
$timestamp = 0;
if (preg_match("/(d|h|m|s|ms)/", $timestring)) {
if (preg_match("/(d|h|m|s|ms)/", (string)$timestring)) {
$timestring = (string)$timestring;
// pos for preg match read + multiply factor
$timegroups = [2 => 86400, 4 => 3600, 6 => 60, 8 => 1];
$matches = [];
@@ -131,7 +135,11 @@ class DateTime
if (!$date) {
return false;
}
list ($year, $month, $day) = array_pad(preg_split("/[\/-]/", $date), 3, null);
list ($year, $month, $day) = array_pad(
preg_split("/[\/-]/", $date) ?: [],
3,
null
);
if (!$year || !$month || !$day) {
return false;
}
@@ -146,12 +154,16 @@ class DateTime
* @param string $datetime date (YYYY-MM-DD) + time (HH:MM:SS), SS can be dropped
* @return bool true if valid date, false if date not valid
*/
public static function checkDateTime($datetime): bool
public static function checkDateTime(string $datetime): bool
{
if (!$datetime) {
return false;
}
list ($year, $month, $day, $hour, $min, $sec) = array_pad(preg_split("/[\/\- :]/", $datetime), 6, null);
list ($year, $month, $day, $hour, $min, $sec) = array_pad(
preg_split("/[\/\- :]/", $datetime) ?: [],
6,
null
);
if (!$year || !$month || !$day) {
return false;
}
@@ -190,8 +202,16 @@ class DateTime
}
// splits the data up with / or -
list ($start_year, $start_month, $start_day) = array_pad(preg_split('/[\/-]/', $start_date), 3, null);
list ($end_year, $end_month, $end_day) = array_pad(preg_split('/[\/-]/', $end_date), 3, null);
list ($start_year, $start_month, $start_day) = array_pad(
preg_split('/[\/-]/', $start_date) ?: [],
3,
null
);
list ($end_year, $end_month, $end_day) = array_pad(
preg_split('/[\/-]/', $end_date) ?: [],
3,
null
);
// check that month & day are two digits and then combine
foreach (['start', 'end'] as $prefix) {
foreach (['month', 'day'] as $date_part) {
@@ -256,7 +276,7 @@ class DateTime
* @param string $start_date valid start date (y/m/d)
* @param string $end_date valid end date (y/m/d)
* @param bool $return_named return array type, false (default), true for named
* @return array 0/overall, 1/weekday, 2/weekend
* @return array<mixed> 0/overall, 1/weekday, 2/weekend
*/
public static function calcDaysInterval($start_date, $end_date, bool $return_named = false): array
{

View File

@@ -125,7 +125,7 @@ class Byte
// detects up to exo bytes
preg_match(
"/([\d.,]*)\s?(eib|pib|tib|gib|mib|kib|eb|pb|tb|gb|mb|kb|e|p|t|g|m|k|b)$/i",
strtolower($number),
strtolower((string)$number),
$matches
);
if (isset($matches[1]) && isset($matches[2])) {
@@ -136,7 +136,7 @@ class Byte
// convert any mb/gb/etc to single m/b
$unit = preg_replace('/[^bkmgtpezy]/i', '', $matches[2]);
if ($unit) {
$number = $number * pow($si ? 1000 : 1024, stripos($valid_units_, $unit[0]));
$number = $number * pow($si ? 1000 : 1024, stripos($valid_units_, $unit[0]) ?: 0);
}
// convert to INT to avoid +E output
$number = (int)round($number);

View File

@@ -18,14 +18,18 @@ class Colors
{
/**
* converts a hex RGB color to the int numbers
* @param string $hexStr RGB hexstring
* @param bool $returnAsString flag to return as string
* @param string $seperator string seperator: default: ","
* @return string|array|bool false on error or array with RGB or a string with the seperator
* @param string $hexStr RGB hexstring
* @param bool $returnAsString flag to return as string
* @param string $seperator string seperator: default: ","
* @return string|array<string,float|int>|bool false on error or array with RGB
* or a string with the seperator
*/
public static function hex2rgb(string $hexStr, bool $returnAsString = false, string $seperator = ',')
{
$hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string
if (!is_string($hexStr)) {
return false;
}
$rgbArray = [];
if (strlen($hexStr) == 6) {
// If a proper hex code, convert using bitwise operation. No overhead... faster
@@ -76,10 +80,10 @@ class Colors
* converts RGB to HSB/V values
* returns:
* array with hue (0-360), sat (0-100%), brightness/value (0-100%)
* @param int $red red 0-255
* @param int $green green 0-255
* @param int $blue blue 0-255
* @return array Hue, Sat, Brightness/Value
* @param int $red red 0-255
* @param int $green green 0-255
* @param int $blue blue 0-255
* @return array<int|float> Hue, Sat, Brightness/Value
*/
public static function rgb2hsb(int $red, int $green, int $blue): array
{
@@ -119,10 +123,10 @@ class Colors
/**
* converts HSB/V to RGB values RGB is full INT
* @param int $H hue 0-360
* @param int $S saturation 0-100 (int)
* @param int $V brightness/value 0-100 (int)
* @return array 0 red/1 green/2 blue array as 0-255
* @param int $H hue 0-360
* @param int $S saturation 0-100 (int)
* @param int $V brightness/value 0-100 (int)
* @return array<int> 0 red/1 green/2 blue array as 0-255
*/
public static function hsb2rgb(int $H, int $S, int $V): array
{
@@ -199,10 +203,10 @@ class Colors
* converts a RGB (0-255) to HSL
* return:
* array with hue (0-360), saturation (0-100%) and luminance (0-100%)
* @param int $red red 0-255
* @param int $green green 0-255
* @param int $blue blue 0-255
* @return array hue/sat/luminance
* @param int $red red 0-255
* @param int $green green 0-255
* @param int $blue blue 0-255
* @return array<float> hue/sat/luminance
*/
public static function rgb2hsl(int $red, int $green, int $blue): array
{
@@ -253,7 +257,7 @@ class Colors
* @param int $hue hue: 0-360 (degrees)
* @param float $sat saturation: 0-100
* @param float $lum luminance: 0-100
* @return array red/blue/green 0-255 each
* @return array<int,float|int> red/blue/green 0-255 each
*/
public static function hsl2rgb(int $hue, float $sat, float $lum): array
{

View File

@@ -39,10 +39,10 @@ class Html
* returns 'checked' or 'selected' if okay
* $needle is a var, $haystack an array or a string
* **** THE RETURN: VALUE WILL CHANGE TO A DEFAULT NULL IF NOT FOUND ****
* @param array|string $haystack (search in) haystack can be an array or a string
* @param string $needle needle (search for)
* @param int $type type: 0: returns selected, 1, returns checked
* @return ?string returns checked or selected, else returns null
* @param array<mixed>|string $haystack (search in) haystack can be an array or a string
* @param string $needle needle (search for)
* @param int $type type: 0: returns selected, 1, returns checked
* @return ?string returns checked or selected, else returns null
*/
public static function checked($haystack, $needle, int $type = 0): ?string
{

View File

@@ -11,6 +11,7 @@ namespace CoreLibs\Convert;
class MimeAppName
{
/** @var array<string,string> */
private static $mime_apps = [];
/**

View File

@@ -12,6 +12,9 @@ class Hash
{
/**
* checks php version and if >=5.2.7 it will flip the string
* can return empty string if none of string sets work
* hash returns false
* preg_replace fails for older php version
* @param string $string string to crc
* @return string crc32b hash (old type)
*/
@@ -24,6 +27,9 @@ class Hash
// flip it back to old (two char groups)
$string = preg_replace("/^([a-z0-9]{2})([a-z0-9]{2})([a-z0-9]{2})([a-z0-9]{2})$/", "$4$3$2$1", $string);
}
if (!is_string($string)) {
$string = '';
}
return $string;
}

View File

@@ -11,9 +11,13 @@ namespace CoreLibs\Create;
class RandomKey
{
// key generation
/** @var array<mixed> */
private static $key_range = [];
/** @var int */
private static $one_key_length;
/** @var int */
private static $key_length = 4; // default key length
/** @var int */
private static $max_key_length = 256; // max allowed length
/**

View File

@@ -38,17 +38,21 @@ namespace CoreLibs\DB\Extended;
class ArrayIO extends \CoreLibs\DB\IO
{
// main calss variables
/** @var array<mixed> */
public $table_array; // the array from the table to work on
/** @var string */
public $table_name; // the table_name
/** @var string */
public $pk_name; // the primary key from this table
/** @var int|string|null */
public $pk_id; // the PK id
/**
* constructor for the array io class, set the
* primary key name automatically (from array)
* @param array $db_config db connection config
* @param array $table_array table array config
* @param string $table_name table name string
* @param array<mixed> $db_config db connection config
* @param array<mixed> $table_array table array config
* @param string $table_name table name string
*/
public function __construct(array $db_config, array $table_array, string $table_name)
{
@@ -174,9 +178,9 @@ class ArrayIO extends \CoreLibs\DB\IO
/**
* deletes one dataset
* @param array $table_array optional override for table array set
* set this as new table array too
* @return array returns the table array that was deleted
* @param array<mixed> $table_array optional override for table array set
* set this as new table array too
* @return array<mixed> returns the table array that was deleted
*/
public function dbDelete($table_array = [])
{
@@ -234,9 +238,9 @@ class ArrayIO extends \CoreLibs\DB\IO
/**
* reads one row into the array
* @param boolean $edit on true convert data, else as is
* @param array $table_array optional table array, overwrites internal set array
* @return array set table array with values
* @param boolean $edit on true convert data, else as is
* @param array<mixed> $table_array optional table array, overwrites internal set array
* @return array<mixed> set table array with values
*/
public function dbRead($edit = false, $table_array = [])
{
@@ -276,7 +280,7 @@ class ArrayIO extends \CoreLibs\DB\IO
// if query was executed okay, else set error
if ($this->dbExec($q)) {
if ($res = $this->dbFetchArray()) {
if (is_array($res = $this->dbFetchArray())) {
reset($this->table_array);
foreach ($this->table_array as $column => $data_array) {
// wenn "edit" dann gib daten wie in DB zurück, ansonten aufbereiten fr ausgabe
@@ -309,9 +313,9 @@ class ArrayIO extends \CoreLibs\DB\IO
/**
* writes one set into DB or updates one set (if PK exists)
* @param boolean $addslashes old convert entities and set set escape
* @param array $table_array optional table array, overwrites internal one
* @return array table array or null
* @param boolean $addslashes old convert entities and set set escape
* @param array<mixed> $table_array optional table array, overwrites internal one
* @return array<mixed> table array or null
*/
public function dbWrite($addslashes = false, $table_array = [])
{
@@ -499,11 +503,12 @@ class ArrayIO extends \CoreLibs\DB\IO
if (!$this->table_array[$this->pk_name]['value']) {
// max id, falls INSERT
$q = 'SELECT MAX(' . $this->pk_name . ') + 1 AS pk_id FROM ' . $this->table_name;
$res = $this->dbReturnRow($q);
if (!isset($res['pk_id'])) {
$res['pk_id'] = 1;
if (is_array($res = $this->dbReturnRow($q))) {
$pk_id = $res['pkd_id'];
} else {
$pk_id = 1;
}
$this->table_array[$this->pk_name]['value'] = $res['pk_id'];
$this->table_array[$this->pk_name]['value'] = $pk_id;
}
if (!$insert) {
@@ -533,8 +538,13 @@ class ArrayIO extends \CoreLibs\DB\IO
}
// set primary key
if ($insert) {
$this->table_array[$this->pk_name]['value'] = $this->insert_id;
$this->pk_id = $this->insert_id;
// FIXME: this has to be fixes by fixing DB::IO clas
$insert_id = $this->dbGetInsertPK();
if (is_array($insert_id)) {
$insert_id = 0;
}
$this->table_array[$this->pk_name]['value'] = $insert_id;
$this->pk_id = $insert_id;
}
// return the table if needed
return $this->table_array;

File diff suppressed because it is too large Load Diff

View File

@@ -50,7 +50,9 @@ namespace CoreLibs\DB\SQL;
class PgSQL
{
/** @var string */
private $last_error_query;
/** @var resource|bool */
private $dbh;
/**
@@ -81,6 +83,9 @@ class PgSQL
public function __dbQuery(string $query)
{
$this->last_error_query = '';
if (!is_resource($this->dbh)) {
return false;
}
// read out the query status and save the query if needed
$result = pg_query($this->dbh, $query);
if (!$result) {
@@ -96,7 +101,11 @@ class PgSQL
*/
public function __dbSendQuery(string $query): bool
{
return pg_send_query($this->dbh, $query);
if (!is_resource($this->dbh)) {
return false;
}
$result = pg_send_query($this->dbh, $query);
return $result ? true : false;
}
/**
@@ -106,7 +115,13 @@ class PgSQL
public function __dbGetResult()
{
$this->last_error_query = '';
if (!is_resource($this->dbh)) {
return false;
}
$result = pg_get_result($this->dbh);
if (!is_resource($result)) {
return false;
}
if ($error = pg_result_error($result)) {
$this->last_error_query = $error;
}
@@ -119,10 +134,11 @@ class PgSQL
*/
public function __dbClose(): void
{
if (is_resource($this->dbh)) {
if (pg_connection_status($this->dbh) === PGSQL_CONNECTION_OK) {
pg_close($this->dbh);
}
if (!is_resource($this->dbh)) {
return;
}
if (pg_connection_status($this->dbh) === PGSQL_CONNECTION_OK) {
pg_close($this->dbh);
}
}
@@ -134,6 +150,9 @@ class PgSQL
*/
public function __dbPrepare(string $name, string $query)
{
if (!is_resource($this->dbh)) {
return false;
}
$result = pg_prepare($this->dbh, $name, $query);
if (!$result) {
$this->last_error_query = $query;
@@ -144,11 +163,14 @@ class PgSQL
/**
* wrapper for pg_execute for running a prepared statement
* @param string $name statement name
* @param array $data data array
* @param array<mixed> $data data array
* @return resource|bool returns status or false for error
*/
public function __dbExecute(string $name, array $data)
{
if (!is_resource($this->dbh)) {
return false;
}
$result = pg_execute($this->dbh, $name, $data);
if (!$result) {
$this->last_error_query = $name;
@@ -192,7 +214,7 @@ class PgSQL
* if through/true false, use __dbResultType(true)
* @param resource $cursor cursor resource
* @param int $result_type result type as int number
* @return array|bool array result data or false on end/error
* @return array<mixed>|bool array result data or false on end/error
*/
public function __dbFetchArray($cursor, int $result_type = PGSQL_BOTH)
{
@@ -217,7 +239,7 @@ class PgSQL
/**
* wrapper for pg_fetch_all
* @param resource $cursor cursor resource
* @return array|bool data array or false for end/error
* @return array<mixed>|bool data array or false for end/error
*/
public function __dbFetchAll($cursor)
{
@@ -240,10 +262,10 @@ class PgSQL
* this only works if db schema is after "no plural names. and pk name is table name + _id
* detects schema prefix in table name
* @param string $query query string
* @param string $pk_name primary key name, if '' then auto detect
* @param string|null $pk_name primary key name, if '' then auto detect
* @return string|int|false primary key value
*/
public function __dbInsertId(string $query, string $pk_name)
public function __dbInsertId(string $query, ?string $pk_name)
{
// only if an insert has been done
if (preg_match("/^insert /i", $query)) {
@@ -258,7 +280,7 @@ class PgSQL
$table = $_table;
}
// no PK name given at all
if (!$pk_name) {
if (empty($pk_name)) {
// if name is plurar, make it singular
// if (preg_match("/.*s$/i", $table))
// $table = substr($table, 0, -1);
@@ -269,7 +291,11 @@ class PgSQL
$q = "SELECT CURRVAL('$seq') AS insert_id";
// I have to do manually or I overwrite the original insert internal vars ...
if ($q = $this->__dbQuery($q)) {
list($id) = $this->__dbFetchArray($q);
// abort if this is not an resource
if (!is_resource($q)) {
return false;
}
list($id) = $this->__dbFetchArray($q) ?: [];
} else {
$id = [-1, $q];
}
@@ -294,7 +320,14 @@ class PgSQL
if ($schema) {
$q = "SHOW search_path";
$cursor = $this->__dbQuery($q);
$search_path = $this->__dbFetchArray($cursor)['search_path'];
if (!is_resource($cursor)) {
return false;
}
$__db_fetch_array = $this->__dbFetchArray($cursor);
if (!is_array($__db_fetch_array)) {
return false;
}
$search_path = $__db_fetch_array['search_path'] ?? '';
if ($search_path != $schema) {
$table_prefix = $schema . '.';
}
@@ -319,8 +352,12 @@ class PgSQL
. "pg_attribute.attnum = any(pg_index.indkey) "
. "AND indisprimary";
$cursor = $this->__dbQuery($q);
if ($cursor) {
return $this->__dbFetchArray($cursor)['column_name'] ?? false;
if (is_resource($cursor)) {
$__db_fetch_array = $this->__dbFetchArray($cursor);
if (!is_array($__db_fetch_array)) {
return false;
}
return $__db_fetch_array['column_name'] ?? false;
} else {
return false;
}
@@ -331,13 +368,13 @@ class PgSQL
/**
* wrapper for pg_connect, writes out failure to screen if error occurs (hidden var)
* @param string $db_host host name
* @param string $db_user user name
* @param string $db_pass password
* @param string $db_name databse name
* @param integer $db_port port (int, 5432 is default)
* @param string $db_ssl SSL (allow is default)
* @return ?resource db handler resource or null on error
* @param string $db_host host name
* @param string $db_user user name
* @param string $db_pass password
* @param string $db_name databse name
* @param integer $db_port port (int, 5432 is default)
* @param string $db_ssl SSL (allow is default)
* @return resource|bool db handler resource or false on error
*/
public function __dbConnect(
string $db_host,
@@ -353,9 +390,9 @@ class PgSQL
}
$this->dbh = pg_connect("host=" . $db_host . " port=" . $db_port . " user="
. $db_user . " password=" . $db_pass . " dbname=" . $db_name . " sslmode=" . $db_ssl);
if (!$this->dbh) {
die("<!-- Can't connect to database //-->");
}
// if (!$this->dbh) {
// die("<!-- Can't connect to database //-->");
// }
return $this->dbh;
}
@@ -367,6 +404,9 @@ class PgSQL
*/
public function __dbPrintError($cursor = null): string
{
if (!is_resource($this->dbh)) {
return '';
}
// run the query again for the error result here
if (!$cursor && $this->last_error_query) {
pg_send_query($this->dbh, $this->last_error_query);
@@ -382,12 +422,15 @@ class PgSQL
/**
* wrapper for pg_meta_data
* @param string $table table name
* @param bool $extended show extended info (default false)
* @return array|bool array data for the table info or false on error
* @param string $table table name
* @param bool $extended show extended info (default false)
* @return array<mixed>|bool array data for the table info or false on error
*/
public function __dbMetaData(string $table, $extended = false)
{
if (!is_resource($this->dbh)) {
return false;
}
// needs to prefixed with @ or it throws a warning on not existing table
return @pg_meta_data($this->dbh, $table, $extended);
}
@@ -399,6 +442,9 @@ class PgSQL
*/
public function __dbEscapeString($string): string
{
if (!is_resource($this->dbh)) {
return '';
}
return pg_escape_string($this->dbh, (string)$string);
}
@@ -411,6 +457,9 @@ class PgSQL
*/
public function __dbEscapeLiteral($string): string
{
if (!is_resource($this->dbh)) {
return '';
}
return pg_escape_string($this->dbh, (string)$string);
}
@@ -421,6 +470,9 @@ class PgSQL
*/
public function __dbEscapeBytea($bytea): string
{
if (!is_resource($this->dbh)) {
return '';
}
return pg_escape_bytea($this->dbh, $bytea);
}
@@ -430,6 +482,9 @@ class PgSQL
*/
public function __dbConnectionBusy(): bool
{
if (!is_resource($this->dbh)) {
return false;
}
return pg_connection_busy($this->dbh);
}
@@ -441,6 +496,9 @@ class PgSQL
*/
public function __dbVersion(): string
{
if (!is_resource($this->dbh)) {
return '';
}
// array has client, protocol, server
// we just need the server
$v = pg_version($this->dbh);
@@ -449,11 +507,12 @@ class PgSQL
/**
* postgresql array to php array
* @param string $text array text from PostgreSQL
* @param array $output (internal) recursive pass on for nested arrays
* @param bool|int $limit (internal) max limit to not overshoot the end, start with false
* @param integer $offset (internal) shift offset for {}
* @return array|int converted PHP array, interal recusrive int position
* @param string $text array text from PostgreSQL
* @param array<mixed> $output (internal) recursive pass on for nested arrays
* @param bool|int $limit (internal) max limit to not overshoot
* the end, start with false
* @param integer $offset (internal) shift offset for {}
* @return array<mixed>|int converted PHP array, interal recusrive int position
*/
public function __dbArrayParse($text, &$output, $limit = false, $offset = 1)
{

View File

@@ -27,38 +27,65 @@ namespace CoreLibs\Debug;
class Logging
{
// page and host name
/** @var string */
private $page_name;
/** @var string */
private $host_name;
/** @var int */
private $host_port;
// internal error reporting vars
/** @var array<mixed> */
private $error_msg = []; // the "connection" to the outside errors
// debug output prefix
/** @var string */
private $error_msg_prefix = ''; // prefix to the error string (the class name)
// debug flags
/** @var array<mixed> */
private $debug_output = []; // if this is true, show debug on desconstructor
/** @var array<mixed> */
private $debug_output_not = [];
/** @var bool */
private $debug_output_all = false;
/** @var array<mixed> */
private $echo_output = []; // errors: echo out, default is 1
/** @var array<mixed> */
private $echo_output_not = [];
/** @var bool */
private $echo_output_all = false;
/** @var array<mixed> */
private $print_output = []; // errors: print to file, default is 0
/** @var array<mixed> */
private $print_output_not = [];
/** @var bool */
private $print_output_all = false;
// debug flags/settings
/** @var string */
private $running_uid = ''; // unique ID set on class init and used in logging as prefix
// log file name
/** @var string */
private $log_folder = '';
/** @var string */
private $log_file_name_ext = 'log'; // use this for date rotate
/** @var int */
private $log_max_filesize = 0; // set in kilobytes
/** @var string */
private $log_print_file = 'error_msg##LOGID####LEVEL####CLASS####PAGENAME####DATE##';
/** @var string */
private $log_file_unique_id; // a unique ID set only once for call derived from this class
/** @var bool */
private $log_print_file_date = true; // if set add Y-m-d and do automatic daily rotation
/** @var string */
private $log_file_id = ''; // a alphanumeric name that has to be set as global definition
/** @var bool */
private $log_per_level = false; // set, it will split per level (first parameter in debug call)
/** @var bool */
private $log_per_class = false; // set, will split log per class
/** @var bool */
private $log_per_page = false; // set, will split log per called file
/** @var bool */
private $log_per_run = false; // create a new log file per run (time stamp + unique ID)
// script running time
/** @var float */
private $script_starttime;
public function __construct()
@@ -282,7 +309,8 @@ class Logging
{
// get the last class entry and wrie that
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) ?? [['class' => get_class($this)]];
return end($backtrace)['class'];
// make sure if false it is an array and then check if not class set return empty string
return (end($backtrace) ?: [])['class'] ?? '';
}
// *** PUBLIC ***
@@ -381,7 +409,7 @@ class Logging
* @param string $flag on/off
* @param string|null $level if not null then check if this array entry is set
* else return false
* @return bool|array if $level is null, return array, else boolean true/false
* @return bool|array<mixed> if $level is null, return array, else boolean true/false
*/
public function getLogLevel(string $type, string $flag, ?string $level = null)
{
@@ -439,8 +467,8 @@ class Logging
* It uses some special code sets so we can convert that to pre flags
* for echo output {##HTMLPRE##} ... {##/HTMLPRE##}
* Do not use this without using it in a string in debug function
* @param array $a Array to format
* @return string print_r formated
* @param array<mixed> $a Array to format
* @return string print_r formated
*/
public function prAr(array $a): string
{
@@ -486,9 +514,13 @@ class Logging
($strip ?
// find any <br> and replace them with \n
// strip rest of html elements (base only)
preg_replace("/(<\/?)(\w+)([^>]*>)/", '', str_replace('<br>', "\n", $prefix . $string)) :
preg_replace(
"/(<\/?)(\w+)([^>]*>)/",
'',
str_replace('<br>', "\n", $prefix . $string)
) :
$prefix . $string
)
) ?: ''
)
. "\n"
);
@@ -522,8 +554,8 @@ class Logging
/**
* merges the given error array with the one from this class
* only merges visible ones
* @param array $error_msg error array
* @return void has no return
* @param array<mixed> $error_msg error array
* @return void has no return
*/
public function mergeErrors(array $error_msg = []): void
{
@@ -593,7 +625,7 @@ class Logging
/**
* Get current error message array
*
* @return array error messages collected
* @return array<mixed> error messages collected
*/
public function getErrorMsg(): array
{

View File

@@ -11,12 +11,18 @@ namespace CoreLibs\Debug;
class RunningTime
{
// hr
/** @var float */
private static $hr_starttime;
/** @var float */
private static $hr_runtime;
/** @var float */
private static $hr_endtime;
// normal
/** @var float */
private static $starttime;
/** @var float */
private static $endtime;
/** @var string */
private static $runningtime_string;
/**
@@ -77,8 +83,8 @@ class RunningTime
* on second call it sends the end time and then also prints the running time
* Sets the internal runningtime_string variable with Start/End/Run time string
* NOTE: for pure running time check it is recommended to use hrRunningTime method
* @param bool|boolean $simple if true prints HTML strings, default text only
* @return float running time as float number
* @param bool $simple if true prints HTML strings, default text only
* @return float running time as float number
*/
public static function runningTime(bool $simple = false): float
{

View File

@@ -31,8 +31,8 @@ class Support
/**
* prints a html formatted (pre) array
* @param array $array any array
* @return string formatted array for output with <pre> tag added
* @param array<mixed> $array any array
* @return string formatted array for output with <pre> tag added
*/
public static function printAr(array $array): string
{

View File

@@ -48,7 +48,7 @@ class System
/**
* get the host name without the port as given by the SELF var
* @return array host name/port name
* @return array<mixed> host name/port name
*/
public static function getHostName(): array
{
@@ -86,7 +86,7 @@ class System
/**
* similar to getPageName, but it retuns the raw array
*
* @return array pathinfo array from PHP SELF
* @return array<string> pathinfo array from PHP SELF
*/
public static function getPageNameArray(): array
{

View File

@@ -28,21 +28,27 @@ namespace CoreLibs\Language\Core;
// over it (it assumes knowledge of StringReader internals)
class CachedFileReader extends \CoreLibs\Language\Core\StringReader
{
/** @var int */
public $error = 0;
/** @var string */
public $fd_str = '';
public function __construct($filename)
/**
* Undocumented function
*
* @param string $filename
*/
public function __construct(string $filename)
{
parent::__construct();
if (file_exists($filename)) {
$length = filesize($filename);
$fd = fopen($filename, 'rb');
if (!$fd) {
if (!is_resource($fd)) {
$this->error = 3; // Cannot read file, probably permissions
} else {
$this->fd_str = fread($fd, filesize($filename) ?: 0) ?: '';
fclose($fd);
}
$this->fd_str = fread($fd, $length);
fclose($fd);
} else {
$this->error = 2; // File doesn't exist
}

View File

@@ -26,9 +26,13 @@ namespace CoreLibs\Language\Core;
class FileReader
{
/** @var int */
public $fr_pos;
/** @var resource|bool */
public $fr_fd;
/** @var int */
public $fr_length;
/** @var int */
public $error = 0;
/**
@@ -38,10 +42,10 @@ class FileReader
public function __construct($filename)
{
if (file_exists($filename)) {
$this->fr_length = filesize($filename);
$this->fr_length = filesize($filename) ?: 0;
$this->fr_pos = 0;
$this->fr_fd = fopen($filename, 'rb');
if (!$this->fr_fd) {
if (!is_resource($this->fr_fd)) {
$this->error = 3; // Cannot read file, probably permissions
}
} else {
@@ -56,23 +60,25 @@ class FileReader
*/
public function read($bytes)
{
if ($bytes) {
fseek($this->fr_fd, $this->fr_pos);
// PHP 5.1.1 does not read more than 8192 bytes in one fread()
// the discussions at PHP Bugs suggest it's the intended behaviour
$data = '';
while ($bytes > 0) {
$chunk = fread($this->fr_fd, $bytes);
$data .= $chunk;
$bytes -= strlen($chunk);
}
$this->fr_pos = ftell($this->fr_fd);
return $data;
} else {
if (!$bytes || !is_resource($this->fr_fd)) {
return '';
}
fseek($this->fr_fd, $this->fr_pos);
// PHP 5.1.1 does not read more than 8192 bytes in one fread()
// the discussions at PHP Bugs suggest it's the intended behaviour
$data = '';
while ($bytes > 0) {
$chunk = fread($this->fr_fd, $bytes);
if ($chunk === false) {
break;
}
$data .= $chunk;
$bytes -= strlen($chunk);
}
$this->fr_pos = ftell($this->fr_fd) ?: 0;
return $data;
}
/**
@@ -82,8 +88,11 @@ class FileReader
*/
public function seekto($pos)
{
if (!is_resource($this->fr_fd)) {
return 0;
}
fseek($this->fr_fd, $pos);
$this->fr_pos = ftell($this->fr_fd);
$this->fr_pos = ftell($this->fr_fd) ?: 0;
return $this->fr_pos;
}
@@ -111,7 +120,9 @@ class FileReader
*/
public function close(): void
{
fclose($this->fr_fd);
if (is_resource($this->fr_fd)) {
fclose($this->fr_fd);
}
}
}

View File

@@ -40,19 +40,31 @@ namespace CoreLibs\Language\Core;
class GetTextReader
{
// public:
/** @var int */
public $error = 0; // public variable that holds error code (0 if no error)
// private:
/** @var int */
private $BYTEORDER = 0; // 0: low endian, 1: big endian
private $STREAM = null;
/** @var FileReader */
private $STREAM;
/** @var bool */
private $short_circuit = false;
/** @var bool */
private $enable_cache = false;
private $originals = null; // offset of original table
private $translations = null; // offset of translation table
private $pluralheader = null; // cache header field for plural forms
/** @var int */
private $originals = 0; // offset of original table
/** @var int */
private $translations = 0; // offset of translation table
/** @var string */
private $pluralheader = ''; // cache header field for plural forms
/** @var int */
private $total = 0; // total string count
/** @var array<mixed>|null */
private $table_originals = null; // table for original strings (offsets)
/** @var array<mixed>|null */
private $table_translations = null; // table for translated strings (offsets)
/** @var array<mixed> */
private $cache_translations = []; // original -> translation mapping
@@ -69,13 +81,12 @@ class GetTextReader
{
if ($this->BYTEORDER == 0) {
// low endian
$input = unpack('V', $this->STREAM->read(4));
return array_shift($input);
$input = unpack('V', $this->STREAM->read(4)) ?: [];
} else {
// big endian
$input = unpack('N', $this->STREAM->read(4));
return array_shift($input);
$input = unpack('N', $this->STREAM->read(4)) ?: [];
}
return array_shift($input);
}
/**
@@ -92,24 +103,24 @@ class GetTextReader
* Reads an array of Integers from the Stream
*
* @param int $count How many elements should be read
* @return array Array of Integers
* @return array<mixed> Array of Integers
*/
public function readintarray($count)
{
if ($this->BYTEORDER == 0) {
// low endian
return unpack('V' . $count, $this->STREAM->read(4 * $count));
return unpack('V' . $count, $this->STREAM->read(4 * $count)) ?: [];
} else {
// big endian
return unpack('N' . $count, $this->STREAM->read(4 * $count));
return unpack('N' . $count, $this->STREAM->read(4 * $count)) ?: [];
}
}
/**
* Constructor
*
* @param object|bool $Reader the StreamReader object
* @param bool $enable_cache Enable or disable caching of strings (default on)
* @param FileReader|bool $Reader the StreamReader object
* @param bool $enable_cache Enable or disable caching of strings (default on)
*/
public function __construct($Reader, $enable_cache = true)
{
@@ -118,6 +129,11 @@ class GetTextReader
$this->short_circuit = true;
return;
}
// bail out for sure if this is not an objet here
if (!is_object($Reader)) {
$this->short_circuit = true;
return;
}
// Caching can be turned off
$this->enable_cache = $enable_cache;
@@ -125,7 +141,7 @@ class GetTextReader
$MAGIC1 = "\x95\x04\x12\xde";
$MAGIC2 = "\xde\x12\x04\x95";
$this->STREAM = (object)$Reader;
$this->STREAM = $Reader;
$magic = $this->read(4);
if ($magic == $MAGIC1) {
$this->BYTEORDER = 1;
@@ -149,8 +165,9 @@ class GetTextReader
* to speed up translation lookups
*
* @access private
* @return void
*/
private function load_tables()
private function loadTables(): void
{
if (
is_array($this->cache_translations) &&
@@ -190,10 +207,10 @@ class GetTextReader
* @param int $num Offset number of original string
* @return string Requested string if found, otherwise ''
*/
private function get_original_string($num)
private function getOriginalString($num)
{
$length = $this->table_originals[$num * 2 + 1];
$offset = $this->table_originals[$num * 2 + 2];
$length = $this->table_originals[$num * 2 + 1] ?? 0;
$offset = $this->table_originals[$num * 2 + 2] ?? 0;
if (!$length) {
return '';
}
@@ -209,10 +226,10 @@ class GetTextReader
* @param int $num Offset number of original string
* @return string Requested string if found, otherwise ''
*/
private function get_translation_string($num)
private function getTranslationString($num)
{
$length = $this->table_translations[$num * 2 + 1];
$offset = $this->table_translations[$num * 2 + 2];
$length = $this->table_translations[$num * 2 + 1] ?? 0;
$offset = $this->table_translations[$num * 2 + 2] ?? 0;
if (!$length) {
return '';
}
@@ -228,18 +245,18 @@ class GetTextReader
* @param string $string string to find
* @param int $start (internally used in recursive function)
* @param int $end (internally used in recursive function)
* @return int|string|float (offset in originals table)
* @return int (offset in originals table)
*/
private function find_string($string, $start = -1, $end = -1)
private function findString($string, $start = -1, $end = -1)
{
if (($start == -1) or ($end == -1)) {
// find_string is called with only one parameter, set start end end
// findString is called with only one parameter, set start end end
$start = 0;
$end = $this->total;
}
if (abs($start - $end) <= 1) {
// We're done, now we either found the string, or it doesn't exist
$txt = $this->get_original_string($start);
$txt = $this->getOriginalString($start);
if ($string == $txt) {
return $start;
} else {
@@ -247,20 +264,20 @@ class GetTextReader
}
} elseif ($start > $end) {
// start > end -> turn around and start over
return $this->find_string($string, $end, $start);
return $this->findString($string, $end, $start);
} else {
// Divide table in two parts
$half = (int)(($start + $end) / 2);
$cmp = strcmp($string, $this->get_original_string($half));
$cmp = strcmp($string, $this->getOriginalString($half));
if ($cmp == 0) {
// string is exactly in the middle => return it
return $half;
} elseif ($cmp < 0) {
// The string is in the upper half
return $this->find_string($string, $start, $half);
return $this->findString($string, $start, $half);
} else {
// Translateshe string is in the lower half
return $this->find_string($string, $half, $end);
return $this->findString($string, $half, $end);
}
}
}
@@ -277,7 +294,7 @@ class GetTextReader
if ($this->short_circuit) {
return $string;
}
$this->load_tables();
$this->loadTables();
if ($this->enable_cache) {
// Caching enabled, get translated string from cache
@@ -288,11 +305,11 @@ class GetTextReader
}
} else {
// Caching not enabled, try to find string
$num = $this->find_string($string);
$num = $this->findString($string);
if ($num == -1) {
return $string;
} else {
return $this->get_translation_string($num);
return $this->getTranslationString($num);
}
}
}
@@ -304,7 +321,7 @@ class GetTextReader
* @param string $expr an expression to match
* @return string sanitized plural form expression
*/
private function sanitize_plural_expression($expr)
private function sanitizePluralExpression($expr)
{
// Get rid of disallowed characters.
$expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr);
@@ -341,7 +358,7 @@ class GetTextReader
* @param string $header header search in plurals
* @return string verbatim plural form header field
*/
private function extract_plural_forms_header_from_po_header($header)
private function extractPluralFormsHeaderFromPoHeader($header)
{
if (preg_match("/(^|\n)plural-forms: ([^\n]*)\n/i", $header, $regs)) {
$expr = $regs[2];
@@ -357,21 +374,21 @@ class GetTextReader
* @access private
* @return string plural form header
*/
private function get_plural_forms()
private function getPluralForms()
{
// lets assume message number 0 is header
// this is true, right?
$this->load_tables();
$this->loadTables();
// cache header field for plural forms
if (! is_string($this->pluralheader)) {
if ($this->enable_cache) {
$header = $this->cache_translations[''];
} else {
$header = $this->get_translation_string(0);
$header = $this->getTranslationString(0);
}
$expr = $this->extract_plural_forms_header_from_po_header($header);
$this->pluralheader = $this->sanitize_plural_expression($expr);
$expr = $this->extractPluralFormsHeaderFromPoHeader($header);
$this->pluralheader = $this->sanitizePluralExpression($expr);
}
return $this->pluralheader;
}
@@ -383,9 +400,9 @@ class GetTextReader
* @param string $n count
* @return int array index of the right plural form
*/
private function select_string($n)
private function selectString($n)
{
$string = $this->get_plural_forms();
$string = $this->getPluralForms();
$string = str_replace('nplurals', "\$total", $string);
$string = str_replace("n", $n, $string);
$string = str_replace('plural', "\$plural", $string);
@@ -421,7 +438,7 @@ class GetTextReader
}
// find out the appropriate form
$select = $this->select_string($number);
$select = $this->selectString($number);
// this should contains all strings separated by NULLs
$key = $single . chr(0) . $plural;
@@ -435,11 +452,11 @@ class GetTextReader
return $list[$select];
}
} else {
$num = $this->find_string($key);
$num = $this->findString($key);
if ($num == -1) {
return ($number != 1) ? $plural : $single;
} else {
$result = $this->get_translation_string($num);
$result = $this->getTranslationString($num);
$list = explode(chr(0), $result);
return $list[$select];
}

View File

@@ -26,7 +26,9 @@ namespace CoreLibs\Language\Core;
class StringReader
{
/** @var int */
public $sr_pos;
/** @var string */
public $sr_str;
/**

View File

@@ -10,6 +10,7 @@ namespace CoreLibs\Language;
class Encoding
{
/** @var string */
private static $mb_error_char = '';
/**
@@ -82,7 +83,7 @@ class Encoding
* @param string $string string to test
* @param string $from_encoding encoding of string to test
* @param string $to_encoding target encoding
* @return bool|array false if no error or array with failed characters
* @return bool|array<string> false if no error or array with failed characters
*/
public static function checkConvertEncoding(string $string, string $from_encoding, string $to_encoding)
{

View File

@@ -33,9 +33,13 @@ use CoreLibs\Language\Core\GetTextReader;
class L10n extends \CoreLibs\Basic
{
/** @var string */
private $lang = '';
/** @var string */
private $mofile = '';
/** @var FileReader|bool */
private $input;
/** @var GetTextReader */
private $l10n;
/**

View File

@@ -59,7 +59,10 @@ class Elements
$hour = !$hour ? date('H', $timestamp) : $hour;
$min = !$min ? date('i', $timestamp) : $min; // add to five min?
// max days in selected month
$days_in_month = date('t', strtotime($year . '-' . $month . '-' . $day . ' ' . $hour . ':' . $min . ':0'));
$days_in_month = date(
't',
strtotime($year . '-' . $month . '-' . $day . ' ' . $hour . ':' . $min . ':0') ?: null
);
$string = '';
// from now to ?
if ($name_pos_back === false) {
@@ -93,7 +96,7 @@ class Elements
// set weekday text based on current month ($month) and year ($year)
$string .= '<option value="' . ($i < 10 ? '0' . $i : $i) . '" '
. ($day == $i ? 'selected' : '') . '>' . $i
. ' (' . date('D', mktime(0, 0, 0, $month, $i, $year)) . ')</option>';
. ' (' . date('D', mktime(0, 0, 0, (int)$month, $i, (int)$year) ?: null) . ')</option>';
}
$string .= '</select> ';
if ($name_pos_back === true) {
@@ -142,8 +145,8 @@ class Elements
$protList = ["http", "https", "ftp", "news", "nntp"];
// find urls w/o protocol
$output = preg_replace("/([^\/])www\.([\w\.-]+)\.([a-zA-Z]{2,4})/", "\\1http://www.\\2.\\3", $output);
$output = preg_replace("/([^\/])ftp\.([\w\.-]+)\.([a-zA-Z]{2,4})/", "\\1ftp://ftp.\\2.\\3", $output);
$output = preg_replace("/([^\/])www\.([\w\.-]+)\.([a-zA-Z]{2,4})/", "\\1http://www.\\2.\\3", $output) ?: '';
$output = preg_replace("/([^\/])ftp\.([\w\.-]+)\.([a-zA-Z]{2,4})/", "\\1ftp://ftp.\\2.\\3", $output) ?: '';
// remove doubles, generate protocol-regex
// DIRTY HACK
@@ -181,7 +184,7 @@ class Elements
);
},
$output
);
) ?: '';
// find email-addresses, but not mailto prefix ones
$output = preg_replace_callback(
"/(mailto:)?(\>)?\b([\w\.-]+)@([\w\.\-]+)\.([a-zA-Z]{2,4})\b(\|([^\||^#]+)(#([^\|]+))?\|)?/",
@@ -197,7 +200,7 @@ class Elements
);
},
$output
);
) ?: '';
// we have one slashes after the Protocol -> internal link no domain, strip out the proto
// $output = preg_replace("/($protRegex)\/(.*)/e", "\\2", $ouput);

View File

@@ -222,48 +222,78 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
{
// for the load statetment describes which elements from
// the load query should be shown and i which format
/** @var array<mixed> */
public $field_array = [];
/** @var string */
public $load_query; // the query needed for loading a data set (one row in the table)
/** @var string */
public $col_name; // the name of the columen (before _<type>) [used for order button]
/** @var int */
public $yes; // the yes flag that triggers the template to show ALL and not only new/load
/** @var string */
public $msg; // the error msg
/** @var int */
public $error; // the error flag set for printing red error msg
/** @var int */
public $warning; // warning flag, for information (saved, loaded, etc)
/** @var string */
public $archive_pk_name; // the pk name for the load select form
/** @var string */
private $int_pk_name; // primary key, only internal usage
/** @var array<mixed> */
public $reference_array = []; // reference arrays -> stored in $this->reference_array[$table_name] => [];
/** @var array<mixed> */
public $element_list; // element list for elements next to each other as a special sub group
/** @var array<mixed> */
public $table_array = [];
/** @var string */
public $my_page_name; // the name of the page without .php extension
/** @var bool */
public $mobile_phone = false;
// buttons and checkboxes
/** @var string */
public $archive;
/** @var string */
public $new;
/** @var string */
public $really_new;
/** @var string */
public $delete;
/** @var string */
public $really_delete;
/** @var string */
public $save;
/** @var string */
public $remove_button;
// security publics
/** @var int */
public $base_acl_level;
/** @var array<mixed> */
public $security_level;
// layout publics
/** @var int */
public $table_width;
// internal lang & encoding vars
/** @var string */
public $lang_dir = '';
/** @var string */
public $lang;
/** @var string */
public $lang_short;
/** @var string */
public $encoding;
// language
/** @var \CoreLibs\Language\L10n */
public $l;
// now some default error msgs (english)
/** @var array<mixed> */
public $language_array = [];
/**
* construct form generator
* @param array $db_config db config array
* @param int|integer $table_width table/div width (default 750)
* @param array<mixed> $db_config db config array
* @param int|integer $table_width table/div width (default 750)
*/
public function __construct(array $db_config, int $table_width = 750)
{
@@ -478,7 +508,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
* array of fields
* @param string $want_key the key where you want the data from
* @param string|null $key_value if set searches for special right value
* @return array found key fields
* @return array<mixed> found key fields
*/
public function formGetColNameArrayFromKey(string $want_key, ?string $key_value = null): array
{
@@ -500,7 +530,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
/**
* formated output for the error && warning msg
* @return array error message with msg, width, clas
* @return array<string,string|int> error message with msg, width, clas
*/
public function formPrintMsg(): array
{
@@ -605,9 +635,9 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
/**
* default delete procedure
* @param array $element_list element array that should be removed
* @param array $remove_name key names that should be removed
* @return void has no return
* @param array<mixed> $element_list element array that should be removed
* @param array<mixed> $remove_name key names that should be removed
* @return void has no return
*/
public function formProcedureDeleteFromElementList(array $element_list, array $remove_name): void
{
@@ -704,7 +734,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
/**
* create the load list and return it as an array
* @return array load list array with primary key, name and selected entry
* @return array<string,mixed> load list array with primary key, name and selected entry
*/
public function formCreateLoad(): array
{
@@ -721,7 +751,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
// load list data
$this->dbExec($this->load_query);
while ($res = $this->dbFetchArray()) {
while (is_array($res = $this->dbFetchArray())) {
$pk_ids[] = $res[$this->int_pk_name];
if (
isset($this->table_array[$this->int_pk_name]['value']) &&
@@ -766,8 +796,8 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
/**
* Create new entry element for HTML output
* @param bool $hide_new_checkbox show or hide the new checkbox, default is false
* @return array return the new create array with name & checkbox show flag
* @param bool $hide_new_checkbox show or hide the new checkbox, default is false
* @return array<string,string|int> return the new create array with name & checkbox show flag
*/
public function formCreateNew($hide_new_checkbox = false): array
{
@@ -798,7 +828,8 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
* create the save and delete element html group data
* @param bool $hide_delete hide the delete button (default false)
* @param bool $hide_delete_checkbox hide the delete checkbox (default false)
* @return array return the hide/show delete framework for html creation
* @return array<string,mixed> return the hide/show delete framework
* for html creation
*/
public function formCreateSaveDelete($hide_delete = false, $hide_delete_checkbox = false): array
{
@@ -853,8 +884,9 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
* @param string $element_name the name from the array, you want to have build
* @param string|null $query can overrule internal query data,
* for drop down, as data comes from a reference table
* for drop_down_text it has to be an array with $key->$valu
* @return array html settings array
* for drop_down_text it has to be an
* array with $key->$value
* @return array<string,mixed> html settings array
*/
public function formCreateElement(string $element_name, ?string $query = null): array
{
@@ -993,7 +1025,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
$data['name'] = $element_name;
$data['value'][] = '';
$data['output'][] = $this->l->__('Please choose .. . ');
while ($res = $this->dbReturn($query)) {
while (is_array($res = $this->dbReturn($query))) {
$data['value'][] = $res[0];
$data['output'][] = $res[1];
if (
@@ -1309,22 +1341,18 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
}
} // while
// do check for reference tables
if (is_array($this->reference_array)) {
reset($this->reference_array);
foreach ($this->reference_array as $key => $value) {
if (
isset($this->reference_array[$key]['mandatory']) &&
$this->reference_array[$key]['mandatory'] &&
!$this->reference_array[$key]['selected'][0]
) {
$this->msg .= sprintf(
$this->l->__('Please select at least one Element from field <b>%s</b>!<br>'),
$this->reference_array[$key]['output_name']
);
}
reset($this->reference_array);
foreach ($this->reference_array as $key => $value) {
if (
isset($this->reference_array[$key]['mandatory']) &&
$this->reference_array[$key]['mandatory'] &&
!$this->reference_array[$key]['selected'][0]
) {
$this->msg .= sprintf(
$this->l->__('Please select at least one Element from field <b>%s</b>!<br>'),
$this->reference_array[$key]['output_name']
);
}
} else {
$this->reference_array = [];
}
// $this->log->debug('edit_error', 'QS: <pre>' . print_r($_POST, true) . '</pre>');
if (is_array($this->element_list)) {
@@ -1502,7 +1530,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
/**
* sets the order to the maximum, if order flag is set in array
* @return array table array with set order number
* @return array<mixed> table array with set order number
*/
public function formSetOrder(): array
{
@@ -1593,7 +1621,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
$q = 'SELECT ' . $this->reference_array[$key]['other_table_pk']
. ' FROM ' . $this->reference_array[$key]['table_name']
. ' WHERE ' . $this->int_pk_name . ' = ' . $this->table_array[$this->int_pk_name]['value'];
while ($res = $this->dbReturn($q)) {
while (is_array($res = $this->dbReturn($q))) {
$this->reference_array[$key]['selected'][] = $res[$this->reference_array[$key]['other_table_pk']];
}
}
@@ -1646,14 +1674,14 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
. ' (' . $this->table_array[$key]['input_name'] . ') VALUES ('
. "'" . $this->dbEscapeString($this->table_array[$key]['input_value']) . "')";
$this->dbExec($q);
if (!empty($this->table_array[$key]['where'])) {
if (!empty($this->table_array[$key]['where']) && is_numeric($this->dbGetInsertPK())) {
// make an update on the just inseted data with the where data als update values
$q = 'UPDATE ' . $this->table_array[$key]['table_name'] . ' SET ';
$q .= $this->table_array[$key]['where'] . ' ';
$q .= 'WHERE ' . $this->table_array[$key]['pk_name'] . ' = ' . $this->insert_id;
$q .= 'WHERE ' . $this->table_array[$key]['pk_name'] . ' = ' . $this->dbGetInsertPK();
$this->dbExec($q);
}
$this->table_array[$key]['value'] = $this->insert_id;
$this->table_array[$key]['value'] = $this->dbGetInsertPK();
} // set value from DB through select or insert
unset($this->table_array[$key]['input_value']);
} // if it is certain field type && if there is something in the temp field
@@ -2039,8 +2067,8 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
/**
* creates HTML hidden input fields out of an hash array
* @param array $hidden_array The list of fields to be added as hidden
* @return array key -> value list of hidden fileds data
* @param array<mixed> $hidden_array The list of fields to be added as hidden
* @return array<mixed> key -> value list of hidden fileds data
*/
public function formCreateHiddenFields(array $hidden_array = []): array
{
@@ -2072,8 +2100,8 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
/**
* creates the multiple select part for a reference_table
* @param string $table_name Table name for reference array lookup
* @return array Reference table output array
* @param string $table_name Table name for reference array lookup
* @return array<string,mixed> Reference table output array
*/
public function formCreateElementReferenceTable(string $table_name): array
{
@@ -2087,7 +2115,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
}
$data['name'] = $this->reference_array[$table_name]['other_table_pk'];
$data['size'] = $this->reference_array[$table_name]['select_size'];
while ($res = $this->dbReturn($this->reference_array[$table_name]['query'])) {
while (is_array($res = $this->dbReturn($this->reference_array[$table_name]['query']))) {
$data['value'][] = $res[0];
$data['output'][] = $res[1];
$data['selected'][] = (\CoreLibs\Convert\Html::checked(
@@ -2109,8 +2137,8 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
* this currently only works for a list that is filled from a sub table and creates
* only a connection to this one new version will allow a sub list with free input
* fields to directly fill a sub table to a master table
* @param string $table_name which element entry to create
* @return array element for html creation
* @param string $table_name Which element entry to create
* @return array<string,mixed> Element for html creation
*/
public function formCreateElementListTable(string $table_name): array
{
@@ -2189,7 +2217,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
// only two elements are allowed: pos 0 is key, pso 1 is visible output name
if (isset($data_array['type']) && $data_array['type'] == 'drop_down_db') {
$md_q = md5($data_array['query']);
while ($res = $this->dbReturn($data_array['query'])) {
while (is_array($res = $this->dbReturn($data_array['query']))) {
/** @phan-suppress-next-line PhanTypeInvalidDimOffset */
$this->log->debug('edit', 'Q[' . $md_q . '] pos: ' . $this->cursor_ext[$md_q]['pos']
. ' | want: ' . ($data_array['preset'] ?? '-')
@@ -2332,7 +2360,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
if (isset($q)) {
$pos = 0; // position in while for overwrite if needed
// read out the list and add the selected data if needed
while ($res = $this->dbReturn($q)) {
while (is_array($res = $this->dbReturn($q))) {
$_data = [];
$prfx = $data['prefix'] ?? ''; // short
// go through each res

View File

@@ -127,7 +127,7 @@ class Image
$return_data = $thumb;
// if we have a delete filename, delete here with glob
if ($delete_filename) {
array_map('unlink', glob($delete_filename . '*'));
array_map('unlink', glob($delete_filename . '*') ?: []);
}
} else {
if (!empty($dummy) && strstr($dummy, '/') === false) {
@@ -255,11 +255,18 @@ class Image
) {
// image, copy source image, offset in image, source x/y, new size, source image size
$thumb = imagecreatetruecolor($thumb_width_r, $thumb_height_r);
if ($thumb === false) {
return false;
}
if ($img_type == IMAGETYPE_PNG) {
$imagecolorallocatealpha = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
if ($imagecolorallocatealpha === false) {
return false;
}
// preservere transaprency
imagecolortransparent(
$thumb,
imagecolorallocatealpha($thumb, 0, 0, 0, 127)
$imagecolorallocatealpha
);
imagealphablending($thumb, false);
imagesavealpha($thumb, true);
@@ -274,7 +281,7 @@ class Image
break;
}
// check that we have a source image resource
if ($source !== null) {
if ($source !== null && $source !== false) {
// resize no shift
if ($high_quality === true) {
imagecopyresized(
@@ -356,10 +363,16 @@ class Image
$thumb_width = 250;
}
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
if ($thumb === false) {
return false;
}
// add outside border px = 5% (rounded up)
// eg 50px -> 2.5px
$gray = imagecolorallocate($thumb, 200, 200, 200);
$white = imagecolorallocate($thumb, 255, 255, 255);
if ($gray === false || $white === false) {
return false;
}
// fill gray background
imagefill($thumb, 0, 0, $gray);
// now create rectangle
@@ -407,55 +420,66 @@ class Image
*/
public static function correctImageOrientation($filename): void
{
if (function_exists('exif_read_data') && is_writeable($filename)) {
list($inc_width, $inc_height, $img_type) = getimagesize($filename);
// add @ to avoid "file not supported error"
$exif = @exif_read_data($filename);
$orientation = null;
$img = null;
if ($exif && isset($exif['Orientation'])) {
$orientation = $exif['Orientation'];
}
if ($orientation != 1) {
switch ($img_type) {
case IMAGETYPE_JPEG:
$img = imagecreatefromjpeg($filename);
break;
case IMAGETYPE_PNG:
$img = imagecreatefrompng($filename);
break;
}
$deg = 0;
// 1 top, 6: left, 8: right, 3: bottom
switch ($orientation) {
case 3:
$deg = 180;
break;
case 6:
$deg = -90;
break;
case 8:
$deg = 90;
break;
}
if ($img !== null) {
if ($deg) {
$img = imagerotate($img, $deg, 0);
}
// then rewrite the rotated image back to the disk as $filename
switch ($img_type) {
case IMAGETYPE_JPEG:
imagejpeg($img, $filename);
break;
case IMAGETYPE_PNG:
imagepng($img, $filename);
break;
}
// clean up image if we have an image
imagedestroy($img);
}
} // only if we need to rotate
} // function exists & file is writeable, else do nothing
// function exists & file is writeable, else do nothing
if (!function_exists('exif_read_data') || !is_writeable($filename)) {
return;
}
list($inc_width, $inc_height, $img_type) = getimagesize($filename);
// add @ to avoid "file not supported error"
$exif = @exif_read_data($filename);
$orientation = null;
$img = null;
if ($exif && isset($exif['Orientation'])) {
$orientation = $exif['Orientation'];
}
// only if we need to rotate, if 1 it is already upright
if ($orientation === null || $orientation == 1) {
return;
}
switch ($img_type) {
case IMAGETYPE_JPEG:
$img = imagecreatefromjpeg($filename);
break;
case IMAGETYPE_PNG:
$img = imagecreatefrompng($filename);
break;
}
// no image loaded (wrong type)
if ($img === null || $img === false) {
return;
}
$deg = 0;
// 1 top, 6: left, 8: right, 3: bottom
switch ($orientation) {
case 3:
$deg = 180;
break;
case 6:
$deg = -90;
break;
case 8:
$deg = 90;
break;
}
// rotate if needed
if ($deg) {
$img = imagerotate($img, $deg, 0);
}
// rotate failed
if ($img === false) {
return;
}
// then rewrite the rotated image back to the disk as $filename
switch ($img_type) {
case IMAGETYPE_JPEG:
imagejpeg($img, $filename);
break;
case IMAGETYPE_PNG:
imagepng($img, $filename);
break;
}
// clean up image if we have an image
imagedestroy($img);
}
}

View File

@@ -26,7 +26,7 @@ class ProgressBar
public $code; // unique code
/** @var string */
public $status = 'new'; // current status (new,show,hide)
/** @var int */
/** @var float|int */
public $step = 0; // current step
/** @var array<string,?int> */
public $position = [ // current bar position
@@ -223,8 +223,8 @@ class ProgressBar
/**
* set the step
* @param float $step percent step to do
* @return void has no return
* @param float $step percent step to do
* @return void
*/
private function __setStep(float $step): void
{
@@ -242,7 +242,7 @@ class ProgressBar
* set frame layout
* @param integer $width bar width
* @param integer $height bar height
* @return void has no return
* @return void
*/
public function setFrame(int $width = 0, int $height = 0): void
{
@@ -271,7 +271,7 @@ class ProgressBar
* @param string $type label type
* @param string $name label name (internal)
* @param string $value label output name (optional)
* @return void has no return
* @return void
*/
public function addLabel(string $type, string $name, string $value = '&nbsp;'): void
{
@@ -377,7 +377,7 @@ class ProgressBar
* @param string $value button text (output)
* @param string $action button action (link)
* @param string $target button action target (default self)
* @return void has no return
* @return void
*/
public function addButton(string $name, string $value, string $action, string $target = 'self'): void
{
@@ -394,7 +394,7 @@ class ProgressBar
* @param int $width width px
* @param int $height height px
* @param string $align alignment (left/right/etc), default empty
* @return void has no return
* @return void
*/
public function setLabelPosition(
string $name,
@@ -440,7 +440,7 @@ class ProgressBar
* set label color
* @param string $name label name to set
* @param string $color color value in rgb html hex
* @return void has no return
* @return void
*/
public function setLabelColor(string $name, string $color): void
{
@@ -456,7 +456,7 @@ class ProgressBar
* set the label background color
* @param string $name label name to set
* @param string $color background color to set in rgb html hex
* @return void has no return
* @return void
*/
public function setLabelBackground(string $name, string $color): void
{
@@ -474,7 +474,7 @@ class ProgressBar
* @param int $size font size in px
* @param string $family font family (default empty)
* @param string $weight font weight (default empty)
* @return void has no return
* @return void
*/
public function setLabelFont(string $name, int $size, string $family = '', string $weight = ''): void
{
@@ -523,7 +523,7 @@ class ProgressBar
* set the label valeu
* @param string $name label name to set
* @param string $value label value (output)
* @return void has no return
* @return void
*/
public function setLabelValue(string $name, string $value): void
{
@@ -539,7 +539,7 @@ class ProgressBar
/**
* set the bar color
* @param string $color color for the progress bar in rgb html hex
* @return void has no return
* @return void
*/
public function setBarColor(string $color): void
{
@@ -554,7 +554,7 @@ class ProgressBar
/**
* set the progress bar background color
* @param string $color background color in rgb html hex
* @return void has no return
* @return void
*/
public function setBarBackground(string $color): void
{
@@ -569,7 +569,7 @@ class ProgressBar
/**
* progress bar direct (left/right)
* @param string $direction set direction as left/right
* @return void has no return
* @return void
*/
public function setBarDirection(string $direction): void
{

View File

@@ -0,0 +1,32 @@
<?php
namespace FileUpload\Core;
interface qqUploadedFile // phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
{
/**
* Save the file to the specified path
*
* @param string $path
* @return boolean TRUE on success
*/
public function save(string $path): bool;
/**
* get qqfile name from _GET array
*
* @return string
*/
public function getName(): string;
/**
* Get file size from _SERVERa array, throws an error if not possible
*
* @return int
*
* @throws \Exception
*/
public function getSize(): int;
}
// __END__

View File

@@ -5,26 +5,40 @@ namespace FileUpload\Core;
/**
* Handle file uploads via regular form post (uses the $_FILES array)
*/
class qqUploadedFileForm
class qqUploadedFileForm implements qqUploadedFile // phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
{
/**
* Save the file to the specified path
*
* @param string $path
* @return boolean TRUE on success
*/
public function save($path)
public function save(string $path): bool
{
if (!move_uploaded_file($_FILES['qqfile']['tmp_name'], $path)) {
return false;
}
return true;
}
public function getName()
/**
* get qqfile name from _FILES array
*
* @return string
*/
public function getName(): string
{
return $_FILES['qqfile']['name'];
return $_FILES['qqfile']['name'] ?? '';
}
public function getSize()
/**
* get files size from _FILES array
*
* @return int
*/
public function getSize(): int
{
return $_FILES['qqfile']['size'];
return (int)$_FILES['qqfile']['size'] ?? 0;
}
}

View File

@@ -5,16 +5,22 @@ namespace FileUpload\Core;
/**
* Handle file uploads via XMLHttpRequest
*/
class qqUploadedFileXhr
class qqUploadedFileXhr implements qqUploadedFile // phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
{
/**
* Save the file to the specified path
*
* @param string $path
* @return boolean TRUE on success
*/
public function save($path)
public function save(string $path): bool
{
$input = fopen("php://input", "r");
$temp = tmpfile();
// abort if not resources
if (!is_resource($input) || !is_resource($temp)) {
return false;
}
$realSize = stream_copy_to_stream($input, $temp);
fclose($input);
@@ -23,17 +29,34 @@ class qqUploadedFileXhr
}
$target = fopen($path, "w");
if (!is_resource($target)) {
return false;
}
fseek($temp, 0, SEEK_SET);
stream_copy_to_stream($temp, $target);
fclose($target);
return true;
}
public function getName()
/**
* get qqfile name from _GET array
*
* @return string
*/
public function getName(): string
{
return $_GET['qqfile'];
return $_GET['qqfile'] ?? '';
}
public function getSize()
/**
* Get file size from _SERVERa array, throws an error if not possible
*
* @return int
*
* @throws \Exception
*/
public function getSize(): int
{
if (isset($_SERVER['CONTENT_LENGTH'])) {
return (int)$_SERVER['CONTENT_LENGTH'];

View File

@@ -2,17 +2,29 @@
namespace FileUpload;
// use \FileUpload\Core;
use FileUpload\Core;
class qqFileUploader
// TODO: find all usages from qqFileUploader and name to Qq
class qqFileUploader // phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
{
private $allowedExtensions = array();
/** @var array<mixed> */
private $allowedExtensions = [];
/** @var int */
private $sizeLimit = 10485760;
/** @var null|Core\qqUploadedFileXhr|Core\qqUploadedFileForm */
private $file;
/** @var string */
public $uploadFileName;
/** @var string */
public $uploadFileExt;
public function __construct(array $allowedExtensions = array(), $sizeLimit = 10485760)
/**
* Undocumented function
*
* @param array<mixed> $allowedExtensions
* @param integer $sizeLimit
*/
public function __construct(array $allowedExtensions = [], int $sizeLimit = 10485760)
{
$allowedExtensions = array_map("strtolower", $allowedExtensions);
@@ -22,18 +34,23 @@ class qqFileUploader
$this->checkServerSettings();
if (isset($_GET['qqfile'])) {
$this->file = new \FileUpload\Core\qqUploadedFileXhr();
$this->file = new Core\qqUploadedFileXhr();
} elseif (isset($_FILES['qqfile'])) {
$this->file = new \FileUpload\Core\qqUploadedFileForm();
$this->file = new Core\qqUploadedFileForm();
} else {
$this->file = false;
$this->file = null;
}
}
private function checkServerSettings()
/**
* Undocumented function
*
* @return void
*/
private function checkServerSettings(): void
{
$postSize = $this->toBytes(ini_get('post_max_size'));
$uploadSize = $this->toBytes(ini_get('upload_max_filesize'));
$postSize = $this->toBytes(ini_get('post_max_size') ?: '');
$uploadSize = $this->toBytes(ini_get('upload_max_filesize') ?: '');
if ($postSize < $this->sizeLimit || $uploadSize < $this->sizeLimit) {
$size = max(1, $this->sizeLimit / 1024 / 1024) . 'M';
@@ -41,10 +58,16 @@ class qqFileUploader
}
}
private function toBytes($str)
/**
* Undocumented function
*
* @param string $str
* @return integer
*/
private function toBytes(string $str): int
{
$val = (int)trim($str);
$last = strtolower($str[strlen($str)-1]);
$last = strtolower($str[strlen($str) - 1]);
switch ($last) {
case 'g':
$val *= 1024;
@@ -59,36 +82,42 @@ class qqFileUploader
}
/**
* Returns array('success'=>true) or array('error'=>'error message')
* Undocumented function
*
* @param string $uploadDirectory
* @param boolean $replaceOldFile
* @return array<string,string|bool> Returns ['success'=>true] or
* ['error'=>'error message']
*/
public function handleUpload($uploadDirectory, $replaceOldFile = false)
public function handleUpload(string $uploadDirectory, bool $replaceOldFile = false): array
{
if (!is_writable($uploadDirectory)) {
return array('error' => "Server error. Upload directory isn't writable.");
return ['error' => "Server error. Upload directory isn't writable."];
}
if (!$this->file) {
return array('error' => 'No files were uploaded.');
if (!is_object($this->file)) {
return ['error' => 'No files were uploaded.'];
}
$size = 0;
$size = $this->file->getSize();
if ($size == 0) {
return array('error' => 'File is empty');
return ['error' => 'File is empty'];
}
if ($size > $this->sizeLimit) {
return array('error' => 'File is too large');
return ['error' => 'File is too large'];
}
$pathinfo = pathinfo($this->file->getName());
$filename = $pathinfo['filename'];
$filename = $pathinfo['filename'] ?? '';
//$filename = md5(uniqid());
$ext = $pathinfo['extension'] ?? '';
if ($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)) {
$these = implode(', ', $this->allowedExtensions);
return array('error' => 'File has an invalid extension, it should be one of '. $these . '.');
return ['error' => 'File has an invalid extension, it should be one of ' . $these . '.'];
}
if (!$replaceOldFile) {
@@ -102,10 +131,12 @@ class qqFileUploader
$this->uploadFileExt = $ext;
if ($this->file->save($uploadDirectory . $filename . '.' . $ext)) {
return array('success' => true);
return ['success' => true];
} else {
return array('error' => 'Could not save uploaded file.' .
'The upload was cancelled, or server error encountered');
return [
'error' => 'Could not save uploaded file.' .
'The upload was cancelled, or server error encountered'
];
}
}
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* TEST sets for DB::IO
*/
namespace Test\DB;
use CoreLibs\DB\IO;
class TestDB
{
/** @var IO */
private $db;
/** @var array<mixed> */
private $config;
/**
* Undocumented function
*/
public function __construct()
{
$this->config = [
'db_name' => $_ENV['DB_NAME_TEST'] ?? '',
'db_user' => $_ENV['DB_USER_TEST'] ?? '',
'db_pass' => $_ENV['DB_PASS_TEST'] ?? '',
'db_host' => $_ENV['DB_HOST_TEST'] ?? '',
'db_port' => 5432,
'db_schema' => 'public',
'db_type' => 'pgsql',
'db_encoding' => '',
'db_ssl' => 'allow'
];
$this->db = new IO($this->config);
}
/**
* Undocumented function
*
* @return void
*/
private function testDBa(): void
{
$this->db->dbInfo();
}
/**
* Undocumented function
*
* @return void
*/
public function testRunDB(): void
{
$this->testDBa();
}
}
// __ENB__

78
www/lib/Test/Test.php Normal file
View File

@@ -0,0 +1,78 @@
<?php
/*
* TEST sets only
*/
declare(strict_types=1);
namespace Test;
use Test\DB;
class Test
{
/** @var DB\TestDB */
private $test_db;
public function __construct()
{
// calls all tests
$this->testPrivate();
$this->testProtected();
$this->testPublic();
// call intern
$this->test_db = new DB\TestDB();
}
public function __destruct()
{
// calls all close tests
}
/**
* Undocumented function
*
* @return string
*/
protected function testPrivate(): string
{
$string = 'TEST Private';
return $string;
}
/**
* Undocumented function
*
* @return string
*/
protected function testProtected(): string
{
$string = 'TEST Protected';
return $string;
}
/**
* Undocumented function
*
* @return string
*/
public function testPublic(): string
{
$string = 'TEST Public';
return $string;
}
/**
* Undocumented function
*
* @return void
*/
public function testClasses(): void
{
$this->test_db->testRunDB();
}
}
// __END__