From 38bd906ba551b0e5b1bb342f40777023cf561a9a Mon Sep 17 00:00:00 2001 From: Jack McDade Date: Tue, 25 Aug 2026 11:57:14 -0400 Subject: [PATCH 1/3] Add TokenRepository::all() for unexpired tokens The cms TokenRepository contract now requires all(). Implement it so shareable preview links can reuse tokens on Eloquent-backed sites. Co-authored-by: Cursor --- src/Tokens/TokenRepository.php | 10 ++++++++++ tests/Repositories/TokenRepositoryTest.php | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/Tokens/TokenRepository.php b/src/Tokens/TokenRepository.php index 6a889e26..28fcc68b 100644 --- a/src/Tokens/TokenRepository.php +++ b/src/Tokens/TokenRepository.php @@ -2,11 +2,21 @@ namespace Statamic\Eloquent\Tokens; +use Illuminate\Support\Collection; use Statamic\Contracts\Tokens\Token as TokenContract; use Statamic\Tokens\TokenRepository as Repository; class TokenRepository extends Repository { + public function all(): Collection + { + return app('statamic.eloquent.tokens.model')::query() + ->where('expire_at', '>', now()) + ->get() + ->map(fn ($model) => Token::fromModel($model)) + ->values(); + } + public function find(string $token): ?Token { $model = app('statamic.eloquent.tokens.model')::whereToken($token)->first(); diff --git a/tests/Repositories/TokenRepositoryTest.php b/tests/Repositories/TokenRepositoryTest.php index 0a3e4eaa..a39a2666 100644 --- a/tests/Repositories/TokenRepositoryTest.php +++ b/tests/Repositories/TokenRepositoryTest.php @@ -36,6 +36,18 @@ public function it_gets_a_token() $this->assertNull($this->repo->find('unknown')); } + #[Test] + public function it_gets_all_non_expired_tokens() + { + $this->repo->make('expired', 'ExampleHandler')->expireAt(now()->subMinute())->save(); + $this->repo->make('fresh', 'ExampleHandler')->expireAt(now()->addHour())->save(); + + $this->assertEquals( + ['abc', 'fresh'], + $this->repo->all()->map->token()->sort()->values()->all() + ); + } + #[Test] public function it_saves_a_token_to_the_database() { From 69bbe07f1575753e6e86a138395965830d1c82cb Mon Sep 17 00:00:00 2001 From: Jack McDade Date: Tue, 25 Aug 2026 12:04:11 -0400 Subject: [PATCH 2/3] Return all tokens from TokenRepository::all() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not filter by expiry — that is the caller's concern. Co-authored-by: Cursor --- src/Tokens/TokenRepository.php | 1 - tests/Repositories/TokenRepositoryTest.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Tokens/TokenRepository.php b/src/Tokens/TokenRepository.php index 28fcc68b..fb0300e1 100644 --- a/src/Tokens/TokenRepository.php +++ b/src/Tokens/TokenRepository.php @@ -11,7 +11,6 @@ class TokenRepository extends Repository public function all(): Collection { return app('statamic.eloquent.tokens.model')::query() - ->where('expire_at', '>', now()) ->get() ->map(fn ($model) => Token::fromModel($model)) ->values(); diff --git a/tests/Repositories/TokenRepositoryTest.php b/tests/Repositories/TokenRepositoryTest.php index a39a2666..2d416be1 100644 --- a/tests/Repositories/TokenRepositoryTest.php +++ b/tests/Repositories/TokenRepositoryTest.php @@ -37,13 +37,13 @@ public function it_gets_a_token() } #[Test] - public function it_gets_all_non_expired_tokens() + public function it_gets_all_tokens() { $this->repo->make('expired', 'ExampleHandler')->expireAt(now()->subMinute())->save(); $this->repo->make('fresh', 'ExampleHandler')->expireAt(now()->addHour())->save(); $this->assertEquals( - ['abc', 'fresh'], + ['abc', 'expired', 'fresh'], $this->repo->all()->map->token()->sort()->values()->all() ); } From a22c9b64ea9893f9ce17d043c0c4441312d49f77 Mon Sep 17 00:00:00 2001 From: Jack McDade Date: Tue, 25 Aug 2026 12:10:29 -0400 Subject: [PATCH 3/3] Don't assume structured entries start with order 1 CMS 6.29 assigns sequential order on save. Snapshot orders before the tree save so prefer-stable and prefer-lowest both pass. Co-authored-by: Cursor --- tests/Entries/EntryRepositoryTest.php | 31 +++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/tests/Entries/EntryRepositoryTest.php b/tests/Entries/EntryRepositoryTest.php index a38ecc2f..1a973f31 100644 --- a/tests/Entries/EntryRepositoryTest.php +++ b/tests/Entries/EntryRepositoryTest.php @@ -94,6 +94,8 @@ public function it_updates_the_order_of_all_entries_in_a_collection() (new Entry)->id(3)->collection($collection)->slug('charlie')->save(); (new Entry)->id(4)->collection($collection)->slug('delta')->save(); + $orders = $this->entryOrders(); + $collection->structure()->in('en')->tree([ ['entry' => 4], ['entry' => 2], @@ -103,12 +105,7 @@ public function it_updates_the_order_of_all_entries_in_a_collection() // Assert that the order is unchanged, to make sure that saving // the structure isn't what caused the order to be updated. - $this->assertEquals([ - 1 => 1, - 2 => 1, - 3 => 1, - 4 => 1, - ], EntryModel::all()->mapWithKeys(fn ($e) => [$e->id => $e->order])->all()); + $this->assertEquals($orders, $this->entryOrders()); (new EntryRepository(new Stache))->updateOrders($collection); @@ -117,7 +114,7 @@ public function it_updates_the_order_of_all_entries_in_a_collection() 2 => 2, 3 => 4, 4 => 1, - ], EntryModel::all()->mapWithKeys(fn ($e) => [$e->id => $e->order])->all()); + ], $this->entryOrders()); } #[Test] @@ -134,6 +131,8 @@ public function it_updates_the_order_of_specific_entries_in_a_collection() (new Entry)->id(3)->collection($collection)->slug('charlie')->save(); (new Entry)->id(4)->collection($collection)->slug('delta')->save(); + $orders = $this->entryOrders(); + $collection->structure()->in('en')->tree([ ['entry' => 4], ['entry' => 2], @@ -143,21 +142,16 @@ public function it_updates_the_order_of_specific_entries_in_a_collection() // Assert that the order is unchanged, to make sure that saving // the structure isn't what caused the order to be updated. - $this->assertEquals([ - 1 => 1, - 2 => 1, - 3 => 1, - 4 => 1, - ], EntryModel::all()->mapWithKeys(fn ($e) => [$e->id => $e->order])->all()); + $this->assertEquals($orders, $this->entryOrders()); (new EntryRepository(new Stache))->updateOrders($collection, [2, 3]); $this->assertEquals([ - 1 => 1, + 1 => $orders[1], 2 => 2, 3 => 4, - 4 => 1, - ], EntryModel::all()->mapWithKeys(fn ($e) => [$e->id => $e->order])->all()); + 4 => $orders[4], + ], $this->entryOrders()); } #[Test] @@ -310,4 +304,9 @@ public function it_skips_missing_entires_when_finding_by_ids() $this->assertEquals([$expected->id()], $actual->map->id()->all()); } + + private function entryOrders(): array + { + return EntryModel::all()->mapWithKeys(fn ($e) => [$e->id => $e->order])->all(); + } }