Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b699d753d | ||
|
|
254a0e4802 | ||
|
|
82f35535ae | ||
|
|
c41796a478 | ||
|
|
a310fab3ee | ||
|
|
9914815285 | ||
|
|
969467fa15 | ||
|
|
f4dd78fff2 | ||
|
|
ba5e78e839 | ||
|
|
1a5ee2e16d | ||
|
|
e1d9985ec8 | ||
|
|
2316c151ac |
@@ -22,6 +22,9 @@ parameters:
|
||||
# - vendor
|
||||
# ignore errores with
|
||||
ignoreErrors:
|
||||
-
|
||||
message: '#Expression in empty\(\) is not falsy.#'
|
||||
path: %currentWorkingDirectory%/src/Language/GetLocale.php
|
||||
#- # this error is ignore because of the PHP 8.0 to 8.1 change for pg_*, only for 8.0 or lower
|
||||
# message: "#^Parameter \\#1 \\$(result|connection) of function pg_\\w+ expects resource(\\|null)?, object\\|resource(\\|bool)? given\\.$#"
|
||||
# path: %currentWorkingDirectory%/www/lib/CoreLibs/DB/SQL/PgSQL.php
|
||||
|
||||
@@ -1 +1 @@
|
||||
9.26.7
|
||||
9.29.0
|
||||
|
||||
@@ -423,14 +423,9 @@ class Login
|
||||
|
||||
// LOGOUT TARGET
|
||||
if (!isset($options['logout_target'])) {
|
||||
if (defined('LOGOUT_TARGET')) {
|
||||
trigger_error(
|
||||
'loginMainCall: LOGOUT_TARGET should not be used',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
$options['logout_target'] = LOGOUT_TARGET;
|
||||
$this->logout_target = $options['logout_target'];
|
||||
}
|
||||
// defaults to ''
|
||||
$options['logout_target'] = '';
|
||||
$this->logout_target = $options['logout_target'];
|
||||
}
|
||||
|
||||
// *** PASSWORD SETTINGS
|
||||
@@ -1560,6 +1555,7 @@ class Login
|
||||
'uid' => $unit['uid'],
|
||||
'cuuid' => $unit['cuuid'],
|
||||
'level' => $this->default_acl_list[$this->acl['unit'][$ea_cuid]]['name'] ?? -1,
|
||||
'level_number' => $this->acl['unit'][$ea_cuid],
|
||||
'default' => $unit['default'],
|
||||
'data' => $unit['data'],
|
||||
'additional_acl' => $unit['additional_acl']
|
||||
@@ -2538,7 +2534,7 @@ HTML;
|
||||
$this->login_user_id,
|
||||
-1,
|
||||
$login_user_id_changed
|
||||
);
|
||||
) ?? '';
|
||||
// flag unclean input data
|
||||
if ($login_user_id_changed > 0) {
|
||||
$this->login_user_id_unclear = true;
|
||||
|
||||
@@ -76,7 +76,7 @@ class EditBase
|
||||
);
|
||||
if ($this->form->mobile_phone) {
|
||||
echo "I am sorry, but this page cannot be viewed by a mobile phone";
|
||||
exit;
|
||||
exit(1);
|
||||
}
|
||||
// $this->log->debug('POST', $this->log->prAr($_POST));
|
||||
}
|
||||
|
||||
@@ -103,11 +103,7 @@ class Basic
|
||||
'VIDEOS', 'DOCUMENTS', 'PDFS', 'BINARIES', 'ICONS', 'UPLOADS', 'CSV', 'JS',
|
||||
'CSS', 'TABLE_ARRAYS', 'SMARTY', 'LANG', 'CACHE', 'TMP', 'LOG', 'TEMPLATES',
|
||||
'TEMPLATES_C', 'DEFAULT_LANG', 'DEFAULT_ENCODING', 'DEFAULT_HASH',
|
||||
'DEFAULT_ACL_LEVEL', 'LOGOUT_TARGET', 'PASSWORD_CHANGE', 'AJAX_REQUEST_TYPE',
|
||||
'USE_PROTOTYPE', 'USE_SCRIPTACULOUS', 'USE_JQUERY', 'PAGE_WIDTH',
|
||||
'MASTER_TEMPLATE_NAME', 'PUBLIC_SCHEMA', 'TEST_SCHEMA', 'DEV_SCHEMA',
|
||||
'LIVE_SCHEMA', 'DB_CONFIG_NAME', 'DB_CONFIG', 'TARGET', 'DEBUG',
|
||||
'SHOW_ALL_ERRORS'
|
||||
'DB_CONFIG_NAME', 'DB_CONFIG', 'TARGET'
|
||||
] as $constant
|
||||
) {
|
||||
if (!defined($constant)) {
|
||||
@@ -1028,8 +1024,12 @@ class Basic
|
||||
*/
|
||||
public function __sha1Short(string $string, bool $use_sha = false): string
|
||||
{
|
||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Create\Hash::__sha1Short()', E_USER_DEPRECATED);
|
||||
return \CoreLibs\Create\Hash::__sha1Short($string, $use_sha);
|
||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Create\Hash::sha1Short() or ::__crc32b()', E_USER_DEPRECATED);
|
||||
if ($use_sha) {
|
||||
return \CoreLibs\Create\Hash::sha1Short($string);
|
||||
} else {
|
||||
return \CoreLibs\Create\Hash::__crc32b($string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1044,8 +1044,8 @@ class Basic
|
||||
*/
|
||||
public function __hash(string $string, string $hash_type = 'adler32'): string
|
||||
{
|
||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Create\Hash::__hash()', E_USER_DEPRECATED);
|
||||
return \CoreLibs\Create\Hash::__hash($string, $hash_type);
|
||||
trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Create\Hash::hash()', E_USER_DEPRECATED);
|
||||
return \CoreLibs\Create\Hash::hash($string, $hash_type);
|
||||
}
|
||||
|
||||
// *** HASH FUNCTIONS END
|
||||
|
||||
@@ -639,16 +639,26 @@ class DateTime
|
||||
*
|
||||
* @param string $start_date valid start date (y/m/d)
|
||||
* @param string $end_date valid end date (y/m/d)
|
||||
* @param bool $return_named return array type, false (default), true for named
|
||||
* @return array<mixed> 0/overall, 1/weekday, 2/weekend
|
||||
* @param bool $return_named [default=false] return array type, false (default), true for named
|
||||
* @param bool $include_end_date [default=true] include end date in calc
|
||||
* @param bool $exclude_start_date [default=false] include end date in calc
|
||||
* @return array{0:int,1:int,2:int,3:bool}|array{overall:int,weekday:int,weekend:int,reverse:bool}
|
||||
* 0/overall, 1/weekday, 2/weekend, 3/reverse
|
||||
*/
|
||||
public static function calcDaysInterval(
|
||||
string $start_date,
|
||||
string $end_date,
|
||||
bool $return_named = false
|
||||
bool $return_named = false,
|
||||
bool $include_end_date = true,
|
||||
bool $exclude_start_date = false
|
||||
): array {
|
||||
// pos 0 all, pos 1 weekday, pos 2 weekend
|
||||
$days = [];
|
||||
$days = [
|
||||
0 => 0,
|
||||
1 => 0,
|
||||
2 => 0,
|
||||
3 => false,
|
||||
];
|
||||
// if anything invalid, return 0,0,0
|
||||
try {
|
||||
$start = new \DateTime($start_date);
|
||||
@@ -659,19 +669,30 @@ class DateTime
|
||||
'overall' => 0,
|
||||
'weekday' => 0,
|
||||
'weekend' => 0,
|
||||
'reverse' => false
|
||||
];
|
||||
} else {
|
||||
return [0, 0, 0];
|
||||
return $days;
|
||||
}
|
||||
}
|
||||
// so we include the last day too, we need to add +1 second in the time
|
||||
$end->setTime(0, 0, 1);
|
||||
// if end date before start date, only this will be filled
|
||||
$days[0] = $end->diff($start)->days;
|
||||
$days[1] = 0;
|
||||
$days[2] = 0;
|
||||
// if start is before end, switch dates and flag
|
||||
$days[3] = false;
|
||||
if ($start > $end) {
|
||||
$new_start = $end;
|
||||
$end = $start;
|
||||
$start = $new_start;
|
||||
$days[3] = true;
|
||||
}
|
||||
// get period for weekends/weekdays
|
||||
$period = new \DatePeriod($start, new \DateInterval('P1D'), $end);
|
||||
$options = 0;
|
||||
if ($include_end_date) {
|
||||
$options |= \DatePeriod::INCLUDE_END_DATE;
|
||||
}
|
||||
if ($exclude_start_date) {
|
||||
$options |= \DatePeriod::EXCLUDE_START_DATE;
|
||||
}
|
||||
$period = new \DatePeriod($start, new \DateInterval('P1D'), $end, $options);
|
||||
foreach ($period as $dt) {
|
||||
$curr = $dt->format('D');
|
||||
if ($curr == 'Sat' || $curr == 'Sun') {
|
||||
@@ -679,18 +700,80 @@ class DateTime
|
||||
} else {
|
||||
$days[1]++;
|
||||
}
|
||||
$days[0]++;
|
||||
}
|
||||
if ($return_named === true) {
|
||||
return [
|
||||
'overall' => $days[0],
|
||||
'weekday' => $days[1],
|
||||
'weekend' => $days[2],
|
||||
'reverse' => $days[3],
|
||||
];
|
||||
} else {
|
||||
return $days;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper for calcDaysInterval with numeric return only
|
||||
*
|
||||
* @param string $start_date valid start date (y/m/d)
|
||||
* @param string $end_date valid end date (y/m/d)
|
||||
* @param bool $include_end_date [default=true] include end date in calc
|
||||
* @param bool $exclude_start_date [default=false] include end date in calc
|
||||
* @return array{0:int,1:int,2:int,3:bool}
|
||||
*/
|
||||
public static function calcDaysIntervalNumIndex(
|
||||
string $start_date,
|
||||
string $end_date,
|
||||
bool $include_end_date = true,
|
||||
bool $exclude_start_date = false
|
||||
): array {
|
||||
$values = self::calcDaysInterval(
|
||||
$start_date,
|
||||
$end_date,
|
||||
false,
|
||||
$include_end_date,
|
||||
$exclude_start_date
|
||||
);
|
||||
return [
|
||||
$values[0] ?? 0,
|
||||
$values[1] ?? 0,
|
||||
$values[2] ?? 0,
|
||||
$values[3] ?? false,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper for calcDaysInterval with named return only
|
||||
*
|
||||
* @param string $start_date valid start date (y/m/d)
|
||||
* @param string $end_date valid end date (y/m/d)
|
||||
* @param bool $include_end_date [default=true] include end date in calc
|
||||
* @param bool $exclude_start_date [default=false] include end date in calc
|
||||
* @return array{overall:int,weekday:int,weekend:int,reverse:bool}
|
||||
*/
|
||||
public static function calcDaysIntervalNamedIndex(
|
||||
string $start_date,
|
||||
string $end_date,
|
||||
bool $include_end_date = true,
|
||||
bool $exclude_start_date = false
|
||||
): array {
|
||||
$values = self::calcDaysInterval(
|
||||
$start_date,
|
||||
$end_date,
|
||||
true,
|
||||
$include_end_date,
|
||||
$exclude_start_date
|
||||
);
|
||||
return [
|
||||
'overall' => $values['overall'] ?? 0,
|
||||
'weekday' => $values['weekday'] ?? 0,
|
||||
'weekend' => $values['weekend'] ?? 0,
|
||||
'reverse' => $values['reverse'] ?? false,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a weekend day (sat/sun) is in the given date range
|
||||
* Can have time too, but is not needed
|
||||
@@ -705,6 +788,13 @@ class DateTime
|
||||
): bool {
|
||||
$dd_start = new \DateTime($start_date);
|
||||
$dd_end = new \DateTime($end_date);
|
||||
// flip if start is after end
|
||||
if ($dd_start > $dd_end) {
|
||||
$new_start = $dd_end;
|
||||
$dd_end = $dd_start;
|
||||
$dd_start = $new_start;
|
||||
}
|
||||
// if start > end, flip
|
||||
if (
|
||||
// starts with a weekend
|
||||
$dd_start->format('N') >= 6 ||
|
||||
|
||||
@@ -10,9 +10,16 @@ namespace CoreLibs\Convert;
|
||||
|
||||
class Html
|
||||
{
|
||||
/** @var int */
|
||||
public const SELECTED = 0;
|
||||
/** @var int */
|
||||
public const CHECKED = 1;
|
||||
|
||||
// TODO: check for not valid htmlentites encoding
|
||||
// as of PHP 8.4: https://www.php.net/manual/en/function.htmlentities.php
|
||||
/** @#var array<string> */
|
||||
// public const VALID_HTMLENT_ENCODINGS = [];
|
||||
|
||||
/**
|
||||
* full wrapper for html entities
|
||||
*
|
||||
@@ -22,14 +29,19 @@ class Html
|
||||
* encodes in UTF-8
|
||||
* does not double encode
|
||||
*
|
||||
* @param mixed $string string to html encode
|
||||
* @param int $flags [default: ENT_QUOTES | ENT_HTML5]
|
||||
* @param mixed $string string to html encode
|
||||
* @param int $flags [default=ENT_QUOTES | ENT_HTML5]
|
||||
* @param string $encoding [default=UTF-8]
|
||||
* @return mixed if string, encoded, else as is (eg null)
|
||||
*/
|
||||
public static function htmlent(mixed $string, int $flags = ENT_QUOTES | ENT_HTML5): mixed
|
||||
{
|
||||
public static function htmlent(
|
||||
mixed $string,
|
||||
int $flags = ENT_QUOTES | ENT_HTML5,
|
||||
string $encoding = 'UTF-8'
|
||||
): mixed {
|
||||
if (is_string($string)) {
|
||||
return htmlentities($string, $flags, 'UTF-8', false);
|
||||
// if not a valid encoding this will throw a warning and use UTF-8
|
||||
return htmlentities($string, $flags, $encoding, false);
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
@@ -37,7 +49,7 @@ class Html
|
||||
/**
|
||||
* strips out all line breaks or replaced with given string
|
||||
* @param string $string string
|
||||
* @param string $replace replace character, default ' '
|
||||
* @param string $replace [default=' '] replace character
|
||||
* @return string cleaned string without any line breaks
|
||||
*/
|
||||
public static function removeLB(string $string, string $replace = ' '): string
|
||||
|
||||
@@ -10,9 +10,14 @@ namespace CoreLibs\Create;
|
||||
|
||||
class Hash
|
||||
{
|
||||
/** @var string default short hash -> deprecated use STANDARD_HASH_SHORT */
|
||||
public const DEFAULT_HASH = 'adler32';
|
||||
/** @var string default long hash (40 chars) */
|
||||
public const STANDARD_HASH_LONG = 'ripemd160';
|
||||
/** @var string default short hash (8 chars) */
|
||||
public const STANDARD_HASH_SHORT = 'adler32';
|
||||
/** @var string this is the standard hash to use hashStd and hash (64 chars) */
|
||||
public const STANDARD_HASH = 'sha256';
|
||||
|
||||
/**
|
||||
* checks php version and if >=5.2.7 it will flip the string
|
||||
@@ -20,6 +25,7 @@ class Hash
|
||||
* hash returns false
|
||||
* preg_replace fails for older php version
|
||||
* Use __hash with crc32b or hash('crc32b', ...) for correct output
|
||||
* For future short hashes use hashShort() instead
|
||||
*
|
||||
* @param string $string string to crc
|
||||
* @return string crc32b hash (old type)
|
||||
@@ -43,19 +49,31 @@ class Hash
|
||||
* replacement for __crc32b call
|
||||
*
|
||||
* @param string $string string to hash
|
||||
* @param bool $use_sha use sha instead of crc32b (default false)
|
||||
* @param bool $use_sha [default=false] use sha1 instead of crc32b
|
||||
* @return string hash of the string
|
||||
* @deprecated use __crc32b() for drop in replacement with default, or sha1Short() for use sha true
|
||||
*/
|
||||
public static function __sha1Short(string $string, bool $use_sha = false): string
|
||||
{
|
||||
if ($use_sha) {
|
||||
// return only the first 9 characters
|
||||
return substr(hash('sha1', $string), 0, 9);
|
||||
return self::sha1Short($string);
|
||||
} else {
|
||||
return self::__crc32b($string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a short sha1
|
||||
*
|
||||
* @param string $string string to hash
|
||||
* @return string hash of the string
|
||||
*/
|
||||
public static function sha1Short(string $string): string
|
||||
{
|
||||
// return only the first 9 characters
|
||||
return substr(hash('sha1', $string), 0, 9);
|
||||
}
|
||||
|
||||
/**
|
||||
* replacemend for __crc32b call (alternate)
|
||||
* defaults to adler 32
|
||||
@@ -63,34 +81,135 @@ class Hash
|
||||
* all that create 8 char long hashes
|
||||
*
|
||||
* @param string $string string to hash
|
||||
* @param string $hash_type hash type (default adler32)
|
||||
* @param string $hash_type [default=STANDARD_HASH_SHORT] hash type (default adler32)
|
||||
* @return string hash of the string
|
||||
* @deprecated use hashShort() of short hashes with adler 32 or hash() for other hash types
|
||||
*/
|
||||
public static function __hash(
|
||||
string $string,
|
||||
string $hash_type = self::DEFAULT_HASH
|
||||
string $hash_type = self::STANDARD_HASH_SHORT
|
||||
): string {
|
||||
return self::hash($string, $hash_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if hash type is valid, returns false if not
|
||||
*
|
||||
* @param string $hash_type
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidHashType(string $hash_type): bool
|
||||
{
|
||||
if (!in_array($hash_type, hash_algos())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if hash hmac type is valid, returns false if not
|
||||
*
|
||||
* @param string $hash_hmac_type
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidHashHmacType(string $hash_hmac_type): bool
|
||||
{
|
||||
if (!in_array($hash_hmac_type, hash_hmac_algos())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a hash over string if any valid hash given.
|
||||
* if no hash type set use sha256
|
||||
*
|
||||
* @param string $string string to hash
|
||||
* @param string $hash_type [default=STANDARD_HASH] hash type (default sha256)
|
||||
* @return string hash of the string
|
||||
*/
|
||||
public static function hash(
|
||||
string $string,
|
||||
string $hash_type = self::STANDARD_HASH
|
||||
): string {
|
||||
// if not empty, check if in valid list
|
||||
if (
|
||||
empty($hash_type) ||
|
||||
!in_array($hash_type, hash_algos())
|
||||
) {
|
||||
// fallback to default hash type if none set or invalid
|
||||
$hash_type = self::DEFAULT_HASH;
|
||||
// fallback to default hash type if empty or invalid
|
||||
$hash_type = self::STANDARD_HASH;
|
||||
}
|
||||
return hash($hash_type, $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function for standard long hashd
|
||||
* creates a hash mac key
|
||||
*
|
||||
* @param string $string string to hash mac
|
||||
* @param string $key key to use
|
||||
* @param string $hash_type [default=STANDARD_HASH]
|
||||
* @return string hash mac string
|
||||
*/
|
||||
public static function hashHmac(
|
||||
string $string,
|
||||
#[\SensitiveParameter]
|
||||
string $key,
|
||||
string $hash_type = self::STANDARD_HASH
|
||||
): string {
|
||||
if (
|
||||
empty($hash_type) ||
|
||||
!in_array($hash_type, hash_hmac_algos())
|
||||
) {
|
||||
// fallback to default hash type if e or invalid
|
||||
$hash_type = self::STANDARD_HASH;
|
||||
}
|
||||
return hash_hmac($hash_type, $string, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* short hash with max length of 8, uses adler32
|
||||
*
|
||||
* @param string $string string to hash
|
||||
* @return string hash of the string
|
||||
*/
|
||||
public static function hashShort(string $string): string
|
||||
{
|
||||
return hash(self::STANDARD_HASH_SHORT, $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function for standard long hash
|
||||
*
|
||||
* @param string $string String to be hashed
|
||||
* @return string Hashed string
|
||||
* @deprecated use hashLong()
|
||||
*/
|
||||
public static function __hashLong(string $string): string
|
||||
{
|
||||
return self::hashLong($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function for standard long hash, uses ripmd160
|
||||
*
|
||||
* @param string $string String to be hashed
|
||||
* @return string Hashed string
|
||||
*/
|
||||
public static function __hashLong(string $string): string
|
||||
public static function hashLong(string $string): string
|
||||
{
|
||||
return hash(self::STANDARD_HASH_LONG, $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* create standard hash basd on STANDAR_HASH, currently sha256
|
||||
*
|
||||
* @param string $string string in
|
||||
* @return string hash of the string
|
||||
*/
|
||||
public static function hashStd(string $string): string
|
||||
{
|
||||
return self::hash($string, self::STANDARD_HASH);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -500,7 +500,7 @@ class IO
|
||||
die('<!-- Cannot load db functions class for: ' . $this->db_type . ' -->');
|
||||
}
|
||||
// write to internal one, once OK
|
||||
$this->db_functions = $db_functions;
|
||||
$this->db_functions = $db_functions; /** @phan-suppress-current-line PhanPossiblyNullTypeMismatchProperty */
|
||||
|
||||
// connect to DB
|
||||
if (!$this->__connectToDB()) {
|
||||
@@ -1413,10 +1413,7 @@ class IO
|
||||
$this->pk_name_table[$table] ?
|
||||
$this->pk_name_table[$table] : 'NULL';
|
||||
}
|
||||
if (
|
||||
!preg_match(self::REGEX_RETURNING, $this->query) &&
|
||||
$this->pk_name && $this->pk_name != 'NULL'
|
||||
) {
|
||||
if (!preg_match(self::REGEX_RETURNING, $this->query) && $this->pk_name != 'NULL') {
|
||||
// check if this query has a ; at the end and remove it
|
||||
$__query = preg_replace("/(;\s*)$/", '', $this->query);
|
||||
// must be query, if preg replace failed, use query as before
|
||||
@@ -1426,7 +1423,7 @@ class IO
|
||||
} elseif (
|
||||
preg_match(self::REGEX_RETURNING, $this->query, $matches)
|
||||
) {
|
||||
if ($this->pk_name && $this->pk_name != 'NULL') {
|
||||
if ($this->pk_name != 'NULL') {
|
||||
// add the primary key if it is not in the returning set
|
||||
if (!preg_match("/$this->pk_name/", $matches[1])) {
|
||||
$this->query .= " , " . $this->pk_name;
|
||||
@@ -2946,7 +2943,7 @@ class IO
|
||||
$query_hash = $this->dbGetQueryHash($query, $params);
|
||||
// clears cache for this query
|
||||
if (empty($this->cursor_ext[$query_hash]['query'])) {
|
||||
$this->__dbError(18, context: [
|
||||
$this->__dbWarning(18, context: [
|
||||
'query' => $query,
|
||||
'params' => $params,
|
||||
'hash' => $query_hash,
|
||||
@@ -4059,7 +4056,7 @@ class IO
|
||||
*/
|
||||
public function dbGetQueryHash(string $query, array $params = []): string
|
||||
{
|
||||
return Hash::__hashLong(
|
||||
return Hash::hashLong(
|
||||
$query . (
|
||||
$params !== [] ?
|
||||
'#' . json_encode($params) : ''
|
||||
@@ -4286,6 +4283,17 @@ class IO
|
||||
return $this->field_names[$pos] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all the $ placeholders
|
||||
*
|
||||
* @param string $query
|
||||
* @return array<string>
|
||||
*/
|
||||
public function dbGetQueryParamPlaceholders(string $query): array
|
||||
{
|
||||
return $this->db_functions->__dbGetQueryParams($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a field type for a field name or pos,
|
||||
* will return false if field is not found in list
|
||||
|
||||
@@ -978,12 +978,12 @@ class PgSQL implements Interface\SqlFunctions
|
||||
}
|
||||
|
||||
/**
|
||||
* Count placeholder queries. $ only
|
||||
* Get the all the $ params, unique list
|
||||
*
|
||||
* @param string $query
|
||||
* @return int
|
||||
* @return array<string>
|
||||
*/
|
||||
public function __dbCountQueryParams(string $query): int
|
||||
public function __dbGetQueryParams(string $query): array
|
||||
{
|
||||
$matches = [];
|
||||
// regex for params: only stand alone $number allowed
|
||||
@@ -998,11 +998,22 @@ class PgSQL implements Interface\SqlFunctions
|
||||
// Matches in 1:, must be array_filtered to remove empty, count with array_unique
|
||||
// Regex located in the ConvertPlaceholder class
|
||||
preg_match_all(
|
||||
ConvertPlaceholder::REGEX_LOOKUP_PLACEHOLDERS,
|
||||
ConvertPlaceholder::REGEX_LOOKUP_NUMBERED,
|
||||
$query,
|
||||
$matches
|
||||
);
|
||||
return count(array_unique(array_filter($matches[3])));
|
||||
return array_unique(array_filter($matches[ConvertPlaceholder::MATCHING_POS]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Count placeholder queries. $ only
|
||||
*
|
||||
* @param string $query
|
||||
* @return int
|
||||
*/
|
||||
public function __dbCountQueryParams(string $query): int
|
||||
{
|
||||
return count($this->__dbGetQueryParams($query));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,76 +14,57 @@ namespace CoreLibs\DB\Support;
|
||||
|
||||
class ConvertPlaceholder
|
||||
{
|
||||
// NOTE for missing: range */+ are not iplemented in the regex below, but - is for now
|
||||
// NOTE some combinations are allowed, but the query will fail before this
|
||||
/** @var string split regex, entries before $ group */
|
||||
private const PATTERN_QUERY_SPLIT =
|
||||
'\?\?|' // UNKNOWN: double ??, is this to avoid something?
|
||||
. '[\(,]|' // for ',' and '(' mostly in INSERT or ANY()
|
||||
. '[<>=]|' // general set for <, >, = in any query with any combination
|
||||
. '\^@|' // text search for start from text with ^@
|
||||
. '\|\||' // concats two elements
|
||||
. '&&|' // array overlap
|
||||
. '\-\|\-|' // range overlap for array
|
||||
. '[^-]-{1}|' // single -, used in JSON too
|
||||
. '->|->>|#>|#>>|@>|<@|@@|@\?|\?{1}|\?\||\?&|#-|' // JSON searches, Array searchs, etc
|
||||
. 'THEN|ELSE' // command parts (CASE)
|
||||
;
|
||||
/** @var string the main regex including the pattern query split */
|
||||
private const PATTERN_ELEMENT = '(?:\'.*?\')?\s*(?:' . self::PATTERN_QUERY_SPLIT . ')\s*';
|
||||
/** @var string text block in SQL, single quited
|
||||
* Note that does not include $$..$$ strings or anything with token name or nested ones
|
||||
*/
|
||||
private const PATTERN_TEXT_BLOCK_SINGLE_QUOTE = '(?:\'(?:[^\'\\\\]|\\\\.)*\')';
|
||||
/** @var string text block in SQL, dollar quoted
|
||||
* NOTE: if this is added everything shifts by one lookup number
|
||||
*/
|
||||
private const PATTERN_TEXT_BLOCK_DOLLAR = '(?:\$(\w*)\$.*?\$\1\$)';
|
||||
/** @var string comment regex
|
||||
* anything that starts with -- and ends with a line break but any character that is not line break inbetween */
|
||||
private const PATTERN_COMMENT = '(?:\-\-[^\r\n]*?\r?\n)*\s*';
|
||||
/** @var string parts to ignore in the SQL */
|
||||
private const PATTERN_IGNORE =
|
||||
// digit -> ignore
|
||||
'\d+|'
|
||||
// other string -> ignore
|
||||
. '(?:\'.*?\')|';
|
||||
/** @var string named parameters */
|
||||
private const PATTERN_NAMED = '(:\w+)';
|
||||
/** @var string question mark parameters */
|
||||
private const PATTERN_QUESTION_MARK = '(?:(?:\?\?)?\s*(\?{1}))';
|
||||
/** @var string numbered parameters */
|
||||
* anything that starts with -- and ends with a line break but any character that is not line break inbetween
|
||||
* this is the FIRST thing in the line and will skip any further lookups */
|
||||
private const PATTERN_COMMENT = '(?:\-\-[^\r\n]*?\r?\n)';
|
||||
// below are the params lookups
|
||||
/** @var string named parameters, must start with single : */
|
||||
private const PATTERN_NAMED = '((?<!:):(?:\w+))';
|
||||
/** @var string question mark parameters, will catch any */
|
||||
private const PATTERN_QUESTION_MARK = '(\?{1})';
|
||||
/** @var string numbered parameters, can only start 1 to 9, second and further digits can be 0-9
|
||||
* This ignores the $$ ... $$ escape syntax. If we find something like this will fail
|
||||
* It is recommended to use proper string escape quiting for writing data to the DB
|
||||
*/
|
||||
private const PATTERN_NUMBERED = '(\$[1-9]{1}(?:[0-9]{1,})?)';
|
||||
// below here are full regex that will be used
|
||||
/** @var string replace regex for named (:...) entries */
|
||||
public const REGEX_REPLACE_NAMED = '/'
|
||||
. '(' . self::PATTERN_ELEMENT . ')'
|
||||
. self::PATTERN_COMMENT
|
||||
. '('
|
||||
. self::PATTERN_IGNORE
|
||||
. self::PATTERN_COMMENT . '|'
|
||||
. self::PATTERN_TEXT_BLOCK_SINGLE_QUOTE . '|'
|
||||
. self::PATTERN_TEXT_BLOCK_DOLLAR . '|'
|
||||
. self::PATTERN_NAMED
|
||||
. ')'
|
||||
. '/s';
|
||||
/** @var string replace regex for question mark (?) entries */
|
||||
public const REGEX_REPLACE_QUESTION_MARK = '/'
|
||||
. '(' . self::PATTERN_ELEMENT . ')'
|
||||
. self::PATTERN_COMMENT
|
||||
. '('
|
||||
. self::PATTERN_IGNORE
|
||||
. self::PATTERN_COMMENT . '|'
|
||||
. self::PATTERN_TEXT_BLOCK_SINGLE_QUOTE . '|'
|
||||
. self::PATTERN_TEXT_BLOCK_DOLLAR . '|'
|
||||
. self::PATTERN_QUESTION_MARK
|
||||
. ')'
|
||||
. '/s';
|
||||
/** @var string replace regex for numbered ($n) entries */
|
||||
public const REGEX_REPLACE_NUMBERED = '/'
|
||||
. '(' . self::PATTERN_ELEMENT . ')'
|
||||
. self::PATTERN_COMMENT
|
||||
. '('
|
||||
. self::PATTERN_IGNORE
|
||||
. self::PATTERN_COMMENT . '|'
|
||||
. self::PATTERN_TEXT_BLOCK_SINGLE_QUOTE . '|'
|
||||
. self::PATTERN_TEXT_BLOCK_DOLLAR . '|'
|
||||
. self::PATTERN_NUMBERED
|
||||
. ')'
|
||||
. '/s';
|
||||
/** @var string the main lookup query for all placeholders */
|
||||
public const REGEX_LOOKUP_PLACEHOLDERS = '/'
|
||||
// prefix string part, must match towards
|
||||
// seperator for ( = , ? - [and json/jsonb in pg doc section 9.15]
|
||||
. self::PATTERN_ELEMENT
|
||||
. self::PATTERN_COMMENT
|
||||
. self::PATTERN_COMMENT . '|'
|
||||
. self::PATTERN_TEXT_BLOCK_SINGLE_QUOTE . '|'
|
||||
. self::PATTERN_TEXT_BLOCK_DOLLAR . '|'
|
||||
// match for replace part
|
||||
. '(?:'
|
||||
// ignore parts
|
||||
. self::PATTERN_IGNORE
|
||||
// :name named part (PDO) [1]
|
||||
. self::PATTERN_NAMED . '|'
|
||||
// ? question mark part (PDO) [2]
|
||||
@@ -94,6 +75,26 @@ class ConvertPlaceholder
|
||||
. ')'
|
||||
// single line -> add line break to matches in "."
|
||||
. '/s';
|
||||
/** @var string lookup for only numbered placeholders */
|
||||
public const REGEX_LOOKUP_NUMBERED = '/'
|
||||
. self::PATTERN_COMMENT . '|'
|
||||
. self::PATTERN_TEXT_BLOCK_SINGLE_QUOTE . '|'
|
||||
. self::PATTERN_TEXT_BLOCK_DOLLAR . '|'
|
||||
// match for replace part
|
||||
. '(?:'
|
||||
// $n numbered part (\PG php) [1]
|
||||
. self::PATTERN_NUMBERED
|
||||
// end match
|
||||
. ')'
|
||||
. '/s';
|
||||
/** @var int position for regex in full placeholder lookup: named */
|
||||
public const LOOOKUP_NAMED_POS = 2;
|
||||
/** @var int position for regex in full placeholder lookup: question mark */
|
||||
public const LOOOKUP_QUESTION_MARK_POS = 3;
|
||||
/** @var int position for regex in full placeholder lookup: numbered */
|
||||
public const LOOOKUP_NUMBERED_POS = 4;
|
||||
/** @var int matches position for replacement and single lookup */
|
||||
public const MATCHING_POS = 2;
|
||||
|
||||
/**
|
||||
* Convert PDO type query with placeholders to \PG style and vica versa
|
||||
@@ -132,11 +133,12 @@ class ConvertPlaceholder
|
||||
$found = -1;
|
||||
}
|
||||
/** @var array<string> 1: named */
|
||||
$named_matches = array_filter($matches[1]);
|
||||
$named_matches = array_filter($matches[self::LOOOKUP_NAMED_POS]);
|
||||
/** @var array<string> 2: open ? */
|
||||
$qmark_matches = array_filter($matches[2]);
|
||||
$qmark_matches = array_filter($matches[self::LOOOKUP_QUESTION_MARK_POS]);
|
||||
/** @var array<string> 3: $n matches */
|
||||
$numbered_matches = array_filter($matches[3]);
|
||||
$numbered_matches = array_filter($matches[self::LOOOKUP_NUMBERED_POS]);
|
||||
// print "**MATCHES**: <pre>" . print_r($matches, true) . "</pre>";
|
||||
// count matches
|
||||
$count_named = count(array_unique($named_matches));
|
||||
$count_qmark = count($qmark_matches);
|
||||
@@ -235,38 +237,37 @@ class ConvertPlaceholder
|
||||
$empty_params = $converted_placeholders['original']['empty_params'];
|
||||
switch ($converted_placeholders['type']) {
|
||||
case 'named':
|
||||
// 0: full
|
||||
// 0: full
|
||||
// 1: pre part
|
||||
// 2: keep part UNLESS '3' is set
|
||||
// 3: replace part :named
|
||||
// 1: replace part :named
|
||||
$pos = 0;
|
||||
$query_new = preg_replace_callback(
|
||||
self::REGEX_REPLACE_NAMED,
|
||||
function ($matches) use (&$pos, &$params_new, &$params_lookup, $params, $empty_params) {
|
||||
// only count up if $match[3] is not yet in lookup table
|
||||
if (!empty($matches[3]) && empty($params_lookup[$matches[3]])) {
|
||||
if (!isset($matches[self::MATCHING_POS])) {
|
||||
throw new \RuntimeException(
|
||||
'Cannot lookup ' . self::MATCHING_POS . ' in matches list',
|
||||
209
|
||||
);
|
||||
}
|
||||
$match = $matches[self::MATCHING_POS];
|
||||
// only count up if $match[1] is not yet in lookup table
|
||||
if (empty($params_lookup[$match])) {
|
||||
$pos++;
|
||||
$params_lookup[$matches[3]] = '$' . $pos;
|
||||
$params_lookup[$match] = '$' . $pos;
|
||||
// skip params setup if param list is empty
|
||||
if (!$empty_params) {
|
||||
$params_new[] = $params[$matches[3]] ??
|
||||
$params_new[] = $params[$match] ??
|
||||
throw new \RuntimeException(
|
||||
'Cannot lookup ' . $matches[3] . ' in params list',
|
||||
'Cannot lookup ' . $match . ' 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
|
||||
)
|
||||
);
|
||||
return $params_lookup[$match] ??
|
||||
throw new \RuntimeException(
|
||||
'Cannot lookup ' . $match . ' in params lookup list',
|
||||
211
|
||||
);
|
||||
},
|
||||
$converted_placeholders['original']['query']
|
||||
);
|
||||
@@ -276,61 +277,61 @@ class ConvertPlaceholder
|
||||
// order and data stays the same
|
||||
$params_new = $params ?? [];
|
||||
}
|
||||
// 0: full
|
||||
// 1: pre part
|
||||
// 2: keep part UNLESS '3' is set
|
||||
// 3: replace part ?
|
||||
// 1: replace part ?
|
||||
$pos = 0;
|
||||
$query_new = preg_replace_callback(
|
||||
self::REGEX_REPLACE_QUESTION_MARK,
|
||||
function ($matches) use (&$pos, &$params_lookup) {
|
||||
if (!isset($matches[self::MATCHING_POS])) {
|
||||
throw new \RuntimeException(
|
||||
'Cannot lookup ' . self::MATCHING_POS . ' in matches list',
|
||||
229
|
||||
);
|
||||
}
|
||||
$match = $matches[self::MATCHING_POS];
|
||||
// only count pos up for actual replacements we will do
|
||||
if (!empty($matches[3])) {
|
||||
if (!empty($match)) {
|
||||
$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
|
||||
);
|
||||
return '$' . $pos;
|
||||
},
|
||||
$converted_placeholders['original']['query']
|
||||
);
|
||||
break;
|
||||
case 'numbered':
|
||||
// 0: full
|
||||
// 1: pre part
|
||||
// 2: keep part UNLESS '3' is set
|
||||
// 3: replace part $numbered
|
||||
// 1: replace part $numbered
|
||||
$pos = 0;
|
||||
$query_new = preg_replace_callback(
|
||||
self::REGEX_REPLACE_NUMBERED,
|
||||
function ($matches) use (&$pos, &$params_new, &$params_lookup, $params, $empty_params) {
|
||||
// only count up if $match[3] is not yet in lookup table
|
||||
if (!empty($matches[3]) && empty($params_lookup[$matches[3]])) {
|
||||
if (!isset($matches[self::MATCHING_POS])) {
|
||||
throw new \RuntimeException(
|
||||
'Cannot lookup ' . self::MATCHING_POS . ' in matches list',
|
||||
239
|
||||
);
|
||||
}
|
||||
$match = $matches[self::MATCHING_POS];
|
||||
// only count up if $match[1] is not yet in lookup table
|
||||
if (empty($params_lookup[$match])) {
|
||||
$pos++;
|
||||
$params_lookup[$matches[3]] = ':' . $pos . '_named';
|
||||
$params_lookup[$match] = ':' . $pos . '_named';
|
||||
// skip params setup if param list is empty
|
||||
if (!$empty_params) {
|
||||
$params_new[] = $params[($pos - 1)] ??
|
||||
throw new \RuntimeException(
|
||||
'Cannot lookup ' . ($pos - 1) . ' in params list',
|
||||
220
|
||||
230
|
||||
);
|
||||
}
|
||||
}
|
||||
// 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
|
||||
)
|
||||
);
|
||||
return $params_lookup[$match] ??
|
||||
throw new \RuntimeException(
|
||||
'Cannot lookup ' . $match . ' in params lookup list',
|
||||
231
|
||||
);
|
||||
},
|
||||
$converted_placeholders['original']['query']
|
||||
);
|
||||
|
||||
@@ -50,7 +50,6 @@ class GetLocale
|
||||
$locale = defined('SITE_LOCALE') && !empty(SITE_LOCALE) ?
|
||||
SITE_LOCALE :
|
||||
// else parse from default, if not 'en'
|
||||
/** @phpstan-ignore-next-line DEFAULT_LOCALE could be empty */
|
||||
(defined('DEFAULT_LOCALE') && !empty(DEFAULT_LOCALE) ?
|
||||
DEFAULT_LOCALE : 'en');
|
||||
}
|
||||
@@ -97,8 +96,7 @@ class GetLocale
|
||||
$encoding = defined('SITE_ENCODING') && !empty(SITE_ENCODING) ?
|
||||
SITE_ENCODING :
|
||||
// or default encoding, if not 'UTF-8'
|
||||
/** @phpstan-ignore-next-line DEFAULT_LOCALE could be empty */
|
||||
(defined('DEFAULT_ENCODING') && !empty(DEFAULT_ENCODING) ?
|
||||
(defined('DEFAULT_ENCODING') ?
|
||||
DEFAULT_ENCODING : 'UTF-8');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,9 +418,7 @@ class ProgressBar
|
||||
// if this is percent, we ignore anything, it is auto positioned
|
||||
if ($this->label[$name]['type'] != 'percent') {
|
||||
foreach (['top', 'left', 'width', 'height'] as $pos_name) {
|
||||
if ($$pos_name !== false) {
|
||||
$this->label[$name][$pos_name] = intval($$pos_name);
|
||||
}
|
||||
$this->label[$name][$pos_name] = intval($$pos_name);
|
||||
}
|
||||
|
||||
if ($align != '') {
|
||||
|
||||
@@ -183,8 +183,9 @@ list($HOST_NAME) = array_pad(explode(':', $_SERVER['HTTP_HOST'], 2), 2, null);
|
||||
define('HOST_NAME', $HOST_NAME);
|
||||
// BAIL ON MISSING MASTER SITE CONFIG
|
||||
if (!isset($SITE_CONFIG[HOST_NAME]['location'])) {
|
||||
echo 'Missing SITE_CONFIG entry for: "' . HOST_NAME . '". Contact Administrator';
|
||||
exit;
|
||||
throw new \InvalidArgumentException(
|
||||
'Missing SITE_CONFIG entry for: "' . HOST_NAME . '". Contact Administrator'
|
||||
);
|
||||
}
|
||||
// BAIL ON MISSING DB CONFIG:
|
||||
// we have either no db selction for this host but have db config entries
|
||||
@@ -200,8 +201,9 @@ if (
|
||||
empty($DB_CONFIG[$SITE_CONFIG[HOST_NAME]['db_host']]))
|
||||
)
|
||||
) {
|
||||
echo 'No matching DB config found for: "' . HOST_NAME . '". Contact Administrator';
|
||||
exit;
|
||||
throw new \InvalidArgumentException(
|
||||
'No matching DB config found for: "' . HOST_NAME . '". Contact Administrator'
|
||||
);
|
||||
}
|
||||
// set SSL on
|
||||
$is_secure = false;
|
||||
|
||||
@@ -48,7 +48,7 @@ header("Content-Type: application/json; charset=UTF-8");
|
||||
if (!empty($http_headers['HTTP_AUTHORIZATION']) && !empty($http_headers['HTTP_RUNAUTHTEST'])) {
|
||||
header("HTTP/1.1 401 Unauthorized");
|
||||
print buildContent($http_headers, '{"code": 401, "content": {"Error": "Not Authorized"}}');
|
||||
exit;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// if server request type is get set file_get to null -> no body
|
||||
@@ -57,7 +57,7 @@ if ($_SERVER['REQUEST_METHOD'] == "GET") {
|
||||
} elseif (($file_get = file_get_contents('php://input')) === false) {
|
||||
header("HTTP/1.1 404 Not Found");
|
||||
print buildContent($http_headers, '{"code": 404, "content": {"Error": "file_get_contents failed"}}');
|
||||
exit;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
print buildContent($http_headers, $file_get);
|
||||
|
||||
@@ -152,7 +152,6 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
// TARGET
|
||||
define('TARGET', 'test');
|
||||
// LOGIN DB SCHEMA
|
||||
// define('LOGIN_DB_SCHEMA', '');
|
||||
|
||||
// SHOULD SET
|
||||
// DEFAULT_ACL_LEVEL (d80)
|
||||
|
||||
@@ -926,48 +926,114 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
|
||||
public function daysIntervalProvider(): array
|
||||
{
|
||||
return [
|
||||
'valid interval /, not named array' => [
|
||||
'2020/1/1',
|
||||
'2020/1/30',
|
||||
false,
|
||||
[29, 22, 8],
|
||||
// normal and format tests
|
||||
'valid interval / not named array' => [
|
||||
'input_a' => '2020/1/1',
|
||||
'input_b' => '2020/1/30',
|
||||
'return_named' => false, // return_named
|
||||
'include_end_date' => true, // include_end_date
|
||||
'exclude_start_date' => false, // exclude_start_date
|
||||
'expected' => [30, 22, 8, false],
|
||||
],
|
||||
'valid interval /, named array' => [
|
||||
'2020/1/1',
|
||||
'2020/1/30',
|
||||
true,
|
||||
['overall' => 29, 'weekday' => 22, 'weekend' => 8],
|
||||
'valid interval / named array' => [
|
||||
'input_a' => '2020/1/1',
|
||||
'input_b' => '2020/1/30',
|
||||
'return_named' => true,
|
||||
'include_end_date' => true,
|
||||
'exclude_start_date' => false,
|
||||
'expected' => ['overall' => 30, 'weekday' => 22, 'weekend' => 8, 'reverse' => false],
|
||||
],
|
||||
'valid interval -' => [
|
||||
'2020-1-1',
|
||||
'2020-1-30',
|
||||
false,
|
||||
[29, 22, 8],
|
||||
],
|
||||
'valid interval switched' => [
|
||||
'2020/1/30',
|
||||
'2020/1/1',
|
||||
false,
|
||||
[28, 0, 0],
|
||||
'valid interval with "-"' => [
|
||||
'input_a' => '2020-1-1',
|
||||
'input_b' => '2020-1-30',
|
||||
'return_named' => false,
|
||||
'include_end_date' => true,
|
||||
'exclude_start_date' => false,
|
||||
'expected' => [30, 22, 8, false],
|
||||
],
|
||||
'valid interval with time' => [
|
||||
'2020/1/1 12:12:12',
|
||||
'2020/1/30 13:13:13',
|
||||
false,
|
||||
[28, 21, 8],
|
||||
'input_a' => '2020/1/1 12:12:12',
|
||||
'input_b' => '2020/1/30 13:13:13',
|
||||
'return_named' => false,
|
||||
'include_end_date' => true,
|
||||
'exclude_start_date' => false,
|
||||
'expected' => [30, 22, 8, false],
|
||||
],
|
||||
// invalid
|
||||
'invalid dates' => [
|
||||
'abc',
|
||||
'xyz',
|
||||
false,
|
||||
[0, 0, 0]
|
||||
'input_a' => 'abc',
|
||||
'input_b' => 'xyz',
|
||||
'return_named' => false,
|
||||
'include_end_date' => true,
|
||||
'exclude_start_date' => false,
|
||||
'expected' => [0, 0, 0, false]
|
||||
],
|
||||
// this test will take a long imte
|
||||
// this test will take a long time
|
||||
'out of bound dates' => [
|
||||
'1900-1-1',
|
||||
'9999-12-31',
|
||||
false,
|
||||
[2958463,2113189,845274],
|
||||
'input_a' => '1900-1-1',
|
||||
'input_b' => '9999-12-31',
|
||||
'return_named' => false,
|
||||
'include_end_date' => true,
|
||||
'exclude_start_date' => false,
|
||||
'expected' => [2958463, 2113189, 845274, false],
|
||||
],
|
||||
// tests for include/exclude
|
||||
'exclude end date' => [
|
||||
'input_b' => '2020/1/1',
|
||||
'input_a' => '2020/1/30',
|
||||
'return_named' => false,
|
||||
'include_end_date' => false,
|
||||
'exclude_start_date' => false,
|
||||
'expected' => [29, 21, 8, false],
|
||||
],
|
||||
'exclude start date' => [
|
||||
'input_b' => '2020/1/1',
|
||||
'input_a' => '2020/1/30',
|
||||
'return_named' => false,
|
||||
'include_end_date' => true,
|
||||
'exclude_start_date' => true,
|
||||
'expected' => [29, 21, 8, false],
|
||||
],
|
||||
'exclude start and end date' => [
|
||||
'input_b' => '2020/1/1',
|
||||
'input_a' => '2020/1/30',
|
||||
'return_named' => false,
|
||||
'include_end_date' => false,
|
||||
'exclude_start_date' => true,
|
||||
'expected' => [28, 20, 8, false],
|
||||
],
|
||||
// reverse
|
||||
'reverse: valid interval' => [
|
||||
'input_a' => '2020/1/30',
|
||||
'input_b' => '2020/1/1',
|
||||
'return_named' => false,
|
||||
'include_end_date' => true,
|
||||
'exclude_start_date' => false,
|
||||
'expected' => [30, 22, 8, true],
|
||||
],
|
||||
'reverse: exclude end date' => [
|
||||
'input_a' => '2020/1/30',
|
||||
'input_b' => '2020/1/1',
|
||||
'return_named' => false,
|
||||
'include_end_date' => false,
|
||||
'exclude_start_date' => false,
|
||||
'expected' => [29, 21, 8, true],
|
||||
],
|
||||
'reverse: exclude start date' => [
|
||||
'input_a' => '2020/1/30',
|
||||
'input_b' => '2020/1/1',
|
||||
'return_named' => false,
|
||||
'include_end_date' => true,
|
||||
'exclude_start_date' => true,
|
||||
'expected' => [29, 21, 8, true],
|
||||
],
|
||||
'reverse: exclude start and end date' => [
|
||||
'input_a' => '2020/1/30',
|
||||
'input_b' => '2020/1/1',
|
||||
'return_named' => false,
|
||||
'include_end_date' => false,
|
||||
'exclude_start_date' => true,
|
||||
'expected' => [28, 20, 8, true],
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -982,20 +1048,52 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
|
||||
*
|
||||
* @param string $input_a
|
||||
* @param string $input_b
|
||||
* @param bool $flag
|
||||
* @param array $expected
|
||||
* @param bool $return_named
|
||||
* @param array $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testCalcDaysInterval(
|
||||
string $input_a,
|
||||
string $input_b,
|
||||
bool $flag,
|
||||
bool $return_named,
|
||||
bool $include_end_date,
|
||||
bool $exclude_start_date,
|
||||
$expected
|
||||
): void {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Combined\DateTime::calcDaysInterval($input_a, $input_b, $flag)
|
||||
\CoreLibs\Combined\DateTime::calcDaysInterval(
|
||||
$input_a,
|
||||
$input_b,
|
||||
return_named:$return_named,
|
||||
include_end_date:$include_end_date,
|
||||
exclude_start_date:$exclude_start_date
|
||||
),
|
||||
'call calcDaysInterval'
|
||||
);
|
||||
if ($return_named) {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Combined\DateTime::calcDaysIntervalNamedIndex(
|
||||
$input_a,
|
||||
$input_b,
|
||||
include_end_date:$include_end_date,
|
||||
exclude_start_date:$exclude_start_date
|
||||
),
|
||||
'call calcDaysIntervalNamedIndex'
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Combined\DateTime::calcDaysIntervalNumIndex(
|
||||
$input_a,
|
||||
$input_b,
|
||||
include_end_date:$include_end_date,
|
||||
exclude_start_date:$exclude_start_date
|
||||
),
|
||||
'call calcDaysIntervalNamedIndex'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1187,7 +1285,38 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
|
||||
'2023-07-03',
|
||||
'2023-07-27',
|
||||
true
|
||||
]
|
||||
],
|
||||
// reverse
|
||||
'reverse: no weekend' => [
|
||||
'2023-07-04',
|
||||
'2023-07-03',
|
||||
false
|
||||
],
|
||||
'reverse: start weekend sat' => [
|
||||
'2023-07-04',
|
||||
'2023-07-01',
|
||||
true
|
||||
],
|
||||
'reverse: start weekend sun' => [
|
||||
'2023-07-04',
|
||||
'2023-07-02',
|
||||
true
|
||||
],
|
||||
'reverse: end weekend sat' => [
|
||||
'2023-07-08',
|
||||
'2023-07-03',
|
||||
true
|
||||
],
|
||||
'reverse: end weekend sun' => [
|
||||
'2023-07-09',
|
||||
'2023-07-03',
|
||||
true
|
||||
],
|
||||
'reverse: long period > 6 days' => [
|
||||
'2023-07-27',
|
||||
'2023-07-03',
|
||||
true
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ final class CoreLibsConvertByteTest extends TestCase
|
||||
4 => '1.00 KB',
|
||||
5 => '1.02KiB',
|
||||
],
|
||||
'invalud string number' => [
|
||||
'invalid string number' => [
|
||||
0 => '1024 MB',
|
||||
1 => '1024 MB',
|
||||
2 => '1024 MB',
|
||||
|
||||
@@ -21,8 +21,10 @@ final class CoreLibsCreateHashTest extends TestCase
|
||||
public function hashData(): array
|
||||
{
|
||||
return [
|
||||
'any string' => [
|
||||
'hash tests' => [
|
||||
// this is the string
|
||||
'text' => 'Some String Text',
|
||||
// hash list special
|
||||
'crc32b_reverse' => 'c5c21d91', // crc32b (in revere)
|
||||
'sha1Short' => '4d2bc9ba0', // sha1Short
|
||||
// via hash
|
||||
@@ -31,6 +33,8 @@ final class CoreLibsCreateHashTest extends TestCase
|
||||
'fnv132' => '9df444f9', // hash: fnv132
|
||||
'fnv1a32' => '2c5f91b9', // hash: fnv1a32
|
||||
'joaat' => '50dab846', // hash: joaat
|
||||
'ripemd160' => 'aeae3f041b20136451519edd9361570909300342', // hash: ripemd160,
|
||||
'sha256' => '9055080e022f224fa835929b80582b3c71c672206fa3a49a87412c25d9d42ceb', // hash: sha256
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -81,7 +85,7 @@ final class CoreLibsCreateHashTest extends TestCase
|
||||
{
|
||||
$list = [];
|
||||
foreach ($this->hashData() as $name => $values) {
|
||||
foreach ([null, 'crc32b', 'adler32', 'fnv132', 'fnv1a32', 'joaat'] as $_hash_type) {
|
||||
foreach ([null, 'crc32b', 'adler32', 'fnv132', 'fnv1a32', 'joaat', 'ripemd160', 'sha256'] as $_hash_type) {
|
||||
// default value test
|
||||
if ($_hash_type === null) {
|
||||
$hash_type = \CoreLibs\Create\Hash::STANDARD_HASH_SHORT;
|
||||
@@ -114,6 +118,22 @@ final class CoreLibsCreateHashTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function hashStandardProvider(): array
|
||||
{
|
||||
$hash_source = 'Some String Text';
|
||||
return [
|
||||
'Long Hash check: ' . \CoreLibs\Create\Hash::STANDARD_HASH => [
|
||||
$hash_source,
|
||||
hash(\CoreLibs\Create\Hash::STANDARD_HASH, $hash_source)
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
@@ -136,9 +156,13 @@ final class CoreLibsCreateHashTest extends TestCase
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* phpcs:disable Generic.Files.LineLength
|
||||
* @covers ::__sha1Short
|
||||
* @covers ::__crc32b
|
||||
* @covers ::sha1Short
|
||||
* @dataProvider sha1ShortProvider
|
||||
* @testdox __sha1Short $input will be $expected (crc32b) and $expected_sha1 (sha1 short) [$_dataName]
|
||||
* @testdox __sha1Short/__crc32b/sha1short $input will be $expected (crc32b) and $expected_sha1 (sha1 short) [$_dataName]
|
||||
* phpcs:enable Generic.Files.LineLength
|
||||
*
|
||||
* @param string $input
|
||||
* @param string $expected
|
||||
@@ -149,16 +173,29 @@ final class CoreLibsCreateHashTest extends TestCase
|
||||
// uses crc32b
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::__sha1Short($input)
|
||||
\CoreLibs\Create\Hash::__sha1Short($input),
|
||||
'__sha1Short depreacted'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::__sha1Short($input, false)
|
||||
\CoreLibs\Create\Hash::__sha1Short($input, false),
|
||||
'__sha1Short (false) depreacted'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::__crc32b($input),
|
||||
'__crc32b'
|
||||
);
|
||||
// sha1 type
|
||||
$this->assertEquals(
|
||||
$expected_sha1,
|
||||
\CoreLibs\Create\Hash::__sha1Short($input, true)
|
||||
\CoreLibs\Create\Hash::__sha1Short($input, true),
|
||||
'__sha1Short (true) depreacted'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected_sha1,
|
||||
\CoreLibs\Create\Hash::sha1Short($input),
|
||||
'sha1Short'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -166,8 +203,10 @@ final class CoreLibsCreateHashTest extends TestCase
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::__hash
|
||||
* @covers ::hashShort
|
||||
* @covers ::hashShort
|
||||
* @dataProvider hashProvider
|
||||
* @testdox __hash $input with $hash_type will be $expected [$_dataName]
|
||||
* @testdox __hash/hashShort/hash $input with $hash_type will be $expected [$_dataName]
|
||||
*
|
||||
* @param string $input
|
||||
* @param string|null $hash_type
|
||||
@@ -179,12 +218,24 @@ final class CoreLibsCreateHashTest extends TestCase
|
||||
if ($hash_type === null) {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::__hash($input)
|
||||
\CoreLibs\Create\Hash::__hash($input),
|
||||
'__hash'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::hashShort($input),
|
||||
'hashShort'
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::__hash($input, $hash_type)
|
||||
\CoreLibs\Create\Hash::__hash($input, $hash_type),
|
||||
'__hash with hash type'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::hash($input, $hash_type),
|
||||
'hash with hash type'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -193,8 +244,9 @@ final class CoreLibsCreateHashTest extends TestCase
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::__hashLong
|
||||
* @covers ::hashLong
|
||||
* @dataProvider hashLongProvider
|
||||
* @testdox __hashLong $input will be $expected [$_dataName]
|
||||
* @testdox __hashLong/hashLong $input will be $expected [$_dataName]
|
||||
*
|
||||
* @param string $input
|
||||
* @param string $expected
|
||||
@@ -206,6 +258,168 @@ final class CoreLibsCreateHashTest extends TestCase
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::__hashLong($input)
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::hashLong($input)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::hash
|
||||
* @covers ::hashStd
|
||||
* @dataProvider hashStandardProvider
|
||||
* @testdox hash/hashStd $input will be $expected [$_dataName]
|
||||
*
|
||||
* @param string $input
|
||||
* @param string $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testHashStandard(string $input, string $expected): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::hashStd($input)
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::hash($input)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::hash
|
||||
* @testdox hash with invalid type
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInvalidHashType(): void
|
||||
{
|
||||
$hash_source = 'Some String Text';
|
||||
$expected = hash(\CoreLibs\Create\Hash::STANDARD_HASH, $hash_source);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::hash($hash_source, 'DOES_NOT_EXIST')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: this only tests default sha256
|
||||
*
|
||||
* @covers ::hashHmac
|
||||
* @testdox hash hmac test
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testHashMac(): void
|
||||
{
|
||||
$hash_key = 'FIX KEY';
|
||||
$hash_source = 'Some String Text';
|
||||
$expected = '16479b3ef6fa44e1cdd8b2dcfaadf314d1a7763635e8738f1e7996d714d9b6bf';
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::hashHmac($hash_source, $hash_key)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::hashHmac
|
||||
* @testdox hash hmac with invalid type
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInvalidHashMacType(): void
|
||||
{
|
||||
$hash_key = 'FIX KEY';
|
||||
$hash_source = 'Some String Text';
|
||||
$expected = hash_hmac(\CoreLibs\Create\Hash::STANDARD_HASH, $hash_source, $hash_key);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\CoreLibs\Create\Hash::hashHmac($hash_source, $hash_key, 'DOES_NOT_EXIST')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public function providerHashTypes(): array
|
||||
{
|
||||
return [
|
||||
'Hash crc32b' => [
|
||||
'crc32b',
|
||||
true,
|
||||
false,
|
||||
],
|
||||
'Hash adler32' => [
|
||||
'adler32',
|
||||
true,
|
||||
false,
|
||||
],
|
||||
'HAsh fnv132' => [
|
||||
'fnv132',
|
||||
true,
|
||||
false,
|
||||
],
|
||||
'Hash fnv1a32' => [
|
||||
'fnv1a32',
|
||||
true,
|
||||
false,
|
||||
],
|
||||
'Hash: joaat' => [
|
||||
'joaat',
|
||||
true,
|
||||
false,
|
||||
],
|
||||
'Hash: ripemd160' => [
|
||||
'ripemd160',
|
||||
true,
|
||||
true,
|
||||
],
|
||||
'Hash: sha256' => [
|
||||
'sha256',
|
||||
true,
|
||||
true,
|
||||
],
|
||||
'Hash: invalid' => [
|
||||
'invalid',
|
||||
false,
|
||||
false
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::isValidHashType
|
||||
* @covers ::isValidHashHmacType
|
||||
* @dataProvider providerHashTypes
|
||||
* @testdox check if $hash_type is valid for hash $hash_ok and hash hmac $hash_hmac_ok [$_dataName]
|
||||
*
|
||||
* @param string $hash_type
|
||||
* @param bool $hash_ok
|
||||
* @param bool $hash_hmac_ok
|
||||
* @return void
|
||||
*/
|
||||
public function testIsValidHashAndHashHmacTypes(string $hash_type, bool $hash_ok, bool $hash_hmac_ok): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
$hash_ok,
|
||||
\CoreLibs\Create\Hash::isValidHashType($hash_type),
|
||||
'hash valid'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$hash_hmac_ok,
|
||||
\CoreLibs\Create\Hash::isValidHashHmacType($hash_type),
|
||||
'hash hmac valid'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
}
|
||||
// check if they already exist, drop them
|
||||
if ($db->dbShowTableMetaData('table_with_primary_key') !== false) {
|
||||
$db->dbExec("CREATE EXTENSION IF NOT EXISTS pgcrypto");
|
||||
$db->dbExec("DROP TABLE table_with_primary_key");
|
||||
$db->dbExec("DROP TABLE table_without_primary_key");
|
||||
$db->dbExec("DROP TABLE test_meta");
|
||||
@@ -4744,7 +4745,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
$res = $db->dbReturnRowParams($query_select, ['CONVERT_TYPE_TEST']);
|
||||
// all hast to be string
|
||||
foreach ($res as $key => $value) {
|
||||
$this->assertIsString($value, 'Aseert string for column: ' . $key);
|
||||
$this->assertIsString($value, 'Assert string for column: ' . $key);
|
||||
}
|
||||
// convert base only
|
||||
$db->dbSetConvertFlag(Convert::on);
|
||||
@@ -4757,10 +4758,10 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
}
|
||||
switch ($type_layout[$name]) {
|
||||
case 'int':
|
||||
$this->assertIsInt($value, 'Aseert int for column: ' . $key . '/' . $name);
|
||||
$this->assertIsInt($value, 'Assert int for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
default:
|
||||
$this->assertIsString($value, 'Aseert string for column: ' . $key . '/' . $name);
|
||||
$this->assertIsString($value, 'Assert string for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -4774,13 +4775,13 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
}
|
||||
switch ($type_layout[$name]) {
|
||||
case 'int':
|
||||
$this->assertIsInt($value, 'Aseert int for column: ' . $key . '/' . $name);
|
||||
$this->assertIsInt($value, 'Assert int for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'float':
|
||||
$this->assertIsFloat($value, 'Aseert float for column: ' . $key . '/' . $name);
|
||||
$this->assertIsFloat($value, 'Assert float for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
default:
|
||||
$this->assertIsString($value, 'Aseert string for column: ' . $key . '/' . $name);
|
||||
$this->assertIsString($value, 'Assert string for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -4794,17 +4795,17 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
}
|
||||
switch ($type_layout[$name]) {
|
||||
case 'int':
|
||||
$this->assertIsInt($value, 'Aseert int for column: ' . $key . '/' . $name);
|
||||
$this->assertIsInt($value, 'Assert int for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'float':
|
||||
$this->assertIsFloat($value, 'Aseert float for column: ' . $key . '/' . $name);
|
||||
$this->assertIsFloat($value, 'Assert float for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'json':
|
||||
case 'jsonb':
|
||||
$this->assertIsArray($value, 'Aseert array for column: ' . $key . '/' . $name);
|
||||
$this->assertIsArray($value, 'Assert array for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
default:
|
||||
$this->assertIsString($value, 'Aseert string for column: ' . $key . '/' . $name);
|
||||
$this->assertIsString($value, 'Assert string for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -4818,25 +4819,25 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
}
|
||||
switch ($type_layout[$name]) {
|
||||
case 'int':
|
||||
$this->assertIsInt($value, 'Aseert int for column: ' . $key . '/' . $name);
|
||||
$this->assertIsInt($value, 'Assert int for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'float':
|
||||
$this->assertIsFloat($value, 'Aseert float for column: ' . $key . '/' . $name);
|
||||
$this->assertIsFloat($value, 'Assert float for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'json':
|
||||
case 'jsonb':
|
||||
$this->assertIsArray($value, 'Aseert array for column: ' . $key . '/' . $name);
|
||||
$this->assertIsArray($value, 'Assert array for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
case 'bytea':
|
||||
// for hex types it must not start with \x
|
||||
$this->assertStringStartsNotWith(
|
||||
'\x',
|
||||
$value,
|
||||
'Aseert bytes not starts with \x for column: ' . $key . '/' . $name
|
||||
'Assert bytes not starts with \x for column: ' . $key . '/' . $name
|
||||
);
|
||||
break;
|
||||
default:
|
||||
$this->assertIsString($value, 'Aseert string for column: ' . $key . '/' . $name);
|
||||
$this->assertIsString($value, 'Assert string for column: ' . $key . '/' . $name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -5235,6 +5236,9 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
$3
|
||||
-- comment 3
|
||||
, $4
|
||||
-- ignore $5, $6
|
||||
-- $7, $8
|
||||
-- digest($9, 10)
|
||||
)
|
||||
SQL,
|
||||
'count' => 4,
|
||||
@@ -5305,8 +5309,57 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
SQL,
|
||||
'count' => 2,
|
||||
'convert' => false,
|
||||
],
|
||||
// special $$ string case
|
||||
'text string, with $ placehoders that could be seen as $$ string' => [
|
||||
'query' => <<<SQL
|
||||
SELECT row_int
|
||||
FROM table_with_primary_key
|
||||
WHERE
|
||||
row_bytea = digest($3::VARCHAR, $4) OR
|
||||
row_varchar = encode(digest($3, $4), 'hex') OR
|
||||
row_bytea = hmac($3, $5, $4) OR
|
||||
row_varchar = encode(hmac($3, $5, $4), 'hex') OR
|
||||
row_bytea = pgp_sym_encrypt($3, $6) OR
|
||||
row_varchar = encode(pgp_sym_encrypt($1, $6), 'hex') OR
|
||||
row_varchar = CASE WHEN row_int = 1 THEN $1 ELSE $2 END
|
||||
SQL,
|
||||
'count' => 6,
|
||||
'convert' => false,
|
||||
],
|
||||
// NOTE, in SQL heredoc we cannot write $$ strings parts
|
||||
'text string, with $ placehoders are in $$ strings' => [
|
||||
'query' => '
|
||||
SELECT row_int
|
||||
FROM table_with_primary_key
|
||||
WHERE
|
||||
row_varchar = $$some string$$ OR
|
||||
row_varchar = $tag$some string$tag$ OR
|
||||
row_varchar = $btag$some $1 string$btag$ OR
|
||||
row_varchar = $btag$some $1 $subtag$ something $subtag$string$btag$ OR
|
||||
row_varchar = $1
|
||||
',
|
||||
'count' => 1,
|
||||
'convert' => false,
|
||||
],
|
||||
// a text string with escaped quite
|
||||
'text string, with escaped quote' => [
|
||||
'query' => <<<SQL
|
||||
SELECT row_int
|
||||
FROM table_with_primary_key
|
||||
WHERE
|
||||
row_varchar = 'foo bar bar baz $5' OR
|
||||
row_varchar = 'foo bar '' barbar $6' OR
|
||||
row_varchar = E'foo bar \' barbar $7' OR
|
||||
row_varchar = CASE WHEN row_int = 1 THEN $1 ELSE $2 END
|
||||
SQL,
|
||||
'count' => 2,
|
||||
'convert' => false,
|
||||
]
|
||||
];
|
||||
$string = <<<SQL
|
||||
'''
|
||||
SQL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -969,44 +969,76 @@ final class CoreLibsUrlRequestsCurlTest extends TestCase
|
||||
"query" => ["foo-get" => "bar"]
|
||||
]);
|
||||
$this->assertEquals("200", $response["code"], "multi call: get response code not matching");
|
||||
$this->assertEquals(
|
||||
'{"HEADERS":{"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
|
||||
. '"HTTP_FIRST_CALL":"get","HTTP_ACCEPT":"*\/*",'
|
||||
. '"HTTP_HOST":"soba.egplusww.jp"},'
|
||||
. '"REQUEST_TYPE":"GET",'
|
||||
. '"PARAMS":{"foo-get":"bar"},"BODY":null}',
|
||||
$response['content'],
|
||||
'multi call: get content not matching'
|
||||
);
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
$this->assertEquals(
|
||||
'{"HEADERS":{"HTTP_HOST":"soba.egplusww.jp",'
|
||||
. '"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1","HTTP_FIRST_CALL":"get",'
|
||||
. '"HTTP_ACCEPT":"*\/*"},"REQUEST_TYPE":"GET","PARAMS":{"foo-get":"bar"},"BODY":null}',
|
||||
$response['content'],
|
||||
'multi call: get content not matching'
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
'{"HEADERS":{"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
|
||||
. '"HTTP_FIRST_CALL":"get","HTTP_ACCEPT":"*\/*",'
|
||||
. '"HTTP_HOST":"soba.egplusww.jp"},'
|
||||
. '"REQUEST_TYPE":"GET",'
|
||||
. '"PARAMS":{"foo-get":"bar"},"BODY":null}',
|
||||
$response['content'],
|
||||
'multi call: get content not matching'
|
||||
);
|
||||
}
|
||||
// post
|
||||
$response = $curl->post($this->url_basic, [
|
||||
"headers" => ["second-call" => "post"],
|
||||
"body" => ["foo-post" => "baz"]
|
||||
]);
|
||||
$this->assertEquals("200", $response["code"], "multi call: post response code not matching");
|
||||
$this->assertEquals(
|
||||
'{"HEADERS":{"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
|
||||
. '"HTTP_SECOND_CALL":"post","HTTP_ACCEPT":"*\/*",'
|
||||
. '"HTTP_HOST":"soba.egplusww.jp"},'
|
||||
. '"REQUEST_TYPE":"POST",'
|
||||
. '"PARAMS":[],"BODY":{"foo-post":"baz"}}',
|
||||
$response['content'],
|
||||
'multi call: post content not matching'
|
||||
);
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
$this->assertEquals(
|
||||
'{"HEADERS":{"HTTP_HOST":"soba.egplusww.jp",'
|
||||
. '"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
|
||||
. '"HTTP_SECOND_CALL":"post","HTTP_ACCEPT":"*\/*"},'
|
||||
. '"REQUEST_TYPE":"POST","PARAMS":[],"BODY":{"foo-post":"baz"}}',
|
||||
$response['content'],
|
||||
'multi call: post content not matching'
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
'{"HEADERS":{"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
|
||||
. '"HTTP_SECOND_CALL":"post","HTTP_ACCEPT":"*\/*",'
|
||||
. '"HTTP_HOST":"soba.egplusww.jp"},'
|
||||
. '"REQUEST_TYPE":"POST",'
|
||||
. '"PARAMS":[],"BODY":{"foo-post":"baz"}}',
|
||||
$response['content'],
|
||||
'multi call: post content not matching'
|
||||
);
|
||||
}
|
||||
// delete
|
||||
$response = $curl->delete($this->url_basic, [
|
||||
"headers" => ["third-call" => "delete"],
|
||||
]);
|
||||
$this->assertEquals("200", $response["code"], "multi call: delete response code not matching");
|
||||
$this->assertEquals(
|
||||
'{"HEADERS":{"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
|
||||
. '"HTTP_THIRD_CALL":"delete","HTTP_ACCEPT":"*\/*",'
|
||||
. '"HTTP_HOST":"soba.egplusww.jp"},'
|
||||
. '"REQUEST_TYPE":"DELETE",'
|
||||
. '"PARAMS":[],"BODY":[]}',
|
||||
$response['content'],
|
||||
'multi call: delete content not matching'
|
||||
);
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
$this->assertEquals(
|
||||
'{"HEADERS":{"HTTP_HOST":"soba.egplusww.jp",'
|
||||
. '"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
|
||||
. '"HTTP_THIRD_CALL":"delete","HTTP_ACCEPT":"*\/*"},'
|
||||
. '"REQUEST_TYPE":"DELETE","PARAMS":[],"BODY":[]}',
|
||||
$response['content'],
|
||||
'multi call: delete content not matching'
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
'{"HEADERS":{"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
|
||||
. '"HTTP_THIRD_CALL":"delete","HTTP_ACCEPT":"*\/*",'
|
||||
. '"HTTP_HOST":"soba.egplusww.jp"},'
|
||||
. '"REQUEST_TYPE":"DELETE",'
|
||||
. '"PARAMS":[],"BODY":[]}',
|
||||
$response['content'],
|
||||
'multi call: delete content not matching'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: auth header set via config
|
||||
|
||||
Reference in New Issue
Block a user