Compare commits

...

18 Commits

Author SHA1 Message Date
Clemens Schwaighofer
1bb4d5f426 UrlRequest curl class added 2024-11-06 18:56:17 +09:00
Clemens Schwaighofer
a65485e56a Release: v9.17.6.1 2024-11-06 13:37:05 +09:00
Clemens Schwaighofer
5e6ba85639 Merge branch 'development' 2024-10-17 14:04:45 +09:00
Clemens Schwaighofer
3cf891a7d2 Release: v9.17.6 2024-10-17 14:02:14 +09:00
Clemens Schwaighofer
6e19f30ff5 Bug fix in DB\IO 2024-10-17 14:01:13 +09:00
Clemens Schwaighofer
95079885c5 Release: v9.17.5 2024-10-17 13:56:59 +09:00
Clemens Schwaighofer
14dab54f2c Update DB\IO and do not print call steck on DB_INFO calls, array list
entry clean up
2024-10-17 13:55:38 +09:00
Clemens Schwaighofer
180fba596a Release: v9.17.4 2024-10-16 16:51:20 +09:00
Clemens Schwaighofer
69e2503a36 Admin\Backend change non filled dat part comment 2024-10-16 16:50:17 +09:00
Clemens Schwaighofer
c06ae55919 Release: v9.17.3 2024-10-16 16:31:05 +09:00
Clemens Schwaighofer
6098d1091a Update the Admin\Backend edit log call with query params and different data compressors 2024-10-16 16:29:29 +09:00
Clemens Schwaighofer
2a8038835f Release: v9.17.2 2024-10-16 12:37:41 +09:00
Clemens Schwaighofer
984dec37e2 Bug fix for Admin\Backend ->action var access 2024-10-16 12:36:38 +09:00
Clemens Schwaighofer
d91fbd5a46 Release: v9.17.1 2024-10-16 12:28:40 +09:00
Clemens Schwaighofer
668954c1c4 Admin\Backend move _POST action read to sub function and trigger not auto loading it 2024-10-16 12:26:33 +09:00
Clemens Schwaighofer
adbae19fca Release: v9.17.0 2024-09-24 15:18:43 +09:00
Clemens Schwaighofer
39de680b66 Extend Error Message collector print warning log 2024-09-24 15:15:23 +09:00
Clemens Schwaighofer
2e81a4da82 Release: v9.16.0 2024-09-20 13:43:20 +09:00
17 changed files with 2885 additions and 147 deletions

View File

@@ -1 +1 @@
9.15.0
9.17.6.1

View File

@@ -31,6 +31,8 @@ declare(strict_types=1);
namespace CoreLibs\Admin;
use CoreLibs\Convert\Json;
class Backend
{
// page name
@@ -42,7 +44,7 @@ class Backend
/** @var array<string> */
public array $action_list = [
'action', 'action_id', 'action_sub_id', 'action_yes', 'action_flag',
'action_menu', 'action_value', 'action_error', 'action_loaded'
'action_menu', 'action_value', 'action_type', 'action_error', 'action_loaded'
];
/** @var string */
public string $action;
@@ -61,20 +63,31 @@ class Backend
/** @var string */
public string $action_value;
/** @var string */
public string $action_type;
/** @var string */
public string $action_error;
// ACL array variable if we want to set acl data from outisde
/** @var array<mixed> */
public array $acl = [];
/** @var int */
public int $default_acl;
// queue key
/** @var string */
public string $queue_key;
/** @var array<string> list of allowed types for edit log write */
private const WRITE_TYPES = ['BINARY', 'BZIP2', 'LZIP', 'STRING', 'SERIAL', 'JSON'];
/** @var array<string> list of available write types for log */
private array $write_types_available = [];
// the current active edit access id
/** @var int|null */
public int|null $edit_access_id;
/** @var string */
public string $page_name;
// error/warning/info messages
/** @var array<mixed> */
public array $messages = [];
@@ -84,6 +97,7 @@ class Backend
public bool $warning = false;
/** @var bool */
public bool $info = false;
// internal lang & encoding vars
/** @var string */
public string $lang_dir = '';
@@ -95,6 +109,7 @@ class Backend
public string $domain;
/** @var string */
public string $encoding;
/** @var \CoreLibs\Logging\Logging logger */
public \CoreLibs\Logging\Logging $log;
/** @var \CoreLibs\DB\IO database */
@@ -103,6 +118,7 @@ class Backend
public \CoreLibs\Language\L10n $l;
/** @var \CoreLibs\Create\Session session class */
public \CoreLibs\Create\Session $session;
// smarty publics [end processing in smarty class]
/** @var array<mixed> */
public array $DATA = [];
@@ -117,18 +133,20 @@ class Backend
/**
* main class constructor
*
* @param \CoreLibs\DB\IO $db Database connection class
* @param \CoreLibs\Logging\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class
* @param \CoreLibs\Language\L10n $l10n l10n language class
* @param int|null $set_default_acl_level Default ACL level
* @param \CoreLibs\DB\IO $db Database connection class
* @param \CoreLibs\Logging\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class
* @param \CoreLibs\Language\L10n $l10n l10n language class
* @param int|null $set_default_acl_level [default=null] Default ACL level
* @param bool $init_action_vars [default=true] If the action vars should be set
*/
public function __construct(
\CoreLibs\DB\IO $db,
\CoreLibs\Logging\Logging $log,
\CoreLibs\Create\Session $session,
\CoreLibs\Language\L10n $l10n,
?int $set_default_acl_level = null
?int $set_default_acl_level = null,
bool $init_action_vars = true
) {
// attach db class
$this->db = $db;
@@ -151,9 +169,9 @@ class Backend
// set the page name
$this->page_name = \CoreLibs\Get\System::getPageName();
// set the action ids
foreach ($this->action_list as $_action) {
$this->$_action = $_POST[$_action] ?? '';
// NOTE: if any of the "action" vars are used somewhere, it is recommended to NOT set them here
if ($init_action_vars) {
$this->adbSetActionVars();
}
if ($set_default_acl_level === null) {
@@ -170,9 +188,12 @@ class Backend
}
// queue key
if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action)) {
if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action ?? '')) {
$this->queue_key = \CoreLibs\Create\RandomKey::randomKeyGen(3);
}
// check what edit log data write types are allowed
$this->adbSetEditLogWriteTypeAvailable();
}
/**
@@ -183,7 +204,26 @@ class Backend
// NO OP
}
// PUBLIC METHODS |=================================================>
// MARK: PRIVATE METHODS
/**
* set the write types that are allowed
*
* @return void
*/
private function adbSetEditLogWriteTypeAvailable()
{
// check what edit log data write types are allowed
$this->write_types_available = self::WRITE_TYPES;
if (!function_exists('bzcompress')) {
$this->write_types_available = array_diff($this->write_types_available, ['BINARY', 'BZIP']);
}
if (!function_exists('gzcompress')) {
$this->write_types_available = array_diff($this->write_types_available, ['LZIP']);
}
}
// MARK: PUBLIC METHODS |=================================================>
/**
* set internal ACL from login ACL
@@ -195,30 +235,95 @@ class Backend
$this->acl = $acl;
}
/**
* Return current set ACL
*
* @return array<mixed>
*/
public function adbGetAcl(): array
{
return $this->acl;
}
/**
* Set _POST action vars if needed
*
* @return void
*/
public function adbSetActionVars()
{
// set the action ids
foreach ($this->action_list as $_action) {
$this->$_action = $_POST[$_action] ?? '';
}
}
/**
* writes all action vars plus other info into edit_log table
*
* @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
* @param string|null $db_schema override target schema
* @param string $event [default=''] any kind of event description,
* @param string|array<mixed> $data [default=''] any kind of data related to that event
* @param string $write_type [default=JSON] write type can be
* JSON, STRING/SERIEAL, BINARY/BZIP or ZLIB
* @param string|null $db_schema [default=null] override target schema
* @return void
*/
public function adbEditLog(
string $event = '',
string|array $data = '',
string $write_type = 'STRING',
string $write_type = 'JSON',
?string $db_schema = null
): void {
$data_binary = '';
$data_write = '';
if ($write_type == 'BINARY') {
$data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data)));
$data_write = 'see bzip compressed data_binary field';
// check if write type is valid, if not fallback to JSON
if (!in_array($write_type, $this->write_types_available)) {
$this->log->warning('Write type not in allowed array, fallback to JSON', context:[
"write_type" => $write_type,
"write_list" => $this->write_types_available,
]);
$write_type = 'JSON';
}
if ($write_type == 'STRING') {
$data_binary = '';
$data_write = $this->db->dbEscapeString(serialize($data));
switch ($write_type) {
case 'BINARY':
case 'BZIP':
$data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data)));
$data_write = Json::jsonConvertArrayTo([
'type' => 'BZIP',
'message' => 'see bzip compressed data_binary field'
]);
break;
case 'ZLIB':
$data_binary = $this->db->dbEscapeBytea((string)gzcompress(serialize($data)));
$data_write = Json::jsonConvertArrayTo([
'type' => 'ZLIB',
'message' => 'see zlib compressed data_binary field'
]);
break;
case 'STRING':
case 'SERIAL':
$data_binary = $this->db->dbEscapeBytea(Json::jsonConvertArrayTo([
'type' => 'SERIAL',
'message' => 'see serial string data field'
]));
$data_write = serialize($data);
break;
case 'JSON':
$data_binary = $this->db->dbEscapeBytea(Json::jsonConvertArrayTo([
'type' => 'JSON',
'message' => 'see json string data field'
]));
// must be converted to array
if (!is_array($data)) {
$data = ["data" => $data];
}
$data_write = Json::jsonConvertArrayTo($data);
break;
default:
$this->log->alert('Invalid type for data compression was set', context:[
"write_type" => $write_type
]);
break;
}
/** @var string $DB_SCHEMA check schema */
@@ -228,44 +333,62 @@ class Backend
} elseif (!empty($this->db->dbGetSchema())) {
$DB_SCHEMA = $this->db->dbGetSchema();
}
$q = "INSERT INTO " . $DB_SCHEMA . ".edit_log "
. "(euid, event_date, event, data, data_binary, page, "
. "ip, user_agent, referer, script_name, query_string, server_name, http_host, "
. "http_accept, http_accept_charset, http_accept_encoding, session_id, "
. "action, action_id, action_yes, action_flag, action_menu, action_loaded, action_value, action_error) "
. "VALUES "
. "(" . $this->db->dbEscapeString(isset($_SESSION['EUID']) && is_numeric($_SESSION['EUID']) ?
$_SESSION['EUID'] :
'NULL')
. ", "
. "NOW(), "
. "'" . $this->db->dbEscapeString((string)$event) . "', "
. "'" . $data_write . "', "
. "'" . $data_binary . "', "
. "'" . $this->db->dbEscapeString((string)$this->page_name) . "', "
. "'" . ($_SERVER["REMOTE_ADDR"] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_USER_AGENT'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_REFERER'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['SCRIPT_FILENAME'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['QUERY_STRING'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['SERVER_NAME'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_HOST'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT_CHARSET'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT_ENCODING'] ?? '') . "', "
. ($this->session->getSessionId() === false ?
"NULL" :
"'" . $this->session->getSessionId() . "'")
. ", "
. "'" . $this->db->dbEscapeString($this->action) . "', "
. "'" . $this->db->dbEscapeString($this->action_id) . "', "
. "'" . $this->db->dbEscapeString($this->action_yes) . "', "
. "'" . $this->db->dbEscapeString($this->action_flag) . "', "
. "'" . $this->db->dbEscapeString($this->action_menu) . "', "
. "'" . $this->db->dbEscapeString($this->action_loaded) . "', "
. "'" . $this->db->dbEscapeString($this->action_value) . "', "
. "'" . $this->db->dbEscapeString($this->action_error) . "')";
$this->db->dbExec($q, 'NULL');
$q = <<<SQL
INSERT INTO {DB_SCHEMA}.edit_log (
euid, event_date, event, data, data_binary, page,
ip, user_agent, referer, script_name, query_string, server_name, http_host,
http_accept, http_accept_charset, http_accept_encoding, session_id,
action, action_id, action_yes, action_flag, action_menu, action_loaded,
action_value, action_type, action_error
) VALUES (
$1, NOW(), $2, $3, $4, $5,
$6, $7, $8, $9, $10, $11, $12,
$13, $14, $15, $16,
$17, $18, $19, $20, $21, $22,
$23, $24, $25
)
SQL;
$this->db->dbExecParams(
str_replace(
['{DB_SCHEMA}'],
[$DB_SCHEMA],
$q
),
[
// row 1
isset($_SESSION['EUID']) && is_numeric($_SESSION['EUID']) ?
$_SESSION['EUID'] : null,
(string)$event,
$data_write,
$data_binary,
(string)$this->page_name,
// row 2
$_SERVER["REMOTE_ADDR"] ?? '',
$_SERVER['HTTP_USER_AGENT'] ?? '',
$_SERVER['HTTP_REFERER'] ?? '',
$_SERVER['SCRIPT_FILENAME'] ?? '',
$_SERVER['QUERY_STRING'] ?? '',
$_SERVER['SERVER_NAME'] ?? '',
$_SERVER['HTTP_HOST'] ?? '',
// row 3
$_SERVER['HTTP_ACCEPT'] ?? '',
$_SERVER['HTTP_ACCEPT_CHARSET'] ?? '',
$_SERVER['HTTP_ACCEPT_ENCODING'] ?? '',
$this->session->getSessionId() !== false ?
$this->session->getSessionId() : null,
// row 4
$this->action ?? '',
$this->action_id ?? '',
$this->action_yes ?? '',
$this->action_flag ?? '',
$this->action_menu ?? '',
$this->action_loaded ?? '',
$this->action_value ?? '',
$this->action_type ?? '',
$this->action_error ?? '',
],
'NULL'
);
}
/**
@@ -515,16 +638,30 @@ class Backend
} elseif (!empty($this->db->dbGetSchema())) {
$DB_SCHEMA = $this->db->dbGetSchema();
}
$q = "INSERT INTO " . $DB_SCHEMA . ".live_queue ("
. "queue_key, key_value, key_name, type, target, data, group_key, action, associate, file"
. ") VALUES ("
. "'" . $this->db->dbEscapeString($queue_key) . "', '" . $this->db->dbEscapeString($key_value) . "', "
. "'" . $this->db->dbEscapeString($key_name) . "', '" . $this->db->dbEscapeString($type) . "', "
. "'" . $this->db->dbEscapeString($target) . "', '" . $this->db->dbEscapeString($data) . "', "
. "'" . $this->queue_key . "', '" . $this->action . "', "
. "'" . $this->db->dbEscapeString((string)$associate) . "', "
. "'" . $this->db->dbEscapeString((string)$file) . "')";
$this->db->dbExec($q);
$q = <<<SQL
INSERT INTO {DB_SCHEMA}.live_queue (
queue_key, key_value, key_name, type,
target, data, group_key, action, associate, file
) VALUES (
$1, $2, $3, $4,
$5, $6, $7, $8, $9, $10
)
SQL;
// $this->db->dbExec($q);
$this->db->dbExecParams(
str_replace(
['{DB_SCHEMA}'],
[$DB_SCHEMA],
$q
),
[
$queue_key, $key_value,
$key_name, $type,
$target, $data,
$this->queue_key, $this->action,
(string)$associate, (string)$file
]
);
}
/**

View File

@@ -509,6 +509,22 @@ class ArrayHandler
}
return $array;
}
/**
* Remove entries from a simple array, will not keep key order
*
* any array content is allowed
*
* https://stackoverflow.com/a/369608
*
* @param array<mixed> $array Array where elements are located
* @param array<mixed> $remove Elements to remove
* @return array<mixed> Array with $remove elements removed
*/
public static function arrayRemoveEntry(array $array, array $remove): array
{
return array_diff($array, $remove);
}
}
// __END__

View File

@@ -823,6 +823,10 @@ class IO
);
break;
default:
// no context on DB_INFO
if ($id == 'DB_INFO') {
$context = [];
}
// used named arguments so we can easy change the order of debug
$this->log->debug(
group_id: $debug_id,
@@ -1814,14 +1818,13 @@ class IO
$html_tags = ['{b}', '{/b}', '{br}'];
$replace_html = ['<b>', '</b>', '<br>'];
$replace_text = ['', '', ' **** '];
$string = '';
$string .= '{b}-DB-info->{/b} Connected to db {b}\'' . $this->db_name . '\'{/b} ';
$string .= 'with schema {b}\'' . $this->db_schema . '\'{/b} ';
$string .= 'as user {b}\'' . $this->db_user . '\'{/b} ';
$string .= 'at host {b}\'' . $this->db_host . '\'{/b} ';
$string .= 'on port {b}\'' . $this->db_port . '\'{/b} ';
$string .= 'with ssl mode {b}\'' . $this->db_ssl . '\'{/b}{br}';
$string .= '{b}-DB-info->{/b} DB IO Class debug output: {b}'
$string = '{b}-DB-info->{/b} Connected to db {b}\'' . $this->db_name . '\'{/b} '
. 'with schema {b}\'' . $this->db_schema . '\'{/b} '
. 'as user {b}\'' . $this->db_user . '\'{/b} '
. 'at host {b}\'' . $this->db_host . '\'{/b} '
. 'on port {b}\'' . $this->db_port . '\'{/b} '
. 'with ssl mode {b}\'' . $this->db_ssl . '\'{/b}{br}'
. '{b}-DB-info->{/b} DB IO Class debug output: {b}'
. ($this->dbGetDebug() ? 'Yes' : 'No') . '{/b}';
if ($log === true) {
// if debug, remove / change b
@@ -1829,7 +1832,7 @@ class IO
$html_tags,
$replace_text,
$string
), 'dbInfo');
), 'DB_INFO');
} else {
$string = $string . '{br}';
}
@@ -1985,7 +1988,7 @@ class IO
if (is_array($array)) {
$this->nbsp = '';
$string .= $this->__printArray($array);
$this->__dbDebugMessage('db', $string, 'dbDumpData');
$this->__dbDebugMessage('db', $string, 'DB_INFO');
}
return $string;
}

View File

@@ -24,16 +24,20 @@ class ErrorMessage
/** @var bool $log_error global flag to log error level message */
private bool $log_error = false;
/** @var bool $log_warning global flat to log warning level messages */
private bool $log_warning = false;
/**
* init ErrorMessage
*
* @param \CoreLibs\Logging\Logging $log
* @param null|bool $log_error [=null], defaults to false if log is not level debug
* @param null|bool $log_warning [=null], defaults to false if log is not level debug
*/
public function __construct(
\CoreLibs\Logging\Logging $log,
?bool $log_error = null
?bool $log_error = null,
?bool $log_warning = null
) {
$this->log = $log;
// if log default logging is debug then log_error is default set to true
@@ -43,6 +47,13 @@ class ErrorMessage
$log_error = $log_error ?? false;
}
$this->log_error = $log_error;
// if log default logging is debug then log_warning is default set to true
if ($this->log->loggingLevelIsDebug() && $log_warning === null) {
$log_warning = true;
} else {
$log_warning = $log_warning ?? false;
}
$this->log_warning = $log_warning;
}
/**
@@ -81,6 +92,8 @@ class ErrorMessage
* @param array<mixed> $context Additionl info for abort/crash messages
* @param bool|null $log_error [=null] log level 'error' to error, if null use global,
* else set for this call only
* @param bool|null $log_warning [=null] log level 'warning' to warning, if null use global,
* else set for this call only
*/
public function setErrorMsg(
string $error_id,
@@ -93,10 +106,14 @@ class ErrorMessage
?string $message = null,
array $context = [],
?bool $log_error = null,
?bool $log_warning = null,
): void {
if ($log_error === null) {
$log_error = $this->log_error;
}
if ($log_warning === null) {
$log_warning = $this->log_warning;
}
$original_level = $level;
$level = MessageLevel::fromName($level)->name;
// if not string set, write message string if set, else level/error id
@@ -121,6 +138,14 @@ class ErrorMessage
'level' => $original_level,
], $context));
break;
case 'warn':
if ($log_warning) {
$this->log->warning($message ?? $str, array_merge([
'id' => $error_id,
'level' => $original_level,
], $context));
}
break;
case 'error':
if ($log_error) {
$this->log->error($message ?? $str, array_merge([
@@ -169,6 +194,8 @@ class ErrorMessage
* @param array<mixed> $context Additionl info for abort/crash messages
* @param bool|null $log_error [=null] log level 'error' to error, if null use global,
* else set for this call only
* @param bool|null $log_warning [=null] log level 'warning' to warning, if null use global,
* else set for this call only
*/
public function setMessage(
string $level,
@@ -181,6 +208,7 @@ class ErrorMessage
?string $message = null,
array $context = [],
?bool $log_error = null,
?bool $log_warning = null,
): void {
$this->setErrorMsg(
$error_id ?? '',
@@ -192,7 +220,8 @@ class ErrorMessage
$jump_target,
$message,
$context,
$log_error
$log_error,
$log_warning
);
}
@@ -314,6 +343,27 @@ class ErrorMessage
{
return $this->log_error;
}
/**
* Set the log warning flag
*
* @param bool $flag True to log level warning too, False for do not (Default)
* @return void
*/
public function setFlagLogWarning(bool $flag): void
{
$this->log_warning = $flag;
}
/**
* Get the current log error flag
*
* @return bool
*/
public function getFlagLogWarning(): bool
{
return $this->log_warning;
}
}
// __END__

View File

@@ -14,7 +14,7 @@ namespace CoreLibs\Logging\Logger;
enum MessageLevel: int
{
case ok = 100;
case success = 110; // special for file uploads
case success = 150; // special for file uploads
case info = 200;
case notice = 250;
case warn = 300;

1022
src/UrlRequests/Curl.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,152 @@
<?php
/**
* AUTHOR: Clemens Schwaighofer
* CREATED: 2024/10/29
* DESCRIPTION:
* Curl Client Trait for get/post/put/delete requests through the php curl inteface
*
* For anything more complex use guzzlehttp/http
* https://docs.guzzlephp.org/en/stable/index.html
*/
// phpcs:disable Generic.Files.LineLength
declare(strict_types=1);
namespace CoreLibs\UrlRequests;
trait CurlTrait
{
/**
* Set the array block that is sent to the request call
* Make sure that if headers is set as key but null it stays null and set to empty array
* if headers key is missing
* "get" calls do not set any body
*
* @param string $type if set as get do not add body, else add body
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Request options
* @return array{auth?:array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool}
*/
private function setOptions(string $type, array $options): array
{
$base = [
"auth" => !array_key_exists('auth', $options) ? [] : $options['auth'],
"headers" => !array_key_exists('headers', $options) ? [] : $options['headers'],
"query" => $options['query'] ?? null,
"http_errors" => !array_key_exists('http_errors', $options) ? null : $options['http_errors'],
];
if ($type != "get") {
$base["body"] = $options['body'] ?? null;
}
return $base;
}
/**
* combined set call for any type of request with options type parameters
* The following options can be set:
* header: as array string:string
* query as string or array string:string
* body as string or array of any type
*
* @param string $type What type of request we send, will throw exception if not a valid one
* @param string $url The url to send
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Request options
* @return array{code:string,headers:array<string,array<string>>,content:string} [default=[]] Result code, headers and content as array, content is json
* @throws \UnexpectedValueException on missing body data when body data is needed
*/
abstract public function request(string $type, string $url, array $options = []): array;
/**
* Makes an request to the target url via curl: GET
* Returns result as string (json)
*
* @param string $url The URL being requested,
* including domain and protocol
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Options to set
* @return array{code:string,headers:array<string,array<string>>,content:string} [default=[]] Result code, headers and content as array, content is json
*/
public function get(string $url, array $options = []): array
{
return $this->request(
"get",
$url,
$this->setOptions('get', $options),
);
}
/**
* Makes an request to the target url via curl: POST
* Returns result as string (json)
*
* @param string $url The URL being requested,
* including domain and protocol
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Options to set
* @return array{code:string,headers:array<string,array<string>>,content:string} Result code, headers and content as array, content is json
*/
public function post(string $url, array $options): array
{
return $this->request(
"post",
$url,
$this->setOptions('post', $options),
);
}
/**
* Makes an request to the target url via curl: PUT
* Returns result as string (json)
*
* @param string $url The URL being requested,
* including domain and protocol
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Options to set
* @return array{code:string,headers:array<string,array<string>>,content:string} Result code, headers and content as array, content is json
*/
public function put(string $url, array $options): array
{
return $this->request(
"put",
$url,
$this->setOptions('put', $options),
);
}
/**
* Makes an request to the target url via curl: PATCH
* Returns result as string (json)
*
* @param string $url The URL being requested,
* including domain and protocol
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Options to set
* @return array{code:string,headers:array<string,array<string>>,content:string} Result code, headers and content as array, content is json
*/
public function patch(string $url, array $options): array
{
return $this->request(
"patch",
$url,
$this->setOptions('patch', $options),
);
}
/**
* Makes an request to the target url via curl: DELETE
* Returns result as string (json)
* Note that DELETE body is optional
*
* @param string $url The URL being requested,
* including domain and protocol
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options Options to set
* @return array{code:string,headers:array<string,array<string>>,content:string} [default=[]] Result code, headers and content as array, content is json
*/
public function delete(string $url, array $options = []): array
{
return $this->request(
"delete",
$url,
$this->setOptions('delete', $options),
);
}
}
// __END__

View File

@@ -0,0 +1,83 @@
<?php
/**
* AUTHOR: Clemens Schwaighofer
* CREATED: 2024/9/20
* DESCRIPTION:
* URL Requests client interface
*/
namespace CoreLibs\UrlRequests\Interface;
interface RequestsInterface
{
/**
* get the config array with all settings
*
* @return array<string,mixed> all current config settings
*/
public function getConfig(): array;
/**
* Return the full url as it was sent
*
* @return string url sent
*/
public function getUrlSent(): string;
/**
* get the parsed url
*
* @return array{scheme?:string,user?:string,host?:string,port?:string,path?:string,query?:string,fragment?:string,pass?:string}
*/
public function getUrlParsedSent(): array;
/**
* Return the full headers as they where sent
*
* @return array<string,string>
*/
public function getHeadersSent(): array;
/**
* set, add or overwrite header
* On default this will overwrite header, and not set
*
* @param array<string,string|array<string>> $header
* @param bool $add [default=false] if set will add header to existing value
* @return void
*/
public function setHeaders(array $header, bool $add = false): void;
/**
* remove header entry
* if key is only set then match only key, if both are set both sides must match
*
* @param array<string,string> $remove_headers
* @return void
*/
public function removeHeaders(array $remove_headers): void;
/**
* Update the base url set, if empty will unset the base url
*
* @param string $base_uri
* @return void
*/
public function setBaseUri(string $base_uri): void;
/**
* combined set call for any type of request with options type parameters
*
* phpcs:disable Generic.Files.LineLength
* @param string $type
* @param string $url
* @param array{auth?:null|array{0:string,1:string,2:string},headers?:null|array<string,string|array<string>>,query?:null|array<string,string>,body?:null|string|array<mixed>,http_errors?:null|bool} $options
* @return array{code:string,headers:array<string,array<string>>,content:string} Result code, headers and content as array, content is json
* @throws \UnexpectedValueException on missing body data when body data is needed
* phpcs:enable Generic.Files.LineLength
*/
public function request(string $type, string $url, array $options = []): array;
}
// __END__

View File

@@ -100,27 +100,6 @@ define('DEFAULT_ACL_LEVEL', 80);
/************* LOGOUT ********************/
// logout target
define('LOGOUT_TARGET', '');
// password change allowed
define('PASSWORD_CHANGE', false);
define('PASSWORD_FORGOT', false);
// min/max password length
define('PASSWORD_MIN_LENGTH', 9);
define('PASSWORD_MAX_LENGTH', 255);
// defines allowed special characters
define('PASSWORD_SPECIAL_RANGE', '@$!%*?&');
// password must have upper case, lower case, number, special
// comment out for not mandatory
define('PASSWORD_LOWER', '(?=.*[a-z])');
define('PASSWORD_UPPER', '(?=.*[A-Z])');
define('PASSWORD_NUMBER', '(?=.*\d)');
define('PASSWORD_SPECIAL', "(?=.*[" . PASSWORD_SPECIAL_RANGE . "])");
// define full regex
define('PASSWORD_REGEX', "/^"
. (defined('PASSWORD_LOWER') ? PASSWORD_LOWER : '')
. (defined('PASSWORD_UPPER') ? PASSWORD_UPPER : '')
. (defined('PASSWORD_NUMBER') ? PASSWORD_NUMBER : '')
. (defined('PASSWORD_SPECIAL') ? PASSWORD_SPECIAL : '')
. "[A-Za-z\d" . PASSWORD_SPECIAL_RANGE . "]{" . PASSWORD_MIN_LENGTH . "," . PASSWORD_MAX_LENGTH . "}$/");
/************* AJAX / ACCESS *************/
// ajax request type
@@ -161,13 +140,6 @@ define('DEFAULT_LOCALE', 'en_US.UTF-8');
// default web page encoding setting
define('DEFAULT_ENCODING', 'UTF-8');
/************* LOGGING *******************/
// below two can be defined here, but they should be
// defined in either the header file or the file itself
// as $LOG_FILE_ID which takes presence over LOG_FILE_ID
// see Basic class constructor
define('LOG_FILE_ID', BASE_NAME);
/************* QUEUE TABLE *************/
// if we have a dev/live system
// set_live is a per page/per item
@@ -291,22 +263,4 @@ if (file_exists(BASE . CONFIGS . 'config.other.php')) {
require BASE . CONFIGS . 'config.other.php';
}
/************* DEBUG *******************/
// turn off debug if debug flag is OFF
if (defined('DEBUG') && DEBUG == false) {
$ECHO_ALL = false;
$DEBUG_ALL = false;
$PRINT_ALL = false;
$DB_DEBUG = false;
$ENABLE_ERROR_HANDLING = false;
$DEBUG_ALL_OVERRIDE = false;
} else {
$ECHO_ALL = false;
$DEBUG_ALL = true;
$PRINT_ALL = true;
$DB_DEBUG = true;
$ENABLE_ERROR_HANDLING = false;
$DEBUG_ALL_OVERRIDE = false;
}
// __END__

View File

@@ -0,0 +1,28 @@
<?php // phpcs:ignore PSR1.Files.SideEffects
/********************************************************************
* AUTHOR: Clemens Schwaighofer
* CREATED: 2018/10/11
* SHORT DESCRIPTION:
* configuration file for core path settings
* CSV target paths, and other download access URLS or paths needed
* HISTORY:
*********************************************************************/
declare(strict_types=1);
// find trigger name "admin/" or "frontend/" in the getcwd() folder
$folder = '';
foreach (['admin', 'frontend'] as $_folder) {
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $_folder)) {
$folder = $_folder;
break;
}
}
// if content path is empty, fallback is default
if (empty($folder)) {
$folder = 'default';
}
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
// __END__

View File

@@ -53,19 +53,6 @@ for (
\gullevek\dotEnv\DotEnv::readEnvFile(
$__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH
);
// find trigger name "admin/" or "frontend/" in the getcwd() folder
$folder = '';
foreach (['admin', 'frontend'] as $_folder) {
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $_folder)) {
$folder = $_folder;
break;
}
}
// if content path is empty, fallback is default
if (empty($folder)) {
$folder = 'default';
}
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
// load master config file that loads all other config files
require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php';
break;

View File

@@ -4,4 +4,7 @@ require "../vendor/autoload.php";
print "Bytes: " . CoreLibs\Convert\Byte::humanReadableByteFormat(123414) . "<br>";
$curl = new CoreLibs\UrlRequests\Curl();
print "Config: " . print_r($curl->getConfig(), true) . "<br>";
// __END__

View File

@@ -0,0 +1,51 @@
<?php // phpcs:ignore PSR1.Files.SideEffects
/**
* AUTHOR: Clemens Schwaighofer
* CREATED: Ymd
* DESCRIPTION:
* DescriptionHere
*/
declare(strict_types=1);
/**
* build return json
*
* @param array<string,mixed> $http_headers
* @param string $body
* @return string
*/
function buildContent(array $http_headers, string $body): string
{
return json_encode([
'HEADERS' => $http_headers,
"REQUEST_TYPE" => $_SERVER['REQUEST_METHOD'],
"PARAMS" => $_GET,
"BODY" => json_decode($body, true)
]);
}
$http_headers = array_filter($_SERVER, function ($value, $key) {
if (str_starts_with($key, 'HTTP_')) {
return true;
}
}, ARRAY_FILTER_USE_BOTH);
header("Content-Type: application/json; charset=UTF-8");
// if the header has Authorization and RunAuthTest then exit with 401
if (!empty($http_headers['HTTP_AUTHORIZATION']) && !empty($http_headers['HTTP_RUNAUTHTEST'])) {
header("HTTP/1.1 401 Unauthorized");
print buildContent($http_headers, '{"code": 401, "content": {"Error": "Not Authorized"}}');
exit;
}
if (($file_get = file_get_contents('php://input')) === false) {
header("HTTP/1.1 404 Not Found");
print buildContent($http_headers, '{"code": 404, "content": {"Error": "file_get_contents failed"}}');
exit;
}
print buildContent($http_headers, $file_get);
// __END__

View File

@@ -10,7 +10,6 @@ use PHPUnit\Framework\TestCase;
* Test class for DB\Extended\ArrayIO
* This will only test the PgSQL parts
* @coversDefaultClass \CoreLibs\DB\Extended\ArrayIO
* @coversDefaultClass \CoreLibs\DB\Extended\ArrayIO
* @testdox \CoreLibs\Extended\ArrayIO method tests for extended DB interface
*/
final class CoreLibsDBExtendedArrayIOTest extends TestCase

View File

@@ -230,6 +230,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'ERROR MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<ERROR> ERROR MESSAGE',
],
'error, logged' => [
@@ -238,6 +239,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'ERROR MESSAGE',
'message' => null,
'log_error' => true,
'log_warning' => null,
'expected' => '<ERROR> ERROR MESSAGE',
],
'error, logged, message' => [
@@ -246,14 +248,43 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'ERROR MESSAGE',
'message' => 'OTHER ERROR MESSAGE',
'log_error' => true,
'log_warning' => null,
'expected' => '<ERROR> OTHER ERROR MESSAGE',
],
'warn, not logged' => [
'id' => '300',
'level' => 'warn',
'str' => 'WARNING MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<WARNING> WARNING MESSAGE',
],
'warn, logged' => [
'id' => '300',
'level' => 'warn',
'str' => 'WARNING MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => true,
'expected' => '<WARNING> WARNING MESSAGE',
],
'warn, logged, message' => [
'id' => '300',
'level' => 'warn',
'str' => 'WARNING MESSAGE',
'message' => 'OTHER WARNING MESSAGE',
'log_error' => null,
'log_warning' => true,
'expected' => '<WARNING> OTHER WARNING MESSAGE',
],
'notice' => [
'id' => '100',
'level' => 'notice',
'str' => 'NOTICE MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<NOTICE> NOTICE MESSAGE',
],
'notice, message' => [
@@ -262,6 +293,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'NOTICE MESSAGE',
'message' => 'OTHER NOTICE MESSAGE',
'log_error' => null,
'log_warning' => null,
'expected' => '<NOTICE> OTHER NOTICE MESSAGE',
],
'crash' => [
@@ -270,6 +302,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'CRASH MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<ALERT> CRASH MESSAGE',
],
'crash, message' => [
@@ -278,6 +311,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'CRASH MESSAGE',
'message' => 'OTHER CRASH MESSAGE',
'log_error' => null,
'log_warning' => null,
'expected' => '<ALERT> OTHER CRASH MESSAGE',
],
'abort' => [
@@ -286,6 +320,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'ABORT MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<CRITICAL> ABORT MESSAGE',
],
'abort, message' => [
@@ -294,6 +329,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'ABORT MESSAGE',
'message' => 'OTHER ABORT MESSAGE',
'log_error' => null,
'log_warning' => null,
'expected' => '<CRITICAL> OTHER ABORT MESSAGE',
],
'unknown' => [
@@ -302,6 +338,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'WRONG LEVEL MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<EMERGENCY> WRONG LEVEL MESSAGE',
],
'unknown, message' => [
@@ -310,6 +347,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'WRONG LEVEL MESSAGE',
'message' => 'OTHER WRONG LEVEL MESSAGE',
'log_error' => null,
'log_warning' => null,
'expected' => '<EMERGENCY> OTHER WRONG LEVEL MESSAGE',
],
];
@@ -326,6 +364,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
* @param string $str
* @param string|null $message
* @param bool|null $log_error
* @param bool|null $log_warning
* @param string $expected
* @return void
*/
@@ -335,6 +374,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
string $str,
?string $message,
?bool $log_error,
?bool $log_warning,
string $expected
): void {
$log = new \CoreLibs\Logging\Logging([
@@ -349,7 +389,8 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
$level,
$str,
message: $message,
log_error: $log_error
log_error: $log_error,
log_warning: $log_warning
);
$file_content = '';
if (is_file($log->getLogFolder() . $log->getLogFile())) {
@@ -363,6 +404,11 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
$expected,
$file_content
);
} elseif ($level == 'warn' && ($log_warning === null || $log_warning === false)) {
$this->assertStringNotContainsString(
$expected,
$file_content
);
} else {
$this->assertStringContainsString(
$expected,
@@ -382,6 +428,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
* @param string $str
* @param string|null $message
* @param bool|null $log_error
* @param bool|null $log_warning
* @param string $expected
* @return void
*/
@@ -391,6 +438,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
string $str,
?string $message,
?bool $log_error,
?bool $log_warning,
string $expected
): void {
$log = new \CoreLibs\Logging\Logging([
@@ -405,7 +453,8 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
$level,
$str,
message: $message,
log_error: $log_error
log_error: $log_error,
log_warning: $log_warning
);
$file_content = '';
if (is_file($log->getLogFolder() . $log->getLogFile())) {
@@ -419,6 +468,11 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
$expected,
$file_content
);
} elseif ($level == 'warn' && $log_warning === false) {
$this->assertStringNotContainsString(
$expected,
$file_content
);
} else {
$this->assertStringContainsString(
$expected,

File diff suppressed because it is too large Load Diff