From d2d06dbeca11f53cda0f3f21524e0309a90b1f5b Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Thu, 29 Jan 2026 09:39:47 +0000 Subject: [PATCH 1/5] Add failing test --- tests/Fieldtypes/ReplicatorTest.php | 93 +++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/tests/Fieldtypes/ReplicatorTest.php b/tests/Fieldtypes/ReplicatorTest.php index 4dc5cd25906..e254a88bbc7 100644 --- a/tests/Fieldtypes/ReplicatorTest.php +++ b/tests/Fieldtypes/ReplicatorTest.php @@ -932,6 +932,99 @@ public function it_can_return_set_defaults_for_nested_sets() ], $response->json('new')); } + /** + * We're purposefully naming the sets the same as its nested field to replicate the reported issue. + * + * @see https://github.com/statamic/cms/issues/13714 + */ + #[Test] + public function it_can_return_set_defaults_for_replicator_inside_grid() + { + $this->partialMock(RowId::class, function (MockInterface $mock) { + $mock->shouldReceive('generate')->andReturn('random-string-1', 'random-string-2'); + }); + + $pageBuilder = Fieldset::make('page_builder')->setContents(['fields' => [ + ['handle' => 'page_builder', 'field' => ['type' => 'replicator', 'sets' => [ + 'replicator_set_group' => [ + 'sets' => [ + 'cards_slider' => [ + 'fields' => [ + [ + 'handle' => 'cards_slider', + 'field' => [ + 'type' => 'group', + 'fields' => [ + [ + 'handle' => 'slider', + 'field' => [ + 'type' => 'group', + 'fields' => [ + [ + 'handle' => 'cards', + 'field' => [ + 'type' => 'replicator', + 'sets' => [ + 'replicator_set_group' => [ + 'sets' => [ + 'card' => [ + 'fields' => [ + ['handle' => 'card_content', 'field' => ['type' => 'text', 'default' => 'the default']], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ]]], + ]]); + + Fieldset::shouldReceive('find')->with('page_builder')->andReturn($pageBuilder); + + $blueprint = Facades\Blueprint::make()->setHandle('default')->setNamespace('collections.pages'); + $blueprint->setContents([ + 'sections' => [ + 'main' => [ + 'fields' => [ + ['import' => 'page_builder'], + ], + ], + ], + ]); + + Facades\Blueprint::partialMock(); + Facades\Blueprint::shouldReceive('find')->with('collections.pages.default')->andReturn($blueprint); + + $response = $this + ->actingAs(tap(Facades\User::make()->makeSuper())->save()) + ->postJson(cp_route('replicator-fieldtype.set'), [ + 'blueprint' => 'collections.pages.default', + 'field' => 'page_builder.cards_slider.cards_slider.slider.cards', + 'set' => 'card', + ]) + ->assertOk(); + + $this->assertEquals([ + 'card_content' => 'the default', + ], $response->json('defaults')); + + $this->assertEquals([ + '_' => '_', + 'card_content' => null, + ], $response->json('new')); + } + public static function groupedSetsProvider() { return [ From 0c9c6f622a837732a2fe42cd3ed372167b0ada34 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Thu, 29 Jan 2026 10:01:48 +0000 Subject: [PATCH 2/5] Add handling for group fields --- .../CP/Fieldtypes/ReplicatorSetController.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Http/Controllers/CP/Fieldtypes/ReplicatorSetController.php b/src/Http/Controllers/CP/Fieldtypes/ReplicatorSetController.php index 787452eab89..baec7455204 100644 --- a/src/Http/Controllers/CP/Fieldtypes/ReplicatorSetController.php +++ b/src/Http/Controllers/CP/Fieldtypes/ReplicatorSetController.php @@ -72,6 +72,7 @@ private function getReplicatorField(Blueprint $blueprint, string $field): Field private function getConfig(array $config, array $remainingFieldPathComponents): array { + $isGroup = isset($config['type']) && $config['type'] === 'group'; $isReplicator = isset($config['type']) && in_array($config['type'], ['bard', 'replicator']); if ($isReplicator) { @@ -88,6 +89,14 @@ private function getConfig(array $config, array $remainingFieldPathComponents): return $this->getConfig($flattenedSets, $remainingFieldPathComponents); } + if ($isGroup) { + array_shift($remainingFieldPathComponents); + + $fields = $this->resolveFields($config['fields'] ?? []); + + return $this->getConfig($fields[$remainingFieldPathComponents[0]]['field'], $remainingFieldPathComponents); + } + $fields = $this->resolveFields($config[$remainingFieldPathComponents[0]]['fields']); array_shift($remainingFieldPathComponents); From 4c356aa0527718de24654243c9ca407b5fe80be8 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Thu, 29 Jan 2026 10:02:18 +0000 Subject: [PATCH 3/5] whoops, rename test --- tests/Fieldtypes/ReplicatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Fieldtypes/ReplicatorTest.php b/tests/Fieldtypes/ReplicatorTest.php index e254a88bbc7..cfdd22fb3f4 100644 --- a/tests/Fieldtypes/ReplicatorTest.php +++ b/tests/Fieldtypes/ReplicatorTest.php @@ -938,7 +938,7 @@ public function it_can_return_set_defaults_for_nested_sets() * @see https://github.com/statamic/cms/issues/13714 */ #[Test] - public function it_can_return_set_defaults_for_replicator_inside_grid() + public function it_can_return_set_defaults_for_replicator_inside_group() { $this->partialMock(RowId::class, function (MockInterface $mock) { $mock->shouldReceive('generate')->andReturn('random-string-1', 'random-string-2'); From 4f63957d906e18f79c5fde13d62b394b831f6b67 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Thu, 29 Jan 2026 10:11:17 +0000 Subject: [PATCH 4/5] Add failing test for grids --- tests/Fieldtypes/ReplicatorTest.php | 80 +++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tests/Fieldtypes/ReplicatorTest.php b/tests/Fieldtypes/ReplicatorTest.php index cfdd22fb3f4..5b62c44d199 100644 --- a/tests/Fieldtypes/ReplicatorTest.php +++ b/tests/Fieldtypes/ReplicatorTest.php @@ -1025,6 +1025,86 @@ public function it_can_return_set_defaults_for_replicator_inside_group() ], $response->json('new')); } + #[Test] + public function it_can_return_set_defaults_for_replicator_inside_grid() + { + $this->partialMock(RowId::class, function (MockInterface $mock) { + $mock->shouldReceive('generate')->andReturn('random-string-1', 'random-string-2'); + }); + + $pageBuilder = Fieldset::make('page_builder')->setContents(['fields' => [ + ['handle' => 'page_builder', 'field' => ['type' => 'replicator', 'sets' => [ + 'replicator_set_group' => [ + 'sets' => [ + 'cards_slider' => [ + 'fields' => [ + [ + 'handle' => 'cards_slider', + 'field' => [ + 'type' => 'grid', + 'fields' => [ + [ + 'handle' => 'cards', + 'field' => [ + 'type' => 'replicator', + 'sets' => [ + 'replicator_set_group' => [ + 'sets' => [ + 'card' => [ + 'fields' => [ + ['handle' => 'card_content', 'field' => ['type' => 'text', 'default' => 'the default']], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ], + ]]], + ]]); + + Fieldset::shouldReceive('find')->with('page_builder')->andReturn($pageBuilder); + + $blueprint = Facades\Blueprint::make()->setHandle('default')->setNamespace('collections.pages'); + $blueprint->setContents([ + 'sections' => [ + 'main' => [ + 'fields' => [ + ['import' => 'page_builder'], + ], + ], + ], + ]); + + Facades\Blueprint::partialMock(); + Facades\Blueprint::shouldReceive('find')->with('collections.pages.default')->andReturn($blueprint); + + $response = $this + ->actingAs(tap(Facades\User::make()->makeSuper())->save()) + ->postJson(cp_route('replicator-fieldtype.set'), [ + 'blueprint' => 'collections.pages.default', + 'field' => 'page_builder.cards_slider.cards_slider.cards', + 'set' => 'card', + ]) + ->assertOk(); + + $this->assertEquals([ + 'card_content' => 'the default', + ], $response->json('defaults')); + + $this->assertEquals([ + '_' => '_', + 'card_content' => null, + ], $response->json('new')); + } + public static function groupedSetsProvider() { return [ From 8b2f5d3d7852fa6c4b027cb48cfc540935089aef Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Thu, 29 Jan 2026 10:13:51 +0000 Subject: [PATCH 5/5] Add handling for grid fields --- .../Controllers/CP/Fieldtypes/ReplicatorSetController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Controllers/CP/Fieldtypes/ReplicatorSetController.php b/src/Http/Controllers/CP/Fieldtypes/ReplicatorSetController.php index baec7455204..6871fb8dd21 100644 --- a/src/Http/Controllers/CP/Fieldtypes/ReplicatorSetController.php +++ b/src/Http/Controllers/CP/Fieldtypes/ReplicatorSetController.php @@ -72,7 +72,7 @@ private function getReplicatorField(Blueprint $blueprint, string $field): Field private function getConfig(array $config, array $remainingFieldPathComponents): array { - $isGroup = isset($config['type']) && $config['type'] === 'group'; + $isGroupOrGrid = isset($config['type']) && in_array($config['type'], ['group', 'grid']); $isReplicator = isset($config['type']) && in_array($config['type'], ['bard', 'replicator']); if ($isReplicator) { @@ -89,7 +89,7 @@ private function getConfig(array $config, array $remainingFieldPathComponents): return $this->getConfig($flattenedSets, $remainingFieldPathComponents); } - if ($isGroup) { + if ($isGroupOrGrid) { array_shift($remainingFieldPathComponents); $fields = $this->resolveFields($config['fields'] ?? []);