From cceb533057c0f1f12e14feee5b650d2a442f628c Mon Sep 17 00:00:00 2001 From: korridor <26689068+korridor@users.noreply.github.com> Date: Sat, 31 Mar 2018 23:50:01 +0200 Subject: [PATCH 1/3] Added the ability to copy a many-to-many relationship with pivot attributes --- src/Cloner.php | 8 +++++- stubs/Article.php | 6 ++++- stubs/User.php | 12 +++++++++ tests/CloneableTest.php | 4 +-- tests/FunctionalTest.php | 53 ++++++++++++++++++++++++++++++++++------ 5 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 stubs/User.php diff --git a/src/Cloner.php b/src/Cloner.php index 25e2417..26ecdda 100644 --- a/src/Cloner.php +++ b/src/Cloner.php @@ -168,7 +168,13 @@ protected function duplicatePivotedRelation($relation, $relation_name, $clone) { // Loop trough current relations and attach to clone $relation->get()->each(function($foreign) use ($clone, $relation_name) { - $clone->$relation_name()->attach($foreign); + $pivot_attributes = array_except($foreign->pivot->getAttributes(), [ + $foreign->pivot->getRelatedKey(), + $foreign->pivot->getForeignKey(), + $foreign->pivot->getCreatedAtColumn(), + $foreign->pivot->getUpdatedAtColumn() + ]); + $clone->$relation_name()->attach($foreign, $pivot_attributes); }); } diff --git a/stubs/Article.php b/stubs/Article.php index fa93ee5..66ad047 100644 --- a/stubs/Article.php +++ b/stubs/Article.php @@ -6,7 +6,7 @@ class Article extends Eloquent { use Cloneable; - public $cloneable_relations = ['photos', 'authors']; + public $cloneable_relations = ['photos', 'authors', 'ratings']; public function photos() { return $this->hasMany('Bkwld\Cloner\Stubs\Photo'); @@ -15,4 +15,8 @@ public function photos() { public function authors() { return $this->belongsToMany('Bkwld\Cloner\Stubs\Author'); } + + public function ratings() { + return $this->belongsToMany(User::class)->withPivot('rating')->withTimestamps(); + } } \ No newline at end of file diff --git a/stubs/User.php b/stubs/User.php new file mode 100644 index 0000000..b86a566 --- /dev/null +++ b/stubs/User.php @@ -0,0 +1,12 @@ +belongsToMany(Article::class)->withPivot('rating')->withTimestamps(); + } +} \ No newline at end of file diff --git a/tests/CloneableTest.php b/tests/CloneableTest.php index dd2d435..0c02f9e 100644 --- a/tests/CloneableTest.php +++ b/tests/CloneableTest.php @@ -37,7 +37,7 @@ public function testDuplicateWithDifferentDB() { public function testGetRelations() { $article = new Article; - $this->assertEquals(['photos', 'authors'], $article->getCloneableRelations()); + $this->assertEquals(['photos', 'authors', 'ratings'], $article->getCloneableRelations()); } public function testAddRelation() { @@ -50,7 +50,7 @@ public function testAddDuplicateRelation() { $article = new Article; $article->addCloneableRelation('test'); $article->addCloneableRelation('test'); - $this->assertEquals(['photos', 'authors', 'test'], $article->getCloneableRelations()); + $this->assertEquals(['photos', 'authors', 'ratings', 'test'], $article->getCloneableRelations()); } } diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index d80f7ff..8549e52 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -6,9 +6,11 @@ use Bkwld\Cloner\Stubs\Article; use Bkwld\Cloner\Stubs\Author; use Bkwld\Cloner\Stubs\Photo; +use Bkwld\Cloner\Stubs\User; use Bkwld\Upchuck\Helpers; use Bkwld\Upchuck\Storage; use Illuminate\Database\Capsule\Manager as DB; +use Illuminate\Database\Schema\Blueprint; use League\Flysystem\Filesystem; use League\Flysystem\Vfs\VfsAdapter as Adapter; use League\Flysystem\MountManager; @@ -17,7 +19,9 @@ class FunctionalTest extends PHPUnit_Framework_TestCase { - protected function initUpchuck() { + private $article; + + protected function initUpchuck() { // Setup filesystem $fs = new Vfs; @@ -68,25 +72,25 @@ protected function setUpDatabase() { // https://github.com/laracasts/TestDummy/blob/master/tests/FactoryTest.php#L31 protected function migrateTables($connection = 'default') { - DB::connection($connection)->getSchemaBuilder()->create('articles', function ($table) { + DB::connection($connection)->getSchemaBuilder()->create('articles', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->timestamps(); }); - DB::connection($connection)->getSchemaBuilder()->create('authors', function ($table) { + DB::connection($connection)->getSchemaBuilder()->create('authors', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); - DB::connection($connection)->getSchemaBuilder()->create('article_author', function ($table) { + DB::connection($connection)->getSchemaBuilder()->create('article_author', function (Blueprint $table) { $table->increments('id'); $table->integer('article_id')->unsigned(); $table->integer('author_id')->unsigned(); }); - DB::connection($connection)->getSchemaBuilder()->create('photos', function ($table) { + DB::connection($connection)->getSchemaBuilder()->create('photos', function (Blueprint $table) { $table->increments('id'); $table->integer('article_id')->unsigned(); $table->string('uid'); @@ -94,6 +98,19 @@ protected function migrateTables($connection = 'default') { $table->boolean('source')->nullable(); $table->timestamps(); }); + + DB::connection($connection)->getSchemaBuilder()->create('users', function (Blueprint $table) { + $table->increments('id'); + $table->string('name'); + $table->timestamps(); + }); + + DB::connection($connection)->getSchemaBuilder()->create('article_user', function (Blueprint $table) { + $table->integer('rating')->unsigned(); + $table->integer('user_id')->unsigned(); + $table->integer('article_id')->unsigned(); + $table->timestamps(); + }); } protected function seed() { @@ -107,6 +124,12 @@ protected function seed() { 'name' => 'Steve', ])); + $this->article->ratings()->attach(User::create([ + 'name' => 'Peter' + ]), [ + 'rating' => 4 + ]); + $this->disk->write('test.jpg', 'contents'); Photo::unguard(); @@ -124,6 +147,9 @@ function testExists() { $this->migrateTables(); $this->seed(); + // Wait 1.5 seconds to be able to detect a difference in the timestamps + usleep(1500000); + $cloner = new Cloner($this->upchuck_adapter, $this->mockEvents()); $clone = $cloner->duplicate($this->article); @@ -132,11 +158,24 @@ function testExists() { $this->assertEquals(2, $clone->id); $this->assertEquals('Test', $clone->title); - // Test mamny to many + // Test many to many $this->assertEquals(1, $clone->authors()->count()); $this->assertEquals('Steve', $clone->authors()->first()->name); $this->assertEquals(2, DB::table('article_author')->count()); + // Test many to many with pivot + $this->assertEquals(1, $clone->ratings()->count()); + $this->assertEquals('Peter', $clone->ratings()->first()->name); + $this->assertEquals(2, DB::table('article_user')->count()); + + // Test if the timestamps in the pivot table have been reset + $this->assertNotNull($this->article->ratings()->first()->pivot->created_at); + $this->assertNotNull($clone->ratings()->first()->pivot->created_at); + $this->assertTrue($this->article->ratings()->first()->pivot->created_at->lt($clone->ratings()->first()->pivot->created_at)); + $this->assertNotNull($this->article->ratings()->first()->pivot->updated_at); + $this->assertNotNull($clone->ratings()->first()->pivot->updated_at); + $this->assertTrue($this->article->ratings()->first()->pivot->updated_at->lt($clone->ratings()->first()->pivot->updated_at)); + // Test one to many $this->assertEquals(1, $clone->photos()->count()); $photo = $clone->photos()->first(); @@ -185,7 +224,7 @@ function testExistsInAltDatabaseAndFilesystem() { $this->assertEquals(1 , $clone->id); $this->assertEquals('Test', $clone->title); - // Test that mamny to many failed + // Test that many to many failed $this->assertEquals(0, DB::connection('alt')->table('authors') ->where('article_id', $clone->id)->count()); From dad7d2ba4521bffba00ebcd41f8930d73c36656f Mon Sep 17 00:00:00 2001 From: korridor <26689068+korridor@users.noreply.github.com> Date: Sat, 31 Mar 2018 23:50:49 +0200 Subject: [PATCH 2/3] Added test for article timestamps --- tests/FunctionalTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index 8549e52..043fe43 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -158,6 +158,12 @@ function testExists() { $this->assertEquals(2, $clone->id); $this->assertEquals('Test', $clone->title); + // Test if the timestamps have been reset + $this->assertNotNull($clone->created_at); + $this->assertTrue($this->article->created_at->lt($clone->created_at)); + $this->assertNotNull($clone->updated_at); + $this->assertTrue($this->article->created_at->lt($clone->updated_at)); + // Test many to many $this->assertEquals(1, $clone->authors()->count()); $this->assertEquals('Steve', $clone->authors()->first()->name); From 00553fc84e3b80c926e8eb2c0791ecab7d130bd3 Mon Sep 17 00:00:00 2001 From: korridor <26689068+korridor@users.noreply.github.com> Date: Sun, 1 Apr 2018 00:18:49 +0200 Subject: [PATCH 3/3] Tab intended my changes --- src/Cloner.php | 14 ++++----- stubs/Article.php | 4 +-- stubs/User.php | 7 +++-- tests/FunctionalTest.php | 68 ++++++++++++++++++++-------------------- 4 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/Cloner.php b/src/Cloner.php index 26ecdda..8284fec 100644 --- a/src/Cloner.php +++ b/src/Cloner.php @@ -167,13 +167,13 @@ protected function duplicatePivotedRelation($relation, $relation_name, $clone) { if ($this->write_connection) return; // Loop trough current relations and attach to clone - $relation->get()->each(function($foreign) use ($clone, $relation_name) { - $pivot_attributes = array_except($foreign->pivot->getAttributes(), [ - $foreign->pivot->getRelatedKey(), - $foreign->pivot->getForeignKey(), - $foreign->pivot->getCreatedAtColumn(), - $foreign->pivot->getUpdatedAtColumn() - ]); + $relation->get()->each(function ($foreign) use ($clone, $relation_name) { + $pivot_attributes = array_except($foreign->pivot->getAttributes(), [ + $foreign->pivot->getRelatedKey(), + $foreign->pivot->getForeignKey(), + $foreign->pivot->getCreatedAtColumn(), + $foreign->pivot->getUpdatedAtColumn() + ]); $clone->$relation_name()->attach($foreign, $pivot_attributes); }); } diff --git a/stubs/Article.php b/stubs/Article.php index 66ad047..5ee409f 100644 --- a/stubs/Article.php +++ b/stubs/Article.php @@ -17,6 +17,6 @@ public function authors() { } public function ratings() { - return $this->belongsToMany(User::class)->withPivot('rating')->withTimestamps(); - } + return $this->belongsToMany(User::class)->withPivot('rating')->withTimestamps(); + } } \ No newline at end of file diff --git a/stubs/User.php b/stubs/User.php index b86a566..ea61f94 100644 --- a/stubs/User.php +++ b/stubs/User.php @@ -6,7 +6,8 @@ class User extends Eloquent { - public function rated_articles() { - return $this->belongsToMany(Article::class)->withPivot('rating')->withTimestamps(); - } + public function rated_articles() { + return $this->belongsToMany(Article::class)->withPivot('rating')->withTimestamps(); + } + } \ No newline at end of file diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index 043fe43..01b881f 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -19,7 +19,7 @@ class FunctionalTest extends PHPUnit_Framework_TestCase { - private $article; + private $article; protected function initUpchuck() { @@ -99,18 +99,18 @@ protected function migrateTables($connection = 'default') { $table->timestamps(); }); - DB::connection($connection)->getSchemaBuilder()->create('users', function (Blueprint $table) { - $table->increments('id'); - $table->string('name'); - $table->timestamps(); - }); - - DB::connection($connection)->getSchemaBuilder()->create('article_user', function (Blueprint $table) { - $table->integer('rating')->unsigned(); - $table->integer('user_id')->unsigned(); - $table->integer('article_id')->unsigned(); - $table->timestamps(); - }); + DB::connection($connection)->getSchemaBuilder()->create('users', function (Blueprint $table) { + $table->increments('id'); + $table->string('name'); + $table->timestamps(); + }); + + DB::connection($connection)->getSchemaBuilder()->create('article_user', function (Blueprint $table) { + $table->integer('rating')->unsigned(); + $table->integer('user_id')->unsigned(); + $table->integer('article_id')->unsigned(); + $table->timestamps(); + }); } protected function seed() { @@ -125,10 +125,10 @@ protected function seed() { ])); $this->article->ratings()->attach(User::create([ - 'name' => 'Peter' - ]), [ - 'rating' => 4 - ]); + 'name' => 'Peter' + ]), [ + 'rating' => 4 + ]); $this->disk->write('test.jpg', 'contents'); @@ -147,8 +147,8 @@ function testExists() { $this->migrateTables(); $this->seed(); - // Wait 1.5 seconds to be able to detect a difference in the timestamps - usleep(1500000); + // Wait 1.5 seconds to be able to detect a difference in the timestamps + usleep(1500000); $cloner = new Cloner($this->upchuck_adapter, $this->mockEvents()); $clone = $cloner->duplicate($this->article); @@ -159,10 +159,10 @@ function testExists() { $this->assertEquals('Test', $clone->title); // Test if the timestamps have been reset - $this->assertNotNull($clone->created_at); - $this->assertTrue($this->article->created_at->lt($clone->created_at)); - $this->assertNotNull($clone->updated_at); - $this->assertTrue($this->article->created_at->lt($clone->updated_at)); + $this->assertNotNull($clone->created_at); + $this->assertTrue($this->article->created_at->lt($clone->created_at)); + $this->assertNotNull($clone->updated_at); + $this->assertTrue($this->article->created_at->lt($clone->updated_at)); // Test many to many $this->assertEquals(1, $clone->authors()->count()); @@ -170,17 +170,17 @@ function testExists() { $this->assertEquals(2, DB::table('article_author')->count()); // Test many to many with pivot - $this->assertEquals(1, $clone->ratings()->count()); - $this->assertEquals('Peter', $clone->ratings()->first()->name); - $this->assertEquals(2, DB::table('article_user')->count()); - - // Test if the timestamps in the pivot table have been reset - $this->assertNotNull($this->article->ratings()->first()->pivot->created_at); - $this->assertNotNull($clone->ratings()->first()->pivot->created_at); - $this->assertTrue($this->article->ratings()->first()->pivot->created_at->lt($clone->ratings()->first()->pivot->created_at)); - $this->assertNotNull($this->article->ratings()->first()->pivot->updated_at); - $this->assertNotNull($clone->ratings()->first()->pivot->updated_at); - $this->assertTrue($this->article->ratings()->first()->pivot->updated_at->lt($clone->ratings()->first()->pivot->updated_at)); + $this->assertEquals(1, $clone->ratings()->count()); + $this->assertEquals('Peter', $clone->ratings()->first()->name); + $this->assertEquals(2, DB::table('article_user')->count()); + + // Test if the timestamps in the pivot table have been reset + $this->assertNotNull($this->article->ratings()->first()->pivot->created_at); + $this->assertNotNull($clone->ratings()->first()->pivot->created_at); + $this->assertTrue($this->article->ratings()->first()->pivot->created_at->lt($clone->ratings()->first()->pivot->created_at)); + $this->assertNotNull($this->article->ratings()->first()->pivot->updated_at); + $this->assertNotNull($clone->ratings()->first()->pivot->updated_at); + $this->assertTrue($this->article->ratings()->first()->pivot->updated_at->lt($clone->ratings()->first()->pivot->updated_at)); // Test one to many $this->assertEquals(1, $clone->photos()->count());