Skip to content

Commit 8450dc7

Browse files
Added action operation type handling
1 parent 33c3673 commit 8450dc7

7 files changed

+141
-0
lines changed

Changelog.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Eloquent History Changelog
22

3+
## Unreleased
4+
##### 2024-XX-YY
5+
6+
- Added the `action` Operation type
7+
- Added the `details` field to the model history table/model
8+
- Added the `logActionSuccess()` and `logActionFailure()` factory methods to the `History` class
9+
310
## 1.4.0
411
##### 2024-03-12
512

src/Contracts/ModelHistoryEvent.php

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ public function summary(): string;
2424

2525
public function comment(): ?string;
2626

27+
/**
28+
* @todo V2 interface candidates
29+
* public function details(): ?string;
30+
*/
31+
2732
public function isASingleFieldChange(): bool;
2833

2934
public function isNoFieldChangeEntry(): bool;

src/History.php

+22
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ public static function addComment(Model $model, string $comment): ModelHistoryEv
8888
], static::commonFields($model)));
8989
}
9090

91+
public static function logActionSuccess(Model $model, ?string $details = null): ModelHistoryEvent
92+
{
93+
return static::logAction($model, true, $details);
94+
}
95+
96+
public static function logActionFailure(Model $model, ?string $details = null): ModelHistoryEvent
97+
{
98+
return static::logAction($model, false, $details);
99+
}
100+
91101
public static function logDeletion(Model $model, ?string $comment = null): ModelHistoryEvent
92102
{
93103
return ModelHistoryEventProxy::create(array_merge([
@@ -150,4 +160,16 @@ protected static function sceneResolver(): SceneResolver
150160

151161
return static::$sceneResolver;
152162
}
163+
164+
protected static function logAction(Model $model, bool $wasSuccessful, ?string $details = null): ModelHistoryEvent
165+
{
166+
return ModelHistoryEventProxy::create(array_merge([
167+
'happened_at' => now(),
168+
'comment' => null,
169+
'details' => $details,
170+
'operation' => Operation::ACTION,
171+
'was_successful' => $wasSuccessful,
172+
'diff' => [],
173+
], static::commonFields($model)));
174+
}
153175
}

src/Models/ModelHistoryEvent.php

+13
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
* @property string $model_type
3838
* @property array $diff;
3939
* @property string|null $comment
40+
* @property bool|null $was_successful
41+
* @property string|null $details
4042
* @property Carbon $happened_at
4143
* @property Carbon $created_at
4244
* @property Carbon $updated_at
@@ -99,6 +101,7 @@ public function summary(): string
99101
Operation::COMMENT => __('Comment has been added'),
100102
Operation::DELETE => __('Has been deleted'),
101103
Operation::RETRIEVE => __('Was retrieved'),
104+
Operation::ACTION => $this->was_successful ? __('Executed successfully') : __('Execution failed'),
102105
default => '',
103106
};
104107
}
@@ -108,6 +111,11 @@ public function comment(): ?string
108111
return $this->comment;
109112
}
110113

114+
public function details(): ?string
115+
{
116+
return $this->details;
117+
}
118+
111119
public function isASingleFieldChange(): bool
112120
{
113121
return 1 === $this->diff()->changeCount();
@@ -122,4 +130,9 @@ public function isACommentOnlyEntry(): bool
122130
{
123131
return 0 === $this->diff()->changeCount() && !is_null($this->comment);
124132
}
133+
134+
public function isAnActionEvent(): bool
135+
{
136+
return $this->operation->is_action;
137+
}
125138
}

src/Models/Operation.php

+11
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@
2424
* @method static self DELETE()
2525
* @method static self RETRIEVE()
2626
* @method static self COMMENT()
27+
* @method static self ACTION()
28+
*
29+
* @property-read bool $is_undefined
30+
* @property-read bool $is_create
31+
* @property-read bool $is_update
32+
* @property-read bool $is_delete
33+
* @property-read bool $is_retrieve
34+
* @property-read bool $is_comment
35+
* @property-read bool $is_action
2736
*/
2837
class Operation extends Enum implements OperationContract
2938
{
@@ -34,4 +43,6 @@ class Operation extends Enum implements OperationContract
3443
public const DELETE = 'delete';
3544
public const RETRIEVE = 'retrieve';
3645
public const COMMENT = 'comment';
46+
47+
public const ACTION = 'action';
3748
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Illuminate\Database\Migrations\Migration;
6+
use Illuminate\Database\Schema\Blueprint;
7+
use Illuminate\Support\Facades\Schema;
8+
9+
return new class () extends Migration {
10+
public function up(): void
11+
{
12+
Schema::table('model_history', function (Blueprint $table) {
13+
$table->boolean('was_successful')->nullable();
14+
$table->text('details')->nullable();
15+
});
16+
}
17+
18+
public function down(): void
19+
{
20+
Schema::table('model_history', function (Blueprint $table) {
21+
$table->dropColumn('was_successful');
22+
$table->dropColumn('details');
23+
});
24+
}
25+
};

tests/HistoryTest.php

+58
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public function it_can_record_if_a_model_was_created()
4343
$this->assertInstanceOf(ModelHistoryEvent::class, $event);
4444
$this->assertCount(3, $event->diff()->changes());
4545
$this->assertEquals(Operation::CREATE, $event->operation->value());
46+
$this->assertNull($event->comment());
4647
}
4748

4849
/** @test */
@@ -56,6 +57,7 @@ public function a_recent_update_can_be_recorded()
5657

5758
$this->assertTrue($event->isASingleFieldChange());
5859
$this->assertTrue($event->diff()->hasChanged('status'));
60+
$this->assertNull($event->comment());
5961
$this->assertEquals(Operation::UPDATE, $event->operation->value());
6062
}
6163

@@ -91,6 +93,62 @@ public function non_diff_changes_can_be_manually_recorded()
9193
$this->assertEquals('Has timed out waiting', $event->comment());
9294
}
9395

96+
/** @test */
97+
public function it_can_record_a_successful_action()
98+
{
99+
$task = SampleTask::create(['title' => 'Hello', 'description' => 'Make me', 'status' => 'todo']);
100+
101+
$event = History::logActionSuccess($task);
102+
103+
$this->assertEquals(Operation::ACTION, $event->operation->value());
104+
$this->assertTrue($event->was_successful);
105+
$this->assertTrue($event->diff()->isEmpty());
106+
$this->assertEmpty($event->diff()->changes());
107+
$this->assertNull($event->comment());
108+
$this->assertNull($event->details());
109+
}
110+
111+
/** @test */
112+
public function it_can_record_a_successful_action_with_details()
113+
{
114+
$task = SampleTask::create(['title' => 'Hello', 'description' => 'Make me', 'status' => 'todo']);
115+
116+
$event = History::logActionSuccess($task, '124 entries updated');
117+
118+
$this->assertEquals(Operation::ACTION, $event->operation->value());
119+
$this->assertTrue($event->was_successful);
120+
$this->assertEquals('124 entries updated', $event->details());
121+
$this->assertNull($event->comment());
122+
}
123+
124+
/** @test */
125+
public function it_can_record_a_failed_action()
126+
{
127+
$task = SampleTask::create(['title' => 'Hello', 'description' => 'Make me', 'status' => 'todo']);
128+
129+
$event = History::logActionFailure($task);
130+
131+
$this->assertEquals(Operation::ACTION, $event->operation->value());
132+
$this->assertFalse($event->was_successful);
133+
$this->assertTrue($event->diff()->isEmpty());
134+
$this->assertEmpty($event->diff()->changes());
135+
$this->assertNull($event->comment());
136+
$this->assertNull($event->details());
137+
}
138+
139+
/** @test */
140+
public function it_can_record_a_failed_action_with_details()
141+
{
142+
$task = SampleTask::create(['title' => 'Hello', 'description' => 'Make me', 'status' => 'todo']);
143+
144+
$event = History::logActionFailure($task, 'Error connecting to the Remote API');
145+
146+
$this->assertEquals(Operation::ACTION, $event->operation->value());
147+
$this->assertFalse($event->was_successful);
148+
$this->assertEquals('Error connecting to the Remote API', $event->details());
149+
$this->assertNull($event->comment());
150+
}
151+
94152
/** @test */
95153
public function deletion_can_be_recorded()
96154
{

0 commit comments

Comments
 (0)