diff --git a/CRM/Utils/Array.php b/CRM/Utils/Array.php index 06aa5a8faf63..ec460a1ebd1a 100644 --- a/CRM/Utils/Array.php +++ b/CRM/Utils/Array.php @@ -1058,6 +1058,40 @@ public static function pathIsset($values, $path) { return TRUE; } + /** + * Remove a key from an array. + * + * This is a helper for when the calling function does not know how many layers deep + * the path array is so cannot easily check. + * + * @param array $values + * @param array $path + * @param bool $cleanup + * If removed item leaves behind an empty array, should you remove the empty array? + * @return bool + * TRUE if anything has been removed. FALSE if no changes were required. + */ + public static function pathUnset(&$values, $path, $cleanup = FALSE) { + if (count($path) === 1) { + if (isset($values[$path[0]])) { + unset($values[$path[0]]); + return TRUE; + } + else { + return FALSE; + } + } + else { + $next = array_shift($path); + $r = static::pathUnset($values[$next], $path, $cleanup); + if ($cleanup && $values[$next] === []) { + $r = TRUE; + unset($values[$next]); + } + return $r; + } + } + /** * Set a single value in an array tree. * diff --git a/tests/phpunit/CRM/Utils/ArrayTest.php b/tests/phpunit/CRM/Utils/ArrayTest.php index 7403576c5fb6..8f1a3b629cf2 100644 --- a/tests/phpunit/CRM/Utils/ArrayTest.php +++ b/tests/phpunit/CRM/Utils/ArrayTest.php @@ -133,6 +133,10 @@ public function testGetSetPathParts() { 'two' => [ 'half' => 2, ], + 'three' => [ + 'first-third' => '1/3', + 'second-third' => '2/3', + ], ]; $this->assertEquals('1', CRM_Utils_Array::pathGet($arr, ['one'])); $this->assertEquals('2', CRM_Utils_Array::pathGet($arr, ['two', 'half'])); @@ -140,6 +144,19 @@ public function testGetSetPathParts() { CRM_Utils_Array::pathSet($arr, ['zoo', 'half'], '3'); $this->assertEquals(3, CRM_Utils_Array::pathGet($arr, ['zoo', 'half'])); $this->assertEquals(3, $arr['zoo']['half']); + + $arrCopy = $arr; + $this->assertEquals(FALSE, CRM_Utils_Array::pathUnset($arr, ['does-not-exist'])); + $this->assertEquals($arrCopy, $arr); + + $this->assertEquals(TRUE, CRM_Utils_Array::pathUnset($arr, ['two', 'half'], FALSE)); + $this->assertEquals([], $arr['two']); + $this->assertTrue(array_key_exists('two', $arr)); + + CRM_Utils_Array::pathUnset($arr, ['three', 'first-third'], TRUE); + $this->assertEquals(['second-third' => '2/3'], $arr['three']); + CRM_Utils_Array::pathUnset($arr, ['three', 'second-third'], TRUE); + $this->assertFalse(array_key_exists('three', $arr)); } public function getSortExamples() {