From a395a65091f91c4ec2799829733c77fc0615eebe Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Wed, 11 Mar 2026 14:30:08 +0000 Subject: [PATCH] Fix dated entries not syncing with origin revisions --- src/Entries/Entry.php | 4 +- tests/Feature/Entries/EntryRevisionsTest.php | 149 +++++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) diff --git a/src/Entries/Entry.php b/src/Entries/Entry.php index 292511a84d6..27577181e46 100644 --- a/src/Entries/Entry.php +++ b/src/Entries/Entry.php @@ -773,7 +773,9 @@ public function makeFromRevision($revision) ->slug($attrs['slug']); if ($this->collection()->dated() && ($date = Arr::get($attrs, 'date'))) { - $entry->date(Carbon::createFromTimestamp($date, config('app.timezone'))); + if ($this->isRoot() || $this->blueprint()->field('date')->isLocalizable()) { + $entry->date(Carbon::createFromTimestamp($date, config('app.timezone'))); + } } return $entry; diff --git a/tests/Feature/Entries/EntryRevisionsTest.php b/tests/Feature/Entries/EntryRevisionsTest.php index 8a4a23a725d..5864db611bf 100644 --- a/tests/Feature/Entries/EntryRevisionsTest.php +++ b/tests/Feature/Entries/EntryRevisionsTest.php @@ -394,6 +394,155 @@ private function restore($entry, $payload) return $this->post($entry->restoreRevisionUrl(), $payload); } + #[Test] + public function localized_entry_with_non_localizable_date_gets_origin_date_when_reconstructed_from_revision() + { + $this->setSites([ + 'en' => ['url' => 'http://localhost/', 'locale' => 'en'], + 'fr' => ['url' => 'http://localhost/fr/', 'locale' => 'fr'], + ]); + + $this->setTestBlueprint('test', [ + 'foo' => ['type' => 'text'], + 'date' => ['type' => 'date', 'localizable' => false], + ]); + $this->setTestRoles(['test' => ['access cp', 'publish blog entries']]); + $user = User::make()->id('user-1')->assignRole('test')->save(); + + $this->collection->sites(['en', 'fr'])->save(); + + $origin = EntryFactory::id('1') + ->slug('test') + ->collection('blog') + ->locale('en') + ->published(true) + ->date('2010-12-25') + ->data([ + 'blueprint' => 'test', + 'title' => 'Title', + 'foo' => 'bar', + ])->create(); + + $localized = EntryFactory::id('2') + ->slug('test') + ->collection('blog') + ->locale('fr') + ->origin($origin) + ->published(true) + ->data(['blueprint' => 'test']) + ->create(); + + $this->assertEquals('2010-12-25', $origin->date()->format('Y-m-d')); + $this->assertEquals('2010-12-25', $localized->date()->format('Y-m-d')); + + tap($localized->makeWorkingCopy(), function ($copy) { + $attrs = $copy->attributes(); + $attrs['data']['foo'] = 'foo modified in localized working copy'; + $copy->attributes($attrs); + })->save(); + + $this->assertTrue($localized->hasWorkingCopy()); + $this->assertEquals('2010-12-25', $localized->fromWorkingCopy()->date()->format('Y-m-d')); + + tap($origin->makeWorkingCopy(), function ($copy) { + $attrs = $copy->attributes(); + $attrs['date'] = Carbon::parse('2020-06-15')->timestamp; + $copy->attributes($attrs); + })->save(); + + $this + ->actingAs($user) + ->publish($origin, ['message' => 'Publish origin with new date']) + ->assertOk(); + + $origin = Entry::find('1'); + $this->assertEquals('2020-06-15', $origin->date()->format('Y-m-d')); + + $localized = Entry::find('2'); + $this->assertEquals('2020-06-15', $localized->date()->format('Y-m-d')); + + $this->assertEquals( + '2020-06-15', + $localized->fromWorkingCopy()->date()->format('Y-m-d'), + 'Localized entry reconstructed from working copy should use origin\'s current date when date field is not localizable' + ); + } + + #[Test] + public function localized_entry_with_localizable_date_keeps_its_own_date_when_reconstructed_from_revision() + { + $this->setSites([ + 'en' => ['url' => 'http://localhost/', 'locale' => 'en'], + 'fr' => ['url' => 'http://localhost/fr/', 'locale' => 'fr'], + ]); + + $this->setTestBlueprint('test', [ + 'foo' => ['type' => 'text'], + 'date' => ['type' => 'date', 'localizable' => true], + ]); + $this->setTestRoles(['test' => ['access cp', 'publish blog entries']]); + $user = User::make()->id('user-1')->assignRole('test')->save(); + + $this->collection->sites(['en', 'fr'])->save(); + + $origin = EntryFactory::id('1') + ->slug('test') + ->collection('blog') + ->locale('en') + ->published(true) + ->date('2010-12-25') + ->data([ + 'blueprint' => 'test', + 'title' => 'Title', + 'foo' => 'bar', + ])->create(); + + $localized = EntryFactory::id('2') + ->slug('test') + ->collection('blog') + ->locale('fr') + ->origin($origin) + ->published(true) + ->date('2015-03-10') + ->data(['blueprint' => 'test']) + ->create(); + + $this->assertEquals('2010-12-25', $origin->date()->format('Y-m-d')); + $this->assertEquals('2015-03-10', $localized->date()->format('Y-m-d')); + + tap($localized->makeWorkingCopy(), function ($copy) { + $attrs = $copy->attributes(); + $attrs['data']['foo'] = 'foo modified in localized working copy'; + $copy->attributes($attrs); + })->save(); + + $this->assertTrue($localized->hasWorkingCopy()); + $this->assertEquals('2015-03-10', $localized->fromWorkingCopy()->date()->format('Y-m-d')); + + tap($origin->makeWorkingCopy(), function ($copy) { + $attrs = $copy->attributes(); + $attrs['date'] = Carbon::parse('2020-06-15')->timestamp; + $copy->attributes($attrs); + })->save(); + + $this + ->actingAs($user) + ->publish($origin, ['message' => 'Publish origin with new date']) + ->assertOk(); + + $origin = Entry::find('1'); + $this->assertEquals('2020-06-15', $origin->date()->format('Y-m-d')); + + $localized = Entry::find('2'); + $this->assertEquals('2015-03-10', $localized->date()->format('Y-m-d')); + + $this->assertEquals( + '2015-03-10', + $localized->fromWorkingCopy()->date()->format('Y-m-d'), + 'Localized entry reconstructed from working copy should keep its own date when date field is localizable' + ); + } + private function setTestBlueprint($handle, $fields) { $blueprint = Blueprint::makeFromFields($fields)->setHandle($handle);