Browse Source

Merge pull request #8233 from cakephp/issue-8177

Correctly sort sparse data that uses numeric keys.
Yves P 10 years ago
parent
commit
107c1cadef
2 changed files with 61 additions and 2 deletions
  1. 8 2
      src/Utility/Hash.php
  2. 53 0
      tests/TestCase/Utility/HashTest.php

+ 8 - 2
src/Utility/Hash.php

@@ -933,12 +933,18 @@ class Hash
             $data = array_values($data);
         }
         $sortValues = static::extract($data, $path);
-        $sortCount = count($sortValues);
         $dataCount = count($data);
 
         // Make sortValues match the data length, as some keys could be missing
         // the sorted value path.
-        if ($sortCount < $dataCount) {
+        $missingData = count($sortValues) < $dataCount;
+        if ($missingData && $numeric) {
+            // Get the path without the leading '{n}.'
+            $itemPath = substr($path, 4);
+            foreach ($data as $key => $value) {
+                $sortValues[$key] = static::get($value, $itemPath);
+            }
+        } elseif ($missingData) {
             $sortValues = array_pad($sortValues, $dataCount, null);
         }
         $result = static::_squash($sortValues);

+ 53 - 0
tests/TestCase/Utility/HashTest.php

@@ -1775,6 +1775,59 @@ class HashTest extends TestCase
     }
 
     /**
+     * Test sorting on a nested key that is sometimes undefined.
+     *
+     * @return void
+     */
+    public function testSortSparse()
+    {
+        $data = [
+            [
+                'id' => 1,
+                'title' => 'element 1',
+                'extra' => 1,
+            ],
+            [
+                'id' => 2,
+                'title' => 'element 2',
+                'extra' => 2,
+            ],
+            [
+                'id' => 3,
+                'title' => 'element 3',
+            ],
+            [
+                'id' => 4,
+                'title' => 'element 4',
+                'extra' => 4,
+            ]
+        ];
+        $result = Hash::sort($data, '{n}.extra', 'desc', 'natural');
+        $expected = [
+            [
+                'id' => 4,
+                'title' => 'element 4',
+                'extra' => 4,
+            ],
+            [
+                'id' => 2,
+                'title' => 'element 2',
+                'extra' => 2,
+            ],
+            [
+                'id' => 1,
+                'title' => 'element 1',
+                'extra' => 1,
+            ],
+            [
+                'id' => 3,
+                'title' => 'element 3',
+            ],
+        ];
+        $this->assertSame($expected, $result);
+    }
+
+    /**
      * Test insert()
      *
      * @return void