Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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);
@ceeram

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

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

Please sign in to comment.
Something went wrong with that request. Please try again.