diff --git a/src/Auditable.php b/src/Auditable.php index 8ebcb68a..ac258dd3 100644 --- a/src/Auditable.php +++ b/src/Auditable.php @@ -2,10 +2,12 @@ namespace OwenIt\Auditing; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Arr; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Event; @@ -754,7 +756,7 @@ public function auditDetach(string $relationName, $ids = null, $touch = true, $c /** * @param string $relationName - * @param \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array $ids + * @param Collection|Model|array $ids * @param bool $detaching * @param array $columns * @param \Closure|null $callback @@ -787,7 +789,7 @@ public function auditSync(string $relationName, $ids, $detaching = true, $column /** * @param string $relationName - * @param \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array $ids + * @param Collection|Model|array $ids * @param array $columns * @param \Closure|null $callback * @return array @@ -800,11 +802,37 @@ public function auditSyncWithoutDetaching(string $relationName, $ids, $columns = return $this->auditSync($relationName, $ids, false, $columns, $callback); } + /** + * @param string $relationName + * @param Collection|Model|array $ids + * @param array $values + * @param bool $detaching + * @param array $columns + * @param \Closure|null $callback + * @return array + */ + public function auditSyncWithPivotValues(string $relationName, $ids, array $values, bool $detaching = true, $columns = ['*'], $callback = null) + { + $this->validateRelationshipMethodExistence($relationName, 'syncWithPivotValues'); + + if ($ids instanceof Model) { + $ids = $ids->getKey(); + } elseif ($ids instanceof \Illuminate\Database\Eloquent\Collection) { + $ids = $ids->isEmpty() ? [] : $ids->pluck($ids->first()->getKeyName())->toArray(); + } elseif ($ids instanceof Collection) { + $ids = $ids->toArray(); + } + + return $this->auditSync($relationName, collect(Arr::wrap($ids))->mapWithKeys(function ($id) use ($values) { + return [$id => $values]; + }), $detaching, $columns, $callback); + } + /** * @param string $relationName * @param string $event - * @param \Illuminate\Support\Collection $old - * @param \Illuminate\Support\Collection $new + * @param Collection $old + * @param Collection $new * @return void */ private function dispatchRelationAuditEvent($relationName, $event, $old, $new) diff --git a/tests/Functional/AuditingTest.php b/tests/Functional/AuditingTest.php index 801d1c50..796477b0 100644 --- a/tests/Functional/AuditingTest.php +++ b/tests/Functional/AuditingTest.php @@ -667,6 +667,49 @@ public function itWillAuditSync() $this->assertGreaterThan($no_of_audits_before, $no_of_audits_after); } + /** + * @test + * @return void + */ + public function itWillAuditSyncWithPivotValues() + { + if (version_compare($this->app->version(), '8.0.0', '<')) { + $this->markTestSkipped('This test is only for Laravel 8.0.0+'); + } + + $firstCategory = factory(Category::class)->create(); + $secondCategory = factory(Category::class)->create(); + $article = factory(Article::class)->create(); + + $article->categories()->attach([$firstCategory->getKey() => [ 'pivot_type' => 'PIVOT_1' ]]); + + $no_of_audits_before = Audit::where('auditable_type', Article::class)->count(); + $categoryBefore = $article->categories()->first()->getKey(); + + $article->auditSyncWithPivotValues( + 'categories', + $secondCategory, + [ 'pivot_type' => 'PIVOT_1' ] + ); + + $no_of_audits_after = Audit::where('auditable_type', Article::class)->count(); + $categoryAfter = $article->categories()->first()->getKey(); + + $this->assertSame($firstCategory->getKey(), $categoryBefore); + $this->assertSame($secondCategory->getKey(), $categoryAfter); + $this->assertGreaterThan($no_of_audits_before, $no_of_audits_after); + + $this->assertSame( + "{$secondCategory->getKey()}", + $article->categories()->pluck('id')->join(',') + ); + + $this->assertSame( + $secondCategory->getKey(), + $article->categories()->wherePivot('pivot_type', 'PIVOT_1')->first()->getKey() + ); + } + /** * @test * @return void @@ -697,7 +740,6 @@ function ($categories) { return $categories->wherePivot('pivot_type', 'PIVOT_1') $this->assertSame($firstCategory->getKey(), $categoryBefore); $this->assertSame($secondCategory->getKey(), $categoryAfter); - $this->assertNotSame($categoryBefore, $categoryAfter); $this->assertGreaterThan($no_of_audits_before, $no_of_audits_after); $this->assertSame( @@ -994,12 +1036,12 @@ public function canAuditAnyCustomEvent() * @return void */ public function canAuditCustomAuditModelImplementation() - { + { $audit = null; Event::listen(Audited::class, function ($event) use (&$audit) { $audit = $event->audit; }); - + $article = new ArticleCustomAuditMorph(); $article->title = $this->faker->unique()->sentence; $article->content = $this->faker->unique()->paragraph(6);