Skip to content

Commit 06f37ec

Browse files
committed
fix: wrong version contents with cast attributes.
1 parent 34c2e41 commit 06f37ec

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

src/Version.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ public function revert(): bool
114114
public function revertWithoutSaving(): ?Model
115115
{
116116
$original = $this->versionable->getRawOriginal();
117+
117118
switch ($this->versionable->getVersionStrategy()) {
118119
case VersionStrategy::DIFF:
119120
// v1 + ... + vN

src/Versionable.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ function (Model $model) {
6868
*/
6969
public function createVersion(array $replacements = [], $time = null): ?Version
7070
{
71+
// get unsaved versionable attributes
72+
$replacements = array_merge($this->getDirty(), $replacements);
73+
7174
if ($this->shouldBeVersioning() || ! empty($replacements)) {
7275
return tap(Version::createForModel($this, $replacements, $time), function () {
7376
$this->removeOldVersions($this->getKeepVersionsCount());
@@ -240,14 +243,18 @@ public function getVersionableAttributes(VersionStrategy $strategy, array $repla
240243
{
241244
$versionable = $this->getVersionable();
242245
$dontVersionable = $this->getDontVersionable();
246+
$refreshedModel = static::query()->withoutGlobalScopes()->findOrFail($this->getKey());
243247

244-
$attributes = match ($strategy) {
245-
VersionStrategy::DIFF => $this->getDirty(),
248+
$keys = match ($strategy) {
249+
VersionStrategy::DIFF => array_keys($this->getDirty()),
246250
// To avoid some attributes are empty (not sync to database)
247251
// we should get the latest version from database.
248-
VersionStrategy::SNAPSHOT => $this->newQueryWithoutScopes()->find($this->getKey())?->attributesToArray() ?? [],
252+
VersionStrategy::SNAPSHOT => array_keys($refreshedModel?->attributesToArray() ?? []),
249253
};
250254

255+
// get the original attributes to avoid the attributes that are castable.
256+
$attributes = Arr::only($refreshedModel->getRawOriginal(), $keys);
257+
251258
if (count($versionable) > 0) {
252259
$attributes = Arr::only($attributes, $versionable);
253260
}

tests/FeatureTest.php

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,20 @@ protected function setUp(): void
3131
*/
3232
public function versions_can_be_created()
3333
{
34-
$post = Post::create(['title' => 'version1', 'content' => 'version1 content']);
34+
$post = Post::create(['title' => 'version1', 'content' => 'version1 content', 'extends' => ['foo' => 'bar']]);
3535

3636
$this->assertCount(1, $post->versions);
3737
$this->assertDatabaseCount('versions', 1);
3838

39+
$version = $post->lastVersion;
40+
41+
$this->assertSame($post->title, $version->contents['title']);
42+
$this->assertSame($post->content, $version->contents['content']);
43+
44+
// json cast
45+
$this->assertIsString($version->contents['extends']);
46+
$this->assertSame($post->getRawOriginal('extends'), $version->contents['extends']);
47+
3948
// version2
4049
$post->update(['title' => 'version2']);
4150
$post->refresh();
@@ -119,29 +128,35 @@ public function it_can_create_version_with_snapshot_strategy()
119128
public function it_can_revert_to_target_version()
120129
{
121130
$post = Post::create(['title' => 'version1', 'content' => 'version1 content']);
122-
$post->update(['title' => 'version2', 'extends' => ['foo' => 'bar']]);
131+
$post->update(['title' => 'version2', 'extends' => ['foo2' => 'bar2']]);
123132
$post->update(['title' => 'version3', 'content' => 'version3 content', 'extends' => ['name' => 'overtrue']]);
124133
$post->update(['title' => 'version4', 'content' => 'version4 content']);
125134

126135
// #29
127-
$version = $post->firstVersion;
128-
$post = $version->revertWithoutSaving();
136+
$version1 = $post->firstVersion;
137+
$post = $version1->revertWithoutSaving();
129138

130139
$this->assertSame('version1', $post->title);
131140
$this->assertSame('version1 content', $post->content);
132141
$this->assertNull($post->extends);
133142

134143
$post->refresh();
135144

145+
146+
$version2 = $post->firstVersion->nextVersion();
147+
$this->assertSame('version2', $version2->contents['title']);
148+
// only title updated
149+
$this->assertNull($version2->contents['content'] ?? null);
150+
$this->assertSame(json_encode(['foo2' => 'bar2']), $version2->contents['extends']);
151+
136152
// revert version 2
137153
$post->revertToVersion($post->firstVersion->nextVersion()->id);
138154
$post->refresh();
139155

140156
// only title updated
141157
$this->assertSame('version2', $post->title);
142158
$this->assertSame('version4 content', $post->content);
143-
144-
$this->assertSame(['foo' => 'bar'], $post->extends);
159+
$this->assertSame(['foo2' => 'bar2'], $post->extends);
145160

146161
// revert version 3
147162
$post->revertToVersion(3);

0 commit comments

Comments
 (0)