Add new funtions and update
- ksortArray and sortArray Sort array and return sorted output in one flow. Allows for case insensitve sort, reverse sort - selectArrayFromOption select array blocks based on a "key": "value" match. Can do recusrive with flat or not flat output, strict matching, case insenstivie The flat combined character can be changed - findArraysMissingKey Search an array for a matching value with optional key match and return array block if in this block a key (or keys) are missing The matching for key and value is always strict, eg 2 and '2' are different, Found path is added with ":" separators, can be overridden by parameter - arraySearchSimple Allow search values to be array for multiple matching (any match)
This commit is contained in:
@@ -0,0 +1,402 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CoreLibs\Combined\ArrayHandler;
|
||||
|
||||
class CoreLibsCombinedArrayHandlerFindArraysMissingKeyTest extends TestCase
|
||||
{
|
||||
private const DATA_SEPARATOR = ':'; // Updated to match your class's separator
|
||||
|
||||
/**
|
||||
* Test finding missing single key when searching by value without specific key
|
||||
*/
|
||||
public function testFindMissingSingleKeyWithValueSearch()
|
||||
{
|
||||
$array = [
|
||||
'item1' => [
|
||||
'name' => 'John',
|
||||
'age' => 25
|
||||
// missing 'email' key
|
||||
],
|
||||
'item2' => [
|
||||
'name' => 'Jane',
|
||||
'age' => 30,
|
||||
'email' => 'jane@example.com'
|
||||
],
|
||||
'item3' => [
|
||||
'name' => 'John', // same value as item1
|
||||
'age' => 35,
|
||||
'email' => 'john2@example.com'
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 'John', 'email');
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals($array['item1'], $result[0]['content']);
|
||||
$this->assertEquals('item1', $result[0]['path']);
|
||||
$this->assertEquals(['email'], $result[0]['missing_key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test finding missing single key when searching by specific key-value pair
|
||||
*/
|
||||
public function testFindMissingSingleKeyWithKeyValueSearch()
|
||||
{
|
||||
$array = [
|
||||
'user1' => [
|
||||
'id' => 1,
|
||||
'name' => 'Alice'
|
||||
// missing 'status' key
|
||||
],
|
||||
'user2' => [
|
||||
'id' => 2,
|
||||
'name' => 'Bob',
|
||||
'status' => 'active'
|
||||
],
|
||||
'user3' => [
|
||||
'id' => 1, // same id as user1
|
||||
'name' => 'Charlie',
|
||||
'status' => 'inactive'
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 1, 'status', 'id');
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals($array['user1'], $result[0]['content']);
|
||||
$this->assertEquals('user1', $result[0]['path']);
|
||||
$this->assertEquals(['status'], $result[0]['missing_key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test finding missing multiple keys
|
||||
*/
|
||||
public function testFindMissingMultipleKeys()
|
||||
{
|
||||
$array = [
|
||||
'record1' => [
|
||||
'name' => 'Test',
|
||||
'value' => 100
|
||||
// missing both 'date' and 'status' keys
|
||||
],
|
||||
'record2' => [
|
||||
'name' => 'Test',
|
||||
'value' => 200,
|
||||
'date' => '2023-01-01'
|
||||
// missing 'status' key
|
||||
],
|
||||
'record3' => [
|
||||
'name' => 'Test',
|
||||
'value' => 300,
|
||||
'date' => '2023-01-02',
|
||||
'status' => 'complete'
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 'Test', ['date', 'status']);
|
||||
|
||||
$this->assertCount(2, $result);
|
||||
|
||||
// First result should be record1 missing both keys
|
||||
$this->assertEquals($array['record1'], $result[0]['content']);
|
||||
$this->assertEquals('record1', $result[0]['path']);
|
||||
$this->assertContains('date', $result[0]['missing_key']);
|
||||
$this->assertContains('status', $result[0]['missing_key']);
|
||||
$this->assertCount(2, $result[0]['missing_key']);
|
||||
|
||||
// Second result should be record2 missing status key
|
||||
$this->assertEquals($array['record2'], $result[1]['content']);
|
||||
$this->assertEquals('record2', $result[1]['path']);
|
||||
$this->assertEquals(['status'], $result[1]['missing_key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with nested arrays
|
||||
*/
|
||||
public function testFindMissingKeyInNestedArrays()
|
||||
{
|
||||
$array = [
|
||||
'section1' => [
|
||||
'items' => [
|
||||
'item1' => [
|
||||
'name' => 'Product A',
|
||||
'price' => 99.99
|
||||
// missing 'category' key
|
||||
],
|
||||
'item2' => [
|
||||
'name' => 'Product B',
|
||||
'price' => 149.99,
|
||||
'category' => 'electronics'
|
||||
]
|
||||
]
|
||||
],
|
||||
'section2' => [
|
||||
'data' => [
|
||||
'name' => 'Product A', // same name as nested item
|
||||
'category' => 'books'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 'Product A', 'category');
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals($array['section1']['items']['item1'], $result[0]['content']);
|
||||
$this->assertEquals('section1:items:item1', $result[0]['path']);
|
||||
$this->assertEquals(['category'], $result[0]['missing_key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test when no arrays are missing the required key
|
||||
*/
|
||||
public function testNoMissingKeys()
|
||||
{
|
||||
$array = [
|
||||
'item1' => [
|
||||
'name' => 'John',
|
||||
'email' => 'john@example.com'
|
||||
],
|
||||
'item2' => [
|
||||
'name' => 'Jane',
|
||||
'email' => 'jane@example.com'
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 'John', 'email');
|
||||
|
||||
$this->assertEmpty($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test when search value is not found in any array
|
||||
*/
|
||||
public function testSearchValueNotFound()
|
||||
{
|
||||
$array = [
|
||||
'item1' => [
|
||||
'name' => 'John',
|
||||
'age' => 25
|
||||
],
|
||||
'item2' => [
|
||||
'name' => 'Jane',
|
||||
'age' => 30
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 'Bob', 'email');
|
||||
|
||||
$this->assertEmpty($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with different data types for search value
|
||||
*/
|
||||
public function testDifferentSearchValueTypes()
|
||||
{
|
||||
$array = [
|
||||
'item1' => [
|
||||
'active' => true,
|
||||
'count' => 5
|
||||
// missing 'label' key
|
||||
],
|
||||
'item2' => [
|
||||
'active' => false,
|
||||
'count' => 10,
|
||||
'label' => 'test'
|
||||
],
|
||||
'item3' => [
|
||||
'active' => true, // same boolean as item1
|
||||
'count' => 15,
|
||||
'label' => 'another'
|
||||
]
|
||||
];
|
||||
|
||||
// Test with boolean
|
||||
$result = ArrayHandler::findArraysMissingKey($array, true, 'label', 'active');
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('item1', $result[0]['path']);
|
||||
|
||||
// Test with integer
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 5, 'label', 'count');
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('item1', $result[0]['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with empty array
|
||||
*/
|
||||
public function testEmptyArray()
|
||||
{
|
||||
$array = [];
|
||||
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 'test', 'key');
|
||||
|
||||
$this->assertEmpty($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with array containing non-array values
|
||||
*/
|
||||
public function testMixedArrayTypes()
|
||||
{
|
||||
$array = [
|
||||
'string_value' => 'hello',
|
||||
'numeric_value' => 123,
|
||||
'array_value' => [
|
||||
'name' => 'test',
|
||||
// missing 'type' key
|
||||
],
|
||||
'another_array' => [
|
||||
'name' => 'test',
|
||||
'type' => 'example'
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 'test', 'type');
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals($array['array_value'], $result[0]['content']);
|
||||
$this->assertEquals('array_value', $result[0]['path']);
|
||||
$this->assertEquals(['type'], $result[0]['missing_key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test path building with deeper nesting
|
||||
*/
|
||||
public function testDeepNestingPathBuilding()
|
||||
{
|
||||
$array = [
|
||||
'level1' => [
|
||||
'level2' => [
|
||||
'level3' => [
|
||||
'items' => [
|
||||
'target_item' => [
|
||||
'name' => 'deep_test',
|
||||
// missing 'required_field'
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 'deep_test', 'required_field');
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('level1:level2:level3:items:target_item', $result[0]['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with custom path separator
|
||||
*/
|
||||
public function testCustomPathSeparator()
|
||||
{
|
||||
$array = [
|
||||
'level1' => [
|
||||
'level2' => [
|
||||
'item' => [
|
||||
'name' => 'test',
|
||||
// missing 'type' key
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 'test', 'type', null, '/');
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('level1/level2/item', $result[0]['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test default path separator behavior
|
||||
*/
|
||||
public function testDefaultPathSeparator()
|
||||
{
|
||||
$array = [
|
||||
'parent' => [
|
||||
'child' => [
|
||||
'name' => 'test',
|
||||
// missing 'value' key
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
// Using default separator (should be ':')
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 'test', 'value');
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('parent:child', $result[0]['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test different path separators don't affect search logic
|
||||
*/
|
||||
public function testPathSeparatorDoesNotAffectSearchLogic()
|
||||
{
|
||||
$array = [
|
||||
'section' => [
|
||||
'data' => [
|
||||
'id' => 123,
|
||||
'name' => 'item'
|
||||
// missing 'status'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
// Test with different separators - results should be identical except for path
|
||||
$result1 = ArrayHandler::findArraysMissingKey($array, 123, 'status', 'id', ':');
|
||||
$result2 = ArrayHandler::findArraysMissingKey($array, 123, 'status', 'id', '.');
|
||||
$result3 = ArrayHandler::findArraysMissingKey($array, 123, 'status', 'id', '/');
|
||||
|
||||
$this->assertCount(1, $result1);
|
||||
$this->assertCount(1, $result2);
|
||||
$this->assertCount(1, $result3);
|
||||
|
||||
// Content and missing_key should be the same
|
||||
$this->assertEquals($result1[0]['content'], $result2[0]['content']);
|
||||
$this->assertEquals($result1[0]['content'], $result3[0]['content']);
|
||||
$this->assertEquals($result1[0]['missing_key'], $result2[0]['missing_key']);
|
||||
$this->assertEquals($result1[0]['missing_key'], $result3[0]['missing_key']);
|
||||
|
||||
// Paths should be different based on separator
|
||||
$this->assertEquals('section:data', $result1[0]['path']);
|
||||
$this->assertEquals('section.data', $result2[0]['path']);
|
||||
$this->assertEquals('section/data', $result3[0]['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* test type checking
|
||||
*/
|
||||
public function testStrictTypeChecking()
|
||||
{
|
||||
$array = [
|
||||
'item1' => [
|
||||
'id' => '123', // string
|
||||
'name' => 'test'
|
||||
// missing 'status'
|
||||
],
|
||||
'item2' => [
|
||||
'id' => 123, // integer
|
||||
'name' => 'test2',
|
||||
'status' => 'active'
|
||||
]
|
||||
];
|
||||
|
||||
// Search for integer 123 - should only match item2
|
||||
$result = ArrayHandler::findArraysMissingKey($array, 123, 'status', 'id');
|
||||
$this->assertEmpty($result); // item2 has the status key
|
||||
|
||||
// Search for string '123' - should only match item1
|
||||
$result = ArrayHandler::findArraysMissingKey($array, '123', 'status', 'id');
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('item1', $result[0]['path']);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -0,0 +1,333 @@
|
||||
<?php
|
||||
|
||||
// This code was create by Claude Sonnet 4
|
||||
// modification for value checks with assertEqualsCanonicalizing
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CoreLibs\Combined\ArrayHandler;
|
||||
|
||||
class CoreLibsCombinedArrayHandlerKsortArrayTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test basic ascending sort (default behavior)
|
||||
*/
|
||||
public function testKsortArrayBasicAscending(): void
|
||||
{
|
||||
$input = [
|
||||
'zebra' => 'value1',
|
||||
'apple' => 'value2',
|
||||
'banana' => 'value3',
|
||||
'cherry' => 'value4'
|
||||
];
|
||||
|
||||
$expected = [
|
||||
'apple' => 'value2',
|
||||
'banana' => 'value3',
|
||||
'cherry' => 'value4',
|
||||
'zebra' => 'value1'
|
||||
];
|
||||
|
||||
$result = ArrayHandler::ksortArray($input);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals(array_keys($expected), array_keys($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test descending sort with reverse=true
|
||||
*/
|
||||
public function testKsortArrayDescending(): void
|
||||
{
|
||||
$input = [
|
||||
'zebra' => 'value1',
|
||||
'apple' => 'value2',
|
||||
'banana' => 'value3',
|
||||
'cherry' => 'value4'
|
||||
];
|
||||
|
||||
$expected = [
|
||||
'zebra' => 'value1',
|
||||
'cherry' => 'value4',
|
||||
'banana' => 'value3',
|
||||
'apple' => 'value2'
|
||||
];
|
||||
|
||||
$result = ArrayHandler::ksortArray($input, false, true);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals(array_keys($expected), array_keys($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case-insensitive ascending sort
|
||||
*/
|
||||
public function testKsortArrayCaseInsensitiveAscending(): void
|
||||
{
|
||||
$input = [
|
||||
'Zebra' => 'value1',
|
||||
'apple' => 'value2',
|
||||
'Banana' => 'value3',
|
||||
'cherry' => 'value4'
|
||||
];
|
||||
|
||||
$expected = [
|
||||
'apple' => 'value2',
|
||||
'Banana' => 'value3',
|
||||
'cherry' => 'value4',
|
||||
'Zebra' => 'value1'
|
||||
];
|
||||
|
||||
$result = ArrayHandler::ksortArray($input, true);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals(array_keys($expected), array_keys($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case-insensitive descending sort
|
||||
*/
|
||||
public function testKsortArrayCaseInsensitiveDescending(): void
|
||||
{
|
||||
$input = [
|
||||
'Zebra' => 'value1',
|
||||
'apple' => 'value2',
|
||||
'Banana' => 'value3',
|
||||
'cherry' => 'value4'
|
||||
];
|
||||
|
||||
$expected = [
|
||||
'Zebra' => 'value1',
|
||||
'cherry' => 'value4',
|
||||
'Banana' => 'value3',
|
||||
'apple' => 'value2'
|
||||
];
|
||||
|
||||
$result = ArrayHandler::ksortArray($input, true, true);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals(array_keys($expected), array_keys($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with mixed case keys to verify case sensitivity behavior
|
||||
*/
|
||||
public function testKsortArrayCaseSensitivityComparison(): void
|
||||
{
|
||||
$input = [
|
||||
'B' => 'value1',
|
||||
'a' => 'value2',
|
||||
'C' => 'value3',
|
||||
'b' => 'value4'
|
||||
];
|
||||
|
||||
// Case-sensitive sort (uppercase comes before lowercase in ASCII)
|
||||
$expectedCaseSensitive = [
|
||||
'B' => 'value1',
|
||||
'C' => 'value3',
|
||||
'a' => 'value2',
|
||||
'b' => 'value4'
|
||||
];
|
||||
|
||||
// Case-insensitive sort
|
||||
$expectedCaseInsensitive = [
|
||||
'a' => 'value2',
|
||||
'B' => 'value1',
|
||||
'b' => 'value4',
|
||||
'C' => 'value3'
|
||||
];
|
||||
|
||||
$resultCaseSensitive = ArrayHandler::ksortArray($input, false);
|
||||
$resultCaseInsensitive = ArrayHandler::ksortArray($input, true);
|
||||
|
||||
$this->assertEquals($expectedCaseSensitive, $resultCaseSensitive);
|
||||
$this->assertEquals($expectedCaseInsensitive, $resultCaseInsensitive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with numeric string keys
|
||||
*/
|
||||
public function testKsortArrayNumericStringKeys(): void
|
||||
{
|
||||
$input = [
|
||||
'10' => 'value1',
|
||||
'2' => 'value2',
|
||||
'1' => 'value3',
|
||||
'20' => 'value4'
|
||||
];
|
||||
|
||||
// String comparison, not numeric
|
||||
$expected = [
|
||||
'1' => 'value3',
|
||||
'10' => 'value1',
|
||||
'2' => 'value2',
|
||||
'20' => 'value4'
|
||||
];
|
||||
|
||||
$result = ArrayHandler::ksortArray($input);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with special characters in keys
|
||||
*/
|
||||
public function testKsortArraySpecialCharacters(): void
|
||||
{
|
||||
$input = [
|
||||
'key_with_underscore' => 'value1',
|
||||
'key-with-dash' => 'value2',
|
||||
'key.with.dot' => 'value3',
|
||||
'key with space' => 'value4',
|
||||
'keyWithCamelCase' => 'value5'
|
||||
];
|
||||
|
||||
$result = ArrayHandler::ksortArray($input);
|
||||
|
||||
// Verify it doesn't throw an error and maintains all keys
|
||||
$this->assertCount(5, $result);
|
||||
$this->assertArrayHasKey('key_with_underscore', $result);
|
||||
$this->assertArrayHasKey('key-with-dash', $result);
|
||||
$this->assertArrayHasKey('key.with.dot', $result);
|
||||
$this->assertArrayHasKey('key with space', $result);
|
||||
$this->assertArrayHasKey('keyWithCamelCase', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with empty array
|
||||
*/
|
||||
public function testKsortArrayEmpty(): void
|
||||
{
|
||||
$input = [];
|
||||
$result = ArrayHandler::ksortArray($input);
|
||||
$this->assertEquals([], $result);
|
||||
$this->assertIsArray($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with single element array
|
||||
*/
|
||||
public function testKsortArraySingleElement(): void
|
||||
{
|
||||
$input = ['onlykey' => 'onlyvalue'];
|
||||
$result = ArrayHandler::ksortArray($input);
|
||||
$this->assertEquals($input, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that original array is not modified (function returns new array)
|
||||
*/
|
||||
public function testKsortArrayDoesNotModifyOriginal(): void
|
||||
{
|
||||
$original = [
|
||||
'zebra' => 'value1',
|
||||
'apple' => 'value2',
|
||||
'banana' => 'value3'
|
||||
];
|
||||
|
||||
$originalCopy = $original; // Keep a copy for comparison
|
||||
$result = ArrayHandler::ksortArray($original);
|
||||
|
||||
// Original array should remain unchanged
|
||||
$this->assertEquals($originalCopy, $original);
|
||||
$this->assertNotEquals(array_keys($original), array_keys($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with complex mixed data types as values
|
||||
*/
|
||||
public function testKsortArrayMixedValueTypes(): void
|
||||
{
|
||||
$input = [
|
||||
'string_key' => 'string_value',
|
||||
'array_key' => ['nested', 'array'],
|
||||
'int_key' => 42,
|
||||
'bool_key' => true,
|
||||
'null_key' => null
|
||||
];
|
||||
|
||||
$result = ArrayHandler::ksortArray($input);
|
||||
|
||||
// Check that all keys are preserved and sorted
|
||||
$expectedKeys = ['array_key', 'bool_key', 'int_key', 'null_key', 'string_key'];
|
||||
$this->assertEquals($expectedKeys, array_keys($result));
|
||||
|
||||
// Check that values are preserved correctly
|
||||
$this->assertEquals('string_value', $result['string_key']);
|
||||
$this->assertEquals(['nested', 'array'], $result['array_key']);
|
||||
$this->assertEquals(42, $result['int_key']);
|
||||
$this->assertTrue($result['bool_key']);
|
||||
$this->assertNull($result['null_key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all parameter combinations
|
||||
*/
|
||||
public function testKsortArrayAllParameterCombinations(): void
|
||||
{
|
||||
$input = [
|
||||
'Delta' => 'value1',
|
||||
'alpha' => 'value2',
|
||||
'Charlie' => 'value3',
|
||||
'bravo' => 'value4'
|
||||
];
|
||||
|
||||
// Test all 4 combinations
|
||||
$result1 = ArrayHandler::ksortArray($input, false, false); // default
|
||||
$result2 = ArrayHandler::ksortArray($input, false, true); // reverse only
|
||||
$result3 = ArrayHandler::ksortArray($input, true, false); // lowercase only
|
||||
$result4 = ArrayHandler::ksortArray($input, true, true); // both
|
||||
|
||||
// Each should produce different ordering
|
||||
$this->assertNotEquals(array_keys($result1), array_keys($result2));
|
||||
$this->assertNotEquals(array_keys($result1), array_keys($result3));
|
||||
$this->assertNotEquals(array_keys($result1), array_keys($result4));
|
||||
$this->assertNotEquals(array_keys($result2), array_keys($result3));
|
||||
$this->assertNotEquals(array_keys($result2), array_keys($result4));
|
||||
$this->assertNotEquals(array_keys($result3), array_keys($result4));
|
||||
|
||||
// But all should have same keys and values, just different order
|
||||
$this->assertEqualsCanonicalizing(array_values($input), array_values($result1));
|
||||
$this->assertEqualsCanonicalizing(array_values($input), array_values($result2));
|
||||
$this->assertEqualsCanonicalizing(array_values($input), array_values($result3));
|
||||
$this->assertEqualsCanonicalizing(array_values($input), array_values($result4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for comprehensive testing
|
||||
*/
|
||||
public function sortingParametersProvider(): array
|
||||
{
|
||||
return [
|
||||
'default' => [false, false],
|
||||
'reverse' => [false, true],
|
||||
'lowercase' => [true, false],
|
||||
'lowercase_reverse' => [true, true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that function works with all parameter combinations using data provider
|
||||
*
|
||||
* @dataProvider sortingParametersProvider
|
||||
*/
|
||||
public function testKsortArrayWithDataProvider(bool $lowerCase, bool $reverse): void
|
||||
{
|
||||
$input = [
|
||||
'Zebra' => 'animal1',
|
||||
'apple' => 'fruit1',
|
||||
'Banana' => 'fruit2',
|
||||
'cat' => 'animal2'
|
||||
];
|
||||
|
||||
$result = ArrayHandler::ksortArray($input, $lowerCase, $reverse);
|
||||
|
||||
// Basic assertions that apply to all combinations
|
||||
$this->assertIsArray($result);
|
||||
$this->assertCount(4, $result);
|
||||
$this->assertArrayHasKey('Zebra', $result);
|
||||
$this->assertArrayHasKey('apple', $result);
|
||||
$this->assertArrayHasKey('Banana', $result);
|
||||
$this->assertArrayHasKey('cat', $result);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -0,0 +1,383 @@
|
||||
<?php
|
||||
|
||||
// create by Claude Sonnet 4
|
||||
|
||||
// testRecursiveSearchWithFlatResult had wrong retunr count
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CoreLibs\Combined\ArrayHandler;
|
||||
|
||||
class CoreLibsCombinedArrayHandlerSelectArrayFromOptionTest extends TestCase
|
||||
{
|
||||
private array $testData;
|
||||
private array $nestedTestData;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->testData = [
|
||||
'item1' => [
|
||||
'name' => 'John',
|
||||
'age' => 25,
|
||||
'status' => 'active',
|
||||
'score' => 85.5
|
||||
],
|
||||
'item2' => [
|
||||
'name' => 'jane',
|
||||
'age' => 30,
|
||||
'status' => 'inactive',
|
||||
'score' => 92.0
|
||||
],
|
||||
'item3' => [
|
||||
'name' => 'Bob',
|
||||
'age' => 25,
|
||||
'status' => 'active',
|
||||
'score' => 78.3
|
||||
],
|
||||
'item4' => [
|
||||
'name' => 'Alice',
|
||||
'age' => 35,
|
||||
'status' => 'pending',
|
||||
'score' => 88.7
|
||||
]
|
||||
];
|
||||
|
||||
$this->nestedTestData = [
|
||||
'level1_a' => [
|
||||
'name' => 'Level1A',
|
||||
'type' => 'parent',
|
||||
'children' => [
|
||||
'child1' => [
|
||||
'name' => 'Child1',
|
||||
'type' => 'child',
|
||||
'active' => true
|
||||
],
|
||||
'child2' => [
|
||||
'name' => 'Child2',
|
||||
'type' => 'child',
|
||||
'active' => false
|
||||
]
|
||||
]
|
||||
],
|
||||
'level1_b' => [
|
||||
'name' => 'Level1B',
|
||||
'type' => 'parent',
|
||||
'children' => [
|
||||
'child3' => [
|
||||
'name' => 'Child3',
|
||||
'type' => 'child',
|
||||
'active' => true,
|
||||
'nested' => [
|
||||
'deep1' => [
|
||||
'name' => 'Deep1',
|
||||
'type' => 'deep',
|
||||
'active' => true
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
'item5' => [
|
||||
'name' => 'Direct',
|
||||
'type' => 'child',
|
||||
'active' => false
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function testEmptyArrayReturnsEmpty(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption([], 'name', 'John');
|
||||
$this->assertEmpty($result);
|
||||
}
|
||||
|
||||
public function testBasicStringSearch(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption($this->testData, 'name', 'John');
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertArrayHasKey('item1', $result);
|
||||
$this->assertEquals('John', $result['item1']['name']);
|
||||
}
|
||||
|
||||
public function testBasicIntegerSearch(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption($this->testData, 'age', 25);
|
||||
|
||||
$this->assertCount(2, $result);
|
||||
$this->assertArrayHasKey('item1', $result);
|
||||
$this->assertArrayHasKey('item3', $result);
|
||||
}
|
||||
|
||||
public function testBasicFloatSearch(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption($this->testData, 'score', 85.5);
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertArrayHasKey('item1', $result);
|
||||
$this->assertEquals(85.5, $result['item1']['score']);
|
||||
}
|
||||
|
||||
public function testBasicBooleanSearch(): void
|
||||
{
|
||||
$data = [
|
||||
'item1' => ['enabled' => true, 'name' => 'Test1'],
|
||||
'item2' => ['enabled' => false, 'name' => 'Test2'],
|
||||
'item3' => ['enabled' => true, 'name' => 'Test3']
|
||||
];
|
||||
|
||||
$result = ArrayHandler::selectArrayFromOption($data, 'enabled', true);
|
||||
|
||||
$this->assertCount(2, $result);
|
||||
$this->assertArrayHasKey('item1', $result);
|
||||
$this->assertArrayHasKey('item3', $result);
|
||||
}
|
||||
|
||||
public function testStrictComparison(): void
|
||||
{
|
||||
$data = [
|
||||
'item1' => ['value' => '25', 'name' => 'String25'],
|
||||
'item2' => ['value' => 25, 'name' => 'Int25'],
|
||||
'item3' => ['value' => 25.0, 'name' => 'Float25']
|
||||
];
|
||||
|
||||
// Non-strict should match all
|
||||
$nonStrictResult = ArrayHandler::selectArrayFromOption($data, 'value', 25, false);
|
||||
$this->assertCount(3, $nonStrictResult);
|
||||
|
||||
// Strict should only match exact type
|
||||
$strictResult = ArrayHandler::selectArrayFromOption($data, 'value', 25, true);
|
||||
$this->assertCount(1, $strictResult);
|
||||
$this->assertArrayHasKey('item2', $strictResult);
|
||||
}
|
||||
|
||||
public function testCaseInsensitiveSearch(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption($this->testData, 'name', 'JANE', false, true);
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertArrayHasKey('item2', $result);
|
||||
$this->assertEquals('jane', $result['item2']['name']);
|
||||
}
|
||||
|
||||
public function testCaseSensitiveSearch(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption($this->testData, 'name', 'JANE', false, false);
|
||||
|
||||
$this->assertEmpty($result);
|
||||
}
|
||||
|
||||
public function testRecursiveSearchWithFlatResult(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption(
|
||||
$this->nestedTestData,
|
||||
'type',
|
||||
'child',
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
':*'
|
||||
);
|
||||
|
||||
$this->assertCount(4, $result);
|
||||
$this->assertArrayHasKey('level1_a:*children:*child1', $result);
|
||||
$this->assertArrayHasKey('level1_a:*children:*child2', $result);
|
||||
$this->assertArrayHasKey('level1_b:*children:*child3', $result);
|
||||
$this->assertArrayHasKey('item5', $result);
|
||||
}
|
||||
|
||||
public function testRecursiveSearchWithNestedResult(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption(
|
||||
$this->nestedTestData,
|
||||
'type',
|
||||
'child',
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false
|
||||
);
|
||||
|
||||
$this->assertCount(3, $result);
|
||||
$this->assertArrayHasKey('level1_a', $result);
|
||||
$this->assertArrayHasKey('level1_b', $result);
|
||||
$this->assertArrayHasKey('item5', $result);
|
||||
|
||||
// Check nested structure is preserved
|
||||
$this->assertArrayHasKey('children', $result['level1_a']);
|
||||
$this->assertArrayHasKey('child1', $result['level1_a']['children']);
|
||||
$this->assertArrayHasKey('child2', $result['level1_a']['children']);
|
||||
}
|
||||
|
||||
public function testRecursiveSearchDeepNesting(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption(
|
||||
$this->nestedTestData,
|
||||
'type',
|
||||
'deep',
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
':*'
|
||||
);
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertArrayHasKey('level1_b:*children:*child3:*nested:*deep1', $result);
|
||||
$this->assertEquals('Deep1', $result['level1_b:*children:*child3:*nested:*deep1']['name']);
|
||||
}
|
||||
|
||||
public function testCustomFlatSeparator(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption(
|
||||
$this->nestedTestData,
|
||||
'type',
|
||||
'child',
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
'|'
|
||||
);
|
||||
|
||||
$this->assertArrayHasKey('level1_a|children|child1', $result);
|
||||
$this->assertArrayHasKey('level1_a|children|child2', $result);
|
||||
$this->assertArrayHasKey('level1_b|children|child3', $result);
|
||||
}
|
||||
|
||||
public function testNonRecursiveSearch(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption(
|
||||
$this->nestedTestData,
|
||||
'type',
|
||||
'child',
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
// Should only find direct matches, not nested ones
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertArrayHasKey('item5', $result);
|
||||
}
|
||||
|
||||
public function testNoMatchesFound(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption($this->testData, 'name', 'NonExistent');
|
||||
|
||||
$this->assertEmpty($result);
|
||||
}
|
||||
|
||||
public function testMissingLookupKey(): void
|
||||
{
|
||||
$result = ArrayHandler::selectArrayFromOption($this->testData, 'nonexistent_key', 'value');
|
||||
|
||||
$this->assertEmpty($result);
|
||||
}
|
||||
|
||||
public function testCombinedStrictAndCaseInsensitive(): void
|
||||
{
|
||||
$data = [
|
||||
'item1' => ['name' => 'Test', 'id' => '123'],
|
||||
'item2' => ['name' => 'test', 'id' => 123],
|
||||
'item3' => ['name' => 'TEST', 'id' => '123']
|
||||
];
|
||||
|
||||
// Case insensitive but strict type matching
|
||||
$result = ArrayHandler::selectArrayFromOption($data, 'id', '123', true, true);
|
||||
|
||||
$this->assertCount(2, $result);
|
||||
$this->assertArrayHasKey('item1', $result);
|
||||
$this->assertArrayHasKey('item3', $result);
|
||||
}
|
||||
|
||||
public function testBooleanWithCaseInsensitive(): void
|
||||
{
|
||||
$data = [
|
||||
'item1' => ['active' => true, 'name' => 'Test1'],
|
||||
'item2' => ['active' => false, 'name' => 'Test2']
|
||||
];
|
||||
|
||||
// Case insensitive flag should not affect boolean comparison
|
||||
$result = ArrayHandler::selectArrayFromOption($data, 'active', true, false, true);
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertArrayHasKey('item1', $result);
|
||||
}
|
||||
|
||||
public function testArrayWithNumericKeys(): void
|
||||
{
|
||||
$data = [
|
||||
0 => ['name' => 'First', 'type' => 'test'],
|
||||
1 => ['name' => 'Second', 'type' => 'test'],
|
||||
2 => ['name' => 'Third', 'type' => 'other']
|
||||
];
|
||||
|
||||
$result = ArrayHandler::selectArrayFromOption($data, 'type', 'test');
|
||||
|
||||
$this->assertCount(2, $result);
|
||||
$this->assertArrayHasKey(0, $result);
|
||||
$this->assertArrayHasKey(1, $result);
|
||||
}
|
||||
|
||||
public function testRecursiveWithMixedKeyTypes(): void
|
||||
{
|
||||
$data = [
|
||||
'string_key' => [
|
||||
'name' => 'Parent',
|
||||
'type' => 'parent',
|
||||
0 => [
|
||||
'name' => 'Child0',
|
||||
'type' => 'child'
|
||||
],
|
||||
'child_key' => [
|
||||
'name' => 'ChildKey',
|
||||
'type' => 'child'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::selectArrayFromOption($data, 'type', 'child', false, false, true, true, ':*');
|
||||
|
||||
$this->assertCount(2, $result);
|
||||
$this->assertArrayHasKey('string_key:*0', $result);
|
||||
$this->assertArrayHasKey('string_key:*child_key', $result);
|
||||
}
|
||||
|
||||
public function testAllParametersCombined(): void
|
||||
{
|
||||
$data = [
|
||||
'parent1' => [
|
||||
'name' => 'Parent1',
|
||||
'status' => 'ACTIVE',
|
||||
'children' => [
|
||||
'child1' => [
|
||||
'name' => 'Child1',
|
||||
'status' => 'active'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::selectArrayFromOption(
|
||||
$data,
|
||||
'status',
|
||||
'active',
|
||||
false, // not strict
|
||||
true, // case insensitive
|
||||
true, // recursive
|
||||
true, // flat result
|
||||
'|' // custom separator
|
||||
);
|
||||
|
||||
$this->assertCount(2, $result);
|
||||
$this->assertArrayHasKey('parent1', $result);
|
||||
$this->assertArrayHasKey('parent1|children|child1', $result);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -0,0 +1,328 @@
|
||||
<?php
|
||||
|
||||
// This code was create by Claude Sonnet 4
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CoreLibs\Combined\ArrayHandler;
|
||||
|
||||
class CoreLibsCombinedArrayHandlerSortArrayTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test basic ascending sort without maintaining keys
|
||||
*/
|
||||
public function testBasicAscendingSort()
|
||||
{
|
||||
$input = [3, 1, 4, 1, 5, 9];
|
||||
$expected = [1, 1, 3, 4, 5, 9];
|
||||
|
||||
$result = ArrayHandler::sortArray($input);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals(array_keys($expected), array_keys($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic descending sort without maintaining keys
|
||||
*/
|
||||
public function testBasicDescendingSort()
|
||||
{
|
||||
$input = [3, 1, 4, 1, 5, 9];
|
||||
$expected = [9, 5, 4, 3, 1, 1];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, false, true);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals(array_keys($expected), array_keys($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ascending sort with key maintenance
|
||||
*/
|
||||
public function testAscendingSortWithKeyMaintenance()
|
||||
{
|
||||
$input = ['c' => 3, 'a' => 1, 'd' => 4, 'b' => 1, 'e' => 5];
|
||||
$expected = ['a' => 1, 'b' => 1, 'c' => 3, 'd' => 4, 'e' => 5];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, false, false, true);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test descending sort with key maintenance
|
||||
*/
|
||||
public function testDescendingSortWithKeyMaintenance()
|
||||
{
|
||||
$input = ['c' => 3, 'a' => 1, 'd' => 4, 'b' => 1, 'e' => 5];
|
||||
$expected = ['e' => 5, 'd' => 4, 'c' => 3, 'a' => 1, 'b' => 1];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, false, true, true);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test string sorting with lowercase conversion
|
||||
*/
|
||||
public function testStringLowerCaseSort()
|
||||
{
|
||||
$input = ['Banana', 'apple', 'Cherry', 'date'];
|
||||
$expected = ['apple', 'Banana', 'Cherry', 'date'];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, true);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test string sorting with lowercase conversion in reverse
|
||||
*/
|
||||
public function testStringLowerCaseSortReverse()
|
||||
{
|
||||
$input = ['Banana', 'apple', 'Cherry', 'date'];
|
||||
$expected = ['date', 'Cherry', 'Banana', 'apple'];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, true, true);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test string sorting with lowercase conversion and key maintenance
|
||||
*/
|
||||
public function testStringLowerCaseSortWithKeys()
|
||||
{
|
||||
$input = ['b' => 'Banana', 'a' => 'apple', 'c' => 'Cherry', 'd' => 'date'];
|
||||
$expected = ['a' => 'apple', 'b' => 'Banana', 'c' => 'Cherry', 'd' => 'date'];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, true, false, true);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test string sorting with lowercase conversion, reverse, and key maintenance
|
||||
*/
|
||||
public function testStringLowerCaseSortReverseWithKeys()
|
||||
{
|
||||
$input = ['b' => 'Banana', 'a' => 'apple', 'c' => 'Cherry', 'd' => 'date'];
|
||||
$expected = ['d' => 'date', 'c' => 'Cherry', 'b' => 'Banana', 'a' => 'apple'];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, true, true, true);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test numeric string sorting with SORT_NUMERIC flag
|
||||
*/
|
||||
public function testNumericStringSorting()
|
||||
{
|
||||
$input = ['10', '2', '1', '20'];
|
||||
$expected = ['1', '2', '10', '20'];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, false, false, false, SORT_NUMERIC);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test natural string sorting with SORT_NATURAL flag
|
||||
*/
|
||||
public function testNaturalStringSorting()
|
||||
{
|
||||
$input = ['img1.png', 'img10.png', 'img2.png', 'img20.png'];
|
||||
$expected = ['img1.png', 'img2.png', 'img10.png', 'img20.png'];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, false, false, false, SORT_NATURAL);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with empty array
|
||||
*/
|
||||
public function testEmptyArray()
|
||||
{
|
||||
$input = [];
|
||||
$expected = [];
|
||||
|
||||
$result = ArrayHandler::sortArray($input);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with single element array
|
||||
*/
|
||||
public function testSingleElementArray()
|
||||
{
|
||||
$input = [42];
|
||||
$expected = [42];
|
||||
|
||||
$result = ArrayHandler::sortArray($input);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with array containing null values
|
||||
*/
|
||||
public function testArrayWithNullValues()
|
||||
{
|
||||
$input = [3, null, 1, null, 2];
|
||||
$expected = [null, null, 1, 2, 3];
|
||||
|
||||
$result = ArrayHandler::sortArray($input);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with mixed data types
|
||||
*/
|
||||
public function testMixedDataTypes()
|
||||
{
|
||||
$input = [3, '1', 4.5, '2', 1];
|
||||
|
||||
$result = ArrayHandler::sortArray($input);
|
||||
|
||||
// Should sort according to PHP's natural comparison rules
|
||||
$this->assertIsArray($result);
|
||||
$this->assertCount(5, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that original array is not modified (immutability)
|
||||
*/
|
||||
public function testOriginalArrayNotModified()
|
||||
{
|
||||
$original = [3, 1, 4, 1, 5, 9];
|
||||
$input = $original;
|
||||
|
||||
$result = ArrayHandler::sortArray($input);
|
||||
|
||||
$this->assertEquals($original, $input);
|
||||
$this->assertNotEquals($input, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case sensitivity without lowercase flag
|
||||
*/
|
||||
public function testCaseSensitivityWithoutLowercase()
|
||||
{
|
||||
$input = ['Banana', 'apple', 'Cherry'];
|
||||
|
||||
$result = ArrayHandler::sortArray($input);
|
||||
|
||||
// Capital letters should come before lowercase in ASCII sort
|
||||
$this->assertEquals('Banana', $result[0]);
|
||||
$this->assertEquals('Cherry', $result[1]);
|
||||
$this->assertEquals('apple', $result[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all parameters combination
|
||||
*/
|
||||
public function testAllParametersCombination()
|
||||
{
|
||||
$input = ['z' => 'Zebra', 'a' => 'apple', 'b' => 'Banana'];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, true, true, true, SORT_REGULAR);
|
||||
|
||||
// Should be sorted by lowercase, reversed, with keys maintained
|
||||
$keys = array_keys($result);
|
||||
$values = array_values($result);
|
||||
|
||||
$this->assertEquals(['z', 'b', 'a'], $keys);
|
||||
$this->assertEquals(['Zebra', 'Banana', 'apple'], $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test floating point numbers
|
||||
*/
|
||||
public function testFloatingPointNumbers()
|
||||
{
|
||||
$input = [3.14, 2.71, 1.41, 1.73];
|
||||
$expected = [1.41, 1.73, 2.71, 3.14];
|
||||
|
||||
$result = ArrayHandler::sortArray($input);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with duplicate values and key maintenance
|
||||
*/
|
||||
public function testDuplicateValuesWithKeyMaintenance()
|
||||
{
|
||||
$input = ['first' => 1, 'second' => 2, 'third' => 1, 'fourth' => 2];
|
||||
|
||||
$result = ArrayHandler::sortArray($input, false, false, true);
|
||||
|
||||
$this->assertCount(4, $result);
|
||||
$this->assertEquals([1, 1, 2, 2], array_values($result));
|
||||
// Keys should be preserved
|
||||
$this->assertArrayHasKey('first', $result);
|
||||
$this->assertArrayHasKey('second', $result);
|
||||
$this->assertArrayHasKey('third', $result);
|
||||
$this->assertArrayHasKey('fourth', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for comprehensive parameter testing
|
||||
*/
|
||||
public function sortParameterProvider(): array
|
||||
{
|
||||
return [
|
||||
'basic_ascending' => [
|
||||
[3, 1, 4, 2],
|
||||
false, false, false, SORT_REGULAR,
|
||||
[1, 2, 3, 4]
|
||||
],
|
||||
'basic_descending' => [
|
||||
[3, 1, 4, 2],
|
||||
false, true, false, SORT_REGULAR,
|
||||
[4, 3, 2, 1]
|
||||
],
|
||||
'lowercase_ascending' => [
|
||||
['Banana', 'apple', 'Cherry'],
|
||||
true, false, false, SORT_REGULAR,
|
||||
['apple', 'Banana', 'Cherry']
|
||||
],
|
||||
'lowercase_descending' => [
|
||||
['Banana', 'apple', 'Cherry'],
|
||||
true, true, false, SORT_REGULAR,
|
||||
['Cherry', 'Banana', 'apple']
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test various parameter combinations using data provider
|
||||
*
|
||||
* @dataProvider sortParameterProvider
|
||||
*/
|
||||
public function testSortParameterCombinations(
|
||||
array $input,
|
||||
bool $lowercase,
|
||||
bool $reverse,
|
||||
bool $maintainKeys,
|
||||
int $params,
|
||||
array $expected
|
||||
) {
|
||||
$result = ArrayHandler::sortArray($input, $lowercase, $reverse, $maintainKeys, $params);
|
||||
|
||||
if (!$maintainKeys) {
|
||||
$this->assertEquals($expected, $result);
|
||||
} else {
|
||||
$this->assertEquals($expected, array_values($result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,9 @@ $test_array = [
|
||||
'element_c' => [
|
||||
'type' => 'email'
|
||||
],
|
||||
'element_d' => [
|
||||
'type' => 'butter'
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -70,7 +73,15 @@ echo "ARRAYSEARCHRECURSIVEALL(email, [array], type): "
|
||||
|
||||
// simple search
|
||||
echo "ARRAYSEARCHSIMPLE([array], type, email): "
|
||||
. (string)ArrayHandler::arraySearchSimple($test_array, 'type', 'email') . "<br>";
|
||||
. Dgs::prBl(ArrayHandler::arraySearchSimple($test_array, 'type', 'email')) . "<br>";
|
||||
echo "ARRAYSEARCHSIMPLE([array], type, not): "
|
||||
. Dgs::prBl(ArrayHandler::arraySearchSimple($test_array, 'type', 'not')) . "<br>";
|
||||
echo "ARRAYSEARCHSIMPLE([array], type, [email,butter]): "
|
||||
. Dgs::prBl(ArrayHandler::arraySearchSimple($test_array, 'type', ['email', 'butter'])) . "<br>";
|
||||
echo "ARRAYSEARCHSIMPLE([array], type, [email,not]): "
|
||||
. Dgs::prBl(ArrayHandler::arraySearchSimple($test_array, 'type', ['email', 'not'])) . "<br>";
|
||||
echo "ARRAYSEARCHSIMPLE([array], type, [never,not]): "
|
||||
. Dgs::prBl(ArrayHandler::arraySearchSimple($test_array, 'type', ['never', 'not'])) . "<br>";
|
||||
|
||||
$array_1 = [
|
||||
'foo' => 'bar'
|
||||
@@ -292,6 +303,231 @@ print "array intersect key: " . DgS::printAr($keys) . ": " . DgS::printAr($out)
|
||||
|
||||
print "array + suffix: " . DgS::printAr(ArrayHandler::arrayModifyKey($array, key_mod_suffix:'_attached')) . "<br>";
|
||||
|
||||
print "<hr>";
|
||||
$unsorted = [9, 5, 'A', 4, 'B', 6, 'c', 'C', 'a'];
|
||||
$unsorted_keys = [
|
||||
'A' => 9, 'B' => 5, 'C' => 'A', 'D' => 4, 'E' => 'B', 'F' => 6, 'G' => 'c',
|
||||
'H1' => 'D', 'B1' => 'd', 'H' => 'C', 'I' => 'a'
|
||||
];
|
||||
print "Unsorted: " . DgS::printAr($unsorted) . "<br>";
|
||||
print "(sort): " . DgS::printAr(ArrayHandler::sortArray($unsorted)) . "<br>";
|
||||
print "(sort, lower): " . DgS::printAr(ArrayHandler::sortArray($unsorted, case_insensitive:true)) . "<br>";
|
||||
print "(sort, reverse): " . DgS::printAr(ArrayHandler::sortArray($unsorted, reverse:true)) . "<br>";
|
||||
print "(sort, lower, reverse): "
|
||||
. DgS::printAr(ArrayHandler::sortArray($unsorted, case_insensitive:true, reverse:true)) . "<br>";
|
||||
print "(sort, keys): " . DgS::printAr(ArrayHandler::sortArray($unsorted_keys, maintain_keys:true)) . "<br>";
|
||||
print "(sort, keys, lower): "
|
||||
. DgS::printAr(ArrayHandler::sortArray($unsorted_keys, maintain_keys:true, case_insensitive:true)) . "<br>";
|
||||
|
||||
print "<hr>";
|
||||
$unsorted = [9 => 'A', 5 => 'B', 'A' => 'C', 4 => 'D', 'B' => 'E', 6 => 'F', 'c' => 'G', 'C' => 'H', 'a' => 'I'];
|
||||
print "Unsorted Keys: " . DgS::printAr($unsorted) . "<br>";
|
||||
print "(sort): " . DgS::printAr(ArrayHandler::sortArray($unsorted)) . "<br>";
|
||||
print "(sort, keys): " . DgS::printAr(ArrayHandler::sortArray($unsorted, maintain_keys:true)) . "<br>";
|
||||
print "(kosrt): " . DgS::printAr(ArrayHandler::ksortArray($unsorted)) . "<br>";
|
||||
print "(kosrt, reverse): " . DgS::printAr(ArrayHandler::ksortArray($unsorted, reverse:true)) . "<br>";
|
||||
print "(kosrt, lower case, reverse): "
|
||||
. DgS::printAr(ArrayHandler::ksortArray($unsorted, case_insensitive:true, reverse:true)) . "<br>";
|
||||
|
||||
|
||||
print "<hr>";
|
||||
$nested = [
|
||||
'B' => 'foo', 'a', '0', 9,
|
||||
1 => ['z', 'b', 'a'],
|
||||
'd' => ['zaip', 'bar', 'baz']
|
||||
];
|
||||
print "Nested: " . DgS::printAr($nested) . "<br>";
|
||||
print "(sort): " . DgS::printAr(ArrayHandler::sortArray($nested)) . "<br>";
|
||||
print "(ksort): " . DgS::printAr(ArrayHandler::ksortArray($nested)) . "<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): " . 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 = [
|
||||
'a' => [
|
||||
'lookup' => 1,
|
||||
'value' => 'Foo',
|
||||
'other' => 'Bar',
|
||||
],
|
||||
'b' => [
|
||||
'lookup' => 1,
|
||||
'value' => 'AAA',
|
||||
'other' => 'Other',
|
||||
],
|
||||
'c' => [
|
||||
'lookup' => 0,
|
||||
'value' => 'CCC',
|
||||
'other' => 'OTHER',
|
||||
],
|
||||
'd' => [
|
||||
'd-1' => [
|
||||
'lookup' => 1,
|
||||
'value' => 'D SUB 1',
|
||||
'other' => 'Other B',
|
||||
],
|
||||
'd-2' => [
|
||||
'lookup' => 0,
|
||||
'value' => 'D SUB 2',
|
||||
'other' => 'Other C',
|
||||
],
|
||||
'more' => [
|
||||
'lookup' => 1,
|
||||
'd-more-1' => [
|
||||
'lookup' => 1,
|
||||
'value' => 'D MORE SUB 1',
|
||||
'other' => 'Other C',
|
||||
],
|
||||
'd-more-2' => [
|
||||
'lookup' => 0,
|
||||
'value' => 'D MORE SUB 0',
|
||||
'other' => 'Other C',
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
print "Search: " . DgS::printAr($search_array) . "<br>";
|
||||
print "Result: " . DgS::printAr(ArrayHandler::selectArrayFromOption(
|
||||
$search_array,
|
||||
'lookup',
|
||||
1,
|
||||
)) . "<br>";
|
||||
print "Result: " . DgS::printAr(ArrayHandler::selectArrayFromOption(
|
||||
$search_array,
|
||||
'lookup',
|
||||
1,
|
||||
recursive:true
|
||||
)) . "<br>";
|
||||
print "Result: " . DgS::printAr(ArrayHandler::selectArrayFromOption(
|
||||
$search_array,
|
||||
'lookup',
|
||||
1,
|
||||
recursive:true,
|
||||
flat_separator:'-=-'
|
||||
)) . "<br>";
|
||||
print "Result: " . DgS::printAr(ArrayHandler::selectArrayFromOption(
|
||||
$search_array,
|
||||
'lookup',
|
||||
1,
|
||||
recursive:true,
|
||||
flat_result:false
|
||||
)) . "<br>";
|
||||
print "Result: " . DgS::printAr(ArrayHandler::selectArrayFromOption(
|
||||
$search_array,
|
||||
'other',
|
||||
'Other',
|
||||
case_insensitive:false,
|
||||
)) . "<br>";
|
||||
|
||||
$nestedTestData = [
|
||||
'level1_a' => [
|
||||
'name' => 'Level1A',
|
||||
'type' => 'parent',
|
||||
'children' => [
|
||||
'child1' => [
|
||||
'name' => 'Child1',
|
||||
'type' => 'child',
|
||||
'active' => true
|
||||
],
|
||||
'child2' => [
|
||||
'name' => 'Child2',
|
||||
'type' => 'child',
|
||||
'active' => false
|
||||
]
|
||||
]
|
||||
],
|
||||
'level1_b' => [
|
||||
'name' => 'Level1B',
|
||||
'type' => 'parent',
|
||||
'children' => [
|
||||
'child3' => [
|
||||
'name' => 'Child3',
|
||||
'type' => 'child',
|
||||
'active' => true,
|
||||
'nested' => [
|
||||
'deep1' => [
|
||||
'name' => 'Deep1',
|
||||
'type' => 'deep',
|
||||
'active' => true
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
'item5' => [
|
||||
'name' => 'Direct',
|
||||
'type' => 'child',
|
||||
'active' => false
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::selectArrayFromOption(
|
||||
$nestedTestData,
|
||||
'type',
|
||||
'child',
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
':*'
|
||||
);
|
||||
print "*1*Result: " . DgS::printAr($result) . "<br>";
|
||||
$data = [
|
||||
'parent1' => [
|
||||
'name' => 'Parent1',
|
||||
'status' => 'ACTIVE',
|
||||
'children' => [
|
||||
'child1' => [
|
||||
'name' => 'Child1',
|
||||
'status' => 'active'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$result = ArrayHandler::selectArrayFromOption(
|
||||
$data,
|
||||
'status',
|
||||
'active',
|
||||
false, // not strict
|
||||
true, // case insensitive
|
||||
true, // recursive
|
||||
true, // flat result
|
||||
'|' // custom separator
|
||||
);
|
||||
print "*2*Result: " . DgS::printAr($result) . "<br>";
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace CoreLibs\Combined;
|
||||
|
||||
class ArrayHandler
|
||||
{
|
||||
public const string DATA_SEPARATOR = '#';
|
||||
public const string DATA_SEPARATOR = ':';
|
||||
|
||||
/**
|
||||
* searches key = value in an array / array
|
||||
@@ -151,7 +151,7 @@ class ArrayHandler
|
||||
* on default does not strict check, so string '4' will match int 4 and vica versa
|
||||
*
|
||||
* @param array<mixed> $array search in as array
|
||||
* @param string|int $key key (key to search in)
|
||||
* @param string|int $key key (key to search in)
|
||||
* @param string|int|bool|array<string|int|bool> $value values list (what to find)
|
||||
* @param bool $strict [false], if set to true, will strict check key/value
|
||||
* @return bool true on found, false on not found
|
||||
@@ -243,45 +243,73 @@ class ArrayHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: move to CoreLibs
|
||||
* Search in an array for value and check in the same array block for the required key
|
||||
* Search in an array for value with or without key and
|
||||
* check in the same array block for the required key
|
||||
* 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
|
||||
*
|
||||
* @param array<mixed> $array
|
||||
* @param string|int|float|bool $search_value
|
||||
* @param string $required_key
|
||||
* @param string|array<string> $required_key
|
||||
* @param ?string $serach_key [null]
|
||||
* @param string $path_separator [DATA_SEPARATOR]
|
||||
* @param string $current_path
|
||||
* @return array<array{content?:array<mixed>,path?:string,missing_key?:string}>
|
||||
*/
|
||||
public static function findArraysMissingKey(
|
||||
array $array,
|
||||
string|int|float|bool $search_value,
|
||||
string $required_key,
|
||||
string|array $required_key,
|
||||
?string $search_key = null,
|
||||
string $path_separator = self::DATA_SEPARATOR,
|
||||
string $current_path = ''
|
||||
): array {
|
||||
$results = [];
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
$path = $current_path ? $current_path . self::DATA_SEPARATOR . $key : $key;
|
||||
$path = $current_path ? $current_path . $path_separator . $key : $key;
|
||||
|
||||
if (is_array($value)) {
|
||||
// Check if this array contains the search value
|
||||
$containsValue = in_array($search_value, $value, true);
|
||||
// either any value match or with key
|
||||
if ($search_key === null) {
|
||||
$containsValue = in_array($search_value, $value, true);
|
||||
} else {
|
||||
$containsValue = array_key_exists($search_key, $value) && $value[$search_key] === $search_value;
|
||||
}
|
||||
|
||||
// If it contains the value but doesn't have the required key
|
||||
if ($containsValue && !array_key_exists($required_key, $value)) {
|
||||
if (
|
||||
$containsValue &&
|
||||
(
|
||||
(
|
||||
is_string($required_key) &&
|
||||
!array_key_exists($required_key, $value)
|
||||
) || (
|
||||
is_array($required_key) &&
|
||||
count(array_intersect($required_key, array_keys($value))) !== count($required_key)
|
||||
)
|
||||
)
|
||||
) {
|
||||
$results[] = [
|
||||
'content' => $value,
|
||||
'path' => $path,
|
||||
'missing_key' => $required_key
|
||||
'missing_key' => is_array($required_key) ?
|
||||
array_values(array_diff($required_key, array_keys($value))) :
|
||||
[$required_key]
|
||||
];
|
||||
}
|
||||
|
||||
// Recursively search nested arrays
|
||||
$results = array_merge(
|
||||
$results,
|
||||
self::findArraysMissingKey($value, $search_value, $required_key, $path)
|
||||
self::findArraysMissingKey(
|
||||
$value,
|
||||
$search_value,
|
||||
$required_key,
|
||||
$search_key,
|
||||
$path_separator,
|
||||
$path
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -290,15 +318,17 @@ class ArrayHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: move to CoreLibs
|
||||
* currenly only over one level, find key => value entry and return set with key
|
||||
* for all matching
|
||||
* Find key => value entry and return set with key for all matching
|
||||
* Can search recursively through nested arrays if recursive flag is set
|
||||
*
|
||||
* @param array<mixed> $array
|
||||
* @param string $lookup
|
||||
* @param array<mixed> $array
|
||||
* @param string $lookup
|
||||
* @param int|string|float|bool $search
|
||||
* @param bool $strict [default=false]
|
||||
* @param bool $case_senstivie [default=false]
|
||||
* @param bool $strict [false]
|
||||
* @param bool $case_insensitive [false]
|
||||
* @param bool $recursive [false]
|
||||
* @param bool $flat_result [true] If set to false and recursive is on the result is a nested array
|
||||
* @param string $flat_separator [DATA_SEPARATOR] if flat result is true, can be any string
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function selectArrayFromOption(
|
||||
@@ -306,28 +336,63 @@ class ArrayHandler
|
||||
string $lookup,
|
||||
int|string|float|bool $search,
|
||||
bool $strict = false,
|
||||
bool $case_senstivie = false,
|
||||
bool $case_insensitive = false,
|
||||
bool $recursive = false,
|
||||
bool $flat_result = true,
|
||||
string $flat_separator = self::DATA_SEPARATOR
|
||||
): array {
|
||||
// skip on empty
|
||||
if ($array == []) {
|
||||
return [];
|
||||
}
|
||||
// init return result
|
||||
$result = [];
|
||||
if ($case_senstivie && is_string($search)) {
|
||||
// case sensitive convert if string
|
||||
if ($case_insensitive && is_string($search)) {
|
||||
$search = strtolower($search);
|
||||
}
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
// skip on not set
|
||||
if (!isset($value[$lookup])) {
|
||||
continue;
|
||||
// Handle current level search
|
||||
if (isset($value[$lookup])) {
|
||||
$compareValue = $value[$lookup];
|
||||
|
||||
if ($case_insensitive && is_string($compareValue)) {
|
||||
$compareValue = strtolower($compareValue);
|
||||
}
|
||||
|
||||
if (
|
||||
($strict && $search === $compareValue) ||
|
||||
(!$strict && $search == $compareValue)
|
||||
) {
|
||||
$result[$key] = $value;
|
||||
}
|
||||
}
|
||||
if ($case_senstivie && is_string($value[$value])) {
|
||||
$value[$lookup] = strtolower($value[$value]);
|
||||
}
|
||||
if (
|
||||
($strict && $search === $value[$lookup]) ||
|
||||
(!$strict && $search == $value[$lookup])
|
||||
) {
|
||||
$result[$key] = $value;
|
||||
continue;
|
||||
// Handle recursive search if flag is set
|
||||
if ($recursive && is_array($value)) {
|
||||
$recursiveResults = self::selectArrayFromOption(
|
||||
$value,
|
||||
$lookup,
|
||||
$search,
|
||||
$strict,
|
||||
$case_insensitive,
|
||||
true,
|
||||
$flat_result,
|
||||
$flat_separator
|
||||
);
|
||||
|
||||
// Merge recursive results with current results
|
||||
// Preserve keys by using array_merge with string keys or + operator
|
||||
foreach ($recursiveResults as $recKey => $recValue) {
|
||||
if ($flat_result) {
|
||||
$result[$key . $flat_separator . $recKey] = $recValue;
|
||||
} else {
|
||||
$result[$key][$recKey] = $recValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -653,8 +718,8 @@ class ArrayHandler
|
||||
* does not change order in array
|
||||
*
|
||||
* @param array<string|int,mixed> $in_array
|
||||
* @param string $key_mod_prefix [default=''] key prefix string
|
||||
* @param string $key_mod_suffix [default=''] key suffix string
|
||||
* @param string $key_mod_prefix [''] key prefix string
|
||||
* @param string $key_mod_suffix [''] key suffix string
|
||||
* @return array<string|int,mixed>
|
||||
*/
|
||||
public static function arrayModifyKey(
|
||||
@@ -680,35 +745,66 @@ class ArrayHandler
|
||||
|
||||
/**
|
||||
* sort array and return in same call
|
||||
* sort ascending, value
|
||||
* sort ascending or descending with or without lower case convert
|
||||
* value only, will loose key connections unless preserve_keys is set to true
|
||||
*
|
||||
* @param array<mixed> $array array to sort by values
|
||||
* @param int $params sort flags
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public function sortArray(array $array, int $params = SORT_REGULAR): array
|
||||
{
|
||||
return sort($array, $params) ? $array : $array;
|
||||
public static function sortArray(
|
||||
array $array,
|
||||
bool $case_insensitive = false,
|
||||
bool $reverse = false,
|
||||
bool $maintain_keys = false,
|
||||
int $params = SORT_REGULAR
|
||||
): array {
|
||||
$fk_sort_lower_case = function (string $a, string $b): int {
|
||||
return strtolower($a) <=> strtolower($b);
|
||||
};
|
||||
$fk_sort_lower_case_reverse = function (string $a, string $b): int {
|
||||
return strtolower($b) <=> strtolower($a);
|
||||
};
|
||||
$case_insensitive ? (
|
||||
$maintain_keys ?
|
||||
(uasort($array, $reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case)) :
|
||||
(usort($array, $reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case))
|
||||
) :
|
||||
(
|
||||
$maintain_keys ?
|
||||
($reverse ? arsort($array, $params) : asort($array, $params)) :
|
||||
($reverse ? rsort($array, $params) : sort($array, $params))
|
||||
);
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* sort by key ascending and return
|
||||
* sort by key ascending or descending and return
|
||||
*
|
||||
* @param array<mixed> $array
|
||||
* @param bool $lower_case [default=false]
|
||||
* @param bool $case_insensitive [false]
|
||||
* @param bool $reverse [false]
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function ksortArray(array $array, bool $lower_case = false): array
|
||||
public static function ksortArray(array $array, bool $case_insensitive = false, bool $reverse = false): array
|
||||
{
|
||||
$fk_sort_lower_case = function (string $a, string $b): int {
|
||||
return strtolower($a) <=> strtolower($b);
|
||||
};
|
||||
$fk_sort_lower_case_reverse = function (string $a, string $b): int {
|
||||
return strtolower($b) <=> strtolower($a);
|
||||
};
|
||||
$fk_sort = function (string $a, string $b): int {
|
||||
return $a <=> $b;
|
||||
};
|
||||
$fk_sort_reverse = function (string $a, string $b): int {
|
||||
return $b <=> $a;
|
||||
};
|
||||
uksort(
|
||||
$array,
|
||||
$lower_case ? $fk_sort_lower_case : $fk_sort
|
||||
$case_insensitive ?
|
||||
($reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case) :
|
||||
($reverse ? $fk_sort_reverse : $fk_sort)
|
||||
);
|
||||
return $array;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user