Skip to content
Merged
25 changes: 23 additions & 2 deletions src/Auditable.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
Expand All @@ -13,6 +14,7 @@
use Illuminate\Support\Facades\Event;
use OwenIt\Auditing\Contracts\AttributeEncoder;
use OwenIt\Auditing\Contracts\AttributeRedactor;
use OwenIt\Auditing\Contracts\Auditable as ContractsAuditable;
use OwenIt\Auditing\Contracts\Resolver;
use OwenIt\Auditing\Events\AuditCustom;
use OwenIt\Auditing\Exceptions\AuditableTransitionException;
Expand Down Expand Up @@ -709,7 +711,17 @@ public function auditDetach(string $relationName, $ids = null, $touch = true, $c
}

$old = $relationCall->get($columns);
$results = $relationCall->detach($ids, $touch);

$pivotClass = $relationCall->getPivotClass();

if ($pivotClass !== Pivot::class && is_a($pivotClass, ContractsAuditable::class, true)) {
$results = $pivotClass::withoutAuditing(function () use ($relationCall, $ids, $touch) {
return $relationCall->detach($ids, $touch);
});
} else {
$results = $relationCall->detach($ids, $touch);
}

$new = $relationCall->get($columns);

$this->dispatchRelationAuditEvent($relationName, 'detach', $old, $new);
Expand Down Expand Up @@ -737,7 +749,16 @@ public function auditSync(string $relationName, $ids, $detaching = true, $column
}

$old = $relationCall->get($columns);
$changes = $relationCall->sync($ids, $detaching);

$pivotClass = $relationCall->getPivotClass();

if ($pivotClass !== Pivot::class && is_a($pivotClass, ContractsAuditable::class, true)) {
$changes = $pivotClass::withoutAuditing(function () use ($relationCall, $ids, $detaching) {
return $relationCall->sync($ids, $detaching);
});
} else {
$changes = $relationCall->sync($ids, $detaching);
}

if (collect($changes)->flatten()->isEmpty()) {
$old = $new = collect([]);
Expand Down
69 changes: 69 additions & 0 deletions tests/Functional/AuditingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use OwenIt\Auditing\Tests\Models\ArticleCustomAuditMorph;
use OwenIt\Auditing\Tests\Models\ArticleExcludes;
use OwenIt\Auditing\Tests\Models\Category;
use OwenIt\Auditing\Tests\Models\Group;
use OwenIt\Auditing\Tests\Models\User;

class AuditingTest extends AuditingTestCase
Expand Down Expand Up @@ -963,4 +964,72 @@ public function test_can_audit_custom_audit_model_implementation(): void
$this->assertNotEmpty($audit);
$this->assertSame(get_class($audit), \OwenIt\Auditing\Tests\Models\CustomAudit::class);
}

/**
* @test
* @return void
*/
public function itWillAuditSyncWithAuditablePivotClass()
{
$group = Group::factory()->create();
$user = User::factory()->create();

$no_of_audits_before = Audit::where('auditable_type', User::class)->count();

$user->auditSync('groups', [$group->getKey() => ["role" => "admin"]]);

$no_of_audits_mid = Audit::where('auditable_type', User::class)->count();
$memberRole = $user->groups()->first()->pivot->role;

$user->auditSync('groups', []);

$no_of_audits_after = Audit::where('auditable_type', User::class)->count();

$this->assertSame("admin", $memberRole);
$this->assertGreaterThan($no_of_audits_before, $no_of_audits_mid);
$this->assertGreaterThan($no_of_audits_mid, $no_of_audits_after);
}

/**
* @test
* @return void
*/
public function itWillAuditAttachWithAuditablePivotClass()
{
$group = Group::factory()->create();
$user = User::factory()->create();

$no_of_audits_before = Audit::where('auditable_type', User::class)->count();

$user->auditAttach('groups', $group);

$attachedGroup = $user->groups()->first()->getKey();
$no_of_audits_after = Audit::where('auditable_type', User::class)->count();

$this->assertSame($group->getKey(), $attachedGroup);
$this->assertGreaterThan($no_of_audits_before, $no_of_audits_after);
}

/**
* @test
* @return void
*/
public function itWillAuditDetachWithAuditablePivotClass()
{
$group = Group::factory()->create();
$user = User::factory()->create();

$user->groups()->attach($group);

$attachedGroup = $user->groups()->first()->getKey();
$no_of_audits_before = Audit::where('auditable_type', User::class)->count();

$detachedGroups = $user->auditDetach('groups', $group);

$no_of_audits_after = Audit::where('auditable_type', User::class)->count();

$this->assertSame($group->getKey(), $attachedGroup);
$this->assertSame(1, $detachedGroups);
$this->assertGreaterThan($no_of_audits_before, $no_of_audits_after);
}
}
12 changes: 12 additions & 0 deletions tests/Models/Group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace OwenIt\Auditing\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use OwenIt\Auditing\Tests\database\factories\GroupFactory;

class Group extends \Illuminate\Database\Eloquent\Model
{
use HasFactory;
protected static string $factory = GroupFactory::class;
}
17 changes: 17 additions & 0 deletions tests/Models/GroupMember.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace OwenIt\Auditing\Tests\Models;

use Illuminate\Database\Eloquent\Relations\Concerns\AsPivot;
use OwenIt\Auditing\Auditable;
use OwenIt\Auditing\Contracts\Auditable as ContractsAuditable;

class GroupMember extends \Illuminate\Database\Eloquent\Model implements ContractsAuditable
{
use AsPivot;
use Auditable;

public $fillable = [
"role"
];
}
5 changes: 5 additions & 0 deletions tests/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,9 @@ public function getFirstNameAttribute(string $value): string
{
return ucfirst($value);
}

public function groups()
{
return $this->belongsToMany(Group::class, 'group_members', 'user_id', 'group_id')->using(GroupMember::class)->withPivot('id','role');
}
}
18 changes: 18 additions & 0 deletions tests/database/factories/GroupFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace OwenIt\Auditing\Tests\database\factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use OwenIt\Auditing\Tests\Models\Group;

class GroupFactory extends Factory
{
protected $model = Group::class;

public function definition()
{
return [
'name' => fake()->unique()->colorName(),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateGroupsTestTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('groups', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});

Schema::create('group_members', function (Blueprint $table) {
$table->increments('id');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('group_id');
$table->enum('role',['member','admin'])->default('member');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('group_members');
Schema::drop('groups');
}
}