Skip to content

Commit 6dce6c8

Browse files
Silvan-WMDEjakobw
authored andcommitted
Introduce PathException for JsonPatch
This exception is thrown in JsonPatch::apply whenever a JsonPointer call fails.
1 parent 0919867 commit 6dce6c8

File tree

3 files changed

+125
-15
lines changed

3 files changed

+125
-15
lines changed

src/JsonPatch.php

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public static function import(array $data)
6161
}
6262

6363
if (!is_object($operation)) {
64-
throw new Exception( 'Invalid patch operation - should be a JSON object' );
64+
throw new Exception('Invalid patch operation - should be a JSON object');
6565
}
6666

6767
if (!isset($operation->op)) {
@@ -145,32 +145,32 @@ public function apply(&$original, $stopOnError = true)
145145
$errors = array();
146146
foreach ($this->operations as $operation) {
147147
try {
148-
$pathItems = JsonPointer::splitPath($operation->path);
148+
$pathItems = $this->splitPath($operation, 'path');
149149
switch (true) {
150150
case $operation instanceof Add:
151-
JsonPointer::add($original, $pathItems, $operation->value, $this->flags);
151+
$this->add($operation, $original, $pathItems, $operation->value);
152152
break;
153153
case $operation instanceof Copy:
154-
$fromItems = JsonPointer::splitPath($operation->from);
155-
$value = JsonPointer::get($original, $fromItems);
156-
JsonPointer::add($original, $pathItems, $value, $this->flags);
154+
$fromItems = $this->splitPath($operation, 'from');
155+
$value = $this->get($operation, 'from', $original, $fromItems);
156+
$this->add($operation, $original, $pathItems, $value);
157157
break;
158158
case $operation instanceof Move:
159-
$fromItems = JsonPointer::splitPath($operation->from);
160-
$value = JsonPointer::get($original, $fromItems);
161-
JsonPointer::remove($original, $fromItems, $this->flags);
162-
JsonPointer::add($original, $pathItems, $value, $this->flags);
159+
$fromItems = $this->splitPath($operation, 'from');
160+
$value = $this->get($operation, 'from', $original, $fromItems);
161+
$this->remove($operation, 'from', $original, $fromItems);
162+
$this->add($operation, $original, $pathItems, $value);
163163
break;
164164
case $operation instanceof Remove:
165-
JsonPointer::remove($original, $pathItems, $this->flags);
165+
$this->remove($operation, 'path', $original, $pathItems);
166166
break;
167167
case $operation instanceof Replace:
168-
JsonPointer::get($original, $pathItems);
169-
JsonPointer::remove($original, $pathItems, $this->flags);
170-
JsonPointer::add($original, $pathItems, $operation->value, $this->flags);
168+
$this->get($operation, 'path', $original, $pathItems);
169+
$this->remove($operation, 'path', $original, $pathItems);
170+
$this->add($operation, $original, $pathItems, $operation->value);
171171
break;
172172
case $operation instanceof Test:
173-
$value = JsonPointer::get($original, $pathItems);
173+
$value = $this->get($operation, 'path', $original, $pathItems);
174174
$diff = new JsonDiff($operation->value, $value,
175175
JsonDiff::STOP_ON_DIFF);
176176
if ($diff->getDiffCnt() !== 0) {
@@ -188,4 +188,41 @@ public function apply(&$original, $stopOnError = true)
188188
}
189189
return $errors;
190190
}
191+
192+
private function splitPath(OpPath $operation, $field)
193+
{
194+
try {
195+
return JsonPointer::splitPath($operation->$field);
196+
} catch (Exception $exception) {
197+
throw new PathException($exception->getMessage(), $operation, $field, $exception->getCode());
198+
}
199+
}
200+
201+
private function add(OpPath $operation, &$original, array $pathItems, $value)
202+
{
203+
try {
204+
JsonPointer::add($original, $pathItems, $value, $this->flags);
205+
} catch (Exception $exception) {
206+
throw new PathException($exception->getMessage(), $operation, 'path', $exception->getCode());
207+
}
208+
}
209+
210+
private function get(OpPath $operation, $field, $original, array $pathItems)
211+
{
212+
try {
213+
return JsonPointer::get($original, $pathItems);
214+
} catch (Exception $exception) {
215+
throw new PathException($exception->getMessage(), $operation, $field, $exception->getCode());
216+
}
217+
}
218+
219+
private function remove($operation, $field, &$original, array $pathItems)
220+
{
221+
try {
222+
JsonPointer::remove($original, $pathItems, $this->flags);
223+
} catch (Exception $exception) {
224+
throw new PathException($exception->getMessage(), $operation, $field, $exception->getCode());
225+
}
226+
}
227+
191228
}

src/PathException.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace Swaggest\JsonDiff;
4+
5+
6+
use Throwable;
7+
8+
class PathException extends Exception
9+
{
10+
/** @var object */
11+
private $operation;
12+
13+
/** @var string */
14+
private $field;
15+
16+
/**
17+
* @param string $message
18+
* @param object $operation
19+
* @param string $field
20+
* @param int $code
21+
* @param Throwable|null $previous
22+
*/
23+
public function __construct(
24+
$message,
25+
$operation,
26+
$field,
27+
$code = 0,
28+
Throwable $previous = null
29+
)
30+
{
31+
parent::__construct($message, $code, $previous);
32+
$this->operation = $operation;
33+
$this->field = $field;
34+
}
35+
36+
/**
37+
* @return object
38+
*/
39+
public function getOperation()
40+
{
41+
return $this->operation;
42+
}
43+
44+
/**
45+
* @return string
46+
*/
47+
public function getField()
48+
{
49+
return $this->field;
50+
}
51+
}

tests/src/JsonPatchTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Swaggest\JsonDiff\JsonPatch;
88
use Swaggest\JsonDiff\MissingFieldException;
99
use Swaggest\JsonDiff\PatchTestOperationFailedException;
10+
use Swaggest\JsonDiff\PathException;
1011
use Swaggest\JsonDiff\UnknownOperationException;
1112

1213
class JsonPatchTest extends \PHPUnit_Framework_TestCase
@@ -174,4 +175,25 @@ public function testTestOperationFailed()
174175
$this->assertSame($actualValue, $testError->getActualValue());
175176
}
176177

178+
public function testPathException()
179+
{
180+
$data = new \stdClass();
181+
$patch = new JsonPatch();
182+
183+
$operation1 = new JsonPatch\Add('/some/path', 22);
184+
$patch->op($operation1);
185+
186+
$operation2 = new JsonPatch\Move('/target', '/source');
187+
$patch->op($operation2);
188+
189+
$errors = $patch->apply($data, false);
190+
191+
$this->assertInstanceOf(PathException::class, $errors[0]);
192+
$this->assertSame($operation1, $errors[0]->getOperation());
193+
$this->assertSame('path', $errors[0]->getField());
194+
195+
$this->assertInstanceOf(PathException::class, $errors[1]);
196+
$this->assertSame($operation2, $errors[1]->getOperation());
197+
$this->assertSame('from', $errors[1]->getField());
198+
}
177199
}

0 commit comments

Comments
 (0)