Skip to content

Commit

Permalink
✨ Add the possibility to pass null to one to many relationships.
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieutu committed Feb 14, 2019
1 parent e9322c7 commit 7452c15
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 86 deletions.
61 changes: 31 additions & 30 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
{
"name": "mathieutu/laravel-json-syncer",
"description": "Export and import your models to/from JSON",
"type": "package",
"require": {
"php": ">=7.0",
"illuminate/support": "^5.4",
"illuminate/database": "^5.4"
},
"require-dev": {
"phpunit/phpunit": "~5.7",
"orchestra/testbench": "~3.0"
},
"license": "MIT",
"authors": [
{
"name": "Mathieu TUDISCO",
"email": "dev@mathieutu.ovh"
}
],
"autoload": {
"psr-4": {
"MathieuTu\\JsonSyncer\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"MathieuTu\\JsonSyncer\\Tests\\": "tests/"
}
},
"minimum-stability": "stable"
"name": "mathieutu/laravel-json-syncer",
"description": "Export and import your models to/from JSON",
"type": "package",
"require": {
"php": ">=7.0",
"illuminate/support": "^5.4",
"illuminate/database": "^5.4",
"ext-json": "*"
},
"require-dev": {
"phpunit/phpunit": "~5.7",
"orchestra/testbench": "~3.0"
},
"license": "MIT",
"authors": [
{
"name": "Mathieu TUDISCO",
"email": "dev@mathieutu.ovh"
}
],
"autoload": {
"psr-4": {
"MathieuTu\\JsonSyncer\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"MathieuTu\\JsonSyncer\\Tests\\": "tests/"
}
},
"minimum-stability": "stable"
}
10 changes: 5 additions & 5 deletions src/Helpers/JsonImporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,8 @@ public function import($objects)
{
$objects = $this->convertObjectsToArray($objects);

$objects = $this->wrap($objects);

foreach ($objects as $attributes) {
$object = $this->importAttributes($attributes);

$this->importRelations($object, $attributes);
}
}
Expand All @@ -51,7 +48,7 @@ protected function convertObjectsToArray($objects): array
$objects = $objects->toArray();
}

return (array) $objects;
return $this->wrap((array) $objects);
}

protected function wrap(array $objects): array
Expand All @@ -71,7 +68,10 @@ protected function importRelations($object, $attributes)
$relationsNames = array_intersect(array_keys($attributes), $this->importable->getJsonImportableRelations());

foreach ($relationsNames as $relationName) {
$this->importChildrenIfImportable($this->getRelationObject($object, $relationName), $this->wrap($attributes[$relationName]));
$children = $this->convertObjectsToArray($attributes[$relationName]);
$relation = $this->getRelationObject($object, $relationName);

$this->importChildrenIfImportable($relation, $children);
}
}

Expand Down
143 changes: 92 additions & 51 deletions tests/JsonImporterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,40 @@ protected function assertAllImportedInDatabase()
$this->assertFooIsImported();
$this->assertBarsAreImported();
$this->assertBazsAreImported();
$this->assertEquals(0, DoNotExport::query()->count());
$this->assertEquals(0, DoNotExport::count());
}

protected function assertFooIsImported()
{
$this->assertEquals(1, Foo::count());
$this->assertEquals(
['id' => 1, 'author' => 'Mathieu TUDISCO', 'username' => '@mathieutu'],
Foo::first()->toArray()
);
}

protected function assertBarsAreImported()
{
$this->assertEquals(2, Bar::count());
$bars = Foo::first()->bars;
$this->assertEquals([
['id' => 1, 'name' => 'bar1', 'foo_id' => 1],
['id' => 2, 'name' => 'bar2', 'foo_id' => 1],
], $bars->toArray());
}

protected function assertBazsAreImported()
{
$this->assertEquals(2, Baz::count());
foreach (Foo::with('bars.baz')->first()->bars as $bar) {
$baz = $bar->baz;
$this->assertEquals(['id' => $baz->id, 'name' => $bar->name . '_baz', 'bar_id' => $bar->id], $baz->toArray());
}
}

public function testImportWithoutRelation()
{
$import = json_decode(file_get_contents(__DIR__ . '/Stubs/import.json'), true);
$import = $this->getImportArray();

unset($import['bars'][1]['baz']);

Expand All @@ -36,55 +64,92 @@ public function testImportWithoutRelation()
$this->assertFooIsImported();
$this->assertBarsAreImported();

$this->assertEquals(1, Baz::query()->count());
$this->assertEquals(1, Baz::count());
$baz = Foo::with('bars.baz')->first()->bars->pluck('baz');
$this->assertEquals([['id' => 1, 'name' => 'bar1_baz', 'bar_id' => '1'], null], $baz->toArray());
}

private function getImportArray(): array
{
return json_decode(file_get_contents(__DIR__ . '/Stubs/import.json'), true);
}

public function testImportWithAnEmptyRelation()
{
$import = json_decode(file_get_contents(__DIR__ . '/Stubs/import.json'), true);
$import = $this->getImportArray();

$import['bars'] = [];

$import = json_encode($import);

Foo::importFromJson($import);

$this->assertEquals(1, Foo::query()->count());
$this->assertEquals(0, Bar::query()->count());
$this->assertEquals(0, Baz::query()->count());
$this->assertEquals(0, DoNotExport::query()->count());
$this->assertEquals(1, Foo::count());
$this->assertEquals(0, Bar::count());
$this->assertEquals(0, Baz::count());
$this->assertEquals(0, DoNotExport::count());
}

public function testImportSeveralTimesWillJustAdd()
{
$import = json_decode(file_get_contents(__DIR__ . '/Stubs/import.json'), true);
$import = $this->getImportArray();

Foo::importFromJson($import);

$fooCount = Foo::query()->count();
$barCount = Bar::query()->count();
$bazCount = Baz::query()->count();
$doNotExportCount = DoNotExport::query()->count();
$fooCount = Foo::count();
$barCount = Bar::count();
$bazCount = Baz::count();
$doNotExportCount = DoNotExport::count();

foreach (range(1, 3) as $time) {
$this->assertEquals($time * $fooCount, Foo::query()->count());
$this->assertEquals($time * $barCount, Bar::query()->count());
$this->assertEquals($time * $bazCount, Baz::query()->count());
$this->assertEquals($time * $doNotExportCount, DoNotExport::query()->count());
$this->assertEquals($time * $fooCount, Foo::count());
$this->assertEquals($time * $barCount, Bar::count());
$this->assertEquals($time * $bazCount, Baz::count());
$this->assertEquals($time * $doNotExportCount, DoNotExport::count());

Foo::importFromJson($import);
}
}

public function testImportFromArray()
{
Foo::importFromJson(json_decode(file_get_contents(__DIR__ . '/Stubs/import.json'), true));
Foo::importFromJson($this->getImportArray());

$this->assertAllImportedInDatabase();
}

public function testImportNullRelation()
{
$objects = $this->getImportArray();
$objects['bars'] = null;

Foo::importFromJson($objects);

$this->assertFooIsImported();

$this->assertEquals(0, Bar::count());
$bars = Foo::first()->bars;
$this->assertEquals([], $bars->toArray());

$this->assertEquals(0, Baz::count());
$this->assertEquals(0, DoNotExport::count());
}

public function testImportNullAttribute()
{
$objects = $this->getImportArray();
$objects['author'] = null;

Foo::importFromJson($objects);

$this->assertEquals(1, Foo::count());
$this->assertEquals(['id' => 1, 'author' => null, 'username' => '@mathieutu'], Foo::first()->toArray());

$this->assertBarsAreImported();
$this->assertBazsAreImported();
$this->assertEquals(0, DoNotExport::count());
}

public function testImportBadJson()
{
$this->expectException(JsonDecodingException::class);
Expand All @@ -94,7 +159,7 @@ public function testImportBadJson()

public function testImportUnWantedData()
{
$import = json_decode(file_get_contents(__DIR__ . '/Stubs/import.json'), true);
$import = $this->getImportArray();
$import['bad'] = 'attribute';

Foo::importFromJson($import);
Expand All @@ -104,7 +169,7 @@ public function testImportUnWantedData()

public function testImportNonRelationMethodWithDefaultRelations()
{
$import = json_decode(file_get_contents(__DIR__ . '/Stubs/import.json'), true);
$import = $this->getImportArray();
$import['otherMethod'] = ['Hello you!'];

Foo::importFromJson($import);
Expand All @@ -117,7 +182,7 @@ public function testImportANonRelationMethodWithCustomRelations()
$this->expectException(UnknownAttributeException::class);
$this->expectExceptionMessage('Unknown attribute or HasOneorMany relation "otherMethod" in "MathieuTu\\JsonSyncer\\Tests\\Stubs\\Foo".');

$import = json_decode(file_get_contents(__DIR__ . '/Stubs/import.json'), true);
$import = $this->getImportArray();
$import['otherMethod'] = [];

(new Foo)->setJsonImportableRelationsForTests(['bars', 'otherMethod'])
Expand All @@ -129,7 +194,7 @@ public function testImportUnknownRelationWithCustomRelations()
$this->expectException(UnknownAttributeException::class);
$this->expectExceptionMessage('Unknown attribute or HasOneorMany relation "test" in "MathieuTu\\JsonSyncer\\Tests\\Stubs\\Foo".');

$import = json_decode(file_get_contents(__DIR__ . '/Stubs/import.json'), true);
$import = $this->getImportArray();
$import['test'] = [];

(new Foo)->setJsonImportableRelationsForTests(['bars', 'test'])
Expand All @@ -138,7 +203,7 @@ public function testImportUnknownRelationWithCustomRelations()

public function testImportWithCustomRelationsAndAttributes()
{
$import = json_decode(file_get_contents(__DIR__ . '/Stubs/import.json'), true);
$import = $this->getImportArray();

(new Foo)->setJsonImportableRelationsForTests(['bars'])
->setJsonImportableAttributesForTests(['author'])
Expand All @@ -155,7 +220,8 @@ public function testIsImportingMethod()
'author' => 'Mathieu',
];

$foo = new class extends Foo {
$foo = new class extends Foo
{
protected $fillable = ['author'];
protected $table = 'foos';

Expand Down Expand Up @@ -188,32 +254,7 @@ public function testImportNonImportableObjects()
];

Baz::importFromJson($baz);
$this->assertEquals(1, Baz::query()->count());
$this->assertEquals(0, DoNotExport::query()->count());
}

protected function assertBazsAreImported()
{
$this->assertEquals(2, Baz::query()->count());
foreach (Foo::with('bars.baz')->first()->bars as $bar) {
$baz = $bar->baz;
$this->assertEquals(['id' => $baz->id, 'name' => $bar->name . '_baz', 'bar_id' => $bar->id], $baz->toArray());
}
}

protected function assertBarsAreImported()
{
$this->assertEquals(2, Bar::query()->count());
$bars = Foo::query()->first()->bars;
$this->assertEquals([
['id' => 1, 'name' => 'bar1', 'foo_id' => 1],
['id' => 2, 'name' => 'bar2', 'foo_id' => 1],
], $bars->toArray());
}

protected function assertFooIsImported()
{
$this->assertEquals(1, Foo::query()->count());
$this->assertEquals(['id' => 1, 'author' => 'Mathieu TUDISCO', 'username' => '@mathieutu'], Foo::query()->first()->toArray());
$this->assertEquals(1, Baz::count());
$this->assertEquals(0, DoNotExport::count());
}
}

0 comments on commit 7452c15

Please sign in to comment.