diff --git a/src/Fields/Field.php b/src/Fields/Field.php index 634f03adff..5d5c2202d9 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 836cb4a6bc..8500ad6915 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,11 @@ private function configSections() return []; } + if ($extraSections = $this->extraConfigFieldsUseSections($extras)) { + $fields = collect($fields)->merge($extraSections); + $extras = collect($extras)->diffKeys($extraSections); + } + $extras = collect($extras) ->map(fn ($field, $handle) => compact('handle', 'field')) ->values()->all(); @@ -260,6 +266,11 @@ private function configFieldsUseSections() return array_keys($fields)[0] === 0; } + private function extraConfigFieldsUseSections($extras) + { + return collect($extras)->filter(fn ($field) => Arr::has($field, 'fields')); + } + public function configFields(): Fields { if ($cached = Blink::get($blink = 'config-fields-'.$this->handle())) { @@ -267,13 +278,21 @@ public function configFields(): Fields } $fields = collect($this->configFieldItems()); + $extraFields = collect($this->extraConfigFieldItems()); if ($this->configFieldsUseSections()) { $fields = $fields->flatMap(fn ($section) => $section['fields']); } + 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($this->extraConfigFieldItems()) + ->merge($extraFields) ->map(function ($field, $handle) { return compact('handle', 'field'); }); diff --git a/tests/Fields/FieldtypeTest.php b/tests/Fields/FieldtypeTest.php index b0519eed40..5e2e0acd09 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)