I believe that if the activitylog can show exactly how the model looked like before it was updated it should also provide the methods to revert the changes to the previous state.
Any drawbacks you could anticipate in adding such feature?
At the end the method would be pretty simple:
$activity->subject->update($activity->changes['old']);
Some conditions before to do it only for update activities.
Drawbacks I could think about would be:
And things like this. Because of this I'm a bit against this feature in the package. The code to implement this is super easy (in this simple way). But I already see the issues like "destroyed model after restore" because of any special app circumstances we can't handle in the package.
I would like to let @freekmurze decide about it.
Not sure if at this point the "cascaded" actions are also logged in such a manner that we could track the changes back to a revertible action. The project I'm having in mind has softDeletes on all models so the destroy method would not really deleting anything....
With destroyed I meant something like "post has no author but is published" because they were set in different activities.
And executing all activities between now and the point to reset to would be an option but could/would create unexpected results.
So it sounds trivial, and is, for a specific usecase. But as package maintainer an added feature should be usable by all/most of the users. And adding a note to the docs is most times not enough because a lot (of the issues we get) don't read the docs. 馃様
I agree that undo is complicated and might corrupt data. But if you know what you're doing, undoing specific Activity is useful. Many people ignore the docs, so it's risky to include it in to the package, but if someone searches for an example - here's my code with simple checks:
class Activity extends \Spatie\Activitylog\Models\Activity
{
public function undo(Bool $unchangedOnly = true, Bool $deleteCreated = true)
{
$subject = $this->subject;
if ($subject !== null) {
if ($this->description == 'updated') {
foreach ($this->properties['old'] as $field => $data) {
if ($unchangedOnly && $subject->$field != $this->properties['attributes'][$field]) {
trigger_error('Subject changed; cannot undo', E_USER_WARNING);
return null;
}
$subject->$field = $data;
}
$subject->save();
return $subject;
} elseif ($this->description == 'created') {
if ($deleteCreated) {
$subject->delete();
return $subject;
} else {
trigger_error('Subject not deleted; $deleteCreated is set to `false`', E_USER_WARNING);
return null;
}
}
}
return null;
}
}
I don't think that Undo/Revert changes is the responsibility of this package.
Primary with the new capability to adjust the "changes" array and custom casts in Laravel core it's impossible for us to properly restore data.
I will close this issue as there's no way we could properly restore data or go back to a given point in history. In case you need such logic you could probably investigate event sourcing.
https://event-sourcing-laravel.com/
https://github.com/spatie/laravel-event-sourcing
https://eventsauce.io/
Most helpful comment
I agree that undo is complicated and might corrupt data. But if you know what you're doing, undoing specific
Activityis useful. Many people ignore the docs, so it's risky to include it in to the package, but if someone searches for an example - here's my code with simple checks: