Skip to content

Commit 12b5c60

Browse files
committed
extracting JsonProcessor
1 parent 455e1ed commit 12b5c60

File tree

5 files changed

+142
-18
lines changed

5 files changed

+142
-18
lines changed

src/Cli/Diff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class Diff extends Command
2929
static function setUpDefinition(Definition $definition, $options)
3030
{
3131
$definition->name = 'json-diff';
32-
$definition->version = 'v1.0.0';
32+
$definition->version = 'v1.1.0';
3333
$definition->description = 'JSON diff and rearrange tool for PHP, https://github.com/swaggest/json-diff';
3434

3535
$options->action = Command\Option::create()->setIsUnnamed()->setIsRequired()

src/Exception.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Swaggest\JsonDiff;
4+
5+
6+
class Exception extends \Exception
7+
{
8+
9+
}

src/JsonDiff.php

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ private function process($original, $new)
155155
if ($original !== $new) {
156156
$this->modifiedCnt++;
157157
$this->modifiedPaths [] = $this->path;
158-
$this->pushByPath($this->modifiedOriginal, $this->path, $original);
159-
$this->pushByPath($this->modifiedNew, $this->path, $new);
158+
JsonProcessor::pushByPath($this->modifiedOriginal, $this->path, $original);
159+
JsonProcessor::pushByPath($this->modifiedNew, $this->path, $new);
160160
}
161161
return $new;
162162
}
@@ -183,7 +183,7 @@ private function process($original, $new)
183183
} else {
184184
$this->removedCnt++;
185185
$this->removedPaths [] = $this->path;
186-
$this->pushByPath($this->removed, $this->path, $originalValue);
186+
JsonProcessor::pushByPath($this->removed, $this->path, $originalValue);
187187
}
188188
$this->path = $path;
189189
}
@@ -192,7 +192,7 @@ private function process($original, $new)
192192
foreach ($newArray as $key => $value) {
193193
$newOrdered[$key] = $value;
194194
$path = $this->path . '/' . urlencode($key);
195-
$this->pushByPath($this->added, $path, $value);
195+
JsonProcessor::pushByPath($this->added, $path, $value);
196196
$this->addedCnt++;
197197
$this->addedPaths [] = $path;
198198
}
@@ -281,17 +281,4 @@ private function rearrangeArray(array $original, array $new)
281281

282282
return $new;
283283
}
284-
285-
private function pushByPath(&$holder, $path, $value)
286-
{
287-
$pathItems = explode('/', $path);
288-
if ('#' === $pathItems[0]) {
289-
array_shift($pathItems);
290-
}
291-
$ref = &$holder;
292-
while (null !== $key = array_shift($pathItems)) {
293-
$ref = &$ref[(string)$key];
294-
}
295-
$ref = $value;
296-
}
297284
}

src/JsonProcessor.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
namespace Swaggest\JsonDiff;
4+
5+
6+
class JsonProcessor
7+
{
8+
public static function pushByPath(&$holder, $path, $value)
9+
{
10+
$pathItems = explode('/', $path);
11+
if ('#' === $pathItems[0]) {
12+
array_shift($pathItems);
13+
}
14+
$ref = &$holder;
15+
while (null !== $key = array_shift($pathItems)) {
16+
if (is_string($key)) {
17+
$key = urldecode($key);
18+
}
19+
if ($ref instanceof \stdClass) {
20+
$ref = &$ref->$key;
21+
} elseif ($ref === null
22+
&& !is_int($key)
23+
&& false === filter_var($key, FILTER_VALIDATE_INT)
24+
) {
25+
$ref = new \stdClass();
26+
$ref = &$ref->$key;
27+
} else {
28+
$ref = &$ref[$key];
29+
}
30+
}
31+
$ref = $value;
32+
}
33+
34+
public static function getByPath(&$holder, $path)
35+
{
36+
$pathItems = explode('/', $path);
37+
if ('#' === $pathItems[0]) {
38+
array_shift($pathItems);
39+
}
40+
$ref = &$holder;
41+
while (null !== $key = array_shift($pathItems)) {
42+
$key = urldecode($key);
43+
if ($ref instanceof \stdClass) {
44+
if (property_exists($ref, $key)) {
45+
$ref = &$ref->$key;
46+
} else {
47+
throw new Exception('Key not found: ' . $key);
48+
}
49+
} else {
50+
if (array_key_exists($key, $ref)) {
51+
$ref = &$ref[$key];
52+
} else {
53+
throw new Exception('Key not found: ' . $key);
54+
}
55+
}
56+
}
57+
return $ref;
58+
}
59+
60+
public static function removeByPath(&$holder, $path)
61+
{
62+
$pathItems = explode('/', $path);
63+
if ('#' === $pathItems[0]) {
64+
array_shift($pathItems);
65+
}
66+
$ref = &$holder;
67+
while (null !== $key = array_shift($pathItems)) {
68+
$parent = &$ref;
69+
$key = urldecode($key);
70+
$refKey = $key;
71+
if ($ref instanceof \stdClass) {
72+
if (property_exists($ref, $key)) {
73+
$ref = &$ref->$key;
74+
} else {
75+
throw new Exception('Key not found: ' . $key);
76+
}
77+
} else {
78+
if (array_key_exists($key, $ref)) {
79+
$ref = &$ref[$key];
80+
} else {
81+
throw new Exception('Key not found: ' . $key);
82+
}
83+
}
84+
}
85+
86+
if (isset($parent) && isset($refKey)) {
87+
if ($parent instanceof \stdClass) {
88+
unset($parent->$refKey);
89+
} else {
90+
unset($parent[$refKey]);
91+
}
92+
}
93+
return $ref;
94+
}
95+
}

tests/src/ProcessorTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Swaggest\JsonDiff\Tests;
4+
5+
6+
use Swaggest\JsonDiff\Exception;
7+
use Swaggest\JsonDiff\JsonProcessor;
8+
9+
class ProcessorTest extends \PHPUnit_Framework_TestCase
10+
{
11+
public function testProcess()
12+
{
13+
$json = new \stdClass();
14+
JsonProcessor::pushByPath($json, '#/l1/l2/l3', 'hello!');
15+
$this->assertSame('{"l1":{"l2":{"l3":"hello!"}}}', json_encode($json));
16+
17+
$this->assertSame('{"l3":"hello!"}', json_encode(JsonProcessor::getByPath($json, '#/l1/l2')));
18+
19+
try {
20+
$this->assertSame('null', json_encode(JsonProcessor::getByPath($json, '#/l1/l2/non-existent')));
21+
} catch (Exception $exception) {
22+
$this->assertSame('Key not found: non-existent', $exception->getMessage());
23+
}
24+
25+
JsonProcessor::removeByPath($json, '#/l1/l2');
26+
$this->assertSame('{"l1":{}}', json_encode($json));
27+
28+
JsonProcessor::pushByPath($json, '#/l1/l2/0/0', 0);
29+
JsonProcessor::pushByPath($json, '#/l1/l2/1/1', 1);
30+
31+
$this->assertSame('{"l1":{"l2":[[0],{"1":1}]}}', json_encode($json));
32+
}
33+
}

0 commit comments

Comments
 (0)