Skip to content

Commit

Permalink
Port case-insensitive sorting to 3.1
Browse files Browse the repository at this point in the history
Refs #7217
  • Loading branch information
markstory committed Aug 26, 2015
1 parent a53c351 commit 4864980
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
23 changes: 22 additions & 1 deletion src/Utility/Hash.php
Expand Up @@ -901,10 +901,19 @@ public static function apply(array $data, $path, $function)
* - `natural` Compare items as strings using "natural ordering" in a human friendly way.
* Will sort foo10 below foo2 as an example.
*
* To do case insensitive sorting, pass the type as an array as follows:
*
* ```
* Hash::sort($data, 'some.attribute', 'asc', ['type' => 'regular', 'ignoreCase' => true]);
* ```
*
* When using the array form, `type` defaults to 'regular'. The `ignoreCase` option
* defaults to `false`.
*
* @param array $data An array of data to sort
* @param string $path A Set-compatible path to the array value
* @param string $dir See directions above. Defaults to 'asc'.
* @param string $type See direction types above. Defaults to 'regular'.
* @param array|string $type See direction types above. Defaults to 'regular'.
* @return array Sorted array of data
* @link http://book.cakephp.org/3.0/en/core-libraries/hash.html#Hash::sort
*/
Expand Down Expand Up @@ -932,7 +941,16 @@ public static function sort(array $data, $path, $dir = 'asc', $type = 'regular')
$values = static::extract($result, '{n}.value');

$dir = strtolower($dir);
$ignoreCase = false;

// $type can be overloaded for case insensitive sort
if (is_array($type)) {
$type += array('ignoreCase' => false, 'type' => 'regular');
$ignoreCase = $type['ignoreCase'];
$type = $type['type'];
}
$type = strtolower($type);

if ($dir === 'asc') {
$dir = SORT_ASC;
} else {
Expand All @@ -947,6 +965,9 @@ public static function sort(array $data, $path, $dir = 'asc', $type = 'regular')
} else {
$type = SORT_REGULAR;
}
if ($ignoreCase) {
$values = array_map('mb_strtolower', $values);
}
array_multisort($values, $dir, $type, $keys, $dir, $type);
$sorted = [];
$keys = array_unique($keys);
Expand Down
47 changes: 47 additions & 0 deletions tests/TestCase/Utility/HashTest.php
Expand Up @@ -1446,6 +1446,53 @@ public function testSortString()
$this->assertEquals($expected, $result);
}


/**
* test sorting with string ignoring case.
*
* @return void
*/
public function testSortStringIgnoreCase()
{
$toSort = [
['Item' => ['name' => 'bar']],
['Item' => ['name' => 'Baby']],
['Item' => ['name' => 'Baz']],
['Item' => ['name' => 'bat']],
];
$sorted = Hash::sort($toSort, '{n}.Item.name', 'asc', ['type' => 'string', 'ignoreCase' => true]);
$expected = [
['Item' => ['name' => 'Baby']],
['Item' => ['name' => 'bar']],
['Item' => ['name' => 'bat']],
['Item' => ['name' => 'Baz']],
];
$this->assertEquals($expected, $sorted);
}

/**
* test regular sorting ignoring case.
*
* @return void
*/
public function testSortRegularIgnoreCase()
{
$toSort = [
['Item' => ['name' => 'bar']],
['Item' => ['name' => 'Baby']],
['Item' => ['name' => 'Baz']],
['Item' => ['name' => 'bat']],
];
$sorted = Hash::sort($toSort, '{n}.Item.name', 'asc', ['type' => 'regular', 'ignoreCase' => true]);
$expected = [
['Item' => ['name' => 'Baby']],
['Item' => ['name' => 'bar']],
['Item' => ['name' => 'bat']],
['Item' => ['name' => 'Baz']],
];
$this->assertEquals($expected, $sorted);
}

/**
* Test insert()
*
Expand Down

0 comments on commit 4864980

Please sign in to comment.