Compare commits

..
5 Commits
Author SHA1 Message Date
cliphouse 68ea44964f findArraysMissingKey: php param documentation update 2026-09-24 11:51:05 +09:00
cliphouse 369f2e2586 Immutable hash for arrays, add not sort keys flag 2026-09-18 21:53:36 +09:00
cliphouse 3a33f07ae7 Add DB:IO strip non assoc entries from result
if we have a mixed result, strip all int key (non assoc) entries from the result
2026-09-18 18:56:43 +09:00
cliphouse 0b057864ae Hash: immutable hash over array
with sorted keys, but arrays stay unsorted
2026-09-18 18:36:40 +09:00
cliphouse 2bb405d741 Add tests for new array functions, other minro fixes for phan && phpstan checks 2026-09-18 17:33:44 +09:00
10 changed files with 662 additions and 89 deletions
@@ -16,7 +16,7 @@ use PHPUnit\Framework\TestCase;
*/ */
final class CoreLibsCombinedArrayHandlerTest extends TestCase final class CoreLibsCombinedArrayHandlerTest extends TestCase
{ {
// we use that for all /** @var array<mixed> we use that for all */
public static $array = [ public static $array = [
'a' => [ 'a' => [
'b' => 'bar', 'b' => 'bar',
@@ -51,7 +51,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* Undocumented function * Undocumented function
* *
* @return array * @return array<mixed>
*/ */
public function arraySearchRecursiveProvider(): array public function arraySearchRecursiveProvider(): array
{ {
@@ -110,7 +110,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* Undocumented function * Undocumented function
* *
* @return array * @return array<mixed>
*/ */
public function arraySearchRecursiveAllProvider(): array public function arraySearchRecursiveAllProvider(): array
{ {
@@ -182,7 +182,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* Undocumented function * Undocumented function
* *
* @return array * @return array<mixed>
*/ */
public function arraySearchSimpleProvider(): array public function arraySearchSimpleProvider(): array
{ {
@@ -383,7 +383,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* Undocumented function * Undocumented function
* *
* @return array * @return array<mixed>
*/ */
public function arraySearchKeyProvider(): array public function arraySearchKeyProvider(): array
{ {
@@ -565,7 +565,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* provides array listing for the merge test * provides array listing for the merge test
* *
* @return array * @return array<mixed>
*/ */
public function arrayMergeRecursiveProvider(): array public function arrayMergeRecursiveProvider(): array
{ {
@@ -602,7 +602,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* for warning checks * for warning checks
* *
* @return array * @return array<mixed>
*/ */
public function arrayMergeRecursiveProviderWarning(): array public function arrayMergeRecursiveProviderWarning(): array
{ {
@@ -634,7 +634,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* Undocumented function * Undocumented function
* *
* @return array * @return array<mixed>
*/ */
public function arrayCompareProvider(): array public function arrayCompareProvider(): array
{ {
@@ -665,7 +665,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* Undocumented function * Undocumented function
* *
* @return array * @return array<mixed>
*/ */
public function inArrayAnyProvider(): array public function inArrayAnyProvider(): array
{ {
@@ -688,6 +688,11 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
]; ];
} }
/**
* Undocumented function
*
* @return array<mixed>
*/
public function genAssocArrayProvider(): array public function genAssocArrayProvider(): array
{ {
return [ return [
@@ -764,7 +769,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* Undocumented function * Undocumented function
* *
* @return array * @return array<mixed>
*/ */
public function flattenArrayProvider(): array public function flattenArrayProvider(): array
{ {
@@ -808,7 +813,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* use the flattenArrayProvider and replace 1 with 2 array pos * use the flattenArrayProvider and replace 1 with 2 array pos
* *
* @return array * @return array<mixed>
*/ */
public function flattenArrayKeyProvider(): array public function flattenArrayKeyProvider(): array
{ {
@@ -825,7 +830,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* use the flattenArrayProvider and replace 1 with 3 array pos * use the flattenArrayProvider and replace 1 with 3 array pos
* *
* @return array * @return array<mixed>
*/ */
public function flattenArrayKeyLeavesOnlyProvider(): array public function flattenArrayKeyLeavesOnlyProvider(): array
{ {
@@ -842,7 +847,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
/** /**
* Undocumented function * Undocumented function
* *
* @return array * @return array<mixed>
*/ */
public function arrayFlatForKeyProvider(): array public function arrayFlatForKeyProvider(): array
{ {
@@ -906,6 +911,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
]; ];
} }
// MARK: arraySearchRecursive
/** /**
* Undocumented function * Undocumented function
* *
@@ -926,6 +933,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: arraySearchRecursiveAll
/** /**
* Undocumented function * Undocumented function
* *
@@ -947,6 +956,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: arraySearchSimple
/** /**
* Undocumented function * Undocumented function
* *
@@ -969,6 +980,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: arraySearchKey
/** /**
* Undocumented function * Undocumented function
* *
@@ -1007,6 +1020,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: arrayMergeRecursive
/** /**
* Undocumented function * Undocumented function
* *
@@ -1031,6 +1046,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: arrayMergeRecursive
/** /**
* Undocumented function * Undocumented function
* *
@@ -1063,6 +1080,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
restore_error_handler(); restore_error_handler();
} }
// MARK: arrayDiff
/** /**
* Undocumented function * Undocumented function
* *
@@ -1083,6 +1102,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: inArrayAny
/** /**
* Undocumented function * Undocumented function
* *
@@ -1103,6 +1124,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: genAssocArray
/** /**
* Undocumented function * Undocumented function
* *
@@ -1125,6 +1148,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: flattenArray
/** /**
* Undocumented function * Undocumented function
* *
@@ -1144,6 +1169,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: flattenArrayKey
/** /**
* Undocumented function * Undocumented function
* *
@@ -1163,6 +1190,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: flattenArrayKeyLeavesOnly
/** /**
* Undocumented function * Undocumented function
* *
@@ -1182,6 +1211,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: arrayFlatForKey
/** /**
* Undocumented function * Undocumented function
* *
@@ -1202,6 +1233,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: arrayGetPrevKey, arrayGetNextKey
/** /**
* Undocumented function * Undocumented function
* *
@@ -1295,6 +1328,13 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: arrayReturnMatchingKeyOnly
/**
* Undocumented function
*
* @return array
*/
public function providerReturnMatchingKeyOnley(): array public function providerReturnMatchingKeyOnley(): array
{ {
return [ return [
@@ -1380,6 +1420,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: arrayModifyKey
/** /**
* provider for arrayModifyKey * provider for arrayModifyKey
* *
@@ -1492,6 +1534,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: sortArray
/** /**
* sort * sort
* *
@@ -1711,7 +1755,9 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
} }
} }
/** // MARK: ksortArray
/**
* sort * sort
* *
* @return array * @return array
@@ -1867,6 +1913,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
} }
} }
// MARK: findArraysMissingKey
/** /**
* Undocumented function * Undocumented function
* *
@@ -2034,6 +2082,8 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
); );
} }
// MARK: selectArrayFromOption
/** /**
* Undocumented function * Undocumented function
* *
@@ -2379,6 +2429,316 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
$result $result
); );
} }
// MARK: getRandomEntryFromArrayProvider
/**
* Get random entry from array provider
*
* @return array<mixed>
*/
public function getRandomEntryFromArrayProvider(): array
{
return [
'empty array' => [
[],
],
'single element array' => [
['only'],
],
'multiple elements array' => [
['first', 'second', 'third'],
],
];
}
/**
* Undocumented function
*
* @covers ::getRandomEntryFromArray
* @dataProvider getRandomEntryFromArrayProvider
* @testdox getRandomEntryFromArray get random value from array [$_dataName]
*
* @param array $input
* @return void
*/
public function testGetRandomEntryFromArray(array $input): void
{
$result = \CoreLibs\Combined\ArrayHandler::getRandomEntryFromArray($input);
if (empty($input)) {
$this->assertNull($result);
} else {
$this->assertContains($result, $input);
}
}
// MARK: removeArrayEntryByValue
/**
* Remove array entry by value provider
*
* @return array<mixed>
*/
public function removeArrayEntryByValueProvider(): array
{
return [
'empty array' => [
[],
'',
null,
[],
],
'single element array' => [
['only'],
'only',
null,
[]
],
'single element array, not found' => [
['only'],
'foo',
null,
['only']
],
'multiple elements array' => [
['first', 'second', 'third'],
'second',
null,
['first', 'third'],
],
'array with multiple identical elements' => [
['first', 'second', 'first', 'third'],
'first',
null,
['second', 'third'],
],
'array with multiple identical elements, other remove' => [
['first', 'second', 'first', 'third'],
'second',
null,
['first', 'first', 'third'],
],
'array with key value entries' => [
[
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'value3',
],
'value2',
null,
[
'key1' => 'value1',
'key3' => 'value3',
]
],
'nested array, array match' => [
[
['first', 'second'],
['third', 'fourth'],
],
['third', 'fourth'],
null,
[
['first', 'second'],
],
],
'strict test, off' => [
['3', 3,],
'3',
null,
[],
],
'strict test, on' => [
['3', 3,],
'3',
true,
[3,],
],
'strict test bool, off' => [
['false', false, 0],
false,
null,
['false'],
],
'strict test bool, on' => [
['false', false, 0],
false,
true,
['false', 0],
],
'strict test float, off' => [
['3.14', 3.14],
3.14,
null,
[],
],
'strict test float, on' => [
['3.14', 3.14],
3.14,
true,
['3.14'],
],
'stric test float and int, off' => [
['1.0', '1', 1.0, 1],
1,
null,
[],
],
'stric test float and int, on' => [
['1.0', '1', 1.0, 1],
1,
true,
['1.0', '1', 1.0],
],
];
}
/**
* Test for removeArrayEntryByValue function
*
* @covers ::removeArrayEntryByValue
* @dataProvider removeArrayEntryByValueProvider
* @testdox removeArrayEntryByValue Remove $value from array $input, with $strict [$_dataName]
*
* @param array $input
* @param string|int|float|bool|array $value
* @param bool|null $strict
* @param array $expected
* @return void
*/
public function testRemoveArrayEntryByValue(
array $input,
string|int|float|bool|array $value,
?bool $strict,
array $expected
): void {
if ($strict !== null) {
$result = \CoreLibs\Combined\ArrayHandler::removeArrayEntryByValue($input, $value, $strict);
} else {
$result = \CoreLibs\Combined\ArrayHandler::removeArrayEntryByValue($input, $value);
}
$this->assertEquals(array_values($expected), array_values($result));
}
// MARK: addStringToEachValueInArray
/**
* Data provider for addStringToEachValueInArray tests.
*
* @return array
*/
public function addStringToEachValueInArrayProvider(): array
{
return [
'empty array' => [
[],
'string',
null,
[],
],
'empty string to add' => [
['a', 'b'],
'',
null,
['a', 'b'],
],
'prefix true' => [
['a', 'b'],
'pre_',
true,
['pre_a', 'pre_b'],
],
'prefix false' => [
['a', 'b'],
'_suf',
false,
['a_suf', 'b_suf'],
],
'mixed values' => [
['a', 'b', 'c', 5, 6],
'X',
true,
['Xa', 'Xb', 'Xc', 'X5', 'X6'],
]
];
}
/**
* Test for addStringToEachValueInArray function
*
* @covers ::addStringToEachValueInArray
* @dataProvider addStringToEachValueInArrayProvider
* @testdox addStringToEachValueInArray Add $string_to_add to each value in $array, with $prefix [$_dataName]
*
* @param array $array
* @param string $string_to_add
* @param bool|null $prefix
* @param array|null $expected
* @return void
*/
public function testAddStringToEachValueInArray(
array $array,
string $string_to_add,
?bool $prefix,
?array $expected
) {
if ($prefix == null) {
$result = \CoreLibs\Combined\ArrayHandler::addStringToEachValueInArray($array, $string_to_add);
} else {
$result = \CoreLibs\Combined\ArrayHandler::addStringToEachValueInArray($array, $string_to_add, $prefix);
}
$this->assertEquals($expected, $result);
}
// MARK: createSortedArrayByKey
/**
* Data provider for createSortedArrayByKey tests.
*
* @return array
*/
public function createSortedArrayByKeyProvider(): array
{
return [
'empty' => [
[],
[],
],
'flat array' => [
['b' => 2, 'a' => 1, 'c' => 3],
['a' => 1, 'b' => 2, 'c' => 3],
],
'nested array' => [
['b' => 2, 'a' => 1, 'c' => ['d' => 4, 'b' => 2]],
['a' => 1, 'b' => 2, 'c' => ['b' => 2, 'd' => 4]],
],
'deeply nested array' => [
['b' => 2, 'a' => 1, 'c' => ['d' => 4, 'b' => 2, 'e' => ['g' => 7, 'f' => 6]]],
['a' => 1, 'b' => 2, 'c' => ['b' => 2, 'd' => 4, 'e' => ['f' => 6, 'g' => 7]]],
],
'mixed key type' => [
['b' => 2, 1 => 'one', 'a' => 1],
[1 => 'one', 'a' => 1, 'b' => 2],
],
];
}
/**
* Test for createSortedArrayByKey function
*
* @covers ::createSortedArrayByKey
* @dataProvider createSortedArrayByKeyProvider
* @testdox createSortedArrayByKey Sort the array by keys recursively [$_dataName]
*
* @param array $input
* @param array $expected
* @return void
*/
public function testCreateSortedArrayByKey(array $input, array $expected): void
{
$result = \CoreLibs\Combined\ArrayHandler::createSortedArrayByKey($input);
$this->assertEquals($expected, $result);
}
} }
// __END__ // __END__
@@ -421,6 +421,100 @@ final class CoreLibsCreateHashTest extends TestCase
'hash hmac valid' 'hash hmac valid'
); );
} }
// MARK: generateImmutableHashForArray
/**
* Data provider for testGenerateImmutableHashForArray.
*
* @return array
*/
public function generateImmutableHashForArrayProvider(): array
{
return [
'Empty array' => [
[],
null,
'064f01fe',
],
'Simple array' => [
['key' => 'value'],
null,
'78f40899',
],
'flat array a' => [
[0, 1, 'b', 'c', 'a'],
null,
'ccec0f5b',
],
'flat array b' => [
['b', 'c', 'a', 1, 0],
null,
'c6040f5b',
],
'flat array b, not sorted' => [
['b', 'c', 'a', 1, 0],
false,
'c6040f5b',
],
'key array a' => [
['A' => 0, 'F' => 1, 'C' => 'b', 'K' => 'c', 'B' => 'a'],
null,
'01f11355',
],
'key array a, not sorted' => [
['A' => 0, 'F' => 1, 'C' => 'b', 'K' => 'c', 'B' => 'a'],
false,
'04911355',
],
'key array b' => [
['A' => 0, 'B' => 'a', 'C' => 'b', 'F' => 1, 'K' => 'c'],
null,
'01f11355',
],
'key array b, not sorted' => [
['A' => 0, 'B' => 'a', 'C' => 'b', 'F' => 1, 'K' => 'c'],
false,
'01f11355',
],
'complex nested array' => [
[
'level1' => [
'level2' => [
'level3' => 'value'
]
]
],
null,
'd8de1565',
]
];
}
/**
* Test for generating an immutable hash from an array.
*
* @covers ::generateImmutableHashForArray
* @dataProvider generateImmutableHashForArrayProvider
* @testdox generate immutable hash for array with result $expected [$_dataName]
*
* @param array<mixed> $input
* @param string $expected
*/
public function testGenerateImmutableHashForArray(array $input, ?bool $sort_keys, string $expected): void
{
if ($sort_keys === null) {
$this->assertEquals(
$expected,
\CoreLibs\Create\Hash::generateImmutableHashForArray($input)
);
} else {
$this->assertEquals(
$expected,
\CoreLibs\Create\Hash::generateImmutableHashForArray($input, $sort_keys)
);
}
}
} }
// __END__ // __END__
+53
View File
@@ -1007,6 +1007,59 @@ final class CoreLibsDBIOTest extends TestCase
$db->dbClose(); $db->dbClose();
} }
// MARK: stripAssocOnly
/**
* Data provider for stripAssocOnly tests
*
* @return array<mixed>
*/
public function stripAssocOnlyProvider(): array
{
return [
'empty' => [
[],
[]
],
'int only' => [
[0 => 'foo', 1 => 'bar'],
[],
],
'mixed' => [
[0 => 'foo', 'col_a' => 'foo', 1 => 'bar', 'col_b' => 'bar'],
['col_a' => 'foo', 'col_b' => 'bar'],
],
'key only' => [
['col_a' => 'foo', 'col_b' => 'bar'],
['col_a' => 'foo', 'col_b' => 'bar'],
]
];
}
/**
* Test for stripAssocOnly function
*
* @covers ::stripAssocOnly
* @dataProvider stripAssocOnlyProvider
* @testdox strip assoc non string entries from return [$_dataName]
*
* @param array<mixed> $input
* @param array<string,mixed> $expected
* @return void
*/
public function testStripAssocOnly(array $input, array $expected): void
{
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
);
$this->assertEquals(
$expected,
$db->stripAssocOnly($input)
);
$db->dbClose();
}
// - string escape tests // - string escape tests
// dbEscapeString, dbEscapeLiteral, dbEscapeIdentifier, // dbEscapeString, dbEscapeLiteral, dbEscapeIdentifier,
+39 -32
View File
@@ -342,38 +342,6 @@ print "(ksort): " . DgS::printAr(ArrayHandler::ksortArray($nested)) . "<br>";
print "<hr>"; print "<hr>";
$search_array = [
'table_lookup' => [
'match' => [
['param' => 'access_d_cd', 'data' => 'a_cd', 'time_validation' => 'on_load',],
['param' => 'other_block', 'data' => 'b_cd'],
['pflaume' => 'other_block', 'data' => 'c_cd'],
['param' => 'third_block', 'data' => 'd_cd', 'time_validation' => 'cool'],
['special' => 'other_block', 'data' => 'e_cd', 'time_validation' => 'other'],
]
]
];
print "Search: " . DgS::printAr($search_array) . "<br>";
print "Result (all): " . Dgs::printAr(ArrayHandler::findArraysMissingKey(
$search_array,
'other_block',
'time_validation'
)) . "<br>";
print "Result (key): " . Dgs::printAr(ArrayHandler::findArraysMissingKey(
$search_array,
'other_block',
'time_validation',
'pflaume'
)) . "<br>";
print "Result (key): " . Dgs::printAr(ArrayHandler::findArraysMissingKey(
$search_array,
'other_block',
['data', 'time_validation'],
'pflaume'
)) . "<br>";
print "<hr>";
$search_array = [ $search_array = [
'a' => [ 'a' => [
'lookup' => 1, 'lookup' => 1,
@@ -528,6 +496,45 @@ $result = ArrayHandler::selectArrayFromOption(
); );
print "*2*Result: " . DgS::printAr($result) . "<br>"; print "*2*Result: " . DgS::printAr($result) . "<br>";
print "<hr>";
$search_array = [
'table_lookup' => [
'match' => [
['param' => 'access_d_cd', 'data' => 'a_cd', 'time_validation' => 'on_load',],
['param' => 'other_block', 'data' => 'b_cd'],
['pflaume' => 'other_block', 'data' => 'c_cd'],
['param' => 'third_block', 'data' => 'd_cd', 'time_validation' => 'cool'],
['special' => 'other_block', 'data' => 'e_cd', 'time_validation' => 'other'],
]
]
];
print "Search: " . DgS::printAr($search_array) . "<br>";
print "Result (all, search single): " . DgS::printAr(ArrayHandler::findArraysMissingKey(
$search_array,
'other_block',
'time_validation'
)) . "<br>";
print "Result (key limit): " . DgS::printAr(ArrayHandler::findArraysMissingKey(
$search_array,
'other_block',
'time_validation',
'pflaume'
)) . "<br>";
print "Result (all, search array): " . DgS::printAr(ArrayHandler::findArraysMissingKey(
$search_array,
'other_block',
['data', 'time_validation'],
)) . "<br>";
print "Result (key limit, search array): " . DgS::printAr(ArrayHandler::findArraysMissingKey(
$search_array,
'other_block',
['data', 'time_validation'],
'pflaume'
)) . "<br>";
print "<hr>";
print "</body></html>"; print "</body></html>";
// __END__ // __END__
+14
View File
@@ -103,6 +103,20 @@ foreach ($hash_types as $hash_type) {
// print "UNIQU ID SHORT : " . Hash::__uniqId() . "<br>"; // print "UNIQU ID SHORT : " . Hash::__uniqId() . "<br>";
// print "UNIQU ID LONG : " . Hash::__uniqIdLong() . "<br>"; // print "UNIQU ID LONG : " . Hash::__uniqIdLong() . "<br>";
$tests = [
// array diff
[0, 1, 'b', 'c', 'a'],
['b', 'c', 'a', 1, 0],
// key set arrays DO NOT diff
['A' => 0, 'F' => 1, 'C' => 'b', 'K' => 'c', 'B' => 'a'],
['A' => 0, 'B' => 'a', 'C' => 'b', 'F' => 1, 'K' => 'c'],
];
foreach ($tests as $test) {
print "IMMUTABLE HASH FOR ARRAY: " . Hash::generateImmutableHashForArray($test) . "<br>";
print "IMMUTABLE HASH FOR ARRAY: " . Hash::generateImmutableHashForArray($test, sort_keys:false) . "<br>";
print "SERIALIZED HASH FOR ARRAY: " . hash(Hash::DEFAULT_HASH, serialize($test)) . "<br>";
}
print "</body></html>"; print "</body></html>";
// __END__ // __END__
+23 -15
View File
@@ -248,12 +248,15 @@ class ArrayHandler
* If not found return an array with the array block there the required key is missing, * If not found return an array with the array block there the required key is missing,
* the path as string with seperator block set and the missing key entry * the path as string with seperator block set and the missing key entry
* *
* @param array<mixed> $in_array * alternate to findArraysWithMissingKey (single missing key)
* @param string|int|float|bool $search_value *
* @param string|array<string> $required_key * @param array<mixed> $in_array Array to search in
* @param ?string $search_key [null] * @param string|int|float|bool $search_value Value that must be set in any
* @param string $path_separator [DATA_SEPARATOR] * (or with search_key in one entry of the array)
* @param string $current_path * @param string|array<string> $required_key Key or Keys that must be set
* @param ?string $search_key [null] limit search_value check to this key
* @param string $path_separator [DATA_SEPARATOR] For the path string separator
* @param string $current_path [''] Current path in the array (used for recursion)
* @return array<array{content?:array<mixed>,path?:string,missing_key?:array<string>}> * @return array<array{content?:array<mixed>,path?:string,missing_key?:array<string>}>
*/ */
public static function findArraysMissingKey( public static function findArraysMissingKey(
@@ -272,14 +275,14 @@ class ArrayHandler
// Check if this array contains the search value // Check if this array contains the search value
// either any value match or with key // either any value match or with key
if ($search_key === null) { if ($search_key === null) {
$containsValue = in_array($search_value, $value, true); $contains_value = in_array($search_value, $value, true);
} else { } else {
$containsValue = array_key_exists($search_key, $value) && $value[$search_key] === $search_value; $contains_value = array_key_exists($search_key, $value) && $value[$search_key] === $search_value;
} }
// If it contains the value but doesn't have the required key // If it contains the value but doesn't have the required key
if ( if (
$containsValue && $contains_value &&
( (
( (
is_string($required_key) && is_string($required_key) &&
@@ -475,8 +478,7 @@ class ArrayHandler
throw new \ArgumentCountError(__FUNCTION__ . ' needs two or more array arguments'); throw new \ArgumentCountError(__FUNCTION__ . ' needs two or more array arguments');
} }
$merged = []; $merged = [];
while ($in_arrays) { foreach ($in_arrays as $in_array) {
$in_array = array_shift($in_arrays);
if (!is_array($in_array)) { if (!is_array($in_array)) {
throw new \TypeError(__FUNCTION__ . ' encountered a non array argument'); throw new \TypeError(__FUNCTION__ . ' encountered a non array argument');
} }
@@ -813,7 +815,6 @@ class ArrayHandler
} }
/** /**
* TODO: move to CoreLibs ArrayCombined
* return one random entry from an array (value) * return one random entry from an array (value)
* the return entry is null if the incoming array is empty * the return entry is null if the incoming array is empty
* the array can also be an array of arrays * the array can also be an array of arrays
@@ -831,9 +832,7 @@ class ArrayHandler
} }
/** /**
* TODO: move to CoreLibs ArrayCombined
* find and remove one value * find and remove one value
* on default removes only the first entry
* on default does not strict compare * on default does not strict compare
* *
* @param array<mixed> $array * @param array<mixed> $array
@@ -846,6 +845,9 @@ class ArrayHandler
string|int|float|bool|array $value, string|int|float|bool|array $value,
bool $strict = false, bool $strict = false,
): array { ): array {
if (empty($array)) {
return $array;
}
return array_filter($array, function ($element) use ($value, $strict) { return array_filter($array, function ($element) use ($value, $strict) {
return $strict ? return $strict ?
$element !== $value : $element !== $value :
@@ -854,7 +856,6 @@ class ArrayHandler
} }
/** /**
* TODO: move to CoreLibs ArrayCombined
* add a string to each element in an array, default is at the end of the value, * add a string to each element in an array, default is at the end of the value,
* can be switched with the prefix flag * can be switched with the prefix flag
* *
@@ -865,6 +866,10 @@ class ArrayHandler
*/ */
public static function addStringToEachValueInArray(array $array, string $string_to_add, bool $prefix = false): array public static function addStringToEachValueInArray(array $array, string $string_to_add, bool $prefix = false): array
{ {
// nothing set, skip
if (empty($string_to_add) || empty($array)) {
return $array;
}
return array_map(function ($value) use ($string_to_add, $prefix) { return array_map(function ($value) use ($string_to_add, $prefix) {
return $prefix ? return $prefix ?
$string_to_add . $value : $string_to_add . $value :
@@ -880,6 +885,9 @@ class ArrayHandler
*/ */
public static function createSortedArrayByKey(array $data): array public static function createSortedArrayByKey(array $data): array
{ {
if (empty($data)) {
return $data;
}
// Sort by keys // Sort by keys
ksort($data); ksort($data);
+23
View File
@@ -8,6 +8,8 @@ declare(strict_types=1);
namespace CoreLibs\Create; namespace CoreLibs\Create;
use CoreLibs\Combined\ArrayHandler;
class Hash class Hash
{ {
/** @var string default short hash -> deprecated use STANDARD_HASH_SHORT */ /** @var string default short hash -> deprecated use STANDARD_HASH_SHORT */
@@ -210,6 +212,27 @@ class Hash
{ {
return self::hash($string, self::STANDARD_HASH); return self::hash($string, self::STANDARD_HASH);
} }
/**
* generate a hash over any array data
* optional will not sort keys and so create hashes based on the original data.
* for correct array comapre it is recommended to keep sort keys on
*
* @param array<mixed> $data
* @param bool $sort_keys [true] Whether to sort the array keys before hashing
* @return string
*/
public static function generateImmutableHashForArray(array $data, bool $sort_keys = true): string
{
// Create a sorted copy to ensure consistent hashing
// Generate hash using serialize for better accuracy
return hash(
self::DEFAULT_HASH,
serialize(
$sort_keys ? ArrayHandler::createSortedArrayByKey($data) : $data
)
);
}
} }
// __END__ // __END__
+5 -5
View File
@@ -154,11 +154,11 @@ class RandomKey
* if override key length is set, it will check on valid key and use this * if override key length is set, it will check on valid key and use this
* this will not set the class key length variable * this will not set the class key length variable
* *
* @param int $key_length [default=-1] key length override, * @param int $key_length [default=-1] key length override,
* if not set use default [LEGACY] * if not set use default [LEGACY]
* @param array<string> $key_range a list of key ranges as array, * @param array<string> ...$key_range a list of key ranges as array,
* if not set use previous set data * if not set use previous set data
* @return string random key * @return string random key
*/ */
public static function randomKeyGen( public static function randomKeyGen(
int $key_length = self::KEY_LENGTH_DEFAULT, int $key_length = self::KEY_LENGTH_DEFAULT,
+36 -22
View File
@@ -520,7 +520,7 @@ class IO
} }
// ************************************************************* // *************************************************************
// PRIVATE METHODS // MARK: PRIVATE METHODS
// ************************************************************* // *************************************************************
/** /**
@@ -1703,11 +1703,11 @@ class IO
} }
// ************************************************************* // *************************************************************
// PUBLIC METHODS // MARK: PUBLIC METHODS
// ************************************************************* // *************************************************************
// *************************** // ***************************
// CLOSE, STATUS, SETTINGS VARIABLE READ // MARK: CLOSE, STATUS, SETTINGS VARIABLE READ
// *************************** // ***************************
/** /**
@@ -1950,7 +1950,7 @@ class IO
} }
// *************************** // ***************************
// DEBUG DATA DUMP // MARK: DEBUG DATA DUMP
// *************************** // ***************************
/** /**
@@ -1978,7 +1978,7 @@ class IO
} }
// *************************** // ***************************
// CHECK QUERY TYPE // MARK: CHECK QUERY TYPE
// *************************** // ***************************
/** /**
@@ -2035,7 +2035,7 @@ class IO
} }
// *************************** // ***************************
// DATA WRITE CONVERSION // MARK: DATA WRITE CONVERSION
// *************************** // ***************************
/** /**
@@ -2156,7 +2156,7 @@ class IO
} }
// *************************** // ***************************
// DATA READ/WRITE CONVERSION // MARK: DATA READ/WRITE CONVERSION
// *************************** // ***************************
/** /**
@@ -2194,7 +2194,7 @@ class IO
} }
// *************************** // ***************************
// DATA READ CONVERSION // MARK: DATA READ CONVERSION
// *************************** // ***************************
/** /**
@@ -2263,8 +2263,22 @@ class IO
return is_array($__db_array_parse) ? $__db_array_parse : []; return is_array($__db_array_parse) ? $__db_array_parse : [];
} }
/**
* Will strip all single numberic entries from the array.
* This is for database return
*
* @param array<mixed> $res
* @return array<string,mixed>
*/
public function stripAssocOnly(array $res): array
{
return array_filter($res, function ($key) {
return !is_numeric($key);
}, ARRAY_FILTER_USE_KEY);
}
// *************************** // ***************************
// TABLE META DATA READ // MARK: TABLE META DATA READ
// *************************** // ***************************
/** /**
@@ -2290,7 +2304,7 @@ class IO
} }
// *************************** // ***************************
// QUERY EXECUSION AND DATA READ // MARK: QUERY EXECUSION AND DATA READ
// *************************** // ***************************
/** /**
@@ -2927,7 +2941,7 @@ class IO
} }
// *************************** // ***************************
// CURSOR RETURN // MARK: CURSOR RETURN
// *************************** // ***************************
/** /**
@@ -2941,7 +2955,7 @@ class IO
} }
// *************************** // ***************************
// CURSOR EXT CACHE RESET // MARK: CURSOR EXT CACHE RESET
// *************************** // ***************************
/** /**
@@ -2971,7 +2985,7 @@ class IO
} }
// *************************** // ***************************
// CURSOR EXT DATA CHECK // MARK: CURSOR EXT DATA CHECK
// *************************** // ***************************
/** /**
@@ -3066,7 +3080,7 @@ class IO
} }
// *************************** // ***************************
// MAXIMUM QUERY EXECUTION CHECK HELPERS // MARK: MAXIMUM QUERY EXECUTION CHECK HELPERS
// *************************** // ***************************
/** /**
@@ -3102,7 +3116,7 @@ class IO
} }
// *************************** // ***************************
// PREPARED QUERY WORK // MARK: PREPARED QUERY WORK
// *************************** // ***************************
/** /**
@@ -3379,7 +3393,7 @@ class IO
} }
// *************************** // ***************************
// ASYNCHRONUS EXECUTION/CHECK // MARK: ASYNCHRONUS EXECUTION/CHECK
// *************************** // ***************************
/** /**
@@ -3539,7 +3553,7 @@ class IO
} }
// *************************** // ***************************
// COMPLEX WRITE WITH CONFIG ARRAYS // MARK: COMPLEX WRITE WITH CONFIG ARRAYS
// *************************** // ***************************
// ** REMARK ** // ** REMARK **
@@ -3720,7 +3734,7 @@ class IO
} }
// *************************** // ***************************
// INTERNAL SETTINGS READ/CHANGE // MARK: INTERNAL SETTINGS READ/CHANGE
// *************************** // ***************************
/** /**
@@ -4048,7 +4062,7 @@ class IO
} }
// *************************** // ***************************
// QUERY DATA AND DB HANDLER // MARK: QUERY DATA AND DB HANDLER
// *************************** // ***************************
/** /**
@@ -4151,7 +4165,7 @@ class IO
} }
// *************************** // ***************************
// INTERNAL VARIABLES READ POST QUERY RUN // MARK: INTERNAL VARIABLES READ POST QUERY RUN
// *************************** // ***************************
/** /**
@@ -4442,7 +4456,7 @@ class IO
} }
// *************************** // ***************************
// ERROR AND WARNING DATA // MARK: ERROR AND WARNING DATA
// *************************** // ***************************
/** /**
@@ -4499,7 +4513,7 @@ class IO
} }
// *************************** // ***************************
// DEPEREACTED CALLS // MARK: DEPEREACTED CALLS
// all call below are no longer in use and throw deprecated errors // all call below are no longer in use and throw deprecated errors
// *************************** // ***************************
@@ -290,7 +290,7 @@ class ConvertPlaceholder
} }
$match = $matches[self::MATCHING_POS]; $match = $matches[self::MATCHING_POS];
// only count pos up for actual replacements we will do // only count pos up for actual replacements we will do
if (!empty($match)) { if (strlen((string)$match) > 0) {
$pos++; $pos++;
$params_lookup[] = '$' . $pos; $params_lookup[] = '$' . $pos;
} }