From: Tim Otten Date: Tue, 5 Jul 2022 23:23:36 +0000 (-0700) Subject: CRM_Utils_Array - All `pathGet()`-like methods will accept empty-path X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=bbb4b90ad2105a9e07f2767b383c6569b8ab8eac;p=civicrm-core.git CRM_Utils_Array - All `pathGet()`-like methods will accept empty-path These two are equivalent: (A) $data['sub1']['sub2']['sub3'] (B) CRM_Utils_Array::pathGet($data, ['sub1', 'sub2', 'sub3']) But what if the list of subpaths is empty -- ie you're accessing the top-level item? (A) $data (B) CRM_Utils_Array::pathGet($data, []) It worked correctly on `pathGet()`, but accessing the top-level using a related methods (eg `pathSet()`) would generate a PHP error. This commit ensures that related methods can be used to check/update the top-level item (ie path===[]). Note that there is some decent test-coverage already for the regular scenarios (eg `testGetSetPathParts()`). --- diff --git a/CRM/Utils/Array.php b/CRM/Utils/Array.php index 627e27d0c1..12822ae357 100644 --- a/CRM/Utils/Array.php +++ b/CRM/Utils/Array.php @@ -1077,6 +1077,9 @@ class CRM_Utils_Array { * @return bool */ public static function pathIsset($values, $path) { + if ($path === []) { + return ($values !== NULL); + } foreach ($path as $key) { if (!is_array($values) || !isset($values[$key])) { return FALSE; @@ -1100,6 +1103,11 @@ class CRM_Utils_Array { * TRUE if anything has been removed. FALSE if no changes were required. */ public static function pathUnset(&$values, $path, $cleanup = FALSE) { + if (count($path) === 0) { + $values = NULL; + return TRUE; + } + if (count($path) === 1) { if (isset($values[$path[0]])) { unset($values[$path[0]]); @@ -1131,6 +1139,10 @@ class CRM_Utils_Array { * Ex: 456. */ public static function pathSet(&$values, $pathParts, $value) { + if ($pathParts === []) { + $values = $value; + return; + } $r = &$values; $last = array_pop($pathParts); foreach ($pathParts as $part) { diff --git a/tests/phpunit/CRM/Utils/ArrayTest.php b/tests/phpunit/CRM/Utils/ArrayTest.php index 17cc44dfbd..42715789d2 100644 --- a/tests/phpunit/CRM/Utils/ArrayTest.php +++ b/tests/phpunit/CRM/Utils/ArrayTest.php @@ -207,6 +207,30 @@ class CRM_Utils_ArrayTest extends CiviUnitTestCase { } + public function testGetSet_EmptyPath() { + $emptyPath = []; + + $x = 'hello'; + $this->assertEquals(TRUE, CRM_Utils_Array::pathIsset($x, $emptyPath)); + $this->assertEquals('hello', CRM_Utils_Array::pathGet($x, $emptyPath)); + $this->assertEquals('hello', $x); + + CRM_Utils_Array::pathSet($x, $emptyPath, 'bon jour'); + $this->assertEquals(TRUE, CRM_Utils_Array::pathIsset($x, $emptyPath)); + $this->assertEquals('bon jour', CRM_Utils_Array::pathGet($x, $emptyPath)); + $this->assertEquals('bon jour', $x); + + CRM_Utils_Array::pathUnset($x, $emptyPath); + $this->assertEquals(FALSE, CRM_Utils_Array::pathIsset($x, $emptyPath)); + $this->assertEquals(NULL, CRM_Utils_Array::pathGet($x, $emptyPath)); + $this->assertEquals(NULL, $x); + + CRM_Utils_Array::pathSet($x, $emptyPath, 'buenos dias'); + $this->assertEquals(TRUE, CRM_Utils_Array::pathIsset($x, $emptyPath)); + $this->assertEquals('buenos dias', CRM_Utils_Array::pathGet($x, $emptyPath)); + $this->assertEquals('buenos dias', $x); + } + public function getSortExamples() { $red = ['label' => 'Red', 'id' => 1, 'weight' => '90']; $orange = ['label' => 'Orange', 'id' => 2, 'weight' => '70'];