Skip to content
Snippets Groups Projects
Unverified Commit 8230d847 authored by Viacheslav Poturaev's avatar Viacheslav Poturaev Committed by GitHub
Browse files

Merge pull request #11 from swaggest/issue-9

resolves #9
parents 81a403c0 59fb701b
No related merge requests found
......@@ -107,6 +107,13 @@ Adds operation to `JsonPatch`.
#### `apply`
Applies patch to `JSON`-decoded data.
#### `setFlags`
Alters default behavior.
Available flag:
* `JsonPatch::STRICT_MODE` Disallow converting empty array to object for key creation.
### `JsonPointer`
#### `escapeSegment`
......
......@@ -19,6 +19,24 @@ use Swaggest\JsonDiff\JsonPatch\Test;
*/
class JsonPatch implements \JsonSerializable
{
/**
* Disallow converting empty array to object for key creation
* @see JsonPointer::STRICT_MODE
*/
const STRICT_MODE = 2;
private $flags = 0;
/**
* @param int $options
* @return $this
*/
public function setFlags($options)
{
$this->flags = $options;
return $this;
}
/** @var OpPath[] */
private $operations = array();
......@@ -118,18 +136,18 @@ class JsonPatch implements \JsonSerializable
$pathItems = JsonPointer::splitPath($operation->path);
switch (true) {
case $operation instanceof Add:
JsonPointer::add($original, $pathItems, $operation->value, false);
JsonPointer::add($original, $pathItems, $operation->value, $this->flags);
break;
case $operation instanceof Copy:
$fromItems = JsonPointer::splitPath($operation->from);
$value = JsonPointer::get($original, $fromItems);
JsonPointer::add($original, $pathItems, $value, false);
JsonPointer::add($original, $pathItems, $value, $this->flags);
break;
case $operation instanceof Move:
$fromItems = JsonPointer::splitPath($operation->from);
$value = JsonPointer::get($original, $fromItems);
JsonPointer::remove($original, $fromItems);
JsonPointer::add($original, $pathItems, $value, false);
JsonPointer::add($original, $pathItems, $value, $this->flags);
break;
case $operation instanceof Remove:
JsonPointer::remove($original, $pathItems);
......@@ -137,7 +155,7 @@ class JsonPatch implements \JsonSerializable
case $operation instanceof Replace:
JsonPointer::get($original, $pathItems);
JsonPointer::remove($original, $pathItems);
JsonPointer::add($original, $pathItems, $operation->value, false);
JsonPointer::add($original, $pathItems, $operation->value, $this->flags);
break;
case $operation instanceof Test:
$value = JsonPointer::get($original, $pathItems);
......
......@@ -5,6 +5,16 @@ namespace Swaggest\JsonDiff;
class JsonPointer
{
/**
* Create intermediate keys if they don't exist
*/
const RECURSIVE_KEY_CREATION = 1;
/**
* Disallow converting empty array to object for key creation
*/
const STRICT_MODE = 2;
/**
* @param string $key
* @param bool $isURIFragmentId
......@@ -76,10 +86,10 @@ class JsonPointer
* @param mixed $holder
* @param string[] $pathItems
* @param mixed $value
* @param bool $recursively
* @param int $flags
* @throws Exception
*/
public static function add(&$holder, $pathItems, $value, $recursively = true)
public static function add(&$holder, $pathItems, $value, $flags = self::RECURSIVE_KEY_CREATION)
{
$ref = &$holder;
while (null !== $key = array_shift($pathItems)) {
......@@ -89,7 +99,7 @@ class JsonPointer
Exception::EMPTY_PROPERTY_NAME_UNSUPPORTED);
}
if ($recursively) {
if ($flags & self::RECURSIVE_KEY_CREATION) {
$ref = &$ref->$key;
} else {
if (!isset($ref->$key) && count($pathItems)) {
......@@ -102,17 +112,17 @@ class JsonPointer
$intKey = filter_var($key, FILTER_VALIDATE_INT);
if ($ref === null && (false === $intKey || $intKey !== 0)) {
$key = (string)$key;
if ($recursively) {
if ($flags & self::RECURSIVE_KEY_CREATION) {
$ref = new \stdClass();
$ref = &$ref->{$key};
} else {
throw new Exception('Non-existent path item: ' . $key);
}
} elseif ([] === $ref && false === $intKey && '-' !== $key) {
} elseif ([] === $ref && 0 === ($flags & self::STRICT_MODE) && false === $intKey && '-' !== $key) {
$ref = new \stdClass();
$ref = &$ref->{$key};
} else {
if ($recursively && $ref === null) $ref = array();
if ($flags & self::RECURSIVE_KEY_CREATION && $ref === null) $ref = array();
if ('-' === $key) {
$ref = &$ref[];
} else {
......@@ -122,7 +132,7 @@ class JsonPointer
if (false === $intKey) {
throw new Exception('Invalid key for array operation');
}
if ($intKey > count($ref) && !$recursively) {
if ($intKey > count($ref) && 0 === ($flags & self::RECURSIVE_KEY_CREATION)) {
throw new Exception('Index is greater than number of items in array');
} elseif ($intKey < 0) {
throw new Exception('Negative index');
......
......@@ -2,7 +2,9 @@
namespace Swaggest\JsonDiff\Tests\Issues;
use Swaggest\JsonDiff\Exception;
use Swaggest\JsonDiff\JsonDiff;
use Swaggest\JsonDiff\JsonPatch;
/**
* @see https://github.com/swaggest/json-diff/issues/9
......@@ -18,5 +20,9 @@ class Issue9Test extends \PHPUnit_Framework_TestCase
$this->assertNotEquals($new, $old);
$patch->apply($old);
$this->assertEquals($new, $old);
$old = json_decode(json_encode(["emptyObject" => []]));
$this->setExpectedException(get_class(new Exception()), 'Invalid key for array operation');
$patch->setFlags(JsonPatch::STRICT_MODE)->apply($old);
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment