Skip to content

Commit a0671b8

Browse files
committed
Adding helper methods to generate JSON Patch representation for resource.
1 parent 013d768 commit a0671b8

File tree

3 files changed

+125
-1
lines changed

3 files changed

+125
-1
lines changed

composer.json

+8-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,17 @@
2020
"OpenCloud": ["lib/", "tests/"]
2121
}
2222
},
23+
"repositories": [
24+
{
25+
"type": "vcs",
26+
"url": "https://github.com/ycombinator/json-patch-php"
27+
}
28+
],
2329
"require": {
2430
"php" : ">=5.3.3",
2531
"guzzle/http" : "~3.8",
26-
"psr/log": "~1.0"
32+
"psr/log": "~1.0",
33+
"mikemccabe/json-patch-php": "dev-master"
2734
},
2835
"require-dev" : {
2936
"phpunit/phpunit": "4.3.*",

lib/OpenCloud/Common/Resource/PersistentResource.php

+43
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use OpenCloud\Common\Exceptions\NameError;
2626
use OpenCloud\Common\Exceptions\UnsupportedExtensionError;
2727
use OpenCloud\Common\Exceptions\UpdateError;
28+
use mikemccabe\JsonPatch\JsonPatch;
2829

2930
abstract class PersistentResource extends BaseResource
3031
{
@@ -345,6 +346,48 @@ public function checkExtension($alias)
345346
return true;
346347
}
347348

349+
/**
350+
* Returns the object's properties as an array
351+
*/
352+
protected function getPropertiesAsArray()
353+
{
354+
$properties = get_object_vars($this);
355+
356+
$propertiesToRemove = array('aliases', 'service', 'parent', 'metadata');
357+
foreach ($propertiesToRemove as $property) {
358+
unset($properties[$property]);
359+
}
360+
361+
return $properties;
362+
}
363+
364+
/**
365+
* Generates a JSON Patch representation and return its
366+
*
367+
* @param mixed $updatedProperties Properties of the resource to update
368+
* @return String JSON Patch representation for updates
369+
*/
370+
protected function generateJsonPatch($updatedProperties)
371+
{
372+
// Normalize current and updated properties into nested arrays
373+
$currentProperties = json_decode(json_encode($this->getPropertiesAsArray()), true);
374+
$updatedProperties = json_decode(json_encode($updatedProperties), true);
375+
376+
// Add any properties that haven't changed to generate the correct patch
377+
// (otherwise unchanging properties are marked as removed in the patch)
378+
foreach ($currentProperties as $key => $value) {
379+
if (!array_key_exists($key, $updatedProperties)) {
380+
$updatedProperties[$key] = $value;
381+
}
382+
}
383+
384+
// Generate JSON Patch representation
385+
$json = json_encode(JsonPatch::diff($currentProperties, $updatedProperties));
386+
$this->checkJsonError();
387+
388+
return $json;
389+
}
390+
348391
/******** DEPRECATED METHODS ********/
349392

350393
/**

tests/OpenCloud/Tests/Common/Resource/PersistentResourceTest.php

+74
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ public function recursivelyAliasPropertyValue($propertyValue)
3131
{
3232
return parent::recursivelyAliasPropertyValue($propertyValue);
3333
}
34+
35+
public function getPropertiesAsArray()
36+
{
37+
return parent::getPropertiesAsArray();
38+
}
39+
40+
public function generateJsonPatch($updateParams)
41+
{
42+
return parent::generateJsonPatch($updateParams);
43+
}
3444
}
3545

3646
class PersistentResourceTest extends OpenCloudTestCase
@@ -106,4 +116,68 @@ public function testRecursivelyAliasPropertyValueWithObjects()
106116
$this->assertEquals($obj3Expected,
107117
$this->persistentResource->recursivelyAliasPropertyValue($obj3));
108118
}
119+
120+
public function testGetPropertiesAsArray()
121+
{
122+
$this->persistentResource->id = 17;
123+
$this->persistentResource->tags = array('foo', 'bar');
124+
$this->persistentResource->domains = array(
125+
(object) array('domain' => 'foo.phpopencloud.com'),
126+
array('domain' => 'bar.phpopencloud.com')
127+
);
128+
$this->persistentResource->origins = array(
129+
array('origin' => 'origin1.phpopencloud.com')
130+
);
131+
$this->persistentResource->status = (object) array('message' => 'Creation in progress');
132+
133+
$expectedArray = array(
134+
'id' => 17,
135+
'tags' => array('foo', 'bar'),
136+
'domains' => array(
137+
(object) array('domain' => 'foo.phpopencloud.com'),
138+
array('domain' => 'bar.phpopencloud.com')
139+
),
140+
'origins' => array(
141+
array('origin' => 'origin1.phpopencloud.com'),
142+
),
143+
'status' => (object) array('message' => 'Creation in progress'),
144+
);
145+
146+
$this->assertEquals($expectedArray, $this->persistentResource->getPropertiesAsArray());
147+
}
148+
149+
public function testGenerateJsonPatch()
150+
{
151+
$this->persistentResource->id = 17;
152+
$this->persistentResource->tags = array('foo', 'bar');
153+
$this->persistentResource->domains = array(
154+
array('domain' => 'foo.phpopencloud.com'),
155+
array('domain' => 'bar.phpopencloud.com')
156+
);
157+
$this->persistentResource->origins = array(
158+
array('origin' => 'origin1.phpopencloud.com')
159+
);
160+
$this->persistentResource->status = array('message' => 'Creation in progress');
161+
162+
$updateParams = array(
163+
'tags' => array('foo', 'qux', 'baz'),
164+
'domains' => array(
165+
array('domain' => 'foo.phpopencloud.com')
166+
),
167+
'origins' => array(
168+
array('origin' => 'origin1.phpopencloud.com'),
169+
array('origin' => 'origin2.phpopencloud.com')
170+
)
171+
);
172+
173+
$expectedJsonPatch = json_encode(array(
174+
array('op' => 'add', 'path' => '/tags/2', 'value' => 'baz'),
175+
array('op' => 'replace', 'path' => '/tags/1', 'value' => 'qux'),
176+
array('op' => 'remove', 'path' => '/domains/1'),
177+
array('op' => 'add', 'path' => '/origins/1', 'value' => array("origin" => "origin2.phpopencloud.com"))
178+
));
179+
180+
$actualJsonPatch = $this->persistentResource->generateJsonPatch($updateParams);
181+
$this->assertEquals($expectedJsonPatch, $actualJsonPatch);
182+
}
109183
}

0 commit comments

Comments
 (0)