Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add additional sort flag support.

Add natural, numeric, and string sorting to Hash.
Fixes #1700
  • Loading branch information...
commit e5ca80b711236934cb1975a1cc082c6cb5b4a004 1 parent 432d00d
@markstory markstory authored
Showing with 96 additions and 6 deletions.
  1. +70 −2 lib/Cake/Test/Case/Utility/HashTest.php
  2. +26 −4 lib/Cake/Utility/Hash.php
View
72 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')))
@@ -1004,6 +1004,74 @@ public function testSort() {
}
/**
+ * 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.
*
* @return void
View
30 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;
@ceeram Collaborator
ceeram added a note

Use of undefined constant SORT_NATURAL - assumed 'SORT_NATURAL'
This doesnt seem to be a valid sort parameter:
http://php.net/manual/en/function.array-multisort.php

Edit:
seems to be added in 5.4:
http://www.php.net/manual/en/function.sort.php

@markstory Owner

Yeah you have to run the newest fanciest PHP to use everything. I'll add a note to the comments about that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ } else {
+ $type = SORT_REGULAR;
+ }
+ array_multisort($values, $dir, $type, $keys, $dir, $type);
$sorted = array();
$keys = array_unique($keys);
Please sign in to comment.
Something went wrong with that request. Please try again.