Add additional sort flag support.

Add natural, numeric, and string sorting to Hash.
Fixes #1700
This commit is contained in:
mark_story 2012-04-01 23:09:15 -04:00
parent 432d00de19
commit e5ca80b711
2 changed files with 96 additions and 6 deletions

View file

@ -976,7 +976,7 @@ class HashTest extends CakeTestCase {
0 => array('Shirt' => array('color' => 'black')),
1 => array('Person' => array('name' => 'Jeff')),
);
$a = Hash::sort($a, '{n}.Person.name', 'ASC');
$a = Hash::sort($a, '{n}.Person.name', 'ASC', 'STRING');
$this->assertEquals($a, $b);
$names = array(
@ -989,7 +989,7 @@ class HashTest extends CakeTestCase {
array('employees' => array(array('name' => array()))),
array('employees' => array(array('name' => array())))
);
$result = Hash::sort($names, '{n}.employees.0.name', 'asc', 1);
$result = Hash::sort($names, '{n}.employees.0.name', 'asc');
$expected = array(
array('employees' => array(
array('name' => array('first' => 'John', 'last' => 'Doe')))
@ -1003,6 +1003,74 @@ class HashTest extends CakeTestCase {
$this->assertEquals($expected, $result);
}
/**
* Test sort() with numeric option.
*
* @return void
*/
public function testSortNumeric() {
$items = array(
array('Item' => array('price' => '155,000')),
array('Item' => array('price' => '139,000')),
array('Item' => array('price' => '275,622')),
array('Item' => array('price' => '230,888')),
array('Item' => array('price' => '66,000')),
);
$result = Hash::sort($items, '{n}.Item.price', 'asc', 'numeric');
$expected = array(
array('Item' => array('price' => '66,000')),
array('Item' => array('price' => '139,000')),
array('Item' => array('price' => '155,000')),
array('Item' => array('price' => '230,888')),
array('Item' => array('price' => '275,622')),
);
$this->assertEquals($expected, $result);
$result = Hash::sort($items, '{n}.Item.price', 'desc', 'numeric');
$expected = array(
array('Item' => array('price' => '275,622')),
array('Item' => array('price' => '230,888')),
array('Item' => array('price' => '155,000')),
array('Item' => array('price' => '139,000')),
array('Item' => array('price' => '66,000')),
);
$this->assertEquals($expected, $result);
}
/**
* Test natural sorting.
*
* @return void
*/
public function testSortNatural() {
$items = array(
array('Item' => array('image' => 'img1.jpg')),
array('Item' => array('image' => 'img99.jpg')),
array('Item' => array('image' => 'img12.jpg')),
array('Item' => array('image' => 'img10.jpg')),
array('Item' => array('image' => 'img2.jpg')),
);
$result = Hash::sort($items, '{n}.Item.image', 'desc', 'natural');
$expected = array(
array('Item' => array('image' => 'img99.jpg')),
array('Item' => array('image' => 'img12.jpg')),
array('Item' => array('image' => 'img10.jpg')),
array('Item' => array('image' => 'img2.jpg')),
array('Item' => array('image' => 'img1.jpg')),
);
$this->assertEquals($expected, $result);
$result = Hash::sort($items, '{n}.Item.image', 'asc', 'natural');
$expected = array(
array('Item' => array('image' => 'img1.jpg')),
array('Item' => array('image' => 'img2.jpg')),
array('Item' => array('image' => 'img10.jpg')),
array('Item' => array('image' => 'img12.jpg')),
array('Item' => array('image' => 'img99.jpg')),
);
$this->assertEquals($expected, $result);
}
/**
* test sorting with out of order keys.
*

View file

@ -717,13 +717,25 @@ class Hash {
/**
* Sorts an array by any value, determined by a Set-compatible path
*
* ### Sort directions
*
* - `asc` Sort ascending.
* - `desc` Sort descending.
*
* ## Sort types
*
* - `numeric` Sort by numeric value.
* - `regular` Sort by numeric value.
* - `string` Sort by numeric value.
*
* @param array $data An array of data to sort
* @param string $path A Set-compatible path to the array value
* @param string $dir Direction of sorting - either ascending (ASC), or descending (DESC)
* @param string $dir See directions above.
* @param string $type See direction types above. Defaults to 'regular'.
* @return array Sorted array of data
* @link http://book.cakephp.org/2.0/en/core-utility-libraries/hash.html#Hash::sort
*/
public static function sort(array $data, $path, $dir) {
public static function sort(array $data, $path, $dir, $type = 'regular') {
$originalKeys = array_keys($data);
$numeric = is_numeric(implode('', $originalKeys));
if ($numeric) {
@ -743,12 +755,22 @@ class Hash {
$values = self::extract($result, '{n}.value');
$dir = strtolower($dir);
$type = strtolower($type);
if ($dir === 'asc') {
$dir = SORT_ASC;
} elseif ($dir === 'desc') {
} else {
$dir = SORT_DESC;
}
array_multisort($values, $dir, $keys, $dir);
if ($type === 'numeric') {
$type = SORT_NUMERIC;
} elseif ($type === 'string') {
$type = SORT_STRING;
} elseif ($type === 'natural') {
$type = SORT_NATURAL;
} else {
$type = SORT_REGULAR;
}
array_multisort($values, $dir, $type, $keys, $dir, $type);
$sorted = array();
$keys = array_unique($keys);