Skip to content

Commit

Permalink
Allow Hash::remove() to remove from ArrayAccess objects
Browse files Browse the repository at this point in the history
Co-authored-by: Corey Taylor <corey.taylor.fl@gamil.com>
  • Loading branch information
Corey Taylor authored and ADmad committed Mar 16, 2024
1 parent d4119f1 commit f6143a1
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 10 deletions.
24 changes: 14 additions & 10 deletions src/Utility/Hash.php
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,17 @@ public static function insert(array $data, string $path, mixed $values = null):
* Perform a simple insert/remove operation.
*
* @param string $op The operation to do.
* @param array $data The data to operate on.
* @param \ArrayAccess|array $data The data to operate on.
* @param list<string> $path The path to work on.
* @param mixed $values The values to insert when doing inserts.
* @return array data.
* @return \ArrayAccess|array data.
*/
protected static function _simpleOp(string $op, array $data, array $path, mixed $values = null): array
{
protected static function _simpleOp(
string $op,
ArrayAccess|array $data,
array $path,
mixed $values = null
): ArrayAccess|array {
$_list = &$data;

$count = count($path);
Expand All @@ -357,12 +361,12 @@ protected static function _simpleOp(string $op, array $data, array $path, mixed
}
$_list[$key] ??= [];
$_list = &$_list[$key];
if (!is_array($_list)) {
if (!is_array($_list) && !$_list instanceof ArrayAccess) {
$_list = [];
}
} elseif ($op === 'remove') {
if ($i === $last) {
if (is_array($_list)) {
if (is_array($_list) || $_list instanceof ArrayAccess) {
unset($_list[$key]);
}

Expand All @@ -383,12 +387,12 @@ protected static function _simpleOp(string $op, array $data, array $path, mixed
* You can use `{n}` and `{s}` to remove multiple elements
* from $data.
*
* @param array $data The data to operate on
* @param array \ArrayAccess|$data The data to operate on
* @param string $path A path expression to use to remove.
* @return array The modified array.
* @return \ArrayAccess|array The modified array.
* @link https://book.cakephp.org/5/en/core-libraries/hash.html#Cake\Utility\Hash::remove
*/
public static function remove(array $data, string $path): array
public static function remove(ArrayAccess|array $data, string $path): ArrayAccess|array

Check failure on line 395 in src/Utility/Hash.php

View workflow job for this annotation

GitHub Actions / Coding Standard & Static Analysis

PHPDoc tag @param has invalid value (array \ArrayAccess|$data The data to operate on): Unexpected token "\\ArrayAccess", expected variable at offset 169

Check failure on line 395 in src/Utility/Hash.php

View workflow job for this annotation

GitHub Actions / Coding Standard & Static Analysis

PHPDoc tag @param has invalid value (array \ArrayAccess|$data The data to operate on): Unexpected token "\\ArrayAccess", expected variable at offset 169
{
$noTokens = !str_contains($path, '[');
$noExpansion = !str_contains($path, '{');
Expand All @@ -413,7 +417,7 @@ public static function remove(array $data, string $path): array

foreach ($data as $k => $v) {

Check failure on line 418 in src/Utility/Hash.php

View workflow job for this annotation

GitHub Actions / Coding Standard & Static Analysis

Argument of an invalid type array|ArrayAccess supplied for foreach, only iterables are supported.

Check failure on line 418 in src/Utility/Hash.php

View workflow job for this annotation

GitHub Actions / Coding Standard & Static Analysis

Argument of an invalid type array|ArrayAccess supplied for foreach, only iterables are supported.
$match = static::_matchToken($k, $token);
if ($match && is_array($v)) {
if ($match && (is_array($v) || $v instanceof ArrayAccess)) {
if ($conditions) {
if (static::_matches($v, $conditions)) {
if ($nextPath !== '') {
Expand Down
36 changes: 36 additions & 0 deletions tests/TestCase/Utility/HashTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2171,6 +2171,42 @@ public function testRemoveMulti(): void
$this->assertSame($expected, $result);
}

public function testRemoveArrayAccess(): void
{
$testObject = new ArrayObject([
'name' => 'about',
'vars' => ['title' => 'page title'],
]);

$a = [
'pages' => [
0 => ['name' => 'main'],
1 => $testObject,
],
];

$result = Hash::remove($a, 'pages.1.vars');
$expected = [
'pages' => [
0 => ['name' => 'main'],
1 => $testObject,
],
];
$this->assertSame($expected, $result);
$this->assertSame(['name' => 'about'], $testObject->getArrayCopy());

$result = new ArrayObject([
'name' => 'about',
'vars' => ['title' => 'page title'],
]);
$result = Hash::remove($result, 'vars.title');
$expected = [
'name' => 'about',
'vars' => [],
];
$this->assertSame($expected, $result->getArrayCopy());
}

/**
* testCheck method
*/
Expand Down

0 comments on commit f6143a1

Please sign in to comment.