Skip to content

Commit

Permalink
Merge pull request #5 from makasim/partial-update
Browse files Browse the repository at this point in the history
Partial update.
  • Loading branch information
makasim authored Mar 3, 2017
2 parents 24ae64e + ce4ebbc commit 9a1b5e2
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 19 deletions.
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"require": {
"php": "^7.0",
"mongodb/mongodb": "^1",
"makasim/values": "^0.2"
"makasim/values": "^0.2",
"mikemccabe/json-patch-php": "^0.1"
},
"require-dev": {
"phpunit/phpunit": "~6.0"
Expand All @@ -25,7 +26,7 @@
"psr-4": { "Makasim\\Yadm\\": "src" },
"files": ["src/functions_include.php"]
},
"autoload0-dev": {
"autoload-dev": {
"psr-4": { "Makasim\\Yadm\\Tests\\": "tests" }
},
"extra": {
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ services:

mongo:
image: mongo:3
ports:
- "27017:27017"
86 changes: 86 additions & 0 deletions src/ChangesCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
namespace Makasim\Yadm;

use function Makasim\Values\get_values;
use mikemccabe\JsonPatch\JsonPatch;

class ChangesCollector
{
private $originalValues;

public function register($object)
{
if ($id = get_object_id($object)) {
$this->originalValues[$id] = get_values($object);
}
}

public function unregister($object)
{
if ($id = get_object_id($object)) {
unset($this->originalValues[$id]);
}
}

public function changes($object)
{
if (false == $id = get_object_id($object)) {
throw new \LogicException(sprintf('Object does not have an id set.'));
}

if (false == array_key_exists($id, $this->originalValues)) {
throw new \LogicException(sprintf('Changes has not been collected. The object with id "%s" original data is missing.'));
}

$diff = JsonPatch::diff($this->originalValues[$id], get_values($object));

$update = ['$set' => [], '$unset' => []];
foreach ($diff as $op) {
switch ($op['op']) {
case 'add':
if (is_array($op['value'])) {
foreach ($op['value'] as $key => $value) {
$update['$set'][$this->pathToDot($op['path']).'.'.$key] = $value;
}
} else {
$update['$set'][$this->pathToDot($op['path'])] = $op['value'];
}

break;
case 'remove':
$update['$unset'][$this->pathToDot($op['path'])] = '';

break;
case 'replace':
$update['$set'][$this->pathToDot($op['path'])] = $op['value'];

break;
default:
throw new \LogicException('JSON Patch operation "'.$op['op'].'"" is not supported.');
}


}

if (empty($update['$set'])) {
unset($update['$set']);
}
if (empty($update['$unset'])) {
unset($update['$unset']);
}

return $update;
}

/**
* @param string $path
*
* @return string
*/
private function pathToDot($path)
{
$path = ltrim($path, '/');

return str_replace('/', '.', $path);
}
}
55 changes: 39 additions & 16 deletions src/MongodbStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ class MongodbStorage
*/
private $hydrator;

/**
* @var ChangesCollector
*/
private $changesCollector;

/**
* @var PessimisticLock
*/
Expand All @@ -25,12 +30,18 @@ class MongodbStorage
/**
* @param Collection $collection
* @param Hydrator $hydrator
* @param ChangesCollector $changesCollector
* @param PessimisticLock|null $pessimisticLock
*/
public function __construct(Collection $collection, Hydrator $hydrator, PessimisticLock $pessimisticLock = null)
{
public function __construct(
Collection $collection,
Hydrator $hydrator,
ChangesCollector $changesCollector = null,
PessimisticLock $pessimisticLock = null
) {
$this->collection = $collection;
$this->hydrator = $hydrator;
$this->changesCollector = $changesCollector ?: new ChangesCollector();
$this->pessimisticLock = $pessimisticLock;
}

Expand All @@ -50,15 +61,14 @@ public function create()
*/
public function insert($model, array $options = [])
{
$values = get_values($model);

$result = $this->collection->insertOne($values, $options);
$result = $this->collection->insertOne(get_values($model), $options);
if (false == $result->isAcknowledged()) {
throw new \LogicException('Operation is not acknowledged');
}

$this->hydrator->hydrate($values, $model);
set_object_id($model, $result->getInsertedId());
$this->changesCollector->register($model);

return $result;
}
Expand All @@ -67,13 +77,13 @@ public function insert($model, array $options = [])
* @param object[] $models
* @param array $options
*
* @return \MongoDB\InsertOneResult
* @return \MongoDB\InsertManyResult
*/
public function insertMany(array $models, array $options = [])
{
$data = [];
foreach ($models as $key => $model) {
$data[$key] = get_values($model);
$data[$key] =get_values($model);
}

$result = $this->collection->insertMany($data, $options);
Expand All @@ -84,6 +94,8 @@ public function insertMany(array $models, array $options = [])
foreach ($result->getInsertedIds() as $key => $modelId) {
$this->hydrator->hydrate($data[$key], $models[$key]);
set_object_id($models[$key], $modelId);

$this->changesCollector->register($models[$key]);
}

return $result;
Expand All @@ -102,14 +114,15 @@ public function update($model, $filter = null, array $options = [])
$filter = ['_id' => new ObjectID(get_object_id($model))];
}

$values = get_values($model);
unset($values['_id']);
$update = $this->changesCollector->changes($model);

$result = $this->collection->updateOne($filter, ['$set' => $values], $options);
$result = $this->collection->updateOne($filter, $update, $options);
if (false == $result->isAcknowledged()) {
throw new \LogicException('Operation is not acknowledged');
}

$this->changesCollector->register($model);

return $result;
}

Expand All @@ -121,15 +134,17 @@ public function update($model, $filter = null, array $options = [])
*/
public function delete($model, array $options = [])
{
$modelId = get_object_id($model);
$values = get_values($model);
unset($values['_id']);
$modelId = new ObjectID(get_object_id($model));

$result = $this->collection->deleteOne(['_id' => new ObjectID($modelId)], $options);
$result = $this->collection->deleteOne(['_id' => $modelId], $options);
if (false == $result->isAcknowledged()) {
throw new \LogicException('Operation is not acknowledged');
}

// TODO remove id???
$this->changesCollector->unregister($model);

return $result;
}

Expand All @@ -144,7 +159,11 @@ public function findOne(array $filter = [], array $options = [])
$options['typeMap'] = ['root' => 'array', 'document' => 'array', 'array' => 'array'];

if ($values = $this->collection->findOne($filter, $options)) {
return $this->hydrator->hydrate($values);
$object = $this->hydrator->hydrate($values);

$this->changesCollector->register($object);

return $object;
}
}

Expand All @@ -160,7 +179,11 @@ public function find(array $filter = [], array $options = [])
$cursor->setTypeMap(['root' => 'array', 'document' => 'array', 'array' => 'array']);

foreach ($cursor as $values) {
yield $this->hydrator->hydrate($values);
$object = $this->hydrator->hydrate($values);

$this->changesCollector->register($object);

yield $object;
}
}

Expand Down
Loading

0 comments on commit 9a1b5e2

Please sign in to comment.