Skip to content

Commit 17d6adb

Browse files
freekmurzeclaude
andcommitted
fix logUnguarded() to respect Model::unguard()
When Model::unguard() is called globally, the $guarded property still contains its default value but isUnguarded() returns true. The code was only checking $guarded, not the unguarded state. Now checks isUnguarded() to properly detect globally unguarded models. Fixes #1123 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent eae92f0 commit 17d6adb

File tree

2 files changed

+57
-6
lines changed

2 files changed

+57
-6
lines changed

src/Traits/LogsActivity.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,15 @@ public function attributesToBeLogged(): array
213213

214214
// Determine if unguarded attributes will be logged.
215215
if ($this->shouldLogUnguarded()) {
216-
217-
// Get only attribute names, not intrested in the values here then guarded
218-
// attributes. get only keys than not present in guarded array, because
219-
// we are logging the unguarded attributes and we cant have both!
220-
221-
$attributes = array_merge($attributes, array_diff(array_keys($this->getAttributes()), $this->getGuarded()));
216+
// If globally unguarded, log all attributes
217+
if (static::isUnguarded()) {
218+
$attributes = array_merge($attributes, array_keys($this->getAttributes()));
219+
} else {
220+
// Get only attribute names, not interested in the values here then guarded
221+
// attributes. get only keys than not present in guarded array, because
222+
// we are logging the unguarded attributes and we can't have both!
223+
$attributes = array_merge($attributes, array_diff(array_keys($this->getAttributes()), $this->getGuarded()));
224+
}
222225
}
223226

224227
if (! empty($this->activitylogOptions->logAttributes)) {
@@ -247,6 +250,12 @@ public function shouldLogUnguarded(): bool
247250
return false;
248251
}
249252

253+
// If the model is globally unguarded via Model::unguard(),
254+
// all attributes should be considered unguarded.
255+
if (static::isUnguarded()) {
256+
return true;
257+
}
258+
250259
// This case means all of the attributes are guarded
251260
// so we'll not have any unguarded anyway.
252261
if (in_array('*', $this->getGuarded())) {

tests/DetectsChangesTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use Carbon\Carbon;
44
use Carbon\CarbonInterval;
5+
use Illuminate\Database\Eloquent\Model;
56
use Illuminate\Database\Eloquent\SoftDeletes;
67
use Illuminate\Support\Arr;
78
use Spatie\Activitylog\Contracts\LoggablePipe;
@@ -1300,6 +1301,47 @@ public function getActivitylogOptions(): LogOptions
13001301
$this->assertEquals([], $this->getLastActivity()->changes()->toArray());
13011302
});
13021303

1304+
it('can log unguarded attributes when Model::unguard() is called globally', function () {
1305+
// Model without explicit $fillable or $guarded
1306+
$articleClass = new class() extends Article {
1307+
use LogsActivity;
1308+
1309+
public function getActivitylogOptions(): LogOptions
1310+
{
1311+
return LogOptions::defaults()
1312+
->logUnguarded()
1313+
->logExcept(['id', 'created_at', 'updated_at', 'deleted_at']);
1314+
}
1315+
};
1316+
1317+
// Globally unguard all models
1318+
Model::unguard();
1319+
1320+
try {
1321+
$article = new $articleClass();
1322+
$article->name = 'my name';
1323+
$article->text = 'my text';
1324+
$article->save();
1325+
1326+
$expectedChanges = [
1327+
'attributes' => [
1328+
'name' => 'my name',
1329+
'text' => 'my text',
1330+
'user_id' => null,
1331+
'json' => null,
1332+
'price' => null,
1333+
'interval' => null,
1334+
'status' => null,
1335+
],
1336+
];
1337+
1338+
$this->assertEquals($expectedChanges, $this->getLastActivity()->changes()->toArray());
1339+
} finally {
1340+
// Re-guard models
1341+
Model::reguard();
1342+
}
1343+
});
1344+
13031345
it('can use hidden as loggable attributes', function () {
13041346
$articleClass = new class() extends Article {
13051347
use LogsActivity;

0 commit comments

Comments
 (0)