From 60a379d03ef837d02743184b95a634470812df71 Mon Sep 17 00:00:00 2001 From: Daniil Zobov Date: Thu, 30 Apr 2020 20:16:31 +0300 Subject: [PATCH] Laravel 7.x support --- README.md | 8 +- composer.json | 10 +- src/Relations/BelongsToManySoft.php | 28 +- .../EloquentBelongsToManySoftTest.php | 1120 ----------------- .../Database/EloquentBelongsToManyTest.php | 265 ++-- 5 files changed, 215 insertions(+), 1216 deletions(-) delete mode 100644 tests/Integration/Database/EloquentBelongsToManySoftTest.php diff --git a/README.md b/README.md index cd19197..91a4393 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Laravel pivot SoftDeletes for Laravel 5.8 & 6.x +# Laravel pivot SoftDeletes for Laravel 5.8 & 6.x & 7.x ## Installation @@ -69,17 +69,17 @@ $this->belongsToMany(Post::class)->withSoftDeletes('custom_deleted_at'); $this->belongsToMany(Post::class)->withSoftDeletes(); // same behavior -$this->belongsToMany(Post::class)->withSoftDeletes()->withoutTrashed(); +$this->belongsToMany(Post::class)->withSoftDeletes()->withoutTrashedPivots(); ``` ### Show exists & trashed: ```php -$this->belongsToMany(Post::class)->withSoftDeletes()->withTrashed(); +$this->belongsToMany(Post::class)->withSoftDeletes()->withTrashedPivots(); ``` ### Show only trashed: ```php -$this->belongsToMany(Post::class)->withSoftDeletes()->onlyTrashed(); +$this->belongsToMany(Post::class)->withSoftDeletes()->onlyTrashedPivots(); ``` ### Restore pivot recods: diff --git a/composer.json b/composer.json index 646b651..7b50181 100644 --- a/composer.json +++ b/composer.json @@ -16,13 +16,13 @@ } ], "require": { - "illuminate/database": "^5.8|^6.0" + "illuminate/database": "^5.8|^6.0|^7.0" }, "require-dev": { - "laravel/framework": "^5.8|^6.0", - "mockery/mockery": "^1.0", - "orchestra/testbench-core": "3.8.*", - "phpunit/phpunit": "^7.5|^8.0" + "laravel/framework": "^5.8|^6.0|^7.0", + "mockery/mockery": "^1.3.1", + "orchestra/testbench-core": "^5.0", + "phpunit/phpunit": "^8.4|^9.0" }, "autoload": { "psr-4": { diff --git a/src/Relations/BelongsToManySoft.php b/src/Relations/BelongsToManySoft.php index 50262a1..89513e0 100644 --- a/src/Relations/BelongsToManySoft.php +++ b/src/Relations/BelongsToManySoft.php @@ -6,11 +6,11 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; /** - * @method self withoutTrashed() Show only non-trashed records - * @method self withTrashed() Show all records - * @method self onlyTrashed() Show only trashed records - * @method int forceDetach(\Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array $ids, bool $touch) Show only trashed records - * @method int syncWithForceDetaching(mixed $ids) Show only trashed records + * @method self withoutTrashedPivots() Show only non-trashed records + * @method self withTrashedPivots() Show all records + * @method self onlyTrashedPivots() Show only trashed records + * @method int forceDetach(\Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array $ids, bool $touch) Force detach records + * @method int syncWithForceDetaching(mixed $ids) Sync many-to-many relationship with force detaching */ class BelongsToManySoft extends BelongsToMany { @@ -67,28 +67,28 @@ public function withSoftDeletes($deletedAt = 'deleted_at') $this->pivotDeletedAt = $deletedAt; - $this->macro('withoutTrashed', function () { - $this->query->withGlobalScope('withoutTrashed', function (Builder $query) { + $this->macro('withoutTrashedPivots', function () { + $this->query->withGlobalScope('withoutTrashedPivots', function (Builder $query) { $query->whereNull( $this->getQualifiedDeletedAtColumnName() ); - })->withoutGlobalScopes(['onlyTrashed']); + })->withoutGlobalScopes(['onlyTrashedPivots']); return $this; }); - $this->macro('withTrashed', function () { - $this->query->withoutGlobalScopes(['withoutTrashed', 'onlyTrashed']); + $this->macro('withTrashedPivots', function () { + $this->query->withoutGlobalScopes(['withoutTrashedPivots', 'onlyTrashedPivots']); return $this; }); - $this->macro('onlyTrashed', function () { - $this->query->withGlobalScope('onlyTrashed', function (Builder $query) { + $this->macro('onlyTrashedPivots', function () { + $this->query->withGlobalScope('onlyTrashedPivots', function (Builder $query) { $query->whereNotNull( $this->getQualifiedDeletedAtColumnName() ); - })->withoutGlobalScopes(['withoutTrashed']); + })->withoutGlobalScopes(['withoutTrashedPivots']); return $this; }); @@ -109,7 +109,7 @@ public function withSoftDeletes($deletedAt = 'deleted_at') }); }); - return $this->withPivot($this->deletedAt())->withoutTrashed(); + return $this->withPivot($this->deletedAt())->withoutTrashedPivots(); } /** diff --git a/tests/Integration/Database/EloquentBelongsToManySoftTest.php b/tests/Integration/Database/EloquentBelongsToManySoftTest.php deleted file mode 100644 index eeeac79..0000000 --- a/tests/Integration/Database/EloquentBelongsToManySoftTest.php +++ /dev/null @@ -1,1120 +0,0 @@ -increments('id'); - $table->string('uuid'); - $table->string('name'); - $table->timestamps(); - }); - - Schema::create('posts', function (Blueprint $table) { - $table->increments('id'); - $table->string('uuid'); - $table->string('title'); - $table->timestamps(); - }); - - Schema::create('tags', function (Blueprint $table) { - $table->increments('id'); - $table->string('name'); - $table->timestamps(); - }); - - Schema::create('users_posts', function (Blueprint $table) { - $table->string('user_uuid'); - $table->string('post_uuid'); - $table->tinyInteger('is_draft')->default(1); - $table->timestamps(); - $table->softDeletes(); - }); - - Schema::create('posts_tags', function (Blueprint $table) { - $table->integer('post_id'); - $table->integer('tag_id'); - $table->string('flag')->default(''); - $table->timestamps(); - $table->softDeletes(); - }); - - Carbon::setTestNow(null); - } - - public function testBasicCreateAndRetrieve() - { - Carbon::setTestNow('2017-10-10 10:10:10'); - - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - - $post->tags()->sync([ - $tag->id => ['flag' => 'taylor'], - $tag2->id => ['flag' => ''], - $tag3->id => ['flag' => 'exclude'], - ]); - - // Tags with flag = exclude should be excluded - $this->assertCount(2, $post->tags); - $this->assertInstanceOf(Collection::class, $post->tags); - $this->assertEquals($tag->name, $post->tags[0]->name); - $this->assertEquals($tag2->name, $post->tags[1]->name); - - // Testing on the pivot model - $this->assertInstanceOf(EloquentPivot::class, $post->tags[0]->pivot); - $this->assertEquals($post->id, $post->tags[0]->pivot->post_id); - $this->assertSame('post_id', $post->tags[0]->pivot->getForeignKey()); - $this->assertSame('tag_id', $post->tags[0]->pivot->getOtherKey()); - $this->assertSame('posts_tags', $post->tags[0]->pivot->getTable()); - $this->assertEquals( - [ - 'post_id' => '1', 'tag_id' => '1', 'flag' => 'taylor', - 'created_at' => '2017-10-10 10:10:10', 'updated_at' => '2017-10-10 10:10:10', 'deleted_at' => null, - ], - $post->tags[0]->pivot->toArray() - ); - } - - public function testRefreshOnOtherModelWorks() - { - $post = Post::create(['title' => Str::random()]); - $tag = Tag::create(['name' => $tagName = Str::random()]); - - $post->tags()->sync([ - $tag->id, - ]); - - $post->load('tags'); - - $loadedTag = $post->tags()->first(); - - $tag->update(['name' => 'newName']); - - $this->assertEquals($tagName, $loadedTag->name); - - $this->assertEquals($tagName, $post->tags[0]->name); - - $loadedTag->refresh(); - - $this->assertSame('newName', $loadedTag->name); - - $post->refresh(); - - $this->assertSame('newName', $post->tags[0]->name); - } - - public function testCustomPivotClass() - { - Carbon::setTestNow('2017-10-10 10:10:10'); - - $post = Post::create(['title' => Str::random()]); - - $tag = TagWithCustomPivot::create(['name' => Str::random()]); - - $post->tagsWithCustomPivot()->attach($tag->id); - - $this->assertInstanceOf(PostTagPivot::class, $post->tagsWithCustomPivot[0]->pivot); - $this->assertSame('1507630210', $post->tagsWithCustomPivot[0]->pivot->getAttributes()['created_at']); - - $this->assertInstanceOf(PostTagPivot::class, $post->tagsWithCustomPivotClass[0]->pivot); - $this->assertSame('posts_tags', $post->tagsWithCustomPivotClass()->getTable()); - - $this->assertEquals([ - 'post_id' => '1', - 'tag_id' => '1', - 'deleted_at' => null, - ], $post->tagsWithCustomAccessor[0]->tag->toArray()); - - $pivot = $post->tagsWithCustomPivot[0]->pivot; - $pivot->tag_id = 2; - $pivot->save(); - - $this->assertEquals(1, PostTagPivot::count()); - $this->assertEquals(1, PostTagPivot::first()->post_id); - $this->assertEquals(2, PostTagPivot::first()->tag_id); - } - - public function testCustomPivotClassUsingSync() - { - Carbon::setTestNow('2017-10-10 10:10:10'); - - $post = Post::create(['title' => Str::random()]); - - $tag = TagWithCustomPivot::create(['name' => Str::random()]); - - $results = $post->tagsWithCustomPivot()->sync([ - $tag->id => ['flag' => 1], - ]); - - $this->assertNotEmpty($results['attached']); - - $results = $post->tagsWithCustomPivot()->sync([ - $tag->id => ['flag' => 1], - ]); - - $this->assertEmpty($results['updated']); - - $results = $post->tagsWithCustomPivot()->sync([]); - - $this->assertNotEmpty($results['detached']); - } - - public function testCustomPivotClassUsingUpdateExistingPivot() - { - Carbon::setTestNow('2017-10-10 10:10:10'); - - $post = Post::create(['title' => Str::random()]); - $tag = TagWithCustomPivot::create(['name' => Str::random()]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag->id, 'flag' => 'empty'], - ]); - - // Test on actually existing pivot - $this->assertEquals( - 1, - $post->tagsWithCustomExtraPivot()->updateExistingPivot($tag->id, ['flag' => 'exclude']) - ); - foreach ($post->tagsWithCustomExtraPivot as $tag) { - $this->assertSame('exclude', $tag->pivot->flag); - } - - // Test on non-existent pivot - $this->assertEquals( - 0, - $post->tagsWithCustomExtraPivot()->updateExistingPivot(0, ['flag' => 'exclude']) - ); - } - - public function testAttachMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $tag4 = Tag::create(['name' => Str::random()]); - $tag5 = Tag::create(['name' => Str::random()]); - $tag6 = Tag::create(['name' => Str::random()]); - $tag7 = Tag::create(['name' => Str::random()]); - $tag8 = Tag::create(['name' => Str::random()]); - - $post->tags()->attach($tag->id); - $this->assertEquals($tag->name, $post->tags[0]->name); - $this->assertNotNull($post->tags[0]->pivot->created_at); - - $post->tags()->attach($tag2->id, ['flag' => 'taylor']); - $post->load('tags'); - $this->assertEquals($tag2->name, $post->tags[1]->name); - $this->assertSame('taylor', $post->tags[1]->pivot->flag); - - $post->tags()->attach([$tag3->id, $tag4->id]); - $post->load('tags'); - $this->assertEquals($tag3->name, $post->tags[2]->name); - $this->assertEquals($tag4->name, $post->tags[3]->name); - - $post->tags()->attach([$tag5->id => ['flag' => 'mohamed'], $tag6->id => ['flag' => 'adam']]); - $post->load('tags'); - $this->assertEquals($tag5->name, $post->tags[4]->name); - $this->assertSame('mohamed', $post->tags[4]->pivot->flag); - $this->assertEquals($tag6->name, $post->tags[5]->name); - $this->assertSame('adam', $post->tags[5]->pivot->flag); - - $post->tags()->attach(new Collection([$tag7, $tag8])); - $post->load('tags'); - $this->assertEquals($tag7->name, $post->tags[6]->name); - $this->assertEquals($tag8->name, $post->tags[7]->name); - } - - public function testDetachMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $tag4 = Tag::create(['name' => Str::random()]); - $tag5 = Tag::create(['name' => Str::random()]); - Tag::create(['name' => Str::random()]); - Tag::create(['name' => Str::random()]); - - $post->tags()->attach(Tag::all()); - - $this->assertEquals(Tag::pluck('name'), $post->tags->pluck('name')); - - $post->tags()->detach($tag->id); - $post->load('tags'); - $this->assertEquals( - Tag::whereNotIn('id', [$tag->id])->pluck('name'), - $post->tags->pluck('name') - ); - - $post->tags()->detach([$tag2->id, $tag3->id]); - $post->load('tags'); - $this->assertEquals( - Tag::whereNotIn('id', [$tag->id, $tag2->id, $tag3->id])->pluck('name'), - $post->tags->pluck('name') - ); - - $post->tags()->detach(new Collection([$tag4, $tag5])); - $post->load('tags'); - $this->assertEquals( - Tag::whereNotIn('id', [$tag->id, $tag2->id, $tag3->id, $tag4->id, $tag5->id])->pluck('name'), - $post->tags->pluck('name') - ); - - $this->assertCount(2, $post->tags); - $post->tags()->detach(); - $post->load('tags'); - $this->assertCount(0, $post->tags); - } - - public function testFirstMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - - $post->tags()->attach(Tag::all()); - - $this->assertEquals($tag->name, $post->tags()->first()->name); - } - - public function testFirstOrFailMethod() - { - $this->expectException(ModelNotFoundException::class); - - $post = Post::create(['title' => Str::random()]); - - $post->tags()->firstOrFail(['id' => 10]); - } - - public function testFindMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - - $post->tags()->attach(Tag::all()); - - $this->assertEquals($tag2->name, $post->tags()->find($tag2->id)->name); - $this->assertCount(2, $post->tags()->findMany([$tag->id, $tag2->id])); - } - - public function testFindOrFailMethod() - { - $this->expectException(ModelNotFoundException::class); - - $post = Post::create(['title' => Str::random()]); - - Tag::create(['name' => Str::random()]); - - $post->tags()->attach(Tag::all()); - - $post->tags()->findOrFail(10); - } - - public function testFindOrNewMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - - $post->tags()->attach(Tag::all()); - - $this->assertEquals($tag->id, $post->tags()->findOrNew($tag->id)->id); - - $this->assertNull($post->tags()->findOrNew('asd')->id); - $this->assertInstanceOf(Tag::class, $post->tags()->findOrNew('asd')); - } - - public function testFirstOrNewMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - - $post->tags()->attach(Tag::all()); - - $this->assertEquals($tag->id, $post->tags()->firstOrNew(['id' => $tag->id])->id); - - $this->assertNull($post->tags()->firstOrNew(['id' => 'asd'])->id); - $this->assertInstanceOf(Tag::class, $post->tags()->firstOrNew(['id' => 'asd'])); - } - - public function testFirstOrCreateMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - - $post->tags()->attach(Tag::all()); - - $this->assertEquals($tag->id, $post->tags()->firstOrCreate(['name' => $tag->name])->id); - - $new = $post->tags()->firstOrCreate(['name' => 'wavez']); - $this->assertSame('wavez', $new->name); - $this->assertNotNull($new->id); - } - - public function testUpdateOrCreateMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - - $post->tags()->attach(Tag::all()); - - $post->tags()->updateOrCreate(['id' => $tag->id], ['name' => 'wavez']); - $this->assertSame('wavez', $tag->fresh()->name); - - $post->tags()->updateOrCreate(['id' => 'asd'], ['name' => 'dives']); - $this->assertNotNull($post->tags()->whereName('dives')->first()); - } - - public function testSyncMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $tag4 = Tag::create(['name' => Str::random()]); - - $post->tags()->sync([$tag->id, $tag2->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - - $output = $post->tags()->sync([$tag->id, $tag3->id, $tag4->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag3->id, $tag4->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - - $this->assertEquals([ - 'attached' => [$tag3->id, $tag4->id], - 'detached' => [1 => $tag2->id], - 'updated' => [], - ], $output); - - $post->tags()->sync([]); - $this->assertEmpty($post->load('tags')->tags); - - $post->tags()->sync([ - $tag->id => ['flag' => 'taylor'], - $tag2->id => ['flag' => 'mohamed'], - ]); - $post->load('tags'); - $this->assertEquals($tag->name, $post->tags[0]->name); - $this->assertSame('taylor', $post->tags[0]->pivot->flag); - $this->assertEquals($tag2->name, $post->tags[1]->name); - $this->assertSame('mohamed', $post->tags[1]->pivot->flag); - } - - public function testSyncWithoutDetachingMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - - $post->tags()->sync([$tag->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - - $post->tags()->syncWithoutDetaching([$tag2->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - } - - public function testToggleMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - - $post->tags()->toggle([$tag->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - - $post->tags()->toggle([$tag2->id, $tag->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag2->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - - $post->tags()->toggle([$tag2->id, $tag->id => ['flag' => 'taylor']]); - $post->load('tags'); - $this->assertEquals( - Tag::whereIn('id', [$tag->id])->pluck('name'), - $post->tags->pluck('name') - ); - $this->assertSame('taylor', $post->tags[0]->pivot->flag); - } - - public function testTouchingParent() - { - $post = Post::create(['title' => Str::random()]); - - $tag = TouchingTag::create(['name' => Str::random()]); - - $post->touchingTags()->attach([$tag->id]); - - $this->assertNotSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - - Carbon::setTestNow('2017-10-10 10:10:10'); - - $tag->update(['name' => $tag->name]); - $this->assertNotSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - - $tag->update(['name' => Str::random()]); - $this->assertSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - } - - public function testTouchingRelatedModelsOnSync() - { - $tag = TouchingTag::create(['name' => Str::random()]); - - $post = Post::create(['title' => Str::random()]); - - $this->assertNotSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - $this->assertNotSame('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); - - Carbon::setTestNow('2017-10-10 10:10:10'); - - $tag->posts()->sync([$post->id]); - - $this->assertSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - $this->assertSame('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); - } - - public function testNoTouchingHappensIfNotConfigured() - { - $tag = Tag::create(['name' => Str::random()]); - - $post = Post::create(['title' => Str::random()]); - - $this->assertNotSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - $this->assertNotSame('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); - - Carbon::setTestNow('2017-10-10 10:10:10'); - - $tag->posts()->sync([$post->id]); - - $this->assertNotSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - $this->assertNotSame('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); - } - - public function testCanRetrieveRelatedIds() - { - $post = Post::create(['title' => Str::random()]); - - DB::table('tags')->insert([ - ['id' => 200, 'name' => 'excluded'], - ['id' => 300, 'name' => Str::random()], - ]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => 200, 'flag' => ''], - ['post_id' => $post->id, 'tag_id' => 300, 'flag' => 'exclude'], - ['post_id' => $post->id, 'tag_id' => 400, 'flag' => ''], - ]); - - $this->assertEquals([200, 400], $post->tags()->allRelatedIds()->toArray()); - } - - public function testCanTouchRelatedModels() - { - $post = Post::create(['title' => Str::random()]); - - DB::table('tags')->insert([ - ['id' => 200, 'name' => Str::random()], - ['id' => 300, 'name' => Str::random()], - ]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => 200, 'flag' => ''], - ['post_id' => $post->id, 'tag_id' => 300, 'flag' => 'exclude'], - ['post_id' => $post->id, 'tag_id' => 400, 'flag' => ''], - ]); - - Carbon::setTestNow('2017-10-10 10:10:10'); - - $post->tags()->touch(); - - foreach ($post->tags()->pluck('tags.updated_at') as $date) { - $this->assertSame('2017-10-10 10:10:10', $date); - } - - $this->assertNotSame('2017-10-10 10:10:10', Tag::find(300)->updated_at); - } - - public function testWherePivotOnString() - { - $tag = Tag::create(['name' => Str::random()]); - $post = Post::create(['title' => Str::random()]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag->id, 'flag' => 'foo'], - ]); - - $relationTag = $post->tags()->wherePivot('flag', 'foo')->first(); - $this->assertEquals($relationTag->getAttributes(), $tag->getAttributes()); - - $relationTag = $post->tags()->wherePivot('flag', '=', 'foo')->first(); - $this->assertEquals($relationTag->getAttributes(), $tag->getAttributes()); - } - - public function testWherePivotOnBoolean() - { - $tag = Tag::create(['name' => Str::random()]); - $post = Post::create(['title' => Str::random()]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag->id, 'flag' => true], - ]); - - $relationTag = $post->tags()->wherePivot('flag', true)->first(); - $this->assertEquals($relationTag->getAttributes(), $tag->getAttributes()); - - $relationTag = $post->tags()->wherePivot('flag', '=', true)->first(); - $this->assertEquals($relationTag->getAttributes(), $tag->getAttributes()); - } - - public function testWherePivotInMethod() - { - $tag = Tag::create(['name' => Str::random()]); - $post = Post::create(['title' => Str::random()]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag->id, 'flag' => 'foo'], - ]); - - $relationTag = $post->tags()->wherePivotIn('flag', ['foo'])->first(); - $this->assertEquals($relationTag->getAttributes(), $tag->getAttributes()); - } - - public function testOrWherePivotInMethod() - { - $tag1 = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $post = Post::create(['title' => Str::random()]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag1->id, 'flag' => 'foo'], - ]); - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag2->id, 'flag' => 'bar'], - ]); - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag3->id, 'flag' => 'baz'], - ]); - - $relationTags = $post->tags()->wherePivotIn('flag', ['foo'])->orWherePivotIn('flag', ['baz'])->get(); - $this->assertEquals($relationTags->pluck('id')->toArray(), [$tag1->id, $tag3->id]); - } - - public function testCanUpdateExistingPivot() - { - $tag = Tag::create(['name' => Str::random()]); - $post = Post::create(['title' => Str::random()]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag->id, 'flag' => 'empty'], - ]); - - $post->tagsWithExtraPivot()->updateExistingPivot($tag->id, ['flag' => 'exclude']); - - foreach ($post->tagsWithExtraPivot as $tag) { - $this->assertSame('exclude', $tag->pivot->flag); - } - } - - public function testCanUpdateExistingPivotUsingArrayableOfIds() - { - $tags = new Collection([ - $tag1 = Tag::create(['name' => Str::random()]), - $tag2 = Tag::create(['name' => Str::random()]), - ]); - $post = Post::create(['title' => Str::random()]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag1->id, 'flag' => 'empty'], - ['post_id' => $post->id, 'tag_id' => $tag2->id, 'flag' => 'empty'], - ]); - - $post->tagsWithExtraPivot()->updateExistingPivot($tags, ['flag' => 'exclude']); - - foreach ($post->tagsWithExtraPivot as $tag) { - $this->assertSame('exclude', $tag->pivot->flag); - } - } - - public function testCanUpdateExistingPivotUsingModel() - { - $tag = Tag::create(['name' => Str::random()]); - $post = Post::create(['title' => Str::random()]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag->id, 'flag' => 'empty'], - ]); - - $post->tagsWithExtraPivot()->updateExistingPivot($tag, ['flag' => 'exclude']); - - foreach ($post->tagsWithExtraPivot as $tag) { - $this->assertSame('exclude', $tag->pivot->flag); - } - } - - public function testCustomRelatedKey() - { - $post = Post::create(['title' => Str::random()]); - - $tag = $post->tagsWithCustomRelatedKey()->create(['name' => Str::random()]); - $this->assertEquals($tag->name, $post->tagsWithCustomRelatedKey()->first()->pivot->tag_id); - - $post->tagsWithCustomRelatedKey()->detach($tag); - - $post->tagsWithCustomRelatedKey()->attach($tag); - $this->assertEquals($tag->name, $post->tagsWithCustomRelatedKey()->first()->pivot->tag_id); - - $post->tagsWithCustomRelatedKey()->detach(new Collection([$tag])); - - $post->tagsWithCustomRelatedKey()->attach(new Collection([$tag])); - $this->assertEquals($tag->name, $post->tagsWithCustomRelatedKey()->first()->pivot->tag_id); - - $post->tagsWithCustomRelatedKey()->updateExistingPivot($tag, ['flag' => 'exclude']); - $this->assertSame('exclude', $post->tagsWithCustomRelatedKey()->first()->pivot->flag); - } - - public function testGlobalScopeColumns() - { - $tag = Tag::create(['name' => Str::random()]); - $post = Post::create(['title' => Str::random()]); - - DB::table('posts_tags')->insert([ - ['post_id' => $post->id, 'tag_id' => $tag->id, 'flag' => 'empty'], - ]); - - $tags = $post->tagsWithGlobalScope; - - $this->assertEquals(['id' => 1], $tags[0]->getAttributes()); - } - - public function testPivotDoesntHavePrimaryKey() - { - $user = User::create(['name' => Str::random()]); - $post1 = Post::create(['title' => Str::random()]); - $post2 = Post::create(['title' => Str::random()]); - - $user->postsWithCustomPivot()->sync([$post1->uuid]); - $this->assertEquals($user->uuid, $user->postsWithCustomPivot()->first()->pivot->user_uuid); - $this->assertEquals($post1->uuid, $user->postsWithCustomPivot()->first()->pivot->post_uuid); - $this->assertEquals(1, $user->postsWithCustomPivot()->first()->pivot->is_draft); - - $user->postsWithCustomPivot()->sync([$post2->uuid]); - $this->assertEquals($user->uuid, $user->postsWithCustomPivot()->first()->pivot->user_uuid); - $this->assertEquals($post2->uuid, $user->postsWithCustomPivot()->first()->pivot->post_uuid); - $this->assertEquals(1, $user->postsWithCustomPivot()->first()->pivot->is_draft); - - $user->postsWithCustomPivot()->updateExistingPivot($post2->uuid, ['is_draft' => 0]); - $this->assertEquals(0, $user->postsWithCustomPivot()->first()->pivot->is_draft); - } - - public function testWithTrashedMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $tag4 = Tag::create(['name' => Str::random()]); - - $post->tags()->sync([$tag->id, $tag2->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - - $post->tags()->sync([$tag->id, $tag3->id, $tag4->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id, $tag3->id, $tag4->id])->pluck('name'), - $post->tags()->withTrashed()->pluck('name') - ); - } - - public function testOnlyTrashedMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $tag4 = Tag::create(['name' => Str::random()]); - - $post->tags()->sync([$tag->id, $tag2->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - - $post->tags()->sync([$tag->id, $tag3->id, $tag4->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag2->id])->pluck('name'), - $post->tags()->onlyTrashed()->pluck('name') - ); - } - - public function testRestoreMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $tag4 = Tag::create(['name' => Str::random()]); - - $post->tags()->sync([$tag->id, $tag2->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - - $post->tags()->sync([$tag->id, $tag3->id, $tag4->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag2->id])->pluck('name'), - $post->tags()->onlyTrashed()->pluck('name') - ); - - $output = $post->tags()->restore([$tag2->id]); - - $this->assertEquals(1, $output); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id, $tag3->id, $tag4->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - } - - public function testRestoreMethodWithCustomPivotClass() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $tag4 = Tag::create(['name' => Str::random()]); - - $post->tagsWithCustomPivot()->sync([$tag->id, $tag2->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id])->pluck('name'), - $post->load('tagsWithCustomPivot')->tagsWithCustomPivot->pluck('name') - ); - - $post->tagsWithCustomPivot()->sync([$tag->id, $tag3->id, $tag4->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag2->id])->pluck('name'), - $post->tagsWithCustomPivot()->onlyTrashed()->pluck('name') - ); - - $output = $post->tagsWithCustomPivot()->restore([$tag2->id]); - - $this->assertEquals(1, $output); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id, $tag3->id, $tag4->id])->pluck('name'), - $post->load('tagsWithCustomPivot')->tagsWithCustomPivot->pluck('name') - ); - } - - public function testForceDetachMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $tag4 = Tag::create(['name' => Str::random()]); - - $post->tags()->sync([$tag->id, $tag2->id, $tag3->id, $tag4->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id, $tag3->id, $tag4->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - - $post->tags()->forceDetach([$tag->id, $tag3->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag2->id, $tag4->id])->pluck('name'), - $post->tags()->withTrashed()->pluck('name') - ); - } - - public function testSyncWithForceDetachingMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $tag4 = Tag::create(['name' => Str::random()]); - - $post->tags()->sync([$tag->id, $tag2->id, $tag3->id, $tag4->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag2->id, $tag3->id, $tag4->id])->pluck('name'), - $post->load('tags')->tags->pluck('name') - ); - - $post->tags()->syncWithForceDetaching([$tag->id, $tag3->id]); - - $this->assertEquals( - Tag::whereIn('id', [$tag->id, $tag3->id])->pluck('name'), - $post->tags()->withTrashed()->pluck('name') - ); - } - - public function testWhereHasMethod() - { - $post = Post::create(['title' => Str::random()]); - - $tag = Tag::create(['name' => Str::random()]); - $tag2 = Tag::create(['name' => Str::random()]); - $tag3 = Tag::create(['name' => Str::random()]); - $tag4 = Tag::create(['name' => Str::random()]); - - $post->tags()->sync([$tag->id, $tag2->id, $tag3->id, $tag4->id]); - $post->tags()->sync([$tag2->id, $tag3->id]); - - $posts = Post::whereHas('tags', function (Builder $builder) use ($tag, $tag4) { - $builder->whereIn('tags.id', [$tag->id, $tag4->id]); - })->get(); - - $this->assertCount(0, $posts); - } -} - -class User extends Model -{ - public $table = 'users'; - public $timestamps = true; - protected $guarded = ['id']; - - protected static function boot() - { - parent::boot(); - static::creating(function ($model) { - $model->setAttribute('uuid', Str::random()); - }); - } - - public function postsWithCustomPivot() - { - return $this->belongsToMany(Post::class, 'users_posts', 'user_uuid', 'post_uuid', 'uuid', 'uuid') - ->using(UserPostPivot::class) - ->withPivot('is_draft') - ->withTimestamps() - ->withSoftDeletes(); - } -} - -class Post extends Model -{ - public $table = 'posts'; - public $timestamps = true; - protected $guarded = ['id']; - protected $touches = ['touchingTags']; - - protected static function boot() - { - parent::boot(); - static::creating(function ($model) { - $model->setAttribute('uuid', Str::random()); - }); - } - - public function tags() - { - return $this->belongsToMany(Tag::class, 'posts_tags', 'post_id', 'tag_id') - ->withPivot('flag') - ->withTimestamps() - ->wherePivot('flag', '<>', 'exclude') - ->withSoftDeletes(); - } - - public function tagsWithExtraPivot() - { - return $this->belongsToMany(Tag::class, 'posts_tags', 'post_id', 'tag_id') - ->withPivot('flag') - ->withSoftDeletes(); - } - - public function touchingTags() - { - return $this->belongsToMany(TouchingTag::class, 'posts_tags', 'post_id', 'tag_id') - ->withTimestamps() - ->withSoftDeletes(); - } - - public function tagsWithCustomPivot() - { - return $this->belongsToMany(TagWithCustomPivot::class, 'posts_tags', 'post_id', 'tag_id') - ->using(PostTagPivot::class) - ->withTimestamps() - ->withSoftDeletes(); - } - - public function tagsWithCustomExtraPivot() - { - return $this->belongsToMany(TagWithCustomPivot::class, 'posts_tags', 'post_id', 'tag_id') - ->using(PostTagPivot::class) - ->withTimestamps() - ->withPivot('flag') - ->withSoftDeletes(); - } - - public function tagsWithCustomPivotClass() - { - return $this->belongsToMany(TagWithCustomPivot::class, PostTagPivot::class, 'post_id', 'tag_id') - ->withSoftDeletes(); - } - - public function tagsWithCustomAccessor() - { - return $this->belongsToMany(TagWithCustomPivot::class, 'posts_tags', 'post_id', 'tag_id') - ->using(PostTagPivot::class) - ->as('tag') - ->withSoftDeletes(); - } - - public function tagsWithCustomRelatedKey() - { - return $this->belongsToMany(Tag::class, 'posts_tags', 'post_id', 'tag_id', 'id', 'name') - ->withPivot('flag') - ->withSoftDeletes(); - } - - public function tagsWithGlobalScope() - { - return $this->belongsToMany(TagWithGlobalScope::class, 'posts_tags', 'post_id', 'tag_id') - ->withSoftDeletes(); - } -} - -class Tag extends Model -{ - public $table = 'tags'; - public $timestamps = true; - protected $guarded = ['id']; - - public function posts() - { - return $this->belongsToMany(Post::class, 'posts_tags', 'tag_id', 'post_id') - ->withSoftDeletes(); - } -} - -class TouchingTag extends Model -{ - public $table = 'tags'; - public $timestamps = true; - protected $guarded = ['id']; - protected $touches = ['posts']; - - public function posts() - { - return $this->belongsToMany(Post::class, 'posts_tags', 'tag_id', 'post_id') - ->withSoftDeletes(); - } -} - -class TagWithCustomPivot extends Model -{ - public $table = 'tags'; - public $timestamps = true; - protected $guarded = ['id']; - - public function posts() - { - return $this->belongsToMany(Post::class, 'posts_tags', 'tag_id', 'post_id') - ->withSoftDeletes(); - } -} - -class UserPostPivot extends Pivot -{ - protected $table = 'users_posts'; -} - -class PostTagPivot extends Pivot -{ - protected $table = 'posts_tags'; - protected $dateFormat = 'U'; -} - -class TagWithGlobalScope extends Model -{ - public $table = 'tags'; - public $timestamps = true; - protected $guarded = ['id']; - - public static function boot() - { - parent::boot(); - - static::addGlobalScope(function ($query) { - $query->select('tags.id'); - }); - } -} diff --git a/tests/Integration/Database/EloquentBelongsToManyTest.php b/tests/Integration/Database/EloquentBelongsToManyTest.php index d1ccfed..57ef94e 100644 --- a/tests/Integration/Database/EloquentBelongsToManyTest.php +++ b/tests/Integration/Database/EloquentBelongsToManyTest.php @@ -2,15 +2,15 @@ namespace DDZobov\PivotSoftDeletes\Tests\Integration\Database\EloquentBelongsToManyTest; -use Illuminate\Support\Str; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\ModelNotFoundException; +use Illuminate\Database\Eloquent\Relations\Pivot; +use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Eloquent\Collection; -use Illuminate\Database\Eloquent\Relations\Pivot; -use Illuminate\Database\Eloquent\ModelNotFoundException; +use Illuminate\Support\Str; use DDZobov\PivotSoftDeletes\Tests\Integration\Database\DatabaseTestCase; /** @@ -59,7 +59,7 @@ protected function setUp(): void Carbon::setTestNow(null); } - public function test_basic_create_and_retrieve() + public function testBasicCreateAndRetrieve() { Carbon::setTestNow('2017-10-10 10:10:10'); @@ -84,19 +84,19 @@ public function test_basic_create_and_retrieve() // Testing on the pivot model $this->assertInstanceOf(Pivot::class, $post->tags[0]->pivot); $this->assertEquals($post->id, $post->tags[0]->pivot->post_id); - $this->assertEquals('post_id', $post->tags[0]->pivot->getForeignKey()); - $this->assertEquals('tag_id', $post->tags[0]->pivot->getOtherKey()); - $this->assertEquals('posts_tags', $post->tags[0]->pivot->getTable()); + $this->assertSame('post_id', $post->tags[0]->pivot->getForeignKey()); + $this->assertSame('tag_id', $post->tags[0]->pivot->getOtherKey()); + $this->assertSame('posts_tags', $post->tags[0]->pivot->getTable()); $this->assertEquals( [ 'post_id' => '1', 'tag_id' => '1', 'flag' => 'taylor', - 'created_at' => '2017-10-10 10:10:10', 'updated_at' => '2017-10-10 10:10:10', + 'created_at' => '2017-10-10T10:10:10.000000Z', 'updated_at' => '2017-10-10T10:10:10.000000Z', ], $post->tags[0]->pivot->toArray() ); } - public function test_refresh_on_other_model_works() + public function testRefreshOnOtherModelWorks() { $post = Post::create(['title' => Str::random()]); $tag = Tag::create(['name' => $tagName = Str::random()]); @@ -117,14 +117,14 @@ public function test_refresh_on_other_model_works() $loadedTag->refresh(); - $this->assertEquals('newName', $loadedTag->name); + $this->assertSame('newName', $loadedTag->name); $post->refresh(); - $this->assertEquals('newName', $post->tags[0]->name); + $this->assertSame('newName', $post->tags[0]->name); } - public function test_custom_pivot_class() + public function testCustomPivotClass() { Carbon::setTestNow('2017-10-10 10:10:10'); @@ -135,10 +135,10 @@ public function test_custom_pivot_class() $post->tagsWithCustomPivot()->attach($tag->id); $this->assertInstanceOf(PostTagPivot::class, $post->tagsWithCustomPivot[0]->pivot); - $this->assertEquals('1507630210', $post->tagsWithCustomPivot[0]->pivot->getAttributes()['created_at']); + $this->assertSame('1507630210', $post->tagsWithCustomPivot[0]->pivot->getAttributes()['created_at']); $this->assertInstanceOf(PostTagPivot::class, $post->tagsWithCustomPivotClass[0]->pivot); - $this->assertEquals('posts_tags', $post->tagsWithCustomPivotClass()->getTable()); + $this->assertSame('posts_tags', $post->tagsWithCustomPivotClass()->getTable()); $this->assertEquals([ 'post_id' => '1', @@ -154,7 +154,7 @@ public function test_custom_pivot_class() $this->assertEquals(2, PostTagPivot::first()->tag_id); } - public function test_custom_pivot_class_using_sync() + public function testCustomPivotClassUsingSync() { Carbon::setTestNow('2017-10-10 10:10:10'); @@ -179,7 +179,7 @@ public function test_custom_pivot_class_using_sync() $this->assertNotEmpty($results['detached']); } - public function test_custom_pivot_class_using_update_existing_pivot() + public function testCustomPivotClassUsingUpdateExistingPivot() { Carbon::setTestNow('2017-10-10 10:10:10'); @@ -196,7 +196,7 @@ public function test_custom_pivot_class_using_update_existing_pivot() $post->tagsWithCustomExtraPivot()->updateExistingPivot($tag->id, ['flag' => 'exclude']) ); foreach ($post->tagsWithCustomExtraPivot as $tag) { - $this->assertEquals('exclude', $tag->pivot->flag); + $this->assertSame('exclude', $tag->pivot->flag); } // Test on non-existent pivot @@ -206,7 +206,35 @@ public function test_custom_pivot_class_using_update_existing_pivot() ); } - public function test_attach_method() + public function testCustomPivotClassUpdatesTimestamps() + { + Carbon::setTestNow('2017-10-10 10:10:10'); + + $post = Post::create(['title' => Str::random()]); + $tag = TagWithCustomPivot::create(['name' => Str::random()]); + + DB::table('posts_tags')->insert([ + [ + 'post_id' => $post->id, 'tag_id' => $tag->id, 'flag' => 'empty', + 'created_at' => '1507630210', + 'updated_at' => '1507630210', + ], + ]); + + Carbon::setTestNow('2017-10-10 10:10:20'); // +10 seconds + + $this->assertEquals( + 1, + $post->tagsWithCustomExtraPivot()->updateExistingPivot($tag->id, ['flag' => 'exclude']) + ); + foreach ($post->tagsWithCustomExtraPivot as $tag) { + $this->assertSame('exclude', $tag->pivot->flag); + $this->assertSame('1507630210', $tag->pivot->getAttributes()['created_at']); + $this->assertSame('1507630220', $tag->pivot->getAttributes()['updated_at']); // +10 seconds + } + } + + public function testAttachMethod() { $post = Post::create(['title' => Str::random()]); @@ -226,7 +254,7 @@ public function test_attach_method() $post->tags()->attach($tag2->id, ['flag' => 'taylor']); $post->load('tags'); $this->assertEquals($tag2->name, $post->tags[1]->name); - $this->assertEquals('taylor', $post->tags[1]->pivot->flag); + $this->assertSame('taylor', $post->tags[1]->pivot->flag); $post->tags()->attach([$tag3->id, $tag4->id]); $post->load('tags'); @@ -236,9 +264,9 @@ public function test_attach_method() $post->tags()->attach([$tag5->id => ['flag' => 'mohamed'], $tag6->id => ['flag' => 'adam']]); $post->load('tags'); $this->assertEquals($tag5->name, $post->tags[4]->name); - $this->assertEquals('mohamed', $post->tags[4]->pivot->flag); + $this->assertSame('mohamed', $post->tags[4]->pivot->flag); $this->assertEquals($tag6->name, $post->tags[5]->name); - $this->assertEquals('adam', $post->tags[5]->pivot->flag); + $this->assertSame('adam', $post->tags[5]->pivot->flag); $post->tags()->attach(new Collection([$tag7, $tag8])); $post->load('tags'); @@ -246,7 +274,7 @@ public function test_attach_method() $this->assertEquals($tag8->name, $post->tags[7]->name); } - public function test_detach_method() + public function testDetachMethod() { $post = Post::create(['title' => Str::random()]); @@ -289,7 +317,7 @@ public function test_detach_method() $this->assertCount(0, $post->tags); } - public function test_first_method() + public function testFirstMethod() { $post = Post::create(['title' => Str::random()]); @@ -300,7 +328,7 @@ public function test_first_method() $this->assertEquals($tag->name, $post->tags()->first()->name); } - public function test_firstOrFail_method() + public function testFirstOrFailMethod() { $this->expectException(ModelNotFoundException::class); @@ -309,7 +337,7 @@ public function test_firstOrFail_method() $post->tags()->firstOrFail(['id' => 10]); } - public function test_find_method() + public function testFindMethod() { $post = Post::create(['title' => Str::random()]); @@ -319,12 +347,16 @@ public function test_find_method() $post->tags()->attach(Tag::all()); $this->assertEquals($tag2->name, $post->tags()->find($tag2->id)->name); + $this->assertCount(0, $post->tags()->findMany([])); $this->assertCount(2, $post->tags()->findMany([$tag->id, $tag2->id])); + $this->assertCount(0, $post->tags()->findMany(new Collection())); + $this->assertCount(2, $post->tags()->findMany(new Collection([$tag->id, $tag2->id]))); } - public function test_findOrFail_method() + public function testFindOrFailMethod() { $this->expectException(ModelNotFoundException::class); + $this->expectExceptionMessage('No query results for model [DDZobov\PivotSoftDeletes\Tests\Integration\Database\EloquentBelongsToManyTest\Tag] 10'); $post = Post::create(['title' => Str::random()]); @@ -335,7 +367,35 @@ public function test_findOrFail_method() $post->tags()->findOrFail(10); } - public function test_findOrNew_method() + public function testFindOrFailMethodWithMany() + { + $this->expectException(ModelNotFoundException::class); + $this->expectExceptionMessage('No query results for model [DDZobov\PivotSoftDeletes\Tests\Integration\Database\EloquentBelongsToManyTest\Tag] 10, 11'); + + $post = Post::create(['title' => Str::random()]); + + Tag::create(['name' => Str::random()]); + + $post->tags()->attach(Tag::all()); + + $post->tags()->findOrFail([10, 11]); + } + + public function testFindOrFailMethodWithManyUsingCollection() + { + $this->expectException(ModelNotFoundException::class); + $this->expectExceptionMessage('No query results for model [DDZobov\PivotSoftDeletes\Tests\Integration\Database\EloquentBelongsToManyTest\Tag] 10, 11'); + + $post = Post::create(['title' => Str::random()]); + + Tag::create(['name' => Str::random()]); + + $post->tags()->attach(Tag::all()); + + $post->tags()->findOrFail(new Collection([10, 11])); + } + + public function testFindOrNewMethod() { $post = Post::create(['title' => Str::random()]); @@ -349,7 +409,7 @@ public function test_findOrNew_method() $this->assertInstanceOf(Tag::class, $post->tags()->findOrNew('asd')); } - public function test_firstOrNew_method() + public function testFirstOrNewMethod() { $post = Post::create(['title' => Str::random()]); @@ -363,7 +423,7 @@ public function test_firstOrNew_method() $this->assertInstanceOf(Tag::class, $post->tags()->firstOrNew(['id' => 'asd'])); } - public function test_firstOrCreate_method() + public function testFirstOrCreateMethod() { $post = Post::create(['title' => Str::random()]); @@ -374,11 +434,11 @@ public function test_firstOrCreate_method() $this->assertEquals($tag->id, $post->tags()->firstOrCreate(['name' => $tag->name])->id); $new = $post->tags()->firstOrCreate(['name' => 'wavez']); - $this->assertEquals('wavez', $new->name); + $this->assertSame('wavez', $new->name); $this->assertNotNull($new->id); } - public function test_updateOrCreate_method() + public function testUpdateOrCreateMethod() { $post = Post::create(['title' => Str::random()]); @@ -387,13 +447,13 @@ public function test_updateOrCreate_method() $post->tags()->attach(Tag::all()); $post->tags()->updateOrCreate(['id' => $tag->id], ['name' => 'wavez']); - $this->assertEquals('wavez', $tag->fresh()->name); + $this->assertSame('wavez', $tag->fresh()->name); $post->tags()->updateOrCreate(['id' => 'asd'], ['name' => 'dives']); $this->assertNotNull($post->tags()->whereName('dives')->first()); } - public function test_sync_method() + public function testSyncMethod() { $post = Post::create(['title' => Str::random()]); @@ -431,12 +491,12 @@ public function test_sync_method() ]); $post->load('tags'); $this->assertEquals($tag->name, $post->tags[0]->name); - $this->assertEquals('taylor', $post->tags[0]->pivot->flag); + $this->assertSame('taylor', $post->tags[0]->pivot->flag); $this->assertEquals($tag2->name, $post->tags[1]->name); - $this->assertEquals('mohamed', $post->tags[1]->pivot->flag); + $this->assertSame('mohamed', $post->tags[1]->pivot->flag); } - public function test_syncWithoutDetaching_method() + public function testSyncWithoutDetachingMethod() { $post = Post::create(['title' => Str::random()]); @@ -458,7 +518,7 @@ public function test_syncWithoutDetaching_method() ); } - public function test_toggle_method() + public function testToggleMethod() { $post = Post::create(['title' => Str::random()]); @@ -485,10 +545,10 @@ public function test_toggle_method() Tag::whereIn('id', [$tag->id])->pluck('name'), $post->tags->pluck('name') ); - $this->assertEquals('taylor', $post->tags[0]->pivot->flag); + $this->assertSame('taylor', $post->tags[0]->pivot->flag); } - public function test_touching_parent() + public function testTouchingParent() { $post = Post::create(['title' => Str::random()]); @@ -496,52 +556,52 @@ public function test_touching_parent() $post->touchingTags()->attach([$tag->id]); - $this->assertNotEquals('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); + $this->assertNotSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); Carbon::setTestNow('2017-10-10 10:10:10'); $tag->update(['name' => $tag->name]); - $this->assertNotEquals('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); + $this->assertNotSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); $tag->update(['name' => Str::random()]); - $this->assertEquals('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); + $this->assertSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); } - public function test_touching_related_models_on_sync() + public function testTouchingRelatedModelsOnSync() { $tag = TouchingTag::create(['name' => Str::random()]); $post = Post::create(['title' => Str::random()]); - $this->assertNotEquals('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - $this->assertNotEquals('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); + $this->assertNotSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); + $this->assertNotSame('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); Carbon::setTestNow('2017-10-10 10:10:10'); $tag->posts()->sync([$post->id]); - $this->assertEquals('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - $this->assertEquals('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); + $this->assertSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); + $this->assertSame('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); } - public function test_no_touching_happens_if_not_configured() + public function testNoTouchingHappensIfNotConfigured() { $tag = Tag::create(['name' => Str::random()]); $post = Post::create(['title' => Str::random()]); - $this->assertNotEquals('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - $this->assertNotEquals('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); + $this->assertNotSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); + $this->assertNotSame('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); Carbon::setTestNow('2017-10-10 10:10:10'); $tag->posts()->sync([$post->id]); - $this->assertNotEquals('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); - $this->assertNotEquals('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); + $this->assertNotSame('2017-10-10 10:10:10', $post->fresh()->updated_at->toDateTimeString()); + $this->assertNotSame('2017-10-10 10:10:10', $tag->fresh()->updated_at->toDateTimeString()); } - public function test_can_retrieve_related_ids() + public function testCanRetrieveRelatedIds() { $post = Post::create(['title' => Str::random()]); @@ -559,7 +619,7 @@ public function test_can_retrieve_related_ids() $this->assertEquals([200, 400], $post->tags()->allRelatedIds()->toArray()); } - public function test_can_touch_related_models() + public function testCanTouchRelatedModels() { $post = Post::create(['title' => Str::random()]); @@ -579,13 +639,13 @@ public function test_can_touch_related_models() $post->tags()->touch(); foreach ($post->tags()->pluck('tags.updated_at') as $date) { - $this->assertEquals('2017-10-10 10:10:10', $date); + $this->assertSame('2017-10-10 10:10:10', $date); } - $this->assertNotEquals('2017-10-10 10:10:10', Tag::find(300)->updated_at); + $this->assertNotSame('2017-10-10 10:10:10', Tag::find(300)->updated_at); } - public function test_where_pivot_on_string() + public function testWherePivotOnString() { $tag = Tag::create(['name' => Str::random()]); $post = Post::create(['title' => Str::random()]); @@ -601,7 +661,7 @@ public function test_where_pivot_on_string() $this->assertEquals($relationTag->getAttributes(), $tag->getAttributes()); } - public function test_where_pivot_on_boolean() + public function testWherePivotOnBoolean() { $tag = Tag::create(['name' => Str::random()]); $post = Post::create(['title' => Str::random()]); @@ -617,7 +677,7 @@ public function test_where_pivot_on_boolean() $this->assertEquals($relationTag->getAttributes(), $tag->getAttributes()); } - public function test_where_pivot_in_method() + public function testWherePivotInMethod() { $tag = Tag::create(['name' => Str::random()]); $post = Post::create(['title' => Str::random()]); @@ -630,7 +690,66 @@ public function test_where_pivot_in_method() $this->assertEquals($relationTag->getAttributes(), $tag->getAttributes()); } - public function test_can_update_existing_pivot() + public function testOrWherePivotInMethod() + { + $tag1 = Tag::create(['name' => Str::random()]); + $tag2 = Tag::create(['name' => Str::random()]); + $tag3 = Tag::create(['name' => Str::random()]); + $post = Post::create(['title' => Str::random()]); + + DB::table('posts_tags')->insert([ + ['post_id' => $post->id, 'tag_id' => $tag1->id, 'flag' => 'foo'], + ]); + DB::table('posts_tags')->insert([ + ['post_id' => $post->id, 'tag_id' => $tag2->id, 'flag' => 'bar'], + ]); + DB::table('posts_tags')->insert([ + ['post_id' => $post->id, 'tag_id' => $tag3->id, 'flag' => 'baz'], + ]); + + $relationTags = $post->tags()->wherePivotIn('flag', ['foo'])->orWherePivotIn('flag', ['baz'])->get(); + $this->assertEquals($relationTags->pluck('id')->toArray(), [$tag1->id, $tag3->id]); + } + + public function testWherePivotNotInMethod() + { + $tag1 = Tag::create(['name' => Str::random()]); + $tag2 = Tag::create(['name' => Str::random()]); + $post = Post::create(['title' => Str::random()]); + + DB::table('posts_tags')->insert([ + ['post_id' => $post->id, 'tag_id' => $tag1->id, 'flag' => 'foo'], + ]); + DB::table('posts_tags')->insert([ + ['post_id' => $post->id, 'tag_id' => $tag2->id, 'flag' => 'bar'], + ]); + + $relationTag = $post->tags()->wherePivotNotIn('flag', ['foo'])->first(); + $this->assertEquals($relationTag->getAttributes(), $tag2->getAttributes()); + } + + public function testOrWherePivotNotInMethod() + { + $tag1 = Tag::create(['name' => Str::random()]); + $tag2 = Tag::create(['name' => Str::random()]); + $tag3 = Tag::create(['name' => Str::random()]); + $post = Post::create(['title' => Str::random()]); + + DB::table('posts_tags')->insert([ + ['post_id' => $post->id, 'tag_id' => $tag1->id, 'flag' => 'foo'], + ]); + DB::table('posts_tags')->insert([ + ['post_id' => $post->id, 'tag_id' => $tag2->id, 'flag' => 'bar'], + ]); + DB::table('posts_tags')->insert([ + ['post_id' => $post->id, 'tag_id' => $tag3->id, 'flag' => 'baz'], + ]); + + $relationTags = $post->tags()->wherePivotIn('flag', ['foo'])->orWherePivotNotIn('flag', ['baz'])->get(); + $this->assertEquals($relationTags->pluck('id')->toArray(), [$tag1->id, $tag2->id]); + } + + public function testCanUpdateExistingPivot() { $tag = Tag::create(['name' => Str::random()]); $post = Post::create(['title' => Str::random()]); @@ -642,11 +761,11 @@ public function test_can_update_existing_pivot() $post->tagsWithExtraPivot()->updateExistingPivot($tag->id, ['flag' => 'exclude']); foreach ($post->tagsWithExtraPivot as $tag) { - $this->assertEquals('exclude', $tag->pivot->flag); + $this->assertSame('exclude', $tag->pivot->flag); } } - public function test_can_update_existing_pivot_using_arrayable_of_ids() + public function testCanUpdateExistingPivotUsingArrayableOfIds() { $tags = new Collection([ $tag1 = Tag::create(['name' => Str::random()]), @@ -662,11 +781,11 @@ public function test_can_update_existing_pivot_using_arrayable_of_ids() $post->tagsWithExtraPivot()->updateExistingPivot($tags, ['flag' => 'exclude']); foreach ($post->tagsWithExtraPivot as $tag) { - $this->assertEquals('exclude', $tag->pivot->flag); + $this->assertSame('exclude', $tag->pivot->flag); } } - public function test_can_update_existing_pivot_using_model() + public function testCanUpdateExistingPivotUsingModel() { $tag = Tag::create(['name' => Str::random()]); $post = Post::create(['title' => Str::random()]); @@ -678,11 +797,11 @@ public function test_can_update_existing_pivot_using_model() $post->tagsWithExtraPivot()->updateExistingPivot($tag, ['flag' => 'exclude']); foreach ($post->tagsWithExtraPivot as $tag) { - $this->assertEquals('exclude', $tag->pivot->flag); + $this->assertSame('exclude', $tag->pivot->flag); } } - public function test_custom_related_key() + public function testCustomRelatedKey() { $post = Post::create(['title' => Str::random()]); @@ -700,10 +819,10 @@ public function test_custom_related_key() $this->assertEquals($tag->name, $post->tagsWithCustomRelatedKey()->first()->pivot->tag_id); $post->tagsWithCustomRelatedKey()->updateExistingPivot($tag, ['flag' => 'exclude']); - $this->assertEquals('exclude', $post->tagsWithCustomRelatedKey()->first()->pivot->flag); + $this->assertSame('exclude', $post->tagsWithCustomRelatedKey()->first()->pivot->flag); } - public function test_global_scope_columns() + public function testGlobalScopeColumns() { $tag = Tag::create(['name' => Str::random()]); $post = Post::create(['title' => Str::random()]); @@ -717,7 +836,7 @@ public function test_global_scope_columns() $this->assertEquals(['id' => 1], $tags[0]->getAttributes()); } - public function test_pivot_doesnt_have_primary_key() + public function testPivotDoesntHavePrimaryKey() { $user = User::create(['name' => Str::random()]); $post1 = Post::create(['title' => Str::random()]); @@ -897,4 +1016,4 @@ public static function boot() $query->select('tags.id'); }); } -} \ No newline at end of file +}