Browse Source

Fix string handling of Hash::remove() and Hash::_simpleOp('remove')

Hash::remove() mishandles '0' in path strings.
Hash::_simpleOp('remove') causes a fatal error when data is a string.
chinpei215 8 years ago
parent
commit
ea5f05b461
2 changed files with 42 additions and 3 deletions
  1. 5 3
      src/Utility/Hash.php
  2. 37 0
      tests/TestCase/Utility/HashTest.php

+ 5 - 3
src/Utility/Hash.php

@@ -365,7 +365,9 @@ class Hash
                 }
             } elseif ($op === 'remove') {
                 if ($i === $last) {
-                    unset($_list[$key]);
+                    if (!is_string($_list)) {
+                        unset($_list[$key]);
+                    }
 
                     return $data;
                 }
@@ -414,7 +416,7 @@ class Hash
             if ($match && is_array($v)) {
                 if ($conditions) {
                     if (static::_matches($v, $conditions)) {
-                        if ($nextPath) {
+                        if ($nextPath !== '') {
                             $data[$k] = static::remove($v, $nextPath);
                         } else {
                             unset($data[$k]);
@@ -426,7 +428,7 @@ class Hash
                 if (empty($data[$k])) {
                     unset($data[$k]);
                 }
-            } elseif ($match && empty($nextPath)) {
+            } elseif ($match && $nextPath === '') {
                 unset($data[$k]);
             }
         }

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

@@ -2127,6 +2127,43 @@ class HashTest extends TestCase
         $this->assertEquals($expected, $result);
         $result = Hash::remove($array, '{n}.{n}.part');
         $this->assertEquals($expected, $result);
+
+        $array = [
+            'foo' => 'string',
+        ];
+        $expected = $array;
+        $result = Hash::remove($array, 'foo.bar');
+        $this->assertEquals($expected, $result);
+
+        $array = [
+            'foo' => 'string',
+            'bar' => [
+                0 => 'a',
+                1 => 'b',
+            ],
+        ];
+        $expected = [
+            'foo' => 'string',
+            'bar' => [
+                1 => 'b',
+            ],
+        ];
+        $result = Hash::remove($array, '{s}.0');
+        $this->assertEquals($expected, $result);
+
+        $array = [
+            'foo' => [
+                0 => 'a',
+                1 => 'b',
+            ],
+        ];
+        $expected = [
+            'foo' => [
+                1 => 'b',
+            ],
+        ];
+        $result = Hash::remove($array, 'foo[1=b].0');
+        $this->assertEquals($expected, $result);
     }
 
     /**