diff --git a/www/admin/class_test.image.php b/www/admin/class_test.image.php
index 0ae756ba..21e8ee71 100644
--- a/www/admin/class_test.image.php
+++ b/www/admin/class_test.image.php
@@ -41,9 +41,9 @@ print '
' . $PAGE_NAME . '
';
$thumb_width = 250;
$thumb_height = 300;
// class
-$image = BASE . LAYOUT . CONTENT_PATH . IMAGES . 'no_picture_square.jpg';
+$image = BASE . CONTENT_PATH . LAYOUT . IMAGES . 'no_picture_square.jpg';
// folders
-$cache_folder = BASE . LAYOUT . CONTENT_PATH . CACHE . IMAGES;
+$cache_folder = BASE . CONTENT_PATH . LAYOUT . CACHE . IMAGES;
$web_folder = LAYOUT . CACHE . IMAGES;
// rotate image first
try {
@@ -58,7 +58,7 @@ echo "CLASS->CREATETHUMBNAILSIMPLE: "
. basename($image) . ": WIDTH: $thumb_width
 . )
";
// static
-$image = BASE . LAYOUT . CONTENT_PATH . IMAGES . 'no_picture.jpg';
+$image = BASE . CONTENT_PATH . LAYOUT . IMAGES . 'no_picture.jpg';
// rotate image first
try {
$image_class::correctImageOrientation($image);
@@ -94,7 +94,7 @@ $images = array(
// return mime type ala mimetype
$finfo = new finfo(FILEINFO_MIME_TYPE);
foreach ($images as $image) {
- $image = BASE . LAYOUT . CONTENT_PATH . IMAGES . $image;
+ $image = BASE . CONTENT_PATH . LAYOUT . IMAGES . $image;
list ($height, $width, $img_type) = \CoreLibs\Convert\SetVarType::setArray(getimagesize($image));
echo "IMAGE INFO: " . $height . "x" . $width . ", TYPE: "
. \CoreLibs\Debug\Support::dumpVar($img_type) . " [" . $finfo->file($image) . "]
";
diff --git a/www/composer.lock b/www/composer.lock
index 33f958f8..8758f4ab 100644
--- a/www/composer.lock
+++ b/www/composer.lock
@@ -8,11 +8,11 @@
"packages": [
{
"name": "egrajp/corelibs-composer-all",
- "version": "dev-master",
+ "version": "dev-development",
"dist": {
"type": "path",
"url": "/storage/var/www/html/developers/clemens/core_data/composer-packages/CoreLibs-Composer-All",
- "reference": "4ab382990ecb9db90386f8ec1a4d87ac8f7c5dd7"
+ "reference": "d3d4cf512f62f139c61629d5aa21cf22ad726241"
},
"require": {
"php": ">=8.2",
@@ -45,11 +45,11 @@
},
{
"name": "egrajp/smarty-extended",
- "version": "4.3.0",
+ "version": "4.4.1",
"dist": {
"type": "zip",
- "url": "https://git.egplusww.jp/api/packages/Composer/composer/files/egrajp%2Fsmarty-extended/4.3.0/egrajp-smarty-extended.4.3.0.zip",
- "shasum": "d41bda35c0d52da35cf911ab0b018655a09f072b"
+ "url": "https://git.egplusww.jp/api/packages/Composer/composer/files/egrajp%2Fsmarty-extended/4.4.1/egrajp-smarty-extended.4.4.1.zip",
+ "shasum": "edd7a0960e49bfcc709e0a525729aaaf9ed0db75"
},
"type": "library",
"autoload": {
@@ -71,7 +71,7 @@
"keywords": [
"templating"
],
- "time": "2023-02-17T14:14:10+09:00"
+ "time": "2024-03-06T18:43:44+09:00"
},
{
"name": "gullevek/dotenv",
diff --git a/www/vendor/composer/installed.json b/www/vendor/composer/installed.json
index c12e083e..0ed99cde 100644
--- a/www/vendor/composer/installed.json
+++ b/www/vendor/composer/installed.json
@@ -2,12 +2,12 @@
"packages": [
{
"name": "egrajp/corelibs-composer-all",
- "version": "dev-master",
- "version_normalized": "dev-master",
+ "version": "dev-development",
+ "version_normalized": "dev-development",
"dist": {
"type": "path",
"url": "/storage/var/www/html/developers/clemens/core_data/composer-packages/CoreLibs-Composer-All",
- "reference": "4ab382990ecb9db90386f8ec1a4d87ac8f7c5dd7"
+ "reference": "d3d4cf512f62f139c61629d5aa21cf22ad726241"
},
"require": {
"php": ">=8.2",
@@ -42,12 +42,14 @@
},
{
"name": "egrajp/smarty-extended",
- "version": "4.3.0",
- "version_normalized": "4.3.0.0",
+ "version": "4.4.1",
+ "version_normalized": "4.4.1.0",
"dist": {
"type": "zip",
- "url": "https://git.egplusww.jp/Composer/Smarty-Extended/archive/v4.3.0.zip"
+ "url": "https://git.egplusww.jp/api/packages/Composer/composer/files/egrajp%2Fsmarty-extended/4.4.1/egrajp-smarty-extended.4.4.1.zip",
+ "shasum": "edd7a0960e49bfcc709e0a525729aaaf9ed0db75"
},
+ "time": "2024-03-06T18:43:44+09:00",
"type": "library",
"installation-source": "dist",
"autoload": {
diff --git a/www/vendor/composer/installed.php b/www/vendor/composer/installed.php
index a0209274..6dc428d7 100644
--- a/www/vendor/composer/installed.php
+++ b/www/vendor/composer/installed.php
@@ -11,9 +11,9 @@
),
'versions' => array(
'egrajp/corelibs-composer-all' => array(
- 'pretty_version' => 'dev-master',
- 'version' => 'dev-master',
- 'reference' => '4ab382990ecb9db90386f8ec1a4d87ac8f7c5dd7',
+ 'pretty_version' => 'dev-development',
+ 'version' => 'dev-development',
+ 'reference' => 'd3d4cf512f62f139c61629d5aa21cf22ad726241',
'type' => 'library',
'install_path' => __DIR__ . '/../egrajp/corelibs-composer-all',
'aliases' => array(),
@@ -29,8 +29,8 @@
'dev_requirement' => false,
),
'egrajp/smarty-extended' => array(
- 'pretty_version' => '4.3.0',
- 'version' => '4.3.0.0',
+ 'pretty_version' => '4.4.1',
+ 'version' => '4.4.1.0',
'reference' => null,
'type' => 'library',
'install_path' => __DIR__ . '/../egrajp/smarty-extended',
diff --git a/www/vendor/egrajp/corelibs-composer-all/.phive/phars.xml b/www/vendor/egrajp/corelibs-composer-all/.phive/phars.xml
index f6d3d32b..72b47dc1 100644
--- a/www/vendor/egrajp/corelibs-composer-all/.phive/phars.xml
+++ b/www/vendor/egrajp/corelibs-composer-all/.phive/phars.xml
@@ -3,7 +3,7 @@
-
-
+
+
diff --git a/www/vendor/egrajp/corelibs-composer-all/phpcs.xml b/www/vendor/egrajp/corelibs-composer-all/phpcs.xml
new file mode 100644
index 00000000..cfc7a3dc
--- /dev/null
+++ b/www/vendor/egrajp/corelibs-composer-all/phpcs.xml
@@ -0,0 +1,18 @@
+
+
+ PSR12 override rules (strict, standard). Switch spaces indent to tab.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/www/vendor/egrajp/corelibs-composer-all/publish/last.published b/www/vendor/egrajp/corelibs-composer-all/publish/last.published
index 5d24a8f4..ee1b03fb 100644
--- a/www/vendor/egrajp/corelibs-composer-all/publish/last.published
+++ b/www/vendor/egrajp/corelibs-composer-all/publish/last.published
@@ -1 +1 @@
-9.8.2
+9.11.1
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Admin/EditBase.php b/www/vendor/egrajp/corelibs-composer-all/src/Admin/EditBase.php
index fa8033ef..f740b53a 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/Admin/EditBase.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/Admin/EditBase.php
@@ -44,7 +44,7 @@ class EditBase
* construct form generator
*
* phpcs:ignore
- * @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[]} $db_config db config array, mandatory
+ * @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[],db_convert_placeholder?:bool,db_convert_placeholder_target?:string,db_debug_replace_placeholder?:bool} $db_config db config array, mandatory
* @param \CoreLibs\Logging\Logging $log Logging class, null auto set
* @param \CoreLibs\Language\L10n $l10n l10n language class, null auto set
* @param \CoreLibs\ACL\Login $login login class for ACL settings
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Check/File.php b/www/vendor/egrajp/corelibs-composer-all/src/Check/File.php
index 36b4bfc8..c8bdc531 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/Check/File.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/Check/File.php
@@ -51,6 +51,23 @@ class File
// return lines in file
return $lines;
}
+
+ /**
+ * get the mime type of a file via finfo
+ * if file not found, throws exception
+ * else returns '' for any other finfo read problem
+ *
+ * @param string $read_file File to read, relative or absolute path
+ * @return string
+ */
+ public static function getMimeType(string $read_file): string
+ {
+ $finfo = new \finfo(FILEINFO_MIME_TYPE);
+ if (!is_file($read_file)) {
+ throw new \UnexpectedValueException('[getMimeType] File not found: ' . $read_file);
+ }
+ return $finfo->file($read_file) ?: '';
+ }
}
// __END__
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Combined/ArrayHandler.php b/www/vendor/egrajp/corelibs-composer-all/src/Combined/ArrayHandler.php
index d664310c..bbe3943f 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/Combined/ArrayHandler.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/Combined/ArrayHandler.php
@@ -236,6 +236,54 @@ class ArrayHandler
return $hit_list;
}
+ /**
+ * main wrapper function for next/prev key
+ *
+ * @param array $array array to search in
+ * @param int|string $key key for next/prev
+ * @param bool $next [=true] if to search next or prev
+ * @return int|string|null Next/prev key or null for end/first
+ */
+ private static function arrayGetKey(array $array, int|string $key, bool $next = true): int|string|null
+ {
+ $keys = array_keys($array);
+ if (($position = array_search($key, $keys, true)) === false) {
+ return null;
+ }
+ $next_position = $next ? $position + 1 : $position - 1;
+
+ if (!isset($keys[$next_position])) {
+ return null;
+ }
+ return $keys[$next_position];
+ }
+
+ /**
+ * Get previous array key from an array
+ * null on not found
+ *
+ * @param array $array
+ * @param int|string $key
+ * @return int|string|null Next key, or null for not found
+ */
+ public static function arrayGetPrevKey(array $array, int|string $key): int|string|null
+ {
+ return self::arrayGetKey($array, $key, false);
+ }
+
+ /**
+ * Get next array key from an array
+ * null on not found
+ *
+ * @param array $array
+ * @param int|string $key
+ * @return int|string|null Next key, or null for not found
+ */
+ public static function arrayGetNextKey(array $array, int|string $key): int|string|null
+ {
+ return self::arrayGetKey($array, $key, true);
+ }
+
/**
* correctly recursive merges as an array as array_merge_recursive
* just glues things together
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Combined/DateTime.php b/www/vendor/egrajp/corelibs-composer-all/src/Combined/DateTime.php
index a807a39d..d46619c5 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/Combined/DateTime.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/Combined/DateTime.php
@@ -108,7 +108,12 @@ class DateTime
if (preg_match("/(h|m|s|ms)/", (string)$timestamp)) {
return (string)$timestamp;
}
- list($timestamp, $ms) = array_pad(explode('.', (string)round((float)$timestamp, 4)), 2, null);
+ // split to 6 (nano seconds)
+ list($timestamp, $ms) = array_pad(explode('.', (string)round((float)$timestamp, 6)), 2, null);
+ // if micro seconds is on and we have none, set to 0
+ if ($show_micro && $ms === null) {
+ $ms = 0;
+ }
// if negative remember
$negative = false;
if ((int)$timestamp < 0) {
@@ -120,6 +125,10 @@ class DateTime
$time_string = '';
// if timestamp is zero, return zero string
if ($timestamp == 0) {
+ // if no seconds and we have no microseconds either, show no micro seconds
+ if ($ms == 0) {
+ $ms = null;
+ }
$time_string = '0s';
} else {
for ($i = 0, $iMax = count($timegroups); $i < $iMax; $i++) {
@@ -133,11 +142,8 @@ class DateTime
}
// only add ms if we have an ms value
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';
- }
+ // prefix the milliseoncds with 0. and round it max 3 digits and then convert to int
+ $ms = round((float)('0.' . $ms), 3) * 1000;
// add ms if there
if ($show_micro) {
$time_string .= ' ' . $ms . 'ms';
@@ -151,6 +157,240 @@ class DateTime
return (string)$time_string;
}
+ /**
+ * update timeStringFormat with year and month support
+ *
+ * The following flags have to be set to be timeStringFormat compatible.
+ * Not that on seconds overflow this method will throw an exception, timeStringFormat returned -1s
+ * show_only_days: true,
+ * skip_zero: false,
+ * skip_last_zero: false,
+ * truncate_nanoseconds: true,
+ * truncate_zero_seconds_if_microseconds: false
+ *
+ * @param int|float $seconds Seconds to convert, maxium 6 decimals,
+ * else \UnexpectedValueException will be thrown
+ * if days too large or years too large \LengthException is thrown
+ * @param string $truncate_after [=''] Truncate after which time name, will not round, hard end
+ * values are parts names or interval short names (y, d, f, ...)
+ * if illegal value \UnexpectedValueException is thrown
+ * @param bool $natural_seperator [=false] use ',' and 'and', if off use space
+ * @param bool $name_space_seperator [=false] add a space between the number and the time name
+ * @param bool $show_microseconds [=true] show microseconds
+ * @param bool $short_time_name [=true] use the short time names (eg s instead of seconds)
+ * @param bool $skip_last_zero [=true] skip all trailing zero values, eg 5m 0s => 5m
+ * @param bool $skip_zero [=true] do not show zero values anywhere, eg 1h 0m 20s => 1h 20s
+ * @param bool $show_only_days [=false] do not show years or months, show only days
+ * if truncate after is set to year or month
+ * throws \UnexpectedValueException
+ * @param bool $auto_fix_microseconds [=false] if the micro seconds decimals are more than 6, round them
+ * on defaul throw \UnexpectedValueException
+ * @param bool $truncate_nanoseconds [=false] if microseconds decimals >3 then normal we show 123.4ms
+ * cut the .4 is set to true
+ * @param bool $truncate_zero_seconds_if_microseconds [=true] if we have 0.123 seconds then if true no seconds
+ * will be shown
+ * @return string
+ * @throws \UnexpectedValueException if seconds has more than 6 decimals
+ * if truncate has an illegal value
+ * if truncate is set to year or month and show_only_days is turned on
+ * @throws \LengthException if seconds is too large and show_days_only is selected and days is negetive
+ * or if years is negativ
+ */
+ public static function intervalStringFormat(
+ int|float $seconds,
+ string $truncate_after = '',
+ bool $natural_seperator = false,
+ bool $name_space_seperator = false,
+ bool $show_microseconds = true,
+ bool $short_time_name = true,
+ bool $skip_last_zero = true,
+ bool $skip_zero = true,
+ bool $show_only_days = false,
+ bool $auto_fix_microseconds = false,
+ bool $truncate_nanoseconds = false,
+ bool $truncate_zero_seconds_if_microseconds = true,
+ ): string {
+ // auto fix long seconds, else \UnexpectedValueException will be thrown on error
+ // check if we have float and -> round to 6
+ if ($auto_fix_microseconds === true && is_float($seconds)) {
+ $seconds = round($seconds, 6);
+ }
+ // flag negative + set abs
+ $negative = $seconds < 0 ? '-' : '';
+ $seconds = abs($seconds);
+ // create base time
+ $date_now = new \DateTime("@0");
+ try {
+ $date_seconds = new \DateTime("@$seconds");
+ } catch (\Exception $e) {
+ throw new \UnexpectedValueException(
+ 'Seconds value is invalid, too large or more than six decimals: ' . $seconds,
+ 1,
+ $e
+ );
+ }
+ $interval = date_diff($date_now, $date_seconds);
+ // if show_only_days and negative but input postive alert that this has to be done in y/m/d ...
+ if ($interval->y < 0) {
+ throw new \LengthException('Input seconds value is too large for years output: ' . $seconds, 2);
+ } elseif ($interval->days < 0 && $show_only_days === true) {
+ throw new \LengthException('Input seconds value is too large for days output: ' . $seconds, 3);
+ }
+ $parts = [
+ 'years' => 'y',
+ 'months' => 'm',
+ 'days' => 'd',
+ 'hours' => 'h',
+ 'minutes' => 'i',
+ 'seconds' => 's',
+ 'microseconds' => 'f',
+ ];
+ $short_name = [
+ 'years' => 'y', 'months' => 'm', 'days' => 'd',
+ 'hours' => 'h', 'minutes' => 'm', 'seconds' => 's',
+ 'microseconds' => 'ms'
+ ];
+ // $skip = false;
+ if (!empty($truncate_after)) {
+ // if truncate after not in key or value in parts
+ if (!in_array($truncate_after, array_keys($parts)) && !in_array($truncate_after, array_values($parts))) {
+ throw new \UnexpectedValueException(
+ 'truncate_after has an invalid value: ' . $truncate_after,
+ 4
+ );
+ }
+ // if truncate after is y or m and we have show_only_days, throw exception
+ if ($show_only_days === true && in_array($truncate_after, ['y', 'years', 'm', 'months'])) {
+ throw new \UnexpectedValueException(
+ 'If show_only_days is turned on, the truncate_after cannot be years or months: '
+ . $truncate_after,
+ 5
+ );
+ }
+ // $skip = true;
+ }
+ $formatted = [];
+ $zero_formatted = [];
+ $value_set = false;
+ $add_zero_seconds = false;
+ foreach ($parts as $time_name => $part) {
+ if (
+ // skip for micro seconds
+ ($show_microseconds === false && $part == 'f') ||
+ // skip for if days only and we have year or month
+ ($show_only_days === true && in_array($part, ['y', 'm']))
+ ) {
+ continue;
+ }
+ $add_value = 0;
+ if ($show_only_days === true && $part == 'd') {
+ $value = $interval->days;
+ } else {
+ $value = $interval->$part;
+ }
+ // print "-> V: $value | $part, $time_name"
+ // . " | Set: " . ($value_set ? 'Y' : 'N') . ", SkipZ: " . ($skip_zero ? 'Y' : 'N')
+ // . " | SkipLZ: " . ($skip_last_zero ? 'Y' : 'N')
+ // . " | " . ($value != 0 ? 'Not zero' : 'ZERO') . "
";
+ if ($value != 0) {
+ if ($part == 'f') {
+ if ($truncate_nanoseconds === true) {
+ $value = round($value, 3);
+ }
+ $value *= 1000;
+ // anything above that is nano seconds?
+ }
+ if ($value) {
+ $value_set = true;
+ }
+ $add_value = 1;
+ } elseif (
+ $value == 0 &&
+ $value_set === true && (
+ $skip_last_zero === false ||
+ $skip_zero === false
+ )
+ ) {
+ $add_value = 2;
+ }
+ // echo "ADD VALUE: $add_value
";
+ if ($add_value) {
+ // build format
+ $format = "$value";
+ if ($name_space_seperator) {
+ $format .= " ";
+ }
+ if ($short_time_name) {
+ $format .= $short_name[$time_name];
+ } elseif ($value == 1) {
+ $format .= substr($time_name, 0, -1);
+ } else {
+ $format .= $time_name;
+ }
+ if ($add_value == 1) {
+ if (count($zero_formatted) && $skip_zero === false) {
+ $formatted = array_merge($formatted, $zero_formatted);
+ }
+ $zero_formatted = [];
+ $formatted[] = $format;
+ } elseif ($add_value == 2) {
+ $zero_formatted[] = $format;
+ }
+ }
+ // if seconds is zero
+ if (
+ $part == 's' && $value == 0 &&
+ $show_microseconds === true &&
+ $truncate_zero_seconds_if_microseconds === false
+ ) {
+ $add_zero_seconds = true;
+ }
+ // stop after a truncate is matching
+ if ($part == $truncate_after || $truncate_after == $time_name) {
+ break;
+ }
+ }
+ // add all zero entries if we have skip last off
+ if (count($zero_formatted) && $skip_last_zero === false) {
+ $formatted = array_merge($formatted, $zero_formatted);
+ }
+ // print "=> F: " . print_r($formatted, true)
+ // . " | Z: " . print_r($zero_list, true)
+ // . " | ZL: " . print_r($zero_last_list, true)
+ // . "
";
+ if (count($formatted) == 0) {
+ // if we have truncate on, then we assume nothing was found
+ if (!empty($truncate_after)) {
+ if (in_array($truncate_after, array_values($parts))) {
+ $truncate_after = array_flip($parts)[$truncate_after];
+ }
+ $time_name = $truncate_after;
+ } else {
+ $time_name = 'seconds';
+ }
+ return '0' . ($name_space_seperator ? ' ' : '')
+ . ($short_time_name ? $short_name[$time_name] : $time_name);
+ } elseif (count($formatted) == 1) {
+ return $negative .
+ ($add_zero_seconds ?
+ '0'
+ . ($name_space_seperator ? ' ' : '')
+ . ($short_time_name ? $short_name['seconds'] : 'seconds')
+ . ' '
+ : ''
+ )
+ . $formatted[0];
+ } elseif ($natural_seperator === false) {
+ return $negative . implode(' ', $formatted);
+ } else {
+ $str = implode(', ', array_slice($formatted, 0, -1));
+ if (!empty($formatted[count($formatted) - 1])) {
+ $str .= ' and ' . (string)array_pop($formatted);
+ }
+ return $negative . $str;
+ }
+ }
+
/**
* does a reverse of the timeStringFormat and converts the string from
* xd xh xm xs xms to a timestamp.microtime format
@@ -435,9 +675,9 @@ class DateTime
foreach ($period as $dt) {
$curr = $dt->format('D');
if ($curr == 'Sat' || $curr == 'Sun') {
- $days[2] ++;
+ $days[2]++;
} else {
- $days[1] ++;
+ $days[1]++;
}
}
if ($return_named === true) {
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Byte.php b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Byte.php
index ebec727a..b0d05ece 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Byte.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Byte.php
@@ -37,7 +37,7 @@ class Byte
* BYTE_FORMAT_ADJUST: sprintf adjusted two 2 decimals
* BYTE_FORMAT_SI: use 1000 instead of 1024
* @return string converted byte number (float) with suffix
- * @throws \Exception 1: no valid flag set
+ * @throws \InvalidArgumentException 1: no valid flag set
*/
public static function humanReadableByteFormat(string|int|float $bytes, int $flags = 0): string
{
@@ -63,7 +63,7 @@ class Byte
$si = false;
}
if ($flags > 7) {
- throw new \Exception("Invalid flags parameter: $flags", 1);
+ throw new \InvalidArgumentException("Invalid flags parameter: $flags", 1);
}
// si or normal
@@ -119,7 +119,7 @@ class Byte
* @param int $flags bitwise flag with use space turned on
* BYTE_FORMAT_SI: use 1000 instead of 1024
* @return string|int|float converted value or original value
- * @throws \Exception 1: no valid flag set
+ * @throws \InvalidArgumentException 1: no valid flag set
*/
public static function stringByteFormat(string|int|float $number, int $flags = 0): string|int|float
{
@@ -130,7 +130,7 @@ class Byte
$si = false;
}
if ($flags != 0 && $flags != 4) {
- throw new \Exception("Invalid flags parameter: $flags", 1);
+ throw new \InvalidArgumentException("Invalid flags parameter: $flags", 1);
}
// matches in regex
$matches = [];
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Strings.php b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Strings.php
index bcbaf058..2935e26d 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Strings.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Strings.php
@@ -118,6 +118,22 @@ class Strings
return $value;
}
}
+
+ /**
+ * Strip any duplicated slahes from a path
+ * eg: //foo///bar/foo.inc -> /foo/bar/foo.inc
+ *
+ * @param string $path Path to strip slashes from
+ * @return string Clean path, on error returns original path
+ */
+ public static function stripMultiplePathSlashes(string $path): string
+ {
+ return preg_replace(
+ '#/+#',
+ '/',
+ $path
+ ) ?? $path;
+ }
}
// __END__
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/DB/Extended/ArrayIO.php b/www/vendor/egrajp/corelibs-composer-all/src/DB/Extended/ArrayIO.php
index b0e6f659..2f19e9df 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/DB/Extended/ArrayIO.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/DB/Extended/ArrayIO.php
@@ -55,7 +55,7 @@ class ArrayIO extends \CoreLibs\DB\IO
* primary key name automatically (from array)
*
* phpcs:ignore
- * @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[]} $db_config db connection config
+ * @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[],db_convert_placeholder?:bool,db_convert_placeholder_target?:string,db_debug_replace_placeholder?:bool} $db_config db connection config
* @param array $table_array table array config
* @param string $table_name table name string
* @param \CoreLibs\Logging\Logging $log Logging class
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/DB/IO.php b/www/vendor/egrajp/corelibs-composer-all/src/DB/IO.php
index d5c90c97..efe3901c 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/DB/IO.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/DB/IO.php
@@ -261,6 +261,7 @@ use CoreLibs\Debug\Support;
use CoreLibs\Create\Uids;
use CoreLibs\Convert\Json;
use CoreLibs\DB\Options\Convert;
+use CoreLibs\DB\Support\ConvertPlaceholder;
// below no ignore is needed if we want to use PgSql interface checks with PHP 8.0
// as main system. Currently all @var sets are written as object
@@ -283,6 +284,8 @@ class IO
public const ERROR_HASH_TYPE = 'adler32';
/** @var string regex to get returning with matches at position 1 */
public const REGEX_RETURNING = '/\s+returning\s+(.+\s*(?:.+\s*)+);?$/i';
+ /** @var array allowed convert target for placeholder: pg or pdo (currently not available) */
+ public const DB_CONVERT_PLACEHOLDER_TARGET = ['pg'];
// REGEX_SELECT
// REGEX_UPDATE
// REGEX INSERT
@@ -299,6 +302,9 @@ class IO
private string $query = '';
/** @var array current params for query */
private array $params = [];
+ // if we do have a convert call, store the convert data in here, else it will be empty
+ /** @var array{}|array{original:array{query:string,params:array},type:''|'named'|'numbered'|'question_mark',found:int,matches:array,params_lookup:array,query:string,params:array} */
+ private array $placeholder_converted = [];
// only inside
// basic vars
// the dbh handler, if disconnected by command is null, bool:false on error,
@@ -326,10 +332,16 @@ class IO
private string $db_ssl;
/** @var array flag for converting types from settings */
private array $db_convert_type = [];
+ /** @var bool convert placeholders from pdo to Pg or the other way around */
+ private bool $db_convert_placeholder = false;
+ /** @var string convert placeholders target, default is 'pg', other allowed is 'pdo' */
+ private string $db_convert_placeholder_target = 'pg';
+ /** @var bool Replace the placeholders in a query for debug output, defaults to false */
+ private bool $db_debug_replace_placeholder = false;
// convert type settings
// 0: OFF (CONVERT_OFF)
// >0: ON
- // 1: convert intN/bool (CONVERT_ON)
+ // 1: convert int/bool (CONVERT_ON)
// 2: convert json/jsonb to array (CONVERT_JSON)
// 4: convert numeric/floatN to float (CONVERT_NUMERIC)
// 8: convert bytea to string data (CONVERT_BYTEA)
@@ -367,6 +379,7 @@ class IO
private string $warning_id;
/** @var string */
private string $error_history_id;
+ // timestamp:string,level:string,id:string,error:string,source:string,pg_error:string,message:string,context:array
/** @var array Stores warning and errors combinded with detail info */
private array $error_history_long = [];
/** @var bool error thrown on class init if we cannot connect to db */
@@ -406,7 +419,7 @@ class IO
* and failure set on failed connection
*
* phpcs:ignore
- * @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[]} $db_config DB configuration array
+ * @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[],db_convert_placeholder?:bool,db_convert_placeholder_target?:string,db_debug_replace_placeholder?:bool} $db_config DB configuration array
* @param \CoreLibs\Logging\Logging $log Logging class
* @throws \RuntimeException If no DB connection can be established on launch
*/
@@ -435,16 +448,15 @@ class IO
'11' => 'No Querystring given',
'12' => 'No Cursor given, no correct query perhaps?',
'13' => 'Query could not be executed without errors',
- '14' => 'Can\'t connect to DB server',
- '15' => 'Can\'t select DB or no db name given',
- '16' => 'No DB Handler found / connect or reconnect failed',
+ '14' => 'No DB Handler found / connect or reconnect failed',
+ '15' => 'Cannot select DB or no db name given',
+ // '16' => 'No DB Handler found / connect or reconnect failed', // 16 merged into 14
'17' => 'All dbReturn* methods work only with SELECT statements, '
. 'please use dbExec for everything else',
'18' => 'Query not found in cache. Nothing has been reset',
- '19' => 'Wrong PK name given or no PK name given at all, can\'t '
- . 'get Insert ID',
- '20' => 'Found given Prepare Statement Name in array, '
- . 'Query not prepared, will use existing one',
+ '19' => 'Wrong PK name given or no PK name given at all, can\'t get Insert ID',
+ '20' => 'Query has already been prepared',
+ '26' => 'Same prepare statement name has been used for a different query',
'21' => 'Query Prepare failed',
'22' => 'Query Execute failed',
'23' => 'Query Execute failed, data array does not match placeholders',
@@ -472,7 +484,13 @@ class IO
'101' => 'Statement name empty for get prepare cursor',
'102' => 'Key empty for get prepare cursir',
'103' => 'No prepared cursor with this name',
- '104' => 'No Key with this name in the prepared cursor array'
+ '104' => 'No Key with this name in the prepared cursor array',
+ // abort on Placeholder convert
+ '200' => 'Cannot have named, question mark or numbered placeholders in the same query',
+ '210' => 'Cannot lookup param named in param list',
+ '211' => 'Cannot lookup param named in param lookup list',
+ '220' => 'Cannot lookup param number in param list',
+ '221' => 'Cannot lookup param number in param lookup list',
];
// load the core DB functions wrapper class
@@ -485,7 +503,6 @@ class IO
// connect to DB
if (!$this->__connectToDB()) {
- $this->__dbError(16);
$this->db_connection_closed = true;
throw new \RuntimeException('INIT: No DB Handler found / connect or reconnect failed', 16);
}
@@ -507,7 +524,7 @@ class IO
* Setup DB config and options
*
* phpcs:ignore
- * @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[]} $db_config
+ * @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[],db_convert_placeholder?:bool,db_convert_placeholder_target?:string,db_debug_replace_placeholder?:bool} $db_config
* @return bool
*/
private function __setConfigOptions(array $db_config): bool
@@ -549,6 +566,26 @@ class IO
$this->db_convert_type[] = $db_convert_type;
$this->__setConvertType($db_convert_type);
}
+ // set placeholder convert flag and target
+ if (
+ isset($db_config['db_convert_placeholder']) &&
+ is_bool($db_config['db_convert_placeholder'])
+ ) {
+ $this->db_convert_placeholder = $db_config['db_convert_placeholder'];
+ }
+ if (
+ isset($db_config['db_convert_placeholder_target']) &&
+ in_array($db_config['db_convert_placeholder_target'], self::DB_CONVERT_PLACEHOLDER_TARGET)
+ ) {
+ $this->db_convert_placeholder_target = $db_config['db_convert_placeholder_target'];
+ }
+
+ if (
+ isset($db_config['db_debug_replace_placeholder']) &&
+ is_bool($db_config['db_debug_replace_placeholder'])
+ ) {
+ $this->db_debug_replace_placeholder = $db_config['db_debug_replace_placeholder'];
+ }
// return status true: ok, false: options error
return true;
@@ -601,7 +638,7 @@ class IO
// if non set or none matching abort
default:
// abort error
- $this->__dbError(10);
+ $this->__dbError(10, context: ['db_type' => $this->db_type]);
$this->db_connection_closed = true;
break;
}
@@ -619,7 +656,14 @@ class IO
{
// no DB name set, abort
if (empty($this->db_name)) {
- $this->__dbError(15);
+ $this->__dbError(15, context: [
+ 'host' => $this->db_host,
+ 'user' => $this->db_user,
+ 'password' => 'sha256:' . hash('sha256', $this->db_pwd),
+ 'database' => $this->db_name,
+ 'port' => $this->db_port,
+ 'ssl' => $this->db_ssl
+ ]);
return false;
}
// generate connect string
@@ -633,7 +677,14 @@ class IO
);
// if no dbh here, we couldn't connect to the DB itself
if (!$this->dbh) {
- $this->__dbError(14);
+ $this->__dbError(14, context: [
+ 'host' => $this->db_host,
+ 'user' => $this->db_user,
+ 'password' => 'sha256:' . hash('sha256', $this->db_pwd),
+ 'database' => $this->db_name,
+ 'port' => $this->db_port,
+ 'ssl' => $this->db_ssl
+ ]);
return false;
}
// 15 error (cant select to DB is not valid in postgres, as connect is different)
@@ -668,59 +719,6 @@ class IO
}
}
- /**
- * checks if query is a SELECT, SHOW or WITH, if not error, 0 return
- * NOTE:
- * Query needs to start with SELECT, SHOW or WITH
- *
- * @param string $query query to check
- * @return bool true if matching, false if not
- */
- private function __checkQueryForSelect(string $query): bool
- {
- // change to string starts with?
- if (preg_match("/^\s*(?:SELECT|SHOW|WITH)\s/i", $query)) {
- return true;
- }
- return false;
- }
-
- /**
- * check for DELETE, INSERT, UPDATE
- * if pure is set to true, only when INSERT is set will return true
- * NOTE:
- * Queries need to start with INSERT, UPDATE, DELETE. Anything else is ignored
- *
- * @param string $query query to check
- * @param bool $pure pure check (only insert), default false
- * @return bool true if matching, false if not
- */
- private function __checkQueryForInsert(string $query, bool $pure = false): bool
- {
- if ($pure && preg_match("/^\s*INSERT\s+?INTO\s/i", $query)) {
- return true;
- }
- if (!$pure && preg_match("/^\s*(?:INSERT\s+?INTO|DELETE\s+?FROM|UPDATE)\s/i", $query)) {
- return true;
- }
- return false;
- }
-
- /**
- * returns true if the query starts with UPDATE
- * query NEEDS to start with UPDATE
- *
- * @param string $query query to check
- * @return bool returns true if the query starts with UPDATE
- */
- private function __checkQueryForUpdate(string $query): bool
- {
- if (preg_match("/^\s*UPDATE\s?(.+)/i", $query)) {
- return true;
- }
- return false;
- }
-
/**
* internal funktion that creates the array
* NOTE:
@@ -881,12 +879,15 @@ class IO
* @param \PgSql\Result|false $cursor current cursor for pg_result_error,
* pg_last_error too, but pg_result_error
* is more accurate (PgSql\Result)
+ * @param bool $force_log [=false] if we want to log this error to log, on default logging is handled in the
+ * dbError/dbWarning calls
* @return array Pos 0: if we could get the method where it was called
* if not found [Uknown Method]
* Pos 1: if we have the pg_error_string from last error
* if nothing then empty string
+ * Pos 2: context array for detailed logging
*/
- private function __dbErrorPreprocessor(\PgSql\Result|false $cursor = false): array
+ private function __dbErrorPreprocessor(\PgSql\Result|false $cursor = false, bool $force_log = false): array
{
$db_prefix = '';
$db_error_string = '';
@@ -923,12 +924,20 @@ class IO
} elseif (!empty($db_error_string)) {
$db_error_string = $db_prefix . ' ' . $db_error_string;
}
- if ($db_error_string) {
+ if ($db_error_string && $force_log) {
$this->__dbDebugMessage('db', $db_error_string, 'DB_ERROR', $where_called);
}
+ $context = [];
+ if ($db_error_string) {
+ $context = [
+ 'pg_error_string' => $db_error_string,
+ 'where_called' => $where_called,
+ ];
+ }
return [
$where_called,
- $db_error_string
+ $db_error_string,
+ $context
];
}
@@ -939,11 +948,12 @@ class IO
* additional pg error message if exists and optional msg given on error call
* all error messages are grouped by error_history_id set when errors are reset
*
- * @param string $level
- * @param string $error_id
- * @param string $where_called
- * @param string $pg_error_string
- * @param string $msg
+ * @param string $level warning or error
+ * @param string $error_id error id
+ * @param string $where_called context wher eerror was colled
+ * @param string $pg_error_string if set, postgresql error string
+ * @param string $message additional message
+ * @param array $context array with more context information (eg query, params, etc)
* @return void
*/
private function __dbErrorHistory(
@@ -951,7 +961,8 @@ class IO
string $error_id,
string $where_called,
string $pg_error_string,
- string $msg
+ string $message,
+ array $context
): void {
if (empty($this->error_history_id)) {
$this->error_history_id = Uids::uniqId(self::ERROR_HASH_TYPE);
@@ -963,7 +974,8 @@ class IO
'error' => $this->error_string[$error_id] ?? '[UNKNOWN ERROR]',
'source' => $where_called,
'pg_error' => $pg_error_string,
- 'msg' => $msg,
+ 'message' => $message,
+ 'context' => $context,
];
}
@@ -972,54 +984,60 @@ class IO
*
* @param integer $error_id Any Error ID, used in debug message string
* @param \PgSql\Result|false $cursor Optional cursor, passed on to preprocessor
- * @param string $msg optional message added to debug
+ * @param string $message Optional message added to debug
+ * @param array $context Optional Context array, passed on as error_data to the main error
* @return void
*/
protected function __dbError(
int $error_id,
\PgSql\Result|false $cursor = false,
- string $msg = ''
+ string $message = '',
+ array $context = []
): void {
$error_id = (string)$error_id;
- [$where_called, $pg_error_string] = $this->__dbErrorPreprocessor($cursor);
+ [$where_called, $pg_error_string, $_context] = $this->__dbErrorPreprocessor($cursor);
// write error msg ...
$this->__dbDebugMessage(
'db',
$error_id . ': ' . ($this->error_string[$error_id] ?? '[UNKNOWN ERROR]')
- . ($msg ? ', ' . $msg : ''),
+ . ($message ? ', ' . $message : ''),
'DB_ERROR',
- $where_called
+ $where_called,
+ array_merge($context, $_context)
);
$this->error_id = $error_id;
- // keep warning history
- $this->__dbErrorHistory('error', $error_id, $where_called, $pg_error_string, $msg);
+ // keep error history
+ $this->__dbErrorHistory('error', $error_id, $where_called, $pg_error_string, $message, $context);
}
/**
* write a warning
*
- * @param integer $warning_id Integer warning id added to debug
+ * @param integer $warning_id Integer warning id added to debug
* @param \PgSql\Result|false $cursor Optional cursor, passed on to preprocessor
- * @param string $msg optional message added to debug
+ * @param string $message Optional message added to debug
+ * @param array $context Optional Context array, passed on as error_data to the main error
* @return void
*/
protected function __dbWarning(
int $warning_id,
\PgSql\Result|false $cursor = false,
- string $msg = ''
+ string $message = '',
+ array $context = []
): void {
$warning_id = (string)$warning_id;
- [$where_called, $pg_error_string] = $this->__dbErrorPreprocessor($cursor);
+ [$where_called, $pg_error_string, $_context] = $this->__dbErrorPreprocessor($cursor);
$this->__dbDebugMessage(
'db',
$warning_id . ': ' . ($this->error_string[$warning_id] ?? '[UNKNOWN WARNING')
- . ($msg ? ', ' . $msg : ''),
+ . ($message ? ', ' . $message : ''),
'DB_WARNING',
- $where_called
+ $where_called,
+ array_merge($context, $_context)
);
$this->warning_id = $warning_id;
// keep warning history
- $this->__dbErrorHistory('warning', $warning_id, $where_called, $pg_error_string, $msg);
+ $this->__dbErrorHistory('warning', $warning_id, $where_called, $pg_error_string, $message, $context);
}
/**
@@ -1120,39 +1138,69 @@ class IO
/**
* for debug purpose replaces $1, $2, etc with actual data
+ * TODO: :name and ? params
+ * Also works with :name parameters
+ * ? parameters, will be ignored
*
* @param string $query Query to replace values in
- * @param array $data The data array
+ * @param array $params The data param array
* @return string string of query with data inside
*/
- private function __dbDebugPrepare(string $query, array $data = []): string
+ private function __dbDebugPrepare(string $query, array $params = []): string
{
// skip anything if there is no data
- if ($data === []) {
+ if ($params === []) {
return $query;
}
// get the keys from data array
- $keys = array_keys($data);
+ $keys = array_keys($params);
+ // check if there is ? or :name i the keys list
// because the placeholders start with $ and at 1,
// we need to increase each key and prefix it with a $ char
for ($i = 0, $iMax = count($keys); $i < $iMax; $i++) {
// note: if I use $ here, the str_replace will
// replace it again. eg $11 '$1'1would be replaced with $1 again
// prefix data set with parameter pos
- $data[$i] = '#' . ($keys[$i] + 1) . ':' . ($data[$i] === null ?
- '"NULL"' : (string)$data[$i]
+ $params[$i] = '#' . ($keys[$i] + 1) . ':' . ($params[$i] === null ?
+ '"NULL"' : (string)$params[$i]
);
// search part
$keys[$i] = '$' . ($keys[$i] + 1);
}
// simply replace the $1, $2, ... with the actual data and return it
+ // note that we do this in return to go from highest number to lowest
return str_replace(
array_reverse($keys),
- array_reverse($data),
+ array_reverse($params),
$query
);
}
+ /**
+ * Created the context/error_data error for debug messages
+ *
+ * @param string $query Query called
+ * @param array $params Params
+ * @return array{}|array Empty array if no params, or params
+ * with optional prepared statement
+ */
+ private function __dbDebugPrepareContext(string $query, array $params = []): array
+ {
+ if ($params === []) {
+ return [];
+ }
+ $error_data = [
+ 'params' => $params
+ ];
+ if ($this->dbGetDebugReplacePlaceholder()) {
+ $error_data['prepared'] = $this->__dbDebugPrepare(
+ $query,
+ $params
+ );
+ }
+ return $error_data;
+ }
+
/**
* extracts schema and table from the query,
* if no schema returns just empty string
@@ -1164,7 +1212,7 @@ class IO
{
$matches = [];
$schema_table = [];
- if ($this->__checkQueryForSelect($query)) {
+ if ($this->dbCheckQueryForSelect($query)) {
// only selects the first one, this is more a fallback
// MATCHES 1 (call), 3 (schema), 4 (table)
preg_match("/\s+?(FROM)\s+?([\"'])?(?:([\w_]+)\.)?([\w_]+)(?:\2)?\s?/i", $query, $matches);
@@ -1254,7 +1302,7 @@ class IO
}
}
}
- $this->cursor_ext[$query_hash]['pos'] ++;
+ $this->cursor_ext[$query_hash]['pos']++;
return $return;
}
@@ -1270,14 +1318,14 @@ class IO
// regex for params: only stand alone $number allowed
// exclude all '' enclosed strings, ignore all numbers [note must start with digit]
// can have space/tab/new line
- // must have = , ( [equal, comma, opening round bracket]
+ // must have <> = , ( [not equal, equal, comma, opening round bracket]
// can have space/tab/new line
// $ number with 1-9 for first and 0-9 for further digits
// /s for matching new line in . list
// [disabled, we don't used ^ or $] /m for multi line match
// Matches in 1:, must be array_filtered to remove empty, count with array_unique
preg_match_all(
- '/(?:\'.*?\')?\s*(?:\?\?|[(=,])\s*(?:\d+|(?:\'.*?\')|(\$[1-9]{1}(?:[0-9]{1,})?))/s',
+ '/(?:\'.*?\')?\s*(?:\?\?|<>|[(=,])\s*(?:\d+|(?:\'.*?\')|(\$[1-9]{1}(?:[0-9]{1,})?))/s',
$query,
$match
);
@@ -1288,20 +1336,25 @@ class IO
* Checks if the placeholder count in the query matches the params given
* on call
*
- * @param string $query Query to check
- * @param int $params_count The parms count expected
+ * @param string $query Query to check
+ * @param array $params The parms to count count expected
* @return bool True for params count ok, else false
*/
- private function __dbCheckQueryParams(string $query, int $params_count): bool
+ private function __dbCheckQueryParams(string $query, array $params): bool
{
$placeholder_count = $this->__dbCountQueryParams($query);
+ $params_count = count($params);
if ($params_count != $placeholder_count) {
$this->__dbError(
23,
false,
- 'Array data count does not match prepared fields. Need: '
- . $placeholder_count . ', has: '
- . $params_count
+ 'Need: ' . $placeholder_count . ', has: ' . $params_count,
+ [
+ 'query' => $query,
+ 'params' => $params,
+ 'placeholder_needed' => $placeholder_count,
+ 'placeholder_provided' => $params_count,
+ ]
);
return false;
}
@@ -1348,7 +1401,6 @@ class IO
if (!$this->dbh) {
// if reconnect fails drop out
if (!$this->__connectToDB()) {
- $this->__dbError(16);
return false;
}
}
@@ -1358,7 +1410,7 @@ class IO
}
// if we do have an insert, check if there is no RETURNING pk_id,
// add it if I can get the PK id
- if ($this->__checkQueryForInsert($this->query, true)) {
+ if ($this->dbCheckQueryForInsert($this->query, true)) {
$this->pk_name = $pk_name;
if ($this->pk_name != 'NULL') {
if (!$this->pk_name) {
@@ -1396,24 +1448,55 @@ class IO
}
// if we have an UPDATE and RETURNING, flag for true, but do not add anything
if (
- $this->__checkQueryForUpdate($this->query) &&
+ $this->dbCheckQueryForUpdate($this->query) &&
preg_match(self::REGEX_RETURNING, $this->query, $matches)
) {
$this->returning_id = true;
}
// import protection, hash needed
$query_hash = $this->dbGetQueryHash($this->query, $this->params);
+ // QUERY PARAMS: run query params check and rewrite
+ if ($this->dbGetConvertPlaceholder() === true) {
+ try {
+ $this->placeholder_converted = ConvertPlaceholder::convertPlaceholderInQuery(
+ $this->query,
+ $this->params,
+ $this->dbGetConvertPlaceholderTarget()
+ );
+ // write the new queries over the old
+ if (!empty($this->placeholder_converted['query'])) {
+ $this->query = $this->placeholder_converted['query'];
+ $this->params = $this->placeholder_converted['params'];
+ }
+ } catch (\OutOfRangeException $e) {
+ $this->__dbError($e->getCode(), context:[
+ 'query' => $this->query,
+ 'params' => $this->params,
+ 'location' => '__dbPrepareExec',
+ 'error' => 'OutOfRangeException',
+ 'exception' => $e
+ ]);
+ return false;
+ } catch (\RuntimeException $e) {
+ $this->__dbError($e->getCode(), context:[
+ 'query' => $this->query,
+ 'params' => $this->params,
+ 'location' => '__dbPrepareExec',
+ 'error' => 'RuntimeException',
+ 'exception' => $e
+ ]);
+ return false;
+ }
+ }
// $this->debug('DB IO', 'Q: ' . $this->query . ', RETURN: ' . $this->returning_id);
// for DEBUG, only on first time ;)
$this->__dbDebug(
'db',
- $this->__dbDebugPrepare(
- $this->query,
- $this->params
- ),
+ $this->query,
'__dbPrepareExec',
- ($this->params === [] ? 'Q' : 'Qp')
+ ($this->params === [] ? 'Q' : 'Qp'),
+ error_data: $this->__dbDebugPrepareContext($this->query, $this->params)
);
// if the array index does not exists set it 0
if (!array_key_exists($query_hash, $this->query_called)) {
@@ -1429,19 +1512,14 @@ class IO
$this->MAX_QUERY_CALL != -1 &&
$this->query_called[$query_hash] > $this->MAX_QUERY_CALL
) {
- $this->__dbError(30, false, $this->query);
- $this->__dbDebugMessage(
- 'db',
- $this->__dbDebugPrepare(
- $this->query,
- $this->params
- ),
- 'dbExec',
- ($this->params === [] ? 'Q[nc]' : 'Qp[nc]')
- );
+ $this->__dbError(30, false, context: [
+ 'query' => $this->query,
+ 'params' => $this->params,
+ 'location' => '__dbPrepareExec'
+ ]);
return false;
}
- $this->query_called[$query_hash] ++;
+ $this->query_called[$query_hash]++;
// return hash
return $query_hash;
}
@@ -1458,14 +1536,17 @@ class IO
// if FALSE returned, set error stuff
// if either the cursor is false
if ($this->cursor === false || $this->db_functions->__dbLastErrorQuery()) {
- // printout Query if debug is turned on
- $this->__dbDebug('db', $this->query, 'dbExec', 'Q[nc]');
// internal error handling
- $this->__dbError(13, $this->cursor);
+ $this->__dbError(13, $this->cursor, context: [
+ 'query' => $this->query,
+ 'params' => $this->params,
+ 'location' => 'dbExec',
+ 'query_id' => 'Q[nc]',
+ ]);
return false;
} else {
// if SELECT do here ...
- if ($this->__checkQueryForSelect($this->query)) {
+ if ($this->dbCheckQueryForSelect($this->query)) {
// count the rows returned (if select)
$this->num_rows = $this->db_functions->__dbNumRows($this->cursor);
// count the fields
@@ -1486,15 +1567,15 @@ class IO
$this->field_names,
$this->field_types
);
- } elseif ($this->__checkQueryForInsert($this->query)) {
+ } elseif ($this->dbCheckQueryForInsert($this->query)) {
// if not select do here
// count affected rows
$this->num_rows = $this->db_functions->__dbAffectedRows($this->cursor);
if (
// ONLY insert with set pk name
- ($this->__checkQueryForInsert($this->query, true) && $this->pk_name != 'NULL') ||
+ ($this->dbCheckQueryForInsert($this->query, true) && $this->pk_name != 'NULL') ||
// insert or update with returning add
- ($this->__checkQueryForInsert($this->query) && $this->returning_id)
+ ($this->dbCheckQueryForInsert($this->query) && $this->returning_id)
) {
$this->__dbSetInsertId(
$this->returning_id,
@@ -1516,15 +1597,13 @@ class IO
* - if many this will also hold all non pk names too
* then try to fill insert_id_arr, this is always multi level
* - fill key: value as single array or multi array
- * insert_id_ext [DEPRECATED, all in insert_id_arr]
* - holds all returning as array
- * TODO: Only use insert_id_arr and use functions to get ok array or single
*
- * @param bool $returning_id
- * @param string $query
- * @param string|null $pk_name
+ * @param bool $returning_id False if no RETURNING, try to get different via insert id
+ * @param string $query Query with RETURNING
+ * @param string|null $pk_name Primary key name
* @param \PgSql\Result|false $cursor (PgSql\Result)
- * @param string|null $stm_name If not null, is dbExecutre run
+ * @param string|null $stm_name [null] If not null, is dbExecute run and not a prepared call
* @return void
*/
private function __dbSetInsertId(
@@ -1546,9 +1625,16 @@ class IO
if ($cursor === false) {
// failed to get insert id
if ($stm_name === null) {
- $this->__dbWarning(34, $cursor, '[dbExec]');
+ $this->__dbWarning(34, $cursor, '[dbExec]', context: [
+ 'query' => $query,
+ 'pk_name' => $pk_name,
+ ]);
} else {
- $this->__dbWarning(34, false, $stm_name . ': CURSOR is null');
+ $this->__dbWarning(34, false, 'CURSOR is null', [
+ 'statement_name' => $stm_name,
+ 'query' => $query,
+ 'pk_name' => $pk_name,
+ ]);
}
return;
}
@@ -1560,7 +1646,11 @@ class IO
$this->insert_id_arr[] = $insert_id;
// throw warning that no pk was found
if ($insert_id === false) {
- $this->__dbWarning(31, $cursor, '[dbExec]');
+ $this->__dbWarning(31, $cursor, '[dbExec]', context: [
+ 'query' => $query,
+ 'pk_name' => $pk_name,
+ 'returning_id' => $returning_id,
+ ]);
}
} else { // was stm_name null or not null and cursor
// we have returning, now we need to check if we get one or many returned
@@ -1577,23 +1667,43 @@ class IO
if (count($this->insert_id_arr) == 0) {
// failed to get insert id
if ($stm_name === null) {
- $this->__dbWarning(33, $cursor, '[dbExec]');
+ $this->__dbWarning(33, $cursor, '[dbExec]', context: [
+ 'query' => $query,
+ 'pk_name' => $pk_name,
+ 'returning_id' => $returning_id,
+ ]);
} else {
$this->__dbWarning(
33,
false,
- $stm_name . ': RETURNING returned no data'
+ 'RETURNING returned no data',
+ context: [
+ 'statement_name' => $stm_name,
+ 'query' => $query,
+ 'pk_name' => $pk_name,
+ 'returning_id' => $returning_id,
+ ]
);
}
} elseif (count($this->insert_id_arr) > 1) {
// this error handling is only for INSERT (), (), ... sets
if ($stm_name === null) {
- $this->__dbWarning(32, $cursor, '[dbExec]');
+ $this->__dbWarning(32, $cursor, '[dbExec]', context: [
+ 'query' => $query,
+ 'pk_name' => $pk_name,
+ 'returning_id' => $returning_id,
+ ]);
} else {
$this->__dbWarning(
32,
false,
- $stm_name . ': RETURNING returned an array (possible multiple insert)'
+ 'RETURNING returned an array (possible multiple insert)',
+ context: [
+ 'statement_name' => $stm_name,
+ 'query' => $query,
+ 'pk_name' => $pk_name,
+ 'returning_id' => $returning_id,
+ ]
);
}
}
@@ -1864,6 +1974,63 @@ class IO
return $string;
}
+ // ***************************
+ // CHECK QUERY TYPE
+ // ***************************
+
+ /**
+ * checks if query is a SELECT, SHOW or WITH, if not error, 0 return
+ * NOTE:
+ * Query needs to start with SELECT, SHOW or WITH
+ *
+ * @param string $query query to check
+ * @return bool true if matching, false if not
+ */
+ public function dbCheckQueryForSelect(string $query): bool
+ {
+ // change to string starts with?
+ if (preg_match("/^\s*(?:SELECT|SHOW|WITH)\s/i", $query)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * check for DELETE, INSERT, UPDATE
+ * if pure is set to true, only when INSERT is set will return true
+ * NOTE:
+ * Queries need to start with INSERT, UPDATE, DELETE. Anything else is ignored
+ *
+ * @param string $query query to check
+ * @param bool $pure pure check (only insert), default false
+ * @return bool true if matching, false if not
+ */
+ public function dbCheckQueryForInsert(string $query, bool $pure = false): bool
+ {
+ if ($pure && preg_match("/^\s*INSERT\s+?INTO\s/i", $query)) {
+ return true;
+ }
+ if (!$pure && preg_match("/^\s*(?:INSERT\s+?INTO|DELETE\s+?FROM|UPDATE)\s/i", $query)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * returns true if the query starts with UPDATE
+ * query NEEDS to start with UPDATE
+ *
+ * @param string $query query to check
+ * @return bool returns true if the query starts with UPDATE
+ */
+ public function dbCheckQueryForUpdate(string $query): bool
+ {
+ if (preg_match("/^\s*UPDATE\s?(.+)/i", $query)) {
+ return true;
+ }
+ return false;
+ }
+
// ***************************
// DATA WRITE CONVERSION
// ***************************
@@ -2110,7 +2277,10 @@ class IO
$table = (!empty($schema) ? $schema . '.' : '') . $table;
$array = $this->db_functions->__dbMetaData($table);
if (!is_array($array)) {
- $this->__dbError(60);
+ $this->__dbError(60, context: [
+ 'table' => $table,
+ 'schema' => $schema
+ ]);
$array = false;
}
return $array;
@@ -2219,6 +2389,8 @@ class IO
'query' => '',
// parameter
'params' => [],
+ // if we convert placeholders, conversion data is stored here
+ 'placeholder_converted' => [],
// cache flag from method call
'cache_flag' => $cache,
// flag if we only have assoc data
@@ -2236,35 +2408,71 @@ class IO
'log_pos' => 1, // how many times called overall
'log' => [], // current run log
];
+
+ // set the query
+ $this->cursor_ext[$query_hash]['query'] = $query;
+ // set the query parameters
+ $this->cursor_ext[$query_hash]['params'] = $params;
+ // before doing ANYTHING check if query is "SELECT ..." everything else does not work
+ if (!$this->dbCheckQueryForSelect($this->cursor_ext[$query_hash]['query'])) {
+ $this->__dbError(17, false, context: [
+ 'query' => $this->cursor_ext[$query_hash]['query'],
+ 'params' => $this->cursor_ext[$query_hash]['params'],
+ 'location' => 'dbReturn',
+ ]);
+ return false;
+ }
+ // QUERY PARAMS: run query params check and rewrite
+ if ($this->dbGetConvertPlaceholder() === true) {
+ try {
+ $this->cursor_ext[$query_hash]['placeholder_converted'] =
+ ConvertPlaceholder::convertPlaceholderInQuery(
+ $this->cursor_ext[$query_hash]['query'],
+ $this->cursor_ext[$query_hash]['params'],
+ $this->dbGetConvertPlaceholderTarget()
+ );
+ if (!empty($this->cursor_ext[$query_hash]['placeholder_converted']['query'])) {
+ $this->cursor_ext[$query_hash]['query'] =
+ $this->cursor_ext[$query_hash]['placeholder_converted']['query'];
+ $this->cursor_ext[$query_hash]['params'] =
+ $this->cursor_ext[$query_hash]['placeholder_converted']['params'];
+ }
+ } catch (\OutOfRangeException $e) {
+ $this->__dbError($e->getCode(), context:[
+ 'query' => $this->cursor_ext[$query_hash]['query'],
+ 'params' => $this->cursor_ext[$query_hash]['params'],
+ 'location' => 'dbReturn',
+ 'error' => 'OutOfRangeException',
+ 'exception' => $e
+ ]);
+ return false;
+ } catch (\RuntimeException $e) {
+ $this->__dbError($e->getCode());
+ $this->__dbError($e->getCode(), context:[
+ 'query' => $this->cursor_ext[$query_hash]['query'],
+ 'params' => $this->cursor_ext[$query_hash]['params'],
+ 'location' => 'dbReturn',
+ 'error' => 'RuntimeException',
+ 'exception' => $e
+ ]);
+ return false;
+ }
+ }
+ // check if params count matches
+ // checks if the params count given matches the expected count
+ if (
+ $this->__dbCheckQueryParams(
+ $this->cursor_ext[$query_hash]['query'],
+ $this->cursor_ext[$query_hash]['params']
+ ) === false
+ ) {
+ return false;
+ }
} else {
- $this->cursor_ext[$query_hash]['log_pos'] ++;
+ $this->cursor_ext[$query_hash]['log_pos']++;
}
// reset log for each read
$this->cursor_ext[$query_hash]['log'] = [];
- // set the query
- $this->cursor_ext[$query_hash]['query'] = $query;
- // before doing ANYTHING check if query is "SELECT ..." everything else does not work
- if (!$this->__checkQueryForSelect($this->cursor_ext[$query_hash]['query'])) {
- $this->__dbError(17, false, $this->cursor_ext[$query_hash]['query']);
- return false;
- }
- // set the query parameters
- $this->cursor_ext[$query_hash]['params'] = $params;
- // check if params count matches
- // checks if the params count given matches the expected count
- if ($this->__dbCheckQueryParams($query, count($params)) === false) {
- // in case we got an error print out query
- $this->__dbDebug(
- 'db',
- $this->__dbDebugPrepare(
- $this->query,
- $this->params
- ),
- 'dbReturn',
- ($this->params === [] ? 'Q[e]' : 'Qp[e]')
- );
- return false;
- }
// set first call to false
$first_call = false;
// init return als false
@@ -2287,18 +2495,18 @@ class IO
// for DEBUG, print out each query executed
$this->__dbDebug(
'db',
- $this->__dbDebugPrepare(
- $this->cursor_ext[$query_hash]['query'],
- $this->cursor_ext[$query_hash]['params']
- ),
+ $this->cursor_ext[$query_hash]['query'],
'dbReturn',
($this->cursor_ext[$query_hash]['params'] === [] ? 'Q' : 'Qp'),
+ error_data: $this->__dbDebugPrepareContext(
+ $this->cursor_ext[$query_hash]['query'],
+ $this->cursor_ext[$query_hash]['params']
+ )
);
// if no DB Handler try to reconnect
if (!$this->dbh) {
// if reconnect fails drop out
if (!$this->__connectToDB()) {
- $this->__dbError(16);
return false;
}
}
@@ -2320,17 +2528,12 @@ class IO
}
// if still no cursor ...
if (!$this->cursor_ext[$query_hash]['cursor']) {
- $this->__dbDebug(
- 'db',
- $this->__dbDebugPrepare(
- $this->cursor_ext[$query_hash]['query'],
- $this->cursor_ext[$query_hash]['params']
- ),
- 'dbReturn',
- ($this->cursor_ext[$query_hash]['params'] === [] ? 'Q[e]' : 'Qp[e]'),
- );
// internal error handling
- $this->__dbError(13, $this->cursor_ext[$query_hash]['cursor']);
+ $this->__dbError(13, $this->cursor_ext[$query_hash]['cursor'], context: [
+ 'query' => $this->cursor_ext[$query_hash]['query'],
+ 'params' => $this->cursor_ext[$query_hash]['params'],
+ 'location' => 'dbReturn'
+ ]);
return false;
} else {
$first_call = true;
@@ -2465,8 +2668,8 @@ class IO
if ($return) {
$this->cursor_ext[$query_hash]['log'][] = 'Return Data';
// internal position counter
- $this->cursor_ext[$query_hash]['pos'] ++;
- $this->cursor_ext[$query_hash]['read_rows'] ++;
+ $this->cursor_ext[$query_hash]['pos']++;
+ $this->cursor_ext[$query_hash]['read_rows']++;
// read is finished
if (
$this->cursor_ext[$query_hash]['read_rows'] ==
@@ -2540,24 +2743,28 @@ class IO
): \PgSql\Result|false {
$this->__dbErrorReset();
// prepare and check if we can actually run it
- if ($this->__dbPrepareExec($query, $params, $pk_name) === false) {
+ if (($query_hash = $this->__dbPrepareExec($query, $params, $pk_name)) === false) {
// bail if no query hash set
return false;
}
// checks if the params count given matches the expected count
- if ($this->__dbCheckQueryParams($query, count($params)) === false) {
+ if ($this->__dbCheckQueryParams($this->query, $this->params) === false) {
return false;
}
// ** actual db exec call
- if ($params === []) {
+ if ($this->params === []) {
$cursor = $this->db_functions->__dbQuery($this->query);
} else {
- $cursor = $this->db_functions->__dbQueryParams($this->query, $params);
+ $cursor = $this->db_functions->__dbQueryParams($this->query, $this->params);
}
// if we faield, just set the master cursors to false too
$this->cursor = $cursor;
if ($cursor === false) {
- $this->__dbError(13);
+ $this->__dbError(13, context: [
+ 'query' => $this->query,
+ 'params' => $this->params,
+ 'location' => 'dbExecParams',
+ ]);
return false;
}
// if FALSE returned, set error stuff
@@ -2637,8 +2844,13 @@ class IO
}
// before doing ANYTHING check if query is
// "SELECT ..." everything else does not work
- if (!$this->__checkQueryForSelect($query)) {
- $this->__dbError(17, false, $query);
+ if (!$this->dbCheckQueryForSelect($query)) {
+ $this->__dbError(17, false, context: [
+ 'query' => $query,
+ 'params' => $params,
+ 'assoc_only' => $assoc_only,
+ 'location' => 'dbReturnRowParams'
+ ]);
return false;
}
$cursor = $this->dbExecParams($query, $params);
@@ -2682,8 +2894,13 @@ class IO
return false;
}
// before doing ANYTHING check if query is "SELECT ..." everything else does not work
- if (!$this->__checkQueryForSelect($query)) {
- $this->__dbError(17, false, $query);
+ if (!$this->dbCheckQueryForSelect($query)) {
+ $this->__dbError(17, false, context: [
+ 'query' => $query,
+ 'params' => $params,
+ 'assoc_only' => $assoc_only,
+ 'location' => 'dbReturnArrayParams'
+ ]);
return false;
}
$cursor = $this->dbExecParams($query, $params);
@@ -2728,7 +2945,11 @@ class IO
$query_hash = $this->dbGetQueryHash($query, $params);
// clears cache for this query
if (empty($this->cursor_ext[$query_hash]['query'])) {
- $this->__dbError(18);
+ $this->__dbError(18, context: [
+ 'query' => $query,
+ 'params' => $params,
+ 'hash' => $query_hash,
+ ]);
return false;
}
unset($this->cursor_ext[$query_hash]);
@@ -2897,7 +3118,6 @@ class IO
if (!$this->dbh) {
// if reconnect fails drop out
if (!$this->__connectToDB()) {
- $this->__dbError(16);
return false;
}
}
@@ -2924,7 +3144,7 @@ class IO
'returning_id' => false
];
// if this is an insert query, check if we can add a return
- if ($this->__checkQueryForInsert($query, true)) {
+ if ($this->dbCheckQueryForInsert($query, true)) {
if ($pk_name != 'NULL') {
// set primary key name
// current: only via parameter
@@ -2972,14 +3192,34 @@ class IO
$this->__dbError(
21,
false,
- $stm_name . ': Prepare field with: ' . $stm_name . ' | ' . $query
+ context: [
+ 'statement_name' => $stm_name,
+ 'query' => $query,
+ 'pk_name' => $pk_name,
+ ]
);
return $result;
}
} else {
- // thrown warning
- $this->__dbWarning(20, false, $stm_name);
- return true;
+ // if we try to use the same statement name for a differnt query, error abort
+ if ($this->prepare_cursor[$stm_name]['query'] != $query) {
+ // thrown error
+ $this->__dbError(26, false, context: [
+ 'statement_name' => $stm_name,
+ 'prepared_query' => $this->prepare_cursor[$stm_name]['query'],
+ 'query' => $query,
+ 'pk_name' => $pk_name,
+ ]);
+ return false;
+ } else {
+ // thrown warning
+ $this->__dbWarning(20, false, context: [
+ 'statement_name' => $stm_name,
+ 'query' => $query,
+ 'pk_name' => $pk_name,
+ ]);
+ return true;
+ }
}
}
@@ -2997,7 +3237,6 @@ class IO
if (!$this->dbh) {
// if reconnect fails drop out
if (!$this->__connectToDB()) {
- $this->__dbError(16);
return false;
}
}
@@ -3019,28 +3258,37 @@ class IO
$this->__dbError(
24,
false,
- $stm_name . ': We do not have a prepared query entry for this statement name.'
+ $stm_name . ': We do not have a prepared query entry for this statement name.',
+ context: ['statement_name' => $stm_name]
);
return false;
}
$this->__dbDebug(
'db',
- $this->__dbDebugPrepare(
+ $this->prepare_cursor[$stm_name]['query'],
+ 'dbExecute',
+ 'Qpe',
+ error_data: array_merge([
+ 'statement_name' => $stm_name,
+ ], $this->__dbDebugPrepareContext(
$this->prepare_cursor[$stm_name]['query'],
$data
- ),
- 'dbExecPrep',
- 'Qpe'
+ ))
);
// if the count does not match
if ($this->prepare_cursor[$stm_name]['count'] != count($data)) {
$this->__dbError(
23,
false,
- $stm_name
- . ': Array data count does not match prepared fields. Need: '
- . $this->prepare_cursor[$stm_name]['count'] . ', has: '
- . count($data)
+ '(' . $stm_name . ') '
+ . 'Need: ' . $this->prepare_cursor[$stm_name]['count'] . ', has: ' . count($data),
+ context: [
+ 'statement_name' => $stm_name,
+ 'query' => $this->prepare_cursor[$stm_name]['query'],
+ 'params' => $data,
+ 'placeholder_needed' => $this->prepare_cursor[$stm_name]['count'],
+ 'placeholder_provided' => count($data)
+ ]
);
return false;
}
@@ -3052,16 +3300,20 @@ class IO
$this->__dbError(
22,
$this->prepare_cursor[$stm_name]['result'],
- $stm_name . ': Execution failed'
+ context: [
+ 'statement_name' => $stm_name,
+ 'query' => $this->prepare_cursor[$stm_name]['query'],
+ 'params' => $data
+ ]
);
return false;
}
if (
// pure insert wth pk name
- ($this->__checkQueryForInsert($this->prepare_cursor[$stm_name]['query'], true) &&
+ ($this->dbCheckQueryForInsert($this->prepare_cursor[$stm_name]['query'], true) &&
$this->prepare_cursor[$stm_name]['pk_name'] != 'NULL') ||
// insert or update with returning set
- ($this->__checkQueryForInsert($this->prepare_cursor[$stm_name]['query']) &&
+ ($this->dbCheckQueryForInsert($this->prepare_cursor[$stm_name]['query']) &&
$this->prepare_cursor[$stm_name]['returning_id'] === true
)
) {
@@ -3122,20 +3374,24 @@ class IO
return false;
}
// checks if the params count given matches the expected count
- if ($this->__dbCheckQueryParams($query, count($params)) === false) {
+ if ($this->__dbCheckQueryParams($this->query, $this->params) === false) {
return false;
}
// ** actual db exec call
if ($params === []) {
$status = $this->db_functions->__dbSendQuery($this->query);
} else {
- $status = $this->db_functions->__dbSendQueryParams($this->query, $params);
+ $status = $this->db_functions->__dbSendQueryParams($this->query, $this->params);
}
// run the async query, this just returns true or false
// the actually result is in dbCheckAsync
if (!$status) {
// if failed, process here
- $this->__dbError(40);
+ $this->__dbError(40, context: [
+ 'query' => $this->query,
+ 'params' => $this->params,
+ 'pk_name' => $pk_name,
+ ]);
return false;
} else {
$this->async_running = (string)$query_hash;
@@ -3216,8 +3472,7 @@ class IO
// if no async running print error
$this->__dbError(
42,
- false,
- 'No async query has been started yet.'
+ false
);
return false;
}
@@ -3461,7 +3716,7 @@ class IO
}
/**
- * Undocumented function
+ * convert db values (set)
*
* @param Convert $convert
* @return void
@@ -3472,7 +3727,7 @@ class IO
}
/**
- * Undocumented function
+ * unsert convert db values flag
*
* @param Convert $convert
* @return void
@@ -3495,7 +3750,7 @@ class IO
}
/**
- * Undocumented function
+ * check if a conert flag is set
*
* @param Convert $convert
* @return bool
@@ -3508,6 +3763,73 @@ class IO
return false;
}
+ /**
+ * Set if we want to auto convert PDO/\Pg placeholders
+ *
+ * @param bool $flag
+ * @return void
+ */
+ public function dbSetConvertPlaceholder(bool $flag): void
+ {
+ $this->db_convert_placeholder = $flag;
+ }
+
+ /**
+ * get the flag status if we want to auto convert placeholders in the query
+ *
+ * @return bool
+ */
+ public function dbGetConvertPlaceholder(): bool
+ {
+ return $this->db_convert_placeholder;
+ }
+
+ /**
+ * Set convert target for placeholders, returns false on error, true on ok
+ *
+ * @param string $target 'pg' or 'pdo', defined in DB_CONVERT_PLACEHOLDER_TARGET
+ * @return bool
+ */
+ public function dbSetConvertPlaceholderTarget(string $target): bool
+ {
+ if (in_array($target, self::DB_CONVERT_PLACEHOLDER_TARGET)) {
+ $this->db_convert_placeholder_target = $target;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the current placeholder convert target
+ *
+ * @return string
+ */
+ public function dbGetConvertPlaceholderTarget(): string
+ {
+ return $this->db_convert_placeholder_target;
+ }
+
+ /**
+ * Set flag if we print the query with replaced placeholders or not
+ *
+ * @param bool $flag
+ * @return void
+ */
+ public function dbSetDebugReplacePlaceholder(bool $flag): void
+ {
+ $this->db_debug_replace_placeholder = $flag;
+ }
+
+ /**
+ * get the current setting for the debug replace placeholder
+ *
+ * @return bool True for replace query, False for not
+ */
+ public function dbGetDebugReplacePlaceholder(): bool
+ {
+ return $this->db_debug_replace_placeholder;
+ }
+
/**
* set max query calls, set to -1 to disable loop
* protection. this will generate a warning
@@ -3525,11 +3847,11 @@ class IO
// if -1 then disable loop check
// DANGEROUS, WARN USER
if ($max_calls == -1) {
- $this->__dbWarning(50);
+ $this->__dbWarning(50, context: ['max_calls' => $max_calls]);
}
// negative or 0
if ($max_calls < -1 || $max_calls == 0) {
- $this->__dbError(51);
+ $this->__dbError(51, context: ['max_calls' => $max_calls]);
// early abort
return false;
}
@@ -3573,7 +3895,7 @@ class IO
case 2:
// setting schema failed (3)
case 3:
- $this->__dbError(71);
+ $this->__dbError(71, context: ['schema' => $db_schema]);
$status = false;
break;
}
@@ -3623,7 +3945,7 @@ class IO
case 2:
// 3 is set failed
case 3:
- $this->__dbError(81);
+ $this->__dbError(81, context: ['encoding' => $db_encoding]);
$status = false;
break;
}
@@ -3748,6 +4070,16 @@ class IO
$this->params = [];
}
+ /**
+ * Returns the placeholder convert set or empty
+ *
+ * @return array{}|array{original:array{query:string,params:array},type:''|'named'|'numbered'|'question_mark',found:int,matches:array,params_lookup:array,query:string,params:array}
+ */
+ public function dbGetPlaceholderConverted(): array
+ {
+ return $this->placeholder_converted;
+ }
+
// ***************************
// INTERNAL VARIABLES READ POST QUERY RUN
// ***************************
@@ -3966,7 +4298,8 @@ class IO
$this->__dbError(
102,
false,
- 'Invalid key name'
+ 'Invalid key name',
+ context: ['key' => $key]
);
return false;
}
@@ -3975,7 +4308,8 @@ class IO
$this->__dbError(
103,
false,
- 'Statement name does not exist in prepare cursor array'
+ 'Statement name does not exist in prepare cursor array',
+ context: ['statement_name' => $stm_name]
);
return false;
}
@@ -3984,7 +4318,11 @@ class IO
$this->__dbError(
104,
false,
- 'Key does not exist in prepare cursor array'
+ 'Key does not exist in prepare cursor array',
+ context: [
+ 'statement_name' => $stm_name,
+ 'key' => $key
+ ]
);
return false;
}
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/DB/Support/ConvertPlaceholder.php b/www/vendor/egrajp/corelibs-composer-all/src/DB/Support/ConvertPlaceholder.php
new file mode 100644
index 00000000..bcfd5613
--- /dev/null
+++ b/www/vendor/egrajp/corelibs-composer-all/src/DB/Support/ConvertPlaceholder.php
@@ -0,0 +1,220 @@
+ $params The parameters that are used for the query, and will be updated
+ * @param string $convert_to Either pdo or pg, will be converted to lower case for check
+ * @return array{original:array{query:string,params:array},type:''|'named'|'numbered'|'question_mark',found:int,matches:array,params_lookup:array,query:string,params:array}
+ * @throws \OutOfRangeException 200
+ */
+ public static function convertPlaceholderInQuery(
+ string $query,
+ array $params,
+ string $convert_to = 'pg'
+ ): array {
+ $convert_to = strtolower($convert_to);
+ $matches = [];
+ $pattern = '/'
+ // prefix string part, must match towards
+ . '(?:\'.*?\')?\s*(?:\?\?|[(=,])\s*'
+ // match for replace part
+ . '(?:'
+ // digit -> ignore
+ . '\d+|'
+ // other string -> ignore
+ . '(?:\'.*?\')|'
+ // :name named part (PDO)
+ . '(:\w+)|'
+ // ? question mark part (PDO)
+ . '(?:(?:\?\?)?\s*(\?{1}))|'
+ // $n numbered part (\PG php)
+ . '(\$[1-9]{1}(?:[0-9]{1,})?)'
+ // end match
+ . ')'
+ // single line -> add line break to matches in "."
+ . '/s';
+ // matches:
+ // 1: :named
+ // 2: ? question mark
+ // 3: $n numbered
+ $found = preg_match_all($pattern, $query, $matches, PREG_UNMATCHED_AS_NULL);
+ // if false or null set to -1
+ // || $found === null
+ if ($found === false) {
+ $found = -1;
+ }
+ /** @var array 1: named */
+ $named_matches = array_filter($matches[1]);
+ /** @var array 2: open ? */
+ $qmark_matches = array_filter($matches[2]);
+ /** @var array 3: $n matches */
+ $numbered_matches = array_filter($matches[3]);
+ // count matches
+ $count_named = count($named_matches);
+ $count_qmark = count($qmark_matches);
+ $count_numbered = count($numbered_matches);
+ // throw if mixed
+ if (
+ ($count_named && $count_qmark) ||
+ ($count_named && $count_numbered) ||
+ ($count_qmark && $count_numbered)
+ ) {
+ throw new \OutOfRangeException('Cannot have named, question mark and numbered in the same query', 200);
+ }
+ // rebuild
+ $matches_return = [];
+ $type = '';
+ $query_new = '';
+ $params_new = [];
+ $params_lookup = [];
+ if ($count_named && $convert_to == 'pg') {
+ $type = 'named';
+ $matches_return = $named_matches;
+ // only check for :named
+ $pattern_replace = '/((?:\'.*?\')?\s*(?:\?\?|[(=,])\s*)(\d+|(?:\'.*?\')|(:\w+))/s';
+ // 0: full
+ // 1: pre part
+ // 2: keep part UNLESS '3' is set
+ // 3: replace part :named
+ $pos = 0;
+ $query_new = preg_replace_callback(
+ $pattern_replace,
+ function ($matches) use (&$pos, &$params_new, &$params_lookup, $params) {
+ // only count up if $match[3] is not yet in lookup table
+ if (!empty($matches[3]) && empty($params_lookup[$matches[3]])) {
+ $pos++;
+ $params_lookup[$matches[3]] = '$' . $pos;
+ $params_new[] = $params[$matches[3]] ??
+ throw new \RuntimeException(
+ 'Cannot lookup ' . $matches[3] . ' in params list',
+ 210
+ );
+ }
+ // add the connectors back (1), and the data sets only if no replacement will be done
+ return $matches[1] . (
+ empty($matches[3]) ?
+ $matches[2] :
+ $params_lookup[$matches[3]] ??
+ throw new \RuntimeException(
+ 'Cannot lookup ' . $matches[3] . ' in params lookup list',
+ 211
+ )
+ );
+ },
+ $query
+ );
+ } elseif ($count_qmark && $convert_to == 'pg') {
+ $type = 'question_mark';
+ $matches_return = $qmark_matches;
+ // order and data stays the same
+ $params_new = $params;
+ // only check for ?
+ $pattern_replace = '/((?:\'.*?\')?\s*(?:\?\?|[(=,])\s*)(\d+|(?:\'.*?\')|(?:(?:\?\?)?\s*(\?{1})))/s';
+ // 0: full
+ // 1: pre part
+ // 2: keep part UNLESS '3' is set
+ // 3: replace part ?
+ $pos = 0;
+ $query_new = preg_replace_callback(
+ $pattern_replace,
+ function ($matches) use (&$pos, &$params_lookup) {
+ // only count pos up for actual replacements we will do
+ if (!empty($matches[3])) {
+ $pos++;
+ $params_lookup[] = '$' . $pos;
+ }
+ // add the connectors back (1), and the data sets only if no replacement will be done
+ return $matches[1] . (
+ empty($matches[3]) ?
+ $matches[2] :
+ '$' . $pos
+ );
+ },
+ $query
+ );
+ // for each ?:DTN: -> replace with $1 ... $n, any remaining :DTN: remove
+ } elseif ($count_numbered && $convert_to == 'pdo') {
+ // convert numbered to named
+ $type = 'numbered';
+ $matches_return = $numbered_matches;
+ // only check for $n
+ $pattern_replace = '/((?:\'.*?\')?\s*(?:\?\?|[(=,])\s*)(\d+|(?:\'.*?\')|(\$[1-9]{1}(?:[0-9]{1,})?))/s';
+ // 0: full
+ // 1: pre part
+ // 2: keep part UNLESS '3' is set
+ // 3: replace part $numbered
+ $pos = 0;
+ $query_new = preg_replace_callback(
+ $pattern_replace,
+ function ($matches) use (&$pos, &$params_new, &$params_lookup, $params) {
+ // only count up if $match[3] is not yet in lookup table
+ if (!empty($matches[3]) && empty($params_lookup[$matches[3]])) {
+ $pos++;
+ $params_lookup[$matches[3]] = ':' . $pos . '_named';
+ $params_new[] = $params[($pos - 1)] ??
+ throw new \RuntimeException(
+ 'Cannot lookup ' . ($pos - 1) . ' in params list',
+ 220
+ );
+ }
+ // add the connectors back (1), and the data sets only if no replacement will be done
+ return $matches[1] . (
+ empty($matches[3]) ?
+ $matches[2] :
+ $params_lookup[$matches[3]] ??
+ throw new \RuntimeException(
+ 'Cannot lookup ' . $matches[3] . ' in params lookup list',
+ 221
+ )
+ );
+ },
+ $query
+ );
+ }
+ // return, old query is always set
+ return [
+ // original
+ 'original' => [
+ 'query' => $query,
+ 'params' => $params,
+ ],
+ // type found, empty if nothing was done
+ 'type' => $type,
+ // int: found, not found; -1: problem (set from false)
+ 'found' => (int)$found,
+ 'matches' => $matches_return,
+ // old to new lookup check
+ 'params_lookup' => $params_lookup,
+ // new
+ 'query' => $query_new ?? '',
+ 'params' => $params_new,
+ ];
+ }
+}
+
+// __END__
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Debug/Support.php b/www/vendor/egrajp/corelibs-composer-all/src/Debug/Support.php
index 456be11c..affec0f7 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/Debug/Support.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/Debug/Support.php
@@ -295,8 +295,7 @@ class Support
* Will start with start_level to skip unwanted from stack
* Defaults to skip level 0 wich is this methid
*
- * @param integer $start_level From what level on, as defaul starts with 1
- * to exclude self
+ * @param integer $start_level [=1] From what level on, starts with 1 to exclude self
* @return array All method names in list where max is last called
*/
public static function getCallerMethodList(int $start_level = 1): array
@@ -304,15 +303,46 @@ class Support
$traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$methods = [];
foreach ($traces as $level => $data) {
- if ($level >= $start_level) {
- if (!empty($data['function'])) {
- array_unshift($methods, $data['function']);
- }
+ if ($level < $start_level) {
+ continue;
+ }
+ if (!empty($data['function'])) {
+ array_unshift($methods, $data['function']);
}
}
return $methods;
}
+ /**
+ * Get the full call stack from a certain starting level
+ * The return string is
+ * file:line:class->method
+ *
+ * Note that '::' is used for static calls
+ *
+ * @param int $start_level [=1] starts with 1 to exclude itself
+ * @return array string with file, line, class and method
+ */
+ public static function getCallStack(int $start_level = 1): array
+ {
+ $call_stack = [];
+ $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+ foreach ($backtrace as $level => $call_trace) {
+ if ($level < $start_level) {
+ continue;
+ }
+ $call_stack[] =
+ ($call_trace['file'] ?? 'n/f') . ':'
+ . ($call_trace['line'] ?? '-') . ':'
+ . (!empty($call_trace['class']) ?
+ $call_trace['class'] . ($call_trace['type'] ?? '') :
+ ''
+ )
+ . $call_trace['function'];
+ }
+ return $call_stack;
+ }
+
/**
* Get the current class where this function is called
* Is mostly used in debug log statements to get the class where the debug
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Output/Form/Generate.php b/www/vendor/egrajp/corelibs-composer-all/src/Output/Form/Generate.php
index a09eab66..3c406d4d 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/Output/Form/Generate.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/Output/Form/Generate.php
@@ -310,7 +310,7 @@ class Generate
* construct form generator
*
* phpcs:ignore
- * @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[]} $db_config db config array, mandatory
+ * @param array{db_name:string,db_user:string,db_pass:string,db_host:string,db_port:int,db_schema:string,db_encoding:string,db_type:string,db_ssl:string,db_convert_type?:string[],db_convert_placeholder?:bool,db_convert_placeholder_target?:string,db_debug_replace_placeholder?:bool} $db_config db config array, mandatory
* @param \CoreLibs\Logging\Logging $log Logging class
* @param \CoreLibs\Language\L10n $l10n l10n language class
* @param array $login_acl Login ACL array,
@@ -826,27 +826,28 @@ class Generate
$pk_selected = $res[$this->int_pk_name];
}
$t_string = '';
- foreach ($this->field_array as $i => $field_array) {
+ foreach ($this->field_array as $field_array) {
if ($t_string) {
$t_string .= ', ';
}
- if (isset($field_array['before_value'])) {
- $t_string .= $field_array['before_value'];
+ if (!empty($field_array['before_value'])) {
+ $t_string .= $this->l->__($field_array['before_value']);
}
// must have res element set
if (
- isset($field_array['name']) &&
+ !empty($field_array['name']) &&
isset($res[$field_array['name']])
) {
- if (isset($field_array['binary'])) {
- if (isset($field_array['binary'][0])) {
- $t_string .= $field_array['binary'][0];
- } elseif (isset($field_array['binary'][1])) {
- $t_string .= $field_array['binary'][1];
- }
+ $_t_value = '';
+ // if we have a binary set, where 0 = YES and 1 = NO
+ if (!empty($field_array['binary'])) {
+ $_t_value = !empty($res[$field_array['name']]) ?
+ ($field_array['binary'][0] ?? 'Yes') :
+ ($field_array['binary'][1] ?? 'No');
} else {
- $t_string .= $res[$field_array['name']];
+ $_t_value = $res[$field_array['name']];
}
+ $t_string .= $this->l->__($_t_value);
}
}
$pk_names[] = $t_string;
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Output/Image.php b/www/vendor/egrajp/corelibs-composer-all/src/Output/Image.php
index 897e6495..9fd82619 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/Output/Image.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/Output/Image.php
@@ -78,7 +78,7 @@ class Image
if (!empty($dummy) && file_exists($filename) && is_file($filename)) {
$return_data = $filename;
} else {
- throw new \Exception('Could not set dummy return file: ' . $dummy . ' in ' . $filename);
+ throw new \RuntimeException('Could not set dummy return file: ' . $dummy . ' in ' . $filename);
}
} else {
$return_data = $dummy;
@@ -204,11 +204,11 @@ class Image
E_USER_DEPRECATED
);
// NOTE: we need to depracte this
- $cache_folder = BASE . LAYOUT . CONTENT_PATH . CACHE . IMAGES;
+ $cache_folder = BASE . CONTENT_PATH . LAYOUT . CACHE . IMAGES;
$web_folder = LAYOUT . CACHE . IMAGES;
if (!is_dir($cache_folder)) {
if (false === mkdir($cache_folder)) {
- $cache_folder = BASE . LAYOUT . CONTENT_PATH . CACHE;
+ $cache_folder = BASE . CONTENT_PATH . LAYOUT . CACHE;
$web_folder = LAYOUT . CACHE;
}
}
diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Output/ProgressBar.php b/www/vendor/egrajp/corelibs-composer-all/src/Output/ProgressBar.php
index 6affd992..5c4f9c76 100644
--- a/www/vendor/egrajp/corelibs-composer-all/src/Output/ProgressBar.php
+++ b/www/vendor/egrajp/corelibs-composer-all/src/Output/ProgressBar.php
@@ -156,7 +156,7 @@ class ProgressBar
{
// avoid divison through 0
if ($this->max - $this->min == 0) {
- $this->max ++;
+ $this->max++;
}
$percent = round(($step - $this->min) / ($this->max - $this->min) * 100);
if ($percent > 100) {
@@ -186,7 +186,7 @@ class ProgressBar
}
// avoid divison through 0
if ($this->max - $this->min == 0) {
- $this->max ++;
+ $this->max++;
}
$pixel = round(($step - $this->min) * ($bar - ($this->pedding * 2)) / ($this->max - $this->min));
if ($step <= $this->min) {
diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Check/CoreLibsCheckFileTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Check/CoreLibsCheckFileTest.php
index c94ad943..56141aa2 100644
--- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Check/CoreLibsCheckFileTest.php
+++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Check/CoreLibsCheckFileTest.php
@@ -28,10 +28,10 @@ final class CoreLibsCheckFileTest extends TestCase
public function filesList(): array
{
return [
- ['filename.txt', 'txt', 5],
- ['filename.csv', 'csv', 15],
- ['filename.tsv', 'tsv', 0],
- ['file_does_not_exits', '', -1],
+ ['filename.txt', 'txt', 5, 'text/plain'],
+ ['filename.csv', 'csv', 15, 'text/csv'],
+ ['filename.tsv', 'tsv', 0, 'text/plain'],
+ ['file_does_not_exits', '', -1, ''],
];
}
@@ -63,6 +63,15 @@ final class CoreLibsCheckFileTest extends TestCase
return $list;
}
+ public function mimeTypeProvider(): array
+ {
+ $list = [];
+ foreach ($this->filesList() as $row) {
+ $list[$row[0] . ' must be mime type ' . $row[3]] = [$row[0], $row[3]];
+ }
+ return $list;
+ }
+
/**
* Tests if file extension matches
*
@@ -115,6 +124,51 @@ final class CoreLibsCheckFileTest extends TestCase
unlink($this->base_folder . $input);
}
}
+
+ /**
+ * Undocumented function
+ *
+ * @covers ::getMimeType
+ * @dataProvider mimeTypeProvider
+ * @testdox getMimeType $input must be mime type $expected [$_dataName]
+ *
+ * @param string $input
+ * @param string $expected
+ * @return void
+ */
+ public function testGetMimeType(string $input, string $expected): void
+ {
+ if (!empty($expected)) {
+ $file = $this->base_folder . $input;
+ $fp = fopen($file, 'w');
+ switch ($expected) {
+ case 'text/csv':
+ for ($i = 1; $i <= 10; $i++) {
+ fwrite($fp, '"This is row","' . $expected . '",' . $i . PHP_EOL);
+ }
+ break;
+ case 'text/tsv':
+ for ($i = 1; $i <= 10; $i++) {
+ fwrite($fp, "\"This is row\"\t\"" . $expected . "\"\t\"" . $i . PHP_EOL);
+ }
+ break;
+ case 'text/plain':
+ fwrite($fp, 'This is mime type: ' . $expected . PHP_EOL);
+ break;
+ }
+ fclose($fp);
+ } else {
+ $this->expectException(\UnexpectedValueException::class);
+ }
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Check\File::getMimeType($this->base_folder . $input)
+ );
+ // unlink file
+ if (is_file($this->base_folder . $input)) {
+ unlink($this->base_folder . $input);
+ }
+ }
}
// __END__
diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php
index 25ade3a5..8dc5729a 100644
--- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php
+++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php
@@ -1098,16 +1098,109 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
* @testdox arrayFlatForKey array $input will be $expected [$_dataName]
*
* @param array $input
+ * @param string $search
* @param array $expected
* @return void
*/
- public function testArrayFlatForKey(array $input, $search, array $expected): void
+ public function testArrayFlatForKey(array $input, string $search, array $expected): void
{
$this->assertEquals(
$expected,
\CoreLibs\Combined\ArrayHandler::arrayFlatForKey($input, $search)
);
}
+
+ /**
+ * Undocumented function
+ *
+ * @return array
+ */
+ public function providerArrayGetNextPrevKey(): array
+ {
+ return [
+ 'find, ok' => [
+ 'input' => [
+ 'a' => 'First',
+ 'b' => 'Second',
+ 'c' => 'Third',
+ ],
+ 'b',
+ 'a',
+ 'c'
+ ],
+ 'find, first' => [
+ 'input' => [
+ 'a' => 'First',
+ 'b' => 'Second',
+ 'c' => 'Third',
+ ],
+ 'a',
+ null,
+ 'b'
+ ],
+ 'find, last' => [
+ 'input' => [
+ 'a' => 'First',
+ 'b' => 'Second',
+ 'c' => 'Third',
+ ],
+ 'c',
+ 'b',
+ null
+ ],
+ 'find, not found' => [
+ 'input' => [
+ 'a' => 'First',
+ 'b' => 'Second',
+ 'c' => 'Third',
+ ],
+ 'z',
+ null,
+ null
+ ],
+ 'int, index' => [
+ 'input' => [
+ 'a',
+ 'b',
+ 'c'
+ ],
+ 1,
+ 0,
+ 2
+ ]
+ ];
+ }
+
+ /**
+ * Undocumented function
+ *
+ * @covers ::arrayGetPrevKey, ::arrayGetNextKey
+ * @dataProvider providerArrayGetNextPrevKey
+ * @testdox arrayGetNextPrevKey get next/prev key for $search wtih $expected_prev/$expected_next [$_dataName]
+ *
+ * @param array $input
+ * @param int|string $search
+ * @param int|string|null $expected_prev
+ * @param int|string|null $expected_next
+ * @return void
+ */
+ public function testArrayGetNextPrevKey(
+ array $input,
+ int|string $search,
+ int|string|null $expected_prev,
+ int|string|null $expected_next
+ ): void {
+ $this->assertEquals(
+ $expected_prev,
+ \CoreLibs\Combined\ArrayHandler::arrayGetPrevKey($input, $search),
+ 'Find prev key in array'
+ );
+ $this->assertEquals(
+ $expected_next,
+ \CoreLibs\Combined\ArrayHandler::arrayGetNextKey($input, $search),
+ 'Find next key in array'
+ );
+ }
}
// __END__
diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedDateTimeTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedDateTimeTest.php
index 7bd68d6a..d7efa9b7 100644
--- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedDateTimeTest.php
+++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedDateTimeTest.php
@@ -66,6 +66,34 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
];
}
+ /**
+ * date string convert test
+ *
+ * @covers ::dateStringFormat
+ * @dataProvider timestampProvider
+ * @testdox dateStringFormat $input (microtime $flag) will be $expected [$_dataName]
+ *
+ * @param int|float $input
+ * @param bool $flag
+ * @param string $expected
+ * @return void
+ */
+ public function testDateStringFormat(
+ $input,
+ bool $flag_show_micro,
+ bool $flag_micro_as_float,
+ string $expected
+ ): void {
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Combined\DateTime::dateStringFormat(
+ $input,
+ $flag_show_micro,
+ $flag_micro_as_float
+ )
+ );
+ }
+
/**
* interval for both directions
*
@@ -74,6 +102,11 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
public function intervalProvider(): array
{
return [
+ 'on hour' => [
+ 3600,
+ false,
+ '1h 0m 0s'
+ ],
'interval no microtime' => [
1641515890,
false,
@@ -82,7 +115,7 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
'interval with microtime' => [
1641515890,
true,
- '18999d 0h 38m 10s',
+ '18999d 0h 38m 10s 0ms',
],
'micro interval no microtime' => [
1641515890.123456,
@@ -92,7 +125,7 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
'micro interval with microtime' => [
1641515890.123456,
true,
- '18999d 0h 38m 10s 1235ms',
+ '18999d 0h 38m 10s 124ms',
],
'negative interval no microtime' => [
-1641515890,
@@ -103,27 +136,27 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
'microtime only' => [
0.123456,
true,
- '0s 1235ms',
+ '0s 123ms',
],
'seconds only' => [
30.123456,
true,
- '30s 1235ms',
+ '30s 123ms',
],
'minutes only' => [
90.123456,
true,
- '1m 30s 1235ms',
+ '1m 30s 123ms',
],
'hours only' => [
3690.123456,
true,
- '1h 1m 30s 1235ms',
+ '1h 1m 30s 123ms',
],
'days only' => [
90090.123456,
true,
- '1d 1h 1m 30s 1235ms',
+ '1d 1h 1m 30s 123ms',
],
'already set' => [
'1d 1h 1m 30s 1235ms',
@@ -143,6 +176,306 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
];
}
+ /**
+ * time seconds convert test
+ *
+ * @covers ::timeStringFormat
+ * @dataProvider intervalProvider
+ * @testdox timeStringFormat $input (microtime $flag) will be $expected [$_dataName]
+ *
+ * @param string|int|float $input
+ * @param bool $flag
+ * @param string $expected
+ * @return void
+ */
+ public function testTimeStringFormat(string|int|float $input, bool $flag, string $expected): void
+ {
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Combined\DateTime::timeStringFormat($input, $flag)
+ );
+ }
+
+ /**
+ * interval seconds convert
+ *
+ * @covers ::intervalStringFormat
+ * @dataProvider intervalProvider
+ * @testdox intervalStringFormat $input (microtime $show_micro) will be $expected [$_dataName]
+ *
+ * @param string|int|float $input
+ * @param bool $show_micro
+ * @param string $expected
+ * @return void
+ */
+ public function testIntervalStringFormat(string|int|float $input, bool $show_micro, string $expected): void
+ {
+ // we skip string input, that is not allowed
+ if (is_string($input)) {
+ $this->assertTrue(true, 'Skip strings');
+ return;
+ }
+ // invalid values throw exception in default
+ if ($input == 999999999999999) {
+ $this->expectException(\LengthException::class);
+ }
+ // below is equal to timeStringFormat
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Combined\DateTime::intervalStringFormat(
+ $input,
+ show_microseconds: $show_micro,
+ show_only_days: true,
+ skip_zero: false,
+ skip_last_zero: false,
+ truncate_nanoseconds: true,
+ truncate_zero_seconds_if_microseconds: false
+ )
+ );
+ }
+
+ /**
+ * Undocumented function
+ *
+ * @return array
+ */
+ public function intervalExtendedProvider(): array
+ {
+ return [
+ // A
+ '(60) default value' => [
+ [
+ 'seconds' => 60,
+ ],
+ 'expected' => '1m',
+ 'exception' => null
+ ],
+ '(60) default value, skip_last_zero:false' => [
+ [
+ 'seconds' => 60,
+ 'skip_last_zero' => false,
+ ],
+ 'expected' => '1m 0s 0ms',
+ 'exception' => null
+ ],
+ // B
+ '(120.1) default value' => [
+ [
+ 'seconds' => 120.1,
+ ],
+ 'expected' => '2m 100ms',
+ 'exception' => null
+ ],
+ '(120.1) default value, skip_zero:false' => [
+ [
+ 'seconds' => 120.1,
+ 'skip_zero' => false,
+ ],
+ 'expected' => '2m 0s 100ms',
+ 'exception' => null
+ ],
+ '(120.1) default value, skip_last_zero:false' => [
+ [
+ 'seconds' => 120.1,
+ 'skip_last_zero' => false,
+ ],
+ 'expected' => '2m 100ms',
+ 'exception' => null
+ ],
+ // C
+ '(3601) default value' => [
+ [
+ 'seconds' => 3601,
+ ],
+ 'expected' => '1h 1s',
+ 'exception' => null
+ ],
+ '(3601) default value, skip_zero:false' => [
+ [
+ 'seconds' => 3601,
+ 'skip_zero' => false,
+ ],
+ 'expected' => '1h 0m 1s',
+ 'exception' => null
+ ],
+ '(3601) default value, skip_last_zero:false' => [
+ [
+ 'seconds' => 3601,
+ 'skip_last_zero' => false,
+ ],
+ 'expected' => '1h 1s 0ms',
+ 'exception' => null
+ ],
+ // TODO create unit tests for ALL edge cases
+ // CREATE abort tests, simple, all others are handled in exception tests
+ 'exception: \UnexpectedValueException:1' => [
+ [
+ 'seconds' => 99999999999999999999999
+ ],
+ 'expected' => null,
+ 'exception' => [
+ 'class' => \UnexpectedValueException::class,
+ 'code' => 1,
+ ],
+ ]
+ ];
+ }
+
+ /**
+ * test all options for interval conversion
+ *
+ * @covers ::intervalStringFormat
+ * @dataProvider intervalExtendedProvider
+ * @testdox intervalStringFormat $input will be $expected / $exception [$_dataName]
+ *
+ * @param array $parameter_list
+ * @param string $expected
+ * @param array $exception
+ * @return void
+ */
+ public function testExtendedIntervalStringFormat(
+ array $parameter_list,
+ ?string $expected,
+ ?array $exception
+ ): void {
+ if ($expected === null && $exception === null) {
+ $this->assertFalse(true, 'Cannot have expected and exception null in test data');
+ }
+ $parameters = [];
+ foreach (
+ [
+ 'seconds' => null,
+ 'truncate_after' => '',
+ 'natural_seperator' => false,
+ 'name_space_seperator' => false,
+ 'show_microseconds' => true,
+ 'short_time_name' => true,
+ 'skip_last_zero' => true,
+ 'skip_zero' => true,
+ 'show_only_days' => false,
+ 'auto_fix_microseconds' => false,
+ 'truncate_nanoseconds' => false,
+ 'truncate_zero_seconds_if_microseconds' => true,
+ ] as $param => $default
+ ) {
+ if (empty($parameter_list[$param]) && $default === null) {
+ $this->assertFalse(true, 'Parameter ' . $param . ' is mandatory ');
+ } elseif (!isset($parameter_list[$param]) || $parameter_list[$param] === null) {
+ $parameters[] = $default;
+ } else {
+ $parameters[] = $parameter_list[$param];
+ }
+ }
+ if ($expected !== null) {
+ $this->assertEquals(
+ $expected,
+ call_user_func_array('CoreLibs\Combined\DateTime::intervalStringFormat', $parameters)
+ );
+ } else {
+ if (empty($exception['class']) || empty($exception['code'])) {
+ $this->assertFalse(true, 'Exception tests need Exception name and Code');
+ }
+ $this->expectException($exception['class']);
+ $this->expectExceptionCode($exception['code']);
+ // if we have a message, must be regex
+ if (!empty($exception['message'])) {
+ $this->expectExceptionMessageMatches($exception['message']);
+ }
+ call_user_func_array('CoreLibs\Combined\DateTime::intervalStringFormat', $parameters);
+ }
+ }
+
+ /**
+ * Undocumented function
+ *
+ * @return array
+ */
+ public function exceptionsIntervalProvider(): array
+ {
+ return [
+ 'UnexpectedValueException: 1 A' => [
+ 'seconds' => 99999999999999999999999,
+ 'params' => [],
+ 'exception' => \UnexpectedValueException::class,
+ 'exception_message' => "/^Seconds value is invalid, too large or more than six decimals: /",
+ 'excpetion_code' => 1,
+ ],
+ 'UnexpectedValueException: 1 B' => [
+ 'seconds' => 123.1234567,
+ 'params' => [],
+ 'exception' => \UnexpectedValueException::class,
+ 'exception_message' => "/^Seconds value is invalid, too large or more than six decimals: /",
+ 'excpetion_code' => 1,
+ ],
+ // exception 2 is very likely covered by exception 1
+ 'LengthException: 3' => [
+ 'seconds' => 999999999999999999,
+ 'params' => [
+ 'show_only_days',
+ ],
+ 'exception' => \LengthException::class,
+ 'exception_message' => "/^Input seconds value is too large for days output: /",
+ 'excpetion_code' => 3,
+ ],
+ 'UnexpectedValueException: 4' => [
+ 'seconds' => 1234567,
+ 'params' => [
+ 'truncate_after'
+ ],
+ 'exception' => \UnexpectedValueException::class,
+ 'exception_message' => "/^truncate_after has an invalid value: /",
+ 'excpetion_code' => 4,
+ ],
+ 'UnexpectedValueException: 5' => [
+ 'seconds' => 1234567,
+ 'params' => [
+ 'show_only_days:truncate_after'
+ ],
+ 'exception' => \UnexpectedValueException::class,
+ 'exception_message' =>
+ "/^If show_only_days is turned on, the truncate_after cannot be years or months: /",
+ 'excpetion_code' => 5,
+ ]
+ ];
+ }
+
+ /**
+ * Test all exceptions
+ *
+ * @covers ::intervalStringFormat
+ * @dataProvider exceptionsIntervalProvider
+ * @testdox intervalStringFormat: test Exceptions
+ *
+ * @param int|float $seconds
+ * @param array $params
+ * @param string $exception
+ * @param string $exception_message
+ * @param int $excpetion_code
+ * @return void
+ */
+ public function testExceptionsIntervalStringFormat(
+ int|float $seconds,
+ array $params,
+ string $exception,
+ string $exception_message,
+ int $excpetion_code,
+ ): void {
+ $this->expectException($exception);
+ $this->expectExceptionMessageMatches($exception_message);
+ $this->expectExceptionCode($excpetion_code);
+ if (empty($params)) {
+ \CoreLibs\Combined\DateTime::intervalStringFormat($seconds);
+ } else {
+ if (in_array('show_only_days', $params)) {
+ \CoreLibs\Combined\DateTime::intervalStringFormat($seconds, show_only_days:true);
+ } elseif (in_array('truncate_after', $params)) {
+ \CoreLibs\Combined\DateTime::intervalStringFormat($seconds, truncate_after: 'v');
+ } elseif (in_array('show_only_days:truncate_after', $params)) {
+ \CoreLibs\Combined\DateTime::intervalStringFormat($seconds, show_only_days:true, truncate_after: 'y');
+ }
+ }
+ }
+
/**
* Undocumented function
*
@@ -203,6 +536,25 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
];
}
+ /**
+ * Undocumented function
+ *
+ * @covers ::stringToTime
+ * @dataProvider reverseIntervalProvider
+ * @testdox stringToTime $input will be $expected [$_dataName]
+ *
+ * @param string|int|float $input
+ * @param string|int|float $expected
+ * @return void
+ */
+ public function testStringToTime($input, $expected): void
+ {
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Combined\DateTime::stringToTime($input)
+ );
+ }
+
/**
* Undocumented function
*
@@ -238,6 +590,25 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
];
}
+ /**
+ * Undocumented function
+ *
+ * @covers ::checkDate
+ * @dataProvider dateProvider
+ * @testdox checkDate $input will be $expected [$_dataName]
+ *
+ * @param string $input
+ * @param bool $expected
+ * @return void
+ */
+ public function testCheckDate(string $input, bool $expected): void
+ {
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Combined\DateTime::checkDate($input)
+ );
+ }
+
/**
* Undocumented function
*
@@ -297,6 +668,25 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
];
}
+ /**
+ * Undocumented function
+ *
+ * @covers ::checkDateTime
+ * @dataProvider dateTimeProvider
+ * @testdox checkDateTime $input will be $expected [$_dataName]
+ *
+ * @param string $input
+ * @param bool $expected
+ * @return void
+ */
+ public function testCheckDateTime(string $input, bool $expected): void
+ {
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Combined\DateTime::checkDateTime($input)
+ );
+ }
+
/**
* Undocumented function
*
@@ -371,6 +761,37 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
];
}
+ /**
+ * Undocumented function
+ *
+ * @covers ::compareDate
+ * @dataProvider dateCompareProvider
+ * @testdox compareDate $input_a compared to $input_b will be $expected [$_dataName]
+ *
+ * @param string $input_a
+ * @param string $input_b
+ * @param int|bool $expected
+ * @param string|null $exception
+ * @param int|null $exception_code
+ * @return void
+ */
+ public function testCompareDate(
+ string $input_a,
+ string $input_b,
+ int|bool $expected,
+ ?string $exception,
+ ?int $exception_code
+ ): void {
+ if ($expected === false) {
+ $this->expectException($exception);
+ $this->expectExceptionCode($exception_code);
+ }
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Combined\DateTime::compareDate($input_a, $input_b)
+ );
+ }
+
/**
* Undocumented function
*
@@ -466,6 +887,37 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
];
}
+ /**
+ * Undocumented function
+ *
+ * @covers ::compareDateTime
+ * @dataProvider dateTimeCompareProvider
+ * @testdox compareDateTime $input_a compared to $input_b will be $expected [$_dataName]
+ *
+ * @param string $input_a
+ * @param string $input_b
+ * @param int|bool $expected
+ * @param string|null $exception
+ * @param int|null $exception_code
+ * @return void
+ */
+ public function testCompareDateTime(
+ string $input_a,
+ string $input_b,
+ int|bool $expected,
+ ?string $exception,
+ ?int $exception_code
+ ): void {
+ if ($expected === false) {
+ $this->expectException($exception);
+ $this->expectExceptionCode($exception_code);
+ }
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Combined\DateTime::compareDateTime($input_a, $input_b)
+ );
+ }
+
/**
* Undocumented function
*
@@ -520,214 +972,6 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
];
}
- /**
- * Undocumented function
- *
- * @return array
- */
- public function dateRangeHasWeekendProvider(): array
- {
- return [
- 'no weekend' => [
- '2023-07-03',
- '2023-07-04',
- false
- ],
- 'start weekend sat' => [
- '2023-07-01',
- '2023-07-04',
- true
- ],
- 'start weekend sun' => [
- '2023-07-02',
- '2023-07-04',
- true
- ],
- 'end weekend sat' => [
- '2023-07-03',
- '2023-07-08',
- true
- ],
- 'end weekend sun' => [
- '2023-07-03',
- '2023-07-09',
- true
- ],
- 'long period > 6 days' => [
- '2023-07-03',
- '2023-07-27',
- true
- ]
- ];
- }
-
- /**
- * date string convert test
- *
- * @covers ::dateStringFormat
- * @dataProvider timestampProvider
- * @testdox dateStringFormat $input (microtime $flag) will be $expected [$_dataName]
- *
- * @param int|float $input
- * @param bool $flag
- * @param string $expected
- * @return void
- */
- public function testDateStringFormat(
- $input,
- bool $flag_show_micro,
- bool $flag_micro_as_float,
- string $expected
- ): void {
- $this->assertEquals(
- $expected,
- \CoreLibs\Combined\DateTime::dateStringFormat(
- $input,
- $flag_show_micro,
- $flag_micro_as_float
- )
- );
- }
-
- /**
- * interval convert test
- *
- * @covers ::timeStringFormat
- * @dataProvider intervalProvider
- * @testdox timeStringFormat $input (microtime $flag) will be $expected [$_dataName]
- *
- * @param int|float $input
- * @param bool $flag
- * @param string $expected
- * @return void
- */
- public function testTimeStringFormat($input, bool $flag, string $expected): void
- {
- $this->assertEquals(
- $expected,
- \CoreLibs\Combined\DateTime::timeStringFormat($input, $flag)
- );
- }
-
- /**
- * Undocumented function
- *
- * @covers ::stringToTime
- * @dataProvider reverseIntervalProvider
- * @testdox stringToTime $input will be $expected [$_dataName]
- *
- * @param string|int|float $input
- * @param string|int|float $expected
- * @return void
- */
- public function testStringToTime($input, $expected): void
- {
- $this->assertEquals(
- $expected,
- \CoreLibs\Combined\DateTime::stringToTime($input)
- );
- }
-
- /**
- * Undocumented function
- *
- * @covers ::checkDate
- * @dataProvider dateProvider
- * @testdox checkDate $input will be $expected [$_dataName]
- *
- * @param string $input
- * @param bool $expected
- * @return void
- */
- public function testCheckDate(string $input, bool $expected): void
- {
- $this->assertEquals(
- $expected,
- \CoreLibs\Combined\DateTime::checkDate($input)
- );
- }
-
- /**
- * Undocumented function
- *
- * @covers ::checkDateTime
- * @dataProvider dateTimeProvider
- * @testdox checkDateTime $input will be $expected [$_dataName]
- *
- * @param string $input
- * @param bool $expected
- * @return void
- */
- public function testCheckDateTime(string $input, bool $expected): void
- {
- $this->assertEquals(
- $expected,
- \CoreLibs\Combined\DateTime::checkDateTime($input)
- );
- }
-
- /**
- * Undocumented function
- *
- * @covers ::compareDate
- * @dataProvider dateCompareProvider
- * @testdox compareDate $input_a compared to $input_b will be $expected [$_dataName]
- *
- * @param string $input_a
- * @param string $input_b
- * @param int|bool $expected
- * @param string|null $exception
- * @param int|null $exception_code
- * @return void
- */
- public function testCompareDate(
- string $input_a,
- string $input_b,
- int|bool $expected,
- ?string $exception,
- ?int $exception_code
- ): void {
- if ($expected === false) {
- $this->expectException($exception);
- $this->expectExceptionCode($exception_code);
- }
- $this->assertEquals(
- $expected,
- \CoreLibs\Combined\DateTime::compareDate($input_a, $input_b)
- );
- }
-
- /**
- * Undocumented function
- *
- * @covers ::compareDateTime
- * @dataProvider dateTimeCompareProvider
- * @testdox compareDateTime $input_a compared to $input_b will be $expected [$_dataName]
- *
- * @param string $input_a
- * @param string $input_b
- * @param int|bool $expected
- * @param string|null $exception
- * @param int|null $exception_code
- * @return void
- */
- public function testCompareDateTime(
- string $input_a,
- string $input_b,
- int|bool $expected,
- ?string $exception,
- ?int $exception_code
- ): void {
- if ($expected === false) {
- $this->expectException($exception);
- $this->expectExceptionCode($exception_code);
- }
- $this->assertEquals(
- $expected,
- \CoreLibs\Combined\DateTime::compareDateTime($input_a, $input_b)
- );
- }
-
/**
* Undocumented function
*
@@ -906,6 +1150,47 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
);
}
+ /**
+ * Undocumented function
+ *
+ * @return array
+ */
+ public function dateRangeHasWeekendProvider(): array
+ {
+ return [
+ 'no weekend' => [
+ '2023-07-03',
+ '2023-07-04',
+ false
+ ],
+ 'start weekend sat' => [
+ '2023-07-01',
+ '2023-07-04',
+ true
+ ],
+ 'start weekend sun' => [
+ '2023-07-02',
+ '2023-07-04',
+ true
+ ],
+ 'end weekend sat' => [
+ '2023-07-03',
+ '2023-07-08',
+ true
+ ],
+ 'end weekend sun' => [
+ '2023-07-03',
+ '2023-07-09',
+ true
+ ],
+ 'long period > 6 days' => [
+ '2023-07-03',
+ '2023-07-27',
+ true
+ ]
+ ];
+ }
+
/**
* Undocumented function
*
diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertByteTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertByteTest.php
index bf49af3b..95838889 100644
--- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertByteTest.php
+++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertByteTest.php
@@ -253,7 +253,8 @@ final class CoreLibsConvertByteTest extends TestCase
*/
public function testHumanReadableByteFormatException(int $flag): void
{
- $this->expectException(\Exception::class);
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionCode(1);
\CoreLibs\Convert\Byte::humanReadableByteFormat(12, $flag);
}
@@ -272,7 +273,8 @@ final class CoreLibsConvertByteTest extends TestCase
*/
public function testStringByteFormatException(int $flag): void
{
- $this->expectException(\Exception::class);
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionCode(1);
\CoreLibs\Convert\Byte::stringByteFormat(12, $flag);
}
}
diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertStringsTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertStringsTest.php
index 90415d20..0b2f79a5 100644
--- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertStringsTest.php
+++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertStringsTest.php
@@ -256,6 +256,80 @@ final class CoreLibsConvertStringsTest extends TestCase
$output
);
}
+
+ /**
+ * provider for testStripMultiplePathSlashes
+ *
+ * @return array
+ */
+ public function stripMultiplePathSlashesProvider(): array
+ {
+ return [
+ 'no slahses' => [
+ 'input' => 'string_abc',
+ 'expected' => 'string_abc',
+ ],
+ 'one slash' => [
+ 'input' => 'some/foo',
+ 'expected' => 'some/foo',
+ ],
+ 'two slashes' => [
+ 'input' => 'some//foo',
+ 'expected' => 'some/foo',
+ ],
+ 'three slashes' => [
+ 'input' => 'some///foo',
+ 'expected' => 'some/foo',
+ ],
+ 'slashes in front' => [
+ 'input' => '/foo',
+ 'expected' => '/foo',
+ ],
+ 'two slashes in front' => [
+ 'input' => '//foo',
+ 'expected' => '/foo',
+ ],
+ 'thee slashes in front' => [
+ 'input' => '///foo',
+ 'expected' => '/foo',
+ ],
+ 'slashes in back' => [
+ 'input' => 'foo/',
+ 'expected' => 'foo/',
+ ],
+ 'two slashes in back' => [
+ 'input' => 'foo//',
+ 'expected' => 'foo/',
+ ],
+ 'thee slashes in back' => [
+ 'input' => 'foo///',
+ 'expected' => 'foo/',
+ ],
+ 'multiple slashes' => [
+ 'input' => '/foo//bar///string/end_times',
+ 'expected' => '/foo/bar/string/end_times',
+ ]
+ ];
+ }
+
+ /**
+ * test multiple slashes clean up
+ *
+ * @covers ::stripMultiplePathSlashes
+ * @dataProvider stripMultiplePathSlashesProvider
+ * @testdox stripMultiplePathSlashes $input will be $expected [$_dataName]
+ *
+ * @param string $input
+ * @param string $expected
+ * @return void
+ */
+ public function testStripMultiplePathSlashes(string $input, string $expected): void
+ {
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Convert\Strings::stripMultiplePathSlashes($input)
+ );
+ }
}
// __END__
diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/DB/CoreLibsDBIOTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/DB/CoreLibsDBIOTest.php
index d1d598f3..93703db8 100644
--- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/DB/CoreLibsDBIOTest.php
+++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/DB/CoreLibsDBIOTest.php
@@ -232,7 +232,7 @@ final class CoreLibsDBIOTest extends TestCase
$this->assertEquals(
$error,
$last_error,
- 'Assert query warning'
+ 'Assert query error'
);
return [$last_warning, $last_error];
}
@@ -251,8 +251,6 @@ final class CoreLibsDBIOTest extends TestCase
*/
public function testDbVersion(): void
{
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -276,8 +274,6 @@ final class CoreLibsDBIOTest extends TestCase
*/
public function testDbVersionNumeric(): void
{
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -306,8 +302,6 @@ final class CoreLibsDBIOTest extends TestCase
*/
public function testDbVersionInfoParameters(): void
{
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -365,8 +359,6 @@ final class CoreLibsDBIOTest extends TestCase
*/
public function testDbVersionInfo(string $parameter, string $expected): void
{
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -1592,8 +1584,6 @@ final class CoreLibsDBIOTest extends TestCase
string $error,
bool $run_many_times = false
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -1832,8 +1822,6 @@ final class CoreLibsDBIOTest extends TestCase
string $error,
string $insert_data
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -2002,8 +1990,6 @@ final class CoreLibsDBIOTest extends TestCase
string $error,
string $insert_data
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -3069,8 +3055,6 @@ final class CoreLibsDBIOTest extends TestCase
string $error,
string $insert_data
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -3465,7 +3449,7 @@ final class CoreLibsDBIOTest extends TestCase
$read_query,
null,
null,
- //
+ // warning: 20
true, '20', '',
//
'result', '', '',
@@ -3482,6 +3466,31 @@ final class CoreLibsDBIOTest extends TestCase
'returning_id' => false,
],
],
+ // prepare with different statement name
+ 'prepare query with same statement name, different query' => [
+ 'double_error',
+ $read_query,
+ // primary key
+ null,
+ // arguments (none)
+ null,
+ // expected return false, warning: no, error: 26
+ false, '', '26',
+ // return expected, warning, error
+ '', '', '',
+ // dummy query for second prepare with wrong query
+ $read_query . ' WHERE uid = $3',
+ [],
+ //
+ $insert_query,
+ //
+ [
+ 'pk_name' => '',
+ 'count' => 0,
+ 'query' => 'SELECT row_int, uid FROM table_with_primary_key',
+ 'returning_id' => false,
+ ],
+ ],
// insert wrong data count compared to needed (execute 23)
'wrong parmeter count' => [
'wrong_param_count',
@@ -3554,8 +3563,6 @@ final class CoreLibsDBIOTest extends TestCase
string $insert_data,
array $prepare_cursor,
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -3575,6 +3582,9 @@ final class CoreLibsDBIOTest extends TestCase
$db->dbPrepare($stm_name, $query) :
$db->dbPrepare($stm_name, $query, $pk_name);
}
+ if ($error_prepare == '26') {
+ $prepare_result = $db->dbPrepare($stm_name, $expected_data_query);
+ }
// if result type, or if forced bool
if (is_string($expected_prepare) && $expected_prepare == 'result') {
// if PHP or newer, must be Object PgSql\Result
@@ -3597,66 +3607,68 @@ final class CoreLibsDBIOTest extends TestCase
// for non fail prepare test exec
// check test result
- $execute_result = $query_data === null ?
- $db->dbExecute($stm_name) :
- $db->dbExecute($stm_name, $query_data);
- if ($expected_execute == 'result') {
- // if PHP or newer, must be Object PgSql\Result
- $this->assertIsObject(
- $execute_result
- );
- // also check that this is correct instance type
- $this->assertInstanceOf(
- 'PgSql\Result',
- $execute_result
- );
- // if this is an select use dbFetchArray to get data and test
- } else {
- $this->assertEquals(
- $expected_execute,
- $execute_result
- );
- }
- // error/warning check
- $this->subAssertErrorTest($db, $warning_execute, $error_execute);
- // now check test result if expected return is result
- if (
- $expected_execute == 'result' &&
- !empty($expected_data_query)
- ) {
- // $expected_data_query
- // $expected_data
- $rows = $db->dbReturnArray($expected_data_query);
- $this->assertEquals(
- $expected_data,
- $rows
- );
- }
- if (
- $expected_execute == 'result' &&
- $execute_result !== false &&
- empty($expected_data_query) &&
- count($expected_data)
- ) {
- // compare previously read data to compare data
- $compare_data = [];
- // read in the query data
- while (is_array($row = $db->dbFetchArray($execute_result, true))) {
- $compare_data[] = $row;
+ if (!$error_prepare) {
+ $execute_result = $query_data === null ?
+ $db->dbExecute($stm_name) :
+ $db->dbExecute($stm_name, $query_data);
+ if ($expected_execute == 'result') {
+ // if PHP or newer, must be Object PgSql\Result
+ $this->assertIsObject(
+ $execute_result
+ );
+ // also check that this is correct instance type
+ $this->assertInstanceOf(
+ 'PgSql\Result',
+ $execute_result
+ );
+ // if this is an select use dbFetchArray to get data and test
+ } else {
+ $this->assertEquals(
+ $expected_execute,
+ $execute_result
+ );
+ }
+ // error/warning check
+ $this->subAssertErrorTest($db, $warning_execute, $error_execute);
+ // now check test result if expected return is result
+ if (
+ $expected_execute == 'result' &&
+ !empty($expected_data_query)
+ ) {
+ // $expected_data_query
+ // $expected_data
+ $rows = $db->dbReturnArray($expected_data_query);
+ $this->assertEquals(
+ $expected_data,
+ $rows
+ );
+ }
+ if (
+ $expected_execute == 'result' &&
+ $execute_result !== false &&
+ empty($expected_data_query) &&
+ count($expected_data)
+ ) {
+ // compare previously read data to compare data
+ $compare_data = [];
+ // read in the query data
+ while (is_array($row = $db->dbFetchArray($execute_result, true))) {
+ $compare_data[] = $row;
+ }
+ $this->assertEquals(
+ $expected_data,
+ $compare_data
+ );
}
- $this->assertEquals(
- $expected_data,
- $compare_data
- );
- }
- // check dbGetPrepareCursorValue
- foreach (['pk_name', 'count', 'query', 'returning_id'] as $key) {
- $this->assertEquals(
- $prepare_cursor[$key],
- $db->dbGetPrepareCursorValue($stm_name, $key),
- 'Prepared cursor: ' . $key . ': failed assertion'
- );
+ // check dbGetPrepareCursorValue
+ foreach (['pk_name', 'count', 'query', 'returning_id'] as $key) {
+ $this->assertEquals(
+ $prepare_cursor[$key],
+ $db->dbGetPrepareCursorValue($stm_name, $key),
+ 'Prepared cursor: ' . $key . ': failed assertion'
+ );
+ }
}
// reset all data
@@ -3844,8 +3856,6 @@ final class CoreLibsDBIOTest extends TestCase
string $expected_get_var,
string $expected_get_db
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config[$connection],
self::$log
@@ -3910,7 +3920,10 @@ final class CoreLibsDBIOTest extends TestCase
// 'main::run::run::run::run::run::run::run::runBare::runTest::testDbErrorHandling::dbSetMaxQueryCall
'source' => "/^(include::)?main::(run::)+runBare::runTest::testDbErrorHandling::dbSetMaxQueryCall$/",
'pg_error' => '',
- 'msg' => '',
+ 'message' => '',
+ 'context' => [
+ 'max_calls' => 0
+ ]
]
],
'trigger warning' => [
@@ -3943,8 +3956,6 @@ final class CoreLibsDBIOTest extends TestCase
string $error_id,
array $expected_history
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -3970,7 +3981,7 @@ final class CoreLibsDBIOTest extends TestCase
foreach ($expected_history as $key => $value) {
// check if starts with / because this is regex (timestamp)
// if (substr($expected_2, 0, 1) == '/) {
- if (strpos($value, '/') === 0) {
+ if (!is_array($value) && strpos($value, '/') === 0) {
// this is regex
$this->assertMatchesRegularExpression(
$value,
@@ -4058,8 +4069,6 @@ final class CoreLibsDBIOTest extends TestCase
bool $expected_set_flag,
string $expected_get_encoding
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config[$connection],
self::$log
@@ -4141,8 +4150,6 @@ final class CoreLibsDBIOTest extends TestCase
?string $encoding_php,
string $text
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config[$connection],
self::$log
@@ -4272,8 +4279,6 @@ final class CoreLibsDBIOTest extends TestCase
string $table,
string $primary_key
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -4330,7 +4335,7 @@ final class CoreLibsDBIOTest extends TestCase
// NOTE if there are different INSERTS before the primary keys
// will not match anymore. Must be updated by hand
// IMPORTANT: if this is stand alone the primary key will not match and fail
- $table_with_primary_key_id = 68;
+ $table_with_primary_key_id = 70;
// 0: query + returning
// 1: params
// 1: pk name for db exec
@@ -4530,8 +4535,6 @@ final class CoreLibsDBIOTest extends TestCase
array|string|int|null $expected_ret_ext,
array $expected_ret_arr
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -4875,8 +4878,6 @@ final class CoreLibsDBIOTest extends TestCase
array $expected_col_names,
array $expected_col_types
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
@@ -5030,6 +5031,147 @@ final class CoreLibsDBIOTest extends TestCase
$db->dbClose();
}
+ // query placeholder convert
+
+ public function queryPlaceholderReplaceProvider(): array
+ {
+ // WHERE row_varchar = $1
+ return [
+ 'select, no change' => [
+ 'query' => << [],
+ 'found' => 0,
+ 'expected_query' => '',
+ 'expected_params' => [],
+ ],
+ 'select, params ?' => [
+ 'query' => << ['string a'],
+ 'found' => 1,
+ 'expected_query' => << ['string a'],
+ ],
+ 'select, params :' => [
+ 'query' => << [':row_varchar' => 'string a'],
+ 'found' => 1,
+ 'expected_query' => << ['string a'],
+ ]
+ ];
+ }
+
+ /**
+ * test query string with placeholders convert
+ *
+ * @dataProvider queryPlaceholderReplaceProvider
+ * @testdox Query replacement test [$_dataName]
+ *
+ * @param string $query
+ * @param array $params
+ * @param string $expected_query
+ * @param array $expected_params
+ * @return void
+ */
+ public function testQueryPlaceholderReplace(
+ string $query,
+ array $params,
+ int $expected_found,
+ string $expected_query,
+ array $expected_params
+ ): void {
+ $db = new \CoreLibs\DB\IO(
+ self::$db_config['valid'],
+ self::$log
+ );
+ $db->dbSetConvertPlaceholder(true);
+ //
+ if ($db->dbCheckQueryForSelect($query)) {
+ $res = $db->dbReturnRowParams($query, $params);
+ $converted = $db->dbGetPlaceholderConverted();
+ } else {
+ $db->dbExecParams($query, $params);
+ $converted = $db->dbGetPlaceholderConverted();
+ }
+ $this->assertEquals(
+ $expected_found,
+ $converted['found'],
+ 'Found not equal'
+ );
+ $this->assertEquals(
+ $expected_query,
+ $converted['query'],
+ 'Query not equal'
+ );
+ $this->assertEquals(
+ $expected_params,
+ $converted['params'],
+ 'Params not equal'
+ );
+ }
+
+ /**
+ * test exception for placeholder convert
+ * -> internally converted to error
+ *
+ * @testdox Query Replace error tests
+ *
+ * @return void
+ */
+ public function testQueryPlaceholderReplaceException(): void
+ {
+ $db = new \CoreLibs\DB\IO(
+ self::$db_config['valid'],
+ self::$log
+ );
+ $db->dbSetConvertPlaceholder(true);
+ $db->dbExecParams(
+ <<assertEquals(
+ 200,
+ $db->dbGetLastError()
+ );
+
+ // catch unset, for :names
+ $db->dbExecParams(
+ << 'a', ':bname' => 'b']
+ );
+ $this->assertEquals(
+ 210,
+ $db->dbGetLastError()
+ );
+
+ // TODO: other way around for to pdo
+ }
+
// TODO implement below checks
// - complex write sets
// dbWriteData, dbWriteDataExt
@@ -5158,8 +5300,6 @@ final class CoreLibsDBIOTest extends TestCase
string $warning_final,
string $error_final
): void {
- // self::$log->setLogLevelAll('debug', true);
- // self::$log->setLogLevelAll('print', true);
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Debug/CoreLibsDebugSupportTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Debug/CoreLibsDebugSupportTest.php
index ab74df7d..74ed67ed 100644
--- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Debug/CoreLibsDebugSupportTest.php
+++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Debug/CoreLibsDebugSupportTest.php
@@ -513,7 +513,7 @@ final class CoreLibsDebugSupportTest extends TestCase
public function testGetCallerMethodList(array $expected): void
{
$compare = Support::getCallerMethodList();
- // 10: legact
+ // 10: legacy
// 11: direct
// 12: full call
switch (count($compare)) {
@@ -571,6 +571,31 @@ final class CoreLibsDebugSupportTest extends TestCase
}
}
+ /**
+ * Undocumented function
+ *
+ * @cover ::getCallStack
+ * @testdox getCallStack check if it returns data [$_dataName]
+ *
+ * @return void
+ */
+ public function testGetCallStack(): void
+ {
+ $call_stack = Support::getCallStack();
+ // print "Get CALL: " . print_r(Support::getCallStack(), true) . "\n";
+ if ($call_stack < 8) {
+ $this->assertFalse(true, 'getCallStack too low: 8');
+ } else {
+ $this->assertTrue(true, 'getCallSteck ok');
+ }
+ // just test top entry
+ $first = array_shift($call_stack);
+ $this->assertStringEndsWith(
+ ':tests\CoreLibsDebugSupportTest->testGetCallStack',
+ $first,
+ );
+ }
+
/**
* test the lowest one (one above base)
*
diff --git a/www/vendor/egrajp/smarty-extended/.gitignore b/www/vendor/egrajp/smarty-extended/.gitignore
index 22d0d82f..7579f743 100644
--- a/www/vendor/egrajp/smarty-extended/.gitignore
+++ b/www/vendor/egrajp/smarty-extended/.gitignore
@@ -1 +1,2 @@
vendor
+composer.lock
diff --git a/www/vendor/egrajp/smarty-extended/ReadMe.md b/www/vendor/egrajp/smarty-extended/ReadMe.md
new file mode 100644
index 00000000..ded4fcec
--- /dev/null
+++ b/www/vendor/egrajp/smarty-extended/ReadMe.md
@@ -0,0 +1,46 @@
+# Composer package from Smarty Extended
+
+This is an updated package for smarty\smarty
+
+Adds:
+
+- translation block
+- label and pos for checkboxes and radio buttons
+
+For local install only
+
+## Setup from central composer
+
+Setup from gitea internal servers
+
+```sh
+composer config repositories.git.egplusww.jp.Composer composer https://git.egplusww.jp/api/packages/Composer/composer
+```
+
+Alternative setup composer local zip file repot:
+`composer config repositories.composer.egplusww.jp composer http://composer.egplusww.jp`
+
+## Install package
+
+`composer require egrajp/smarty-extended:^4.3`
+
+## How to update
+
+1) update the original composer for ^4.3
+2) copy over the src/sysplugins and all base files in src/
+3) check either function.html_checkboxes.php and function.html_options.php have changed
+4) copy src/plugins except the above two files, be sure to keep the block.t.php and function_popup*.php
+5) Create new release version as official relase number
+
+## Updated files (different from master)
+
+### New
+
+`src/plugins/block.t.php`
+`src/plugins/function_popup.php`
+`src/plugins/function_popup.init.php`
+
+### Changed
+
+`src/plugins/function.html_checkboxes.php`
+`src/plugins/function.html_options.php`
diff --git a/www/vendor/egrajp/smarty-extended/composer.json b/www/vendor/egrajp/smarty-extended/composer.json
index 13fc8762..dfc944f8 100644
--- a/www/vendor/egrajp/smarty-extended/composer.json
+++ b/www/vendor/egrajp/smarty-extended/composer.json
@@ -8,9 +8,9 @@
"homepage": "https://github.com/smarty-php/smarty/",
"license": "LGPL-3.0",
"autoload": {
- "psr-4": {
- "Smarty\\": "src/"
- }
+ "classmap": [
+ "src/"
+ ]
},
"authors": [
{
diff --git a/www/vendor/egrajp/smarty-extended/publish/.gitignore b/www/vendor/egrajp/smarty-extended/publish/.gitignore
new file mode 100644
index 00000000..81a38be6
--- /dev/null
+++ b/www/vendor/egrajp/smarty-extended/publish/.gitignore
@@ -0,0 +1 @@
+.env*
diff --git a/www/vendor/egrajp/smarty-extended/publish/last.published b/www/vendor/egrajp/smarty-extended/publish/last.published
new file mode 100644
index 00000000..eda862a9
--- /dev/null
+++ b/www/vendor/egrajp/smarty-extended/publish/last.published
@@ -0,0 +1 @@
+4.3.4
diff --git a/www/vendor/egrajp/smarty-extended/publish/package-download/.gitignore b/www/vendor/egrajp/smarty-extended/publish/package-download/.gitignore
new file mode 100644
index 00000000..c4c4ffc6
--- /dev/null
+++ b/www/vendor/egrajp/smarty-extended/publish/package-download/.gitignore
@@ -0,0 +1 @@
+*.zip
diff --git a/www/vendor/egrajp/smarty-extended/publish/publish.sh b/www/vendor/egrajp/smarty-extended/publish/publish.sh
new file mode 100755
index 00000000..7095275c
--- /dev/null
+++ b/www/vendor/egrajp/smarty-extended/publish/publish.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+
+BASE_FOLDER=$(dirname $(readlink -f $0))"/";
+PACKAGE_DOWNLOAD="${BASE_FOLDER}package-download/";
+if [ ! -d "${PACKAGE_DOWNLOAD}" ]; then
+ mkdir "${PACKAGE_DOWNLOAD}";
+fi;
+VERSION=$(git tag --list | sort -V | tail -n1 | sed -e "s/^v//");
+file_last_published="${BASE_FOLDER}last.published";
+go_flag="$1";
+
+if [ -z "${VERSION}" ]; then
+ echo "Version must be set in the form x.y.z without any leading characters";
+ exit;
+fi;
+# compare version, if different or newer, deploy
+if [ -f "${file_last_published}" ]; then
+ LAST_PUBLISHED_VERSION=$(cat ${file_last_published});
+ if $(dpkg --compare-versions "${VERSION}" le "${LAST_PUBLISHED_VERSION}"); then
+ echo "git tag version ${VERSION} is not newer than previous published version ${LAST_PUBLISHED_VERSION}";
+ exit;
+ fi;
+fi;
+
+# read in the .env.deploy file and we must have
+# GITEA_UPLOAD_FILENAME
+# GITLAB_USER
+# GITLAB_TOKEN
+# GITLAB_URL
+# GITEA_USER
+# GITEA_DEPLOY_TOKEN
+# GITEA_URL_DL
+# GITEA_URL_PUSH
+if [ ! -f "${BASE_FOLDER}.env.deploy" ]; then
+ echo "Deploy enviroment file .env.deploy is missing";
+ exit;
+fi;
+set -o allexport;
+cd ${BASE_FOLDER};
+source .env.deploy;
+cd -;
+set +o allexport;
+
+if [ "${go_flag}" != "go" ]; then
+ echo "No go flag given";
+ echo "Would publish ${VERSION}";
+ echo "[END]";
+ exit;
+fi;
+
+echo "[START]";
+# gitea
+if [ ! -z "${GITEA_UPLOAD_FILENAME}" ] &&
+ [ ! -z "${GITEA_URL_DL}" ] && [ ! -z "${GITEA_URL_PUSH}" ] &&
+ [ ! -z "${GITEA_USER}" ] && [ ! -z "${GITEA_TOKEN}" ]; then
+ curl -LJO \
+ --output-dir "${PACKAGE_DOWNLOAD}" \
+ ${GITEA_URL_DL}/v${VERSION}.zip;
+ # echo "curl -LJO \
+ # --output-dir "${PACKAGE_DOWNLOAD}" \
+ # ${GITEA_URL_DL}/v${VERSION}.zip;"
+ curl --user ${GITEA_USER}:${GITEA_TOKEN} \
+ --upload-file "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" \
+ ${GITEA_URL_PUSH}?version=${VERSION};
+ # echo "curl --user ${GITEA_USER}:${GITEA_TOKEN} \
+ # --upload-file "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" \
+ # ${GITEA_URL_PUSH}?version=${VERSION};"
+ echo "${VERSION}" > "${file_last_published}";
+else
+ echo "Missing either GITEA_UPLOAD_FILENAME, GITEA_URL_DL, GITEA_URL_PUSH, GITEA_USER or GITEA_TOKEN environment variable";
+fi;
+
+# gitlab
+if [ ! -z "${GITLAB_URL}" ] && [ ! -z "${GITLAB_DEPLOY_TOKEN}" ]; then
+ curl --data tag=v${VERSION} \
+ --header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
+ "${GITLAB_URL}";
+ curl --data branch=master \
+ --header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
+ "${GITLAB_URL}";
+ echo "${VERSION}" > "${file_last_published}";
+else
+ echo "Missing GITLAB_DEPLOY_TOKEN environment variable";
+fi;
+echo "";
+echo "[DONE]";
+
+# __END__
diff --git a/www/vendor/egrajp/smarty-extended/src/Smarty.class.php b/www/vendor/egrajp/smarty-extended/src/Smarty.class.php
index 5351b579..0a47c835 100644
--- a/www/vendor/egrajp/smarty-extended/src/Smarty.class.php
+++ b/www/vendor/egrajp/smarty-extended/src/Smarty.class.php
@@ -107,7 +107,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/**
* smarty version
*/
- const SMARTY_VERSION = '4.3.0';
+ const SMARTY_VERSION = '4.4.1';
/**
* define variable scopes
*/
diff --git a/www/vendor/egrajp/smarty-extended/src/debug.tpl b/www/vendor/egrajp/smarty-extended/src/debug.tpl
index 4f82a582..cd932566 100644
--- a/www/vendor/egrajp/smarty-extended/src/debug.tpl
+++ b/www/vendor/egrajp/smarty-extended/src/debug.tpl
@@ -167,9 +167,7 @@