From cf3595379c08e8f8b326bc46bd2f3326614fef6e Mon Sep 17 00:00:00 2001 From: oddvalue Date: Fri, 23 Jun 2023 15:17:35 +0100 Subject: [PATCH] [Fix] Prevent multiple current records after publishing draft (#39) * [Fix] Prevent multiple current records after publishing draft * Fix styling --------- Co-authored-by: oddvalue --- src/Concerns/HasDrafts.php | 31 ++++++++++++++-------- src/Scopes/PublishingScope.php | 48 +++++++++++++++++----------------- tests/PublishingTest.php | 25 ++++++++++++++++++ 3 files changed, 69 insertions(+), 35 deletions(-) diff --git a/src/Concerns/HasDrafts.php b/src/Concerns/HasDrafts.php index 91bfa14..cb3992f 100644 --- a/src/Concerns/HasDrafts.php +++ b/src/Concerns/HasDrafts.php @@ -147,19 +147,19 @@ public function getDraftableAttributes(): array public function setCurrent(): void { - $oldCurrent = $this->revisions()->withDrafts()->current()->excludeRevision($this)->first(); + $this->{$this->getIsCurrentColumn()} = true; - static::saved(function (Model $model) use ($oldCurrent): void { - if ($model->isNot($this) || ! $oldCurrent) { + static::saved(function (Model $model): void { + if ($model->isNot($this)) { return; } - $oldCurrent->{$this->getIsCurrentColumn()} = false; - $oldCurrent->timestamps = false; - $oldCurrent->saveQuietly(); + $this->revisions() + ->withDrafts() + ->current() + ->excludeRevision($this) + ->update([$this->getIsCurrentColumn() => false]); }); - - $this->{$this->getIsCurrentColumn()} = true; } public function setLive(): void @@ -199,7 +199,9 @@ public function setLive(): void if ($related = $this->{$relationName}) { $replicated = $related->replicate(); - $method = method_exists($replicated, 'getDraftableAttributes') ? 'getDraftableAttributes' : 'getAttributes'; + $method = method_exists($replicated, 'getDraftableAttributes') + ? 'getDraftableAttributes' + : 'getAttributes'; $published->{$relationName}()->create($replicated->$method()); } @@ -209,7 +211,9 @@ public function setLive(): void $this->{$relationName}()->get()->each(function ($model) use ($published, $relationName) { $replicated = $model->replicate(); - $method = method_exists($replicated, 'getDraftableAttributes') ? 'getDraftableAttributes' : 'getAttributes'; + $method = method_exists($replicated, 'getDraftableAttributes') + ? 'getDraftableAttributes' + : 'getAttributes'; $published->{$relationName}()->create($replicated->$method()); }); @@ -380,11 +384,16 @@ public function getIsCurrentColumn(): string public function getUuidColumn(): string { - return defined(static::class.'::UUID') + return defined(static::class . '::UUID') ? static::UUID : config('drafts.column_names.uuid', 'uuid'); } + public function isCurrent(): bool + { + return $this->{$this->getIsCurrentColumn()} ?? false; + } + /* |-------------------------------------------------------------------------- | RELATIONS diff --git a/src/Scopes/PublishingScope.php b/src/Scopes/PublishingScope.php index bf3cac7..2672d75 100644 --- a/src/Scopes/PublishingScope.php +++ b/src/Scopes/PublishingScope.php @@ -31,30 +31,30 @@ public function extend(Builder $builder): void } } -// protected function addPublish(Builder $builder): void -// { -// $builder->macro('publish', function (Builder $builder) { -// $builder->withDrafts(); -// -// return $builder->update([$builder->getModel()->getIsPublishedColumn() => now()]); -// }); -// } -// -// protected function addUnpublish(Builder $builder): void -// { -// $builder->macro('unpublish', function (Builder $builder) { -// return $builder->update([$builder->getModel()->getIsPublishedColumn() => null]); -// }); -// } -// -// protected function addSchedule(Builder $builder): void -// { -// $builder->macro('schedule', function (Builder $builder, string | \DateTimeInterface $date) { -// $builder->withDrafts(); -// -// return $builder->update([$builder->getModel()->getIsPublishedColumn() => $date]); -// }); -// } + // protected function addPublish(Builder $builder): void + // { + // $builder->macro('publish', function (Builder $builder) { + // $builder->withDrafts(); + // + // return $builder->update([$builder->getModel()->getIsPublishedColumn() => now()]); + // }); + // } + // + // protected function addUnpublish(Builder $builder): void + // { + // $builder->macro('unpublish', function (Builder $builder) { + // return $builder->update([$builder->getModel()->getIsPublishedColumn() => null]); + // }); + // } + // + // protected function addSchedule(Builder $builder): void + // { + // $builder->macro('schedule', function (Builder $builder, string | \DateTimeInterface $date) { + // $builder->withDrafts(); + // + // return $builder->update([$builder->getModel()->getIsPublishedColumn() => $date]); + // }); + // } protected function addPublished(Builder $builder): void { diff --git a/tests/PublishingTest.php b/tests/PublishingTest.php index a1f3514..9979250 100644 --- a/tests/PublishingTest.php +++ b/tests/PublishingTest.php @@ -66,3 +66,28 @@ expect(Post::withoutDrafts()->pluck('id')) ->toHaveCount(1); }); + +it('can publish a draft that is not the current one', function () { + \Oddvalue\LaravelDrafts\Facades\LaravelDrafts::withDrafts(); + + Post::factory()->create(['title' => 'a']); + + $post = Post::where('title', 'a')->first(); + $post->title = 'b'; + $b = $post->saveAsDraft(); + + $post = Post::where('title', 'b')->first(); + $post->title = 'c'; + $post->saveAsDraft(); + + expect(Post::where('title', 'a')->first()->isPublished())->toBeTrue(); + expect(Post::where('title', 'c')->first()->isCurrent())->toBeTrue(); + + $draftB = Post::where('title', 'b')->first(); + $draftB->setLive(); + $draftB->save(); + + expect(Post::where('title', 'a')->first()->isPublished())->toBeFalse(); + expect(Post::where('title', 'b')->first()->isPublished())->toBeTrue(); + expect(Post::current()->count())->toBe(1); +});