diff --git a/lib/Cake/Test/Case/Utility/HashTest.php b/lib/Cake/Test/Case/Utility/HashTest.php index 3e0b1c53e90..a8233137eed 100644 --- a/lib/Cake/Test/Case/Utility/HashTest.php +++ b/lib/Cake/Test/Case/Utility/HashTest.php @@ -976,7 +976,7 @@ public function testSort() { 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 @@ public function testSort() { 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 @@ public function testSort() { $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. * diff --git a/lib/Cake/Utility/Hash.php b/lib/Cake/Utility/Hash.php index dc96c769ebf..b29eb8641e2 100644 --- a/lib/Cake/Utility/Hash.php +++ b/lib/Cake/Utility/Hash.php @@ -717,13 +717,25 @@ public static function apply(array $data, $path, $function) { /** * 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 @@ public static function sort(array $data, $path, $dir) { $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);