Update pointer key by reference

This commit is contained in:
Andrea Marco Sartori 2023-03-27 23:03:21 +10:00
parent 4f172a0fc6
commit 7d841f4d77
4 changed files with 33 additions and 8 deletions

View File

@ -113,7 +113,7 @@ final class Pointer implements Stringable
* @param mixed $key * @param mixed $key
* @return mixed * @return mixed
*/ */
public function call(mixed $value, mixed $key): mixed public function call(mixed $value, mixed &$key): mixed
{ {
if ($this->callback === null) { if ($this->callback === null) {
return $value; return $value;

View File

@ -51,7 +51,7 @@ final class State
*/ */
public function __construct(private Pointers $pointers, private Closure $lazyLoad) public function __construct(private Pointers $pointers, private Closure $lazyLoad)
{ {
$this->tree = new Tree($this->pointers); $this->tree = new Tree($pointers);
} }
/** /**
@ -91,7 +91,7 @@ final class State
* @param mixed $key * @param mixed $key
* @return mixed * @return mixed
*/ */
public function callPointer(mixed $value, mixed $key): mixed public function callPointer(mixed $value, mixed &$key): mixed
{ {
return $this->pointers->matching()->call($value, $key); return $this->pointers->matching()->call($value, $key);
} }
@ -107,11 +107,15 @@ final class State
$this->tree->traverseToken($token, $this->expectsKey); $this->tree->traverseToken($token, $this->expectsKey);
if ($this->tree->isMatched() && ((!$this->expectsKey && $token->isValue()) || $this->tree->isDeep())) { if ($this->tree->isMatched() && ((!$this->expectsKey && $token->isValue()) || $this->tree->isDeep())) {
$shouldLazyLoad = $token instanceof CompoundBegin && $this->pointers->matching()->isLazy(); $this->pointers->markAsFound();
if ($token instanceof CompoundBegin && $this->pointers->matching()->isLazy()) {
$this->buffer = ($this->lazyLoad)();
$token->shouldLazyLoad = true;
} else {
/** @phpstan-ignore-next-line */ /** @phpstan-ignore-next-line */
$this->buffer = $shouldLazyLoad ? ($this->lazyLoad)() : $this->buffer . $token; $this->buffer .= $token;
/** @var CompoundBegin $token */ }
$shouldLazyLoad && $token->shouldLazyLoad = true;
} }
$token->mutateState($this); $token->mutateState($this);

View File

@ -96,6 +96,23 @@ final class Dataset
yield from self::forSinglePointersWithFixture('pointers/single_pointer_to_array.php'); yield from self::forSinglePointersWithFixture('pointers/single_pointer_to_array.php');
} }
/**
* Retrieve the dataset to test the key update
*
* @return Generator
*/
public static function forKeyUpdate(): Generator
{
$json = fixture('json/complex_object.json');
$pointers = [
'/type' => function ($value, &$key) {
$key = 'foo';
},
];
yield [$json, $pointers, ['foo' => 'donut']];
}
/** /**
* Retrieve the dataset to test multiple pointers * Retrieve the dataset to test multiple pointers
* *

View File

@ -23,6 +23,10 @@ it('eager loads lazy pointers into an array', function (string $json, string $po
expect(JsonParser::parse($json)->lazyPointer($pointer)->toArray())->toBe($expected); expect(JsonParser::parse($json)->lazyPointer($pointer)->toArray())->toBe($expected);
})->with(Dataset::forSinglePointersToArray()); })->with(Dataset::forSinglePointersToArray());
it('can modify key and value of a pointer', function (string $json, array $pointers, array $expected) {
expect(JsonParser::parse($json)->pointers($pointers)->toArray())->toBe($expected);
})->with(Dataset::forKeyUpdate());
it('loads JSON from multiple JSON pointers', function (string $json, array $pointers, array $parsed) { it('loads JSON from multiple JSON pointers', function (string $json, array $pointers, array $parsed) {
expect(JsonParser::parse($json)->pointers($pointers))->toPointTo($parsed); expect(JsonParser::parse($json)->pointers($pointers))->toPointTo($parsed);
})->with(Dataset::forMultiplePointers()); })->with(Dataset::forMultiplePointers());