From 30b44f310bfbbdd9b0ac7844eafcdb3dac0d514f Mon Sep 17 00:00:00 2001 From: Guillermo Azurdia Date: Mon, 2 Feb 2026 13:02:10 -0500 Subject: [PATCH 1/6] Make fieldtype accept extra sections --- src/Fields/Field.php | 4 ++ src/Fields/Fieldtype.php | 24 ++++++++++++ tests/Fields/FieldtypeTest.php | 69 ++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/src/Fields/Field.php b/src/Fields/Field.php index 634f03adff9..53a844bff27 100644 --- a/src/Fields/Field.php +++ b/src/Fields/Field.php @@ -174,6 +174,10 @@ protected function addNullableRule($rules) public function isRequired() { + if (! isset($this->rules()[$this->handle])) { + return false; + } + return collect($this->rules()[$this->handle])->contains('required'); } diff --git a/src/Fields/Fieldtype.php b/src/Fields/Fieldtype.php index 836cb4a6bc7..da3a84ceb57 100644 --- a/src/Fields/Fieldtype.php +++ b/src/Fields/Fieldtype.php @@ -4,6 +4,7 @@ use Facades\Statamic\Fields\FieldtypeRepository; use Illuminate\Contracts\Support\Arrayable; +use Illuminate\Support\Arr; use Statamic\Extend\HasHandle; use Statamic\Extend\RegistersItself; use Statamic\Facades\Blink; @@ -215,6 +216,14 @@ private function configSections() return []; } + if ($this->extraConfigFieldsUseSections()) { + $extraSections = collect($extras)->filter(fn ($field) => Arr::has($field, 'fields')); + + $fields = collect($fields)->merge($extraSections); + + $extras = collect($extras)->diffKeys($extraSections); + } + $extras = collect($extras) ->map(fn ($field, $handle) => compact('handle', 'field')) ->values()->all(); @@ -260,6 +269,15 @@ private function configFieldsUseSections() return array_keys($fields)[0] === 0; } + private function extraConfigFieldsUseSections() + { + if (empty($fields = $this->extraConfigFieldItems())) { + return false; + } + + return array_keys($fields)[0] === 0; + } + public function configFields(): Fields { if ($cached = Blink::get($blink = 'config-fields-'.$this->handle())) { @@ -267,12 +285,18 @@ public function configFields(): Fields } $fields = collect($this->configFieldItems()); + $extraFields = collect($this->extraConfigFieldItems()); if ($this->configFieldsUseSections()) { $fields = $fields->flatMap(fn ($section) => $section['fields']); } + if ($this->extraConfigFieldsUseSections()) { + $extraFields = $extraFields->flatMap(fn ($section) => $section['fields']); + } + $fields = $fields + ->merge($extraFields) ->merge($this->extraConfigFieldItems()) ->map(function ($field, $handle) { return compact('handle', 'field'); diff --git a/tests/Fields/FieldtypeTest.php b/tests/Fields/FieldtypeTest.php index b0519eed407..5e2e0acd094 100644 --- a/tests/Fields/FieldtypeTest.php +++ b/tests/Fields/FieldtypeTest.php @@ -309,6 +309,67 @@ public function it_can_append_multiple_config_fields() $this->assertEquals('textarea', $fields->get('description')->type()); } + #[Test] + public function it_can_append_new_section_config_fields() + { + TestAppendConfigSectionFields::appendConfigFields([ + [ + 'display' => __('Extra section'), + 'fields' => [ + 'more_options' => [ + 'display' => __('Options'), + 'instructions' => __('Instructions for this field'), + 'type' => 'array', + ], + 'extra_html_class' => [ + 'display' => __('Append HTML Classes options'), + 'instructions' => __('Instructions for this field'), + 'type' => 'textarea', + ], + ], + ], + ]); + + $fields = (new TestAppendConfigSectionFields())->configFields(); + + $this->assertCount(4, $fields->all()); + $this->assertEquals('array', $fields->get('more_options')->type()); + $this->assertEquals('textarea', $fields->get('extra_html_class')->type()); + } + + #[Test] + public function it_can_append_new_sections_config_fields() + { + TestAppendConfigSectionFields::appendConfigFields([ + [ + 'display' => __('Extra section'), + 'fields' => [ + 'more_options' => [ + 'display' => __('Options'), + 'instructions' => __('Instructions for this field'), + 'type' => 'array', + ], + ], + ], + [ + 'display' => __('New Extra section'), + 'fields' => [ + 'extra_html_class' => [ + 'display' => __('Append HTML Classes options'), + 'instructions' => __('Instructions for this field'), + 'type' => 'textarea', + ], + ], + ], + ]); + + $fields = (new TestAppendConfigSectionFields())->configFields(); + + $this->assertCount(4, $fields->all()); + $this->assertEquals('array', $fields->get('more_options')->type()); + $this->assertEquals('textarea', $fields->get('extra_html_class')->type()); + } + #[Test] public function it_wont_override_previously_appended_config_fields() { @@ -645,6 +706,14 @@ class TestAppendConfigFields extends Fieldtype ]; } +class TestAppendConfigSectionFields extends Fieldtype +{ + protected $configFields = [ + 'foo' => ['type' => 'textarea'], + 'max_items' => ['type' => 'integer'], + ]; +} + class TestFieldtypeWithConfigFieldsProperty extends Fieldtype { public function __construct($property) From 84fcbbeea48cc631479f13798b6b9ee76342850c Mon Sep 17 00:00:00 2001 From: Guillermo Azurdia Date: Mon, 2 Feb 2026 13:16:08 -0500 Subject: [PATCH 2/6] Add null validation --- src/Fields/Fieldtype.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Fields/Fieldtype.php b/src/Fields/Fieldtype.php index da3a84ceb57..40fa29981a8 100644 --- a/src/Fields/Fieldtype.php +++ b/src/Fields/Fieldtype.php @@ -292,7 +292,7 @@ public function configFields(): Fields } if ($this->extraConfigFieldsUseSections()) { - $extraFields = $extraFields->flatMap(fn ($section) => $section['fields']); + $extraFields = $extraFields->flatMap(fn ($section) => $section['fields'] ?? null); } $fields = $fields From f4e151f0bd816c759b008ef12e24c2ea49659c02 Mon Sep 17 00:00:00 2001 From: Guillermo Azurdia Date: Mon, 2 Feb 2026 13:33:50 -0500 Subject: [PATCH 3/6] github pr rerun checks From cb5e019e3566d092e277dce6e5f19fc3f516adae Mon Sep 17 00:00:00 2001 From: Guillermo Azurdia Date: Mon, 2 Feb 2026 23:41:37 -0500 Subject: [PATCH 4/6] Improve extra sections --- src/Fields/Fieldtype.php | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Fields/Fieldtype.php b/src/Fields/Fieldtype.php index 40fa29981a8..8500ad6915f 100644 --- a/src/Fields/Fieldtype.php +++ b/src/Fields/Fieldtype.php @@ -216,11 +216,8 @@ private function configSections() return []; } - if ($this->extraConfigFieldsUseSections()) { - $extraSections = collect($extras)->filter(fn ($field) => Arr::has($field, 'fields')); - + if ($extraSections = $this->extraConfigFieldsUseSections($extras)) { $fields = collect($fields)->merge($extraSections); - $extras = collect($extras)->diffKeys($extraSections); } @@ -269,13 +266,9 @@ private function configFieldsUseSections() return array_keys($fields)[0] === 0; } - private function extraConfigFieldsUseSections() + private function extraConfigFieldsUseSections($extras) { - if (empty($fields = $this->extraConfigFieldItems())) { - return false; - } - - return array_keys($fields)[0] === 0; + return collect($extras)->filter(fn ($field) => Arr::has($field, 'fields')); } public function configFields(): Fields @@ -291,13 +284,15 @@ public function configFields(): Fields $fields = $fields->flatMap(fn ($section) => $section['fields']); } - if ($this->extraConfigFieldsUseSections()) { - $extraFields = $extraFields->flatMap(fn ($section) => $section['fields'] ?? null); + if ($extraSections = $this->extraConfigFieldsUseSections($extraFields)) { + $mergeFields = $extraSections->flatMap(fn ($section) => $section['fields'] ?? null); + + $fields = collect($fields)->merge($mergeFields); + $extraFields = collect($extraFields)->diffKeys($extraSections); } $fields = $fields ->merge($extraFields) - ->merge($this->extraConfigFieldItems()) ->map(function ($field, $handle) { return compact('handle', 'field'); }); From 75ba78cd8e7889059c2e1d96eb7728fdf1ae599a Mon Sep 17 00:00:00 2001 From: Guillermo Azurdia Date: Mon, 2 Feb 2026 23:59:46 -0500 Subject: [PATCH 5/6] Remove extra space --- src/Fields/Field.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Fields/Field.php b/src/Fields/Field.php index 53a844bff27..39a6269b80e 100644 --- a/src/Fields/Field.php +++ b/src/Fields/Field.php @@ -174,10 +174,10 @@ protected function addNullableRule($rules) public function isRequired() { - if (! isset($this->rules()[$this->handle])) { + if (!isset($this->rules()[$this->handle])) { return false; } - + return collect($this->rules()[$this->handle])->contains('required'); } From 567c596f31478a02c58cb01132b90ef99994c42c Mon Sep 17 00:00:00 2001 From: Guillermo Azurdia Date: Tue, 3 Feb 2026 00:25:57 -0500 Subject: [PATCH 6/6] Add space --- src/Fields/Field.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Fields/Field.php b/src/Fields/Field.php index 39a6269b80e..5d5c2202d91 100644 --- a/src/Fields/Field.php +++ b/src/Fields/Field.php @@ -174,7 +174,7 @@ protected function addNullableRule($rules) public function isRequired() { - if (!isset($this->rules()[$this->handle])) { + if (! isset($this->rules()[$this->handle])) { return false; }