From 8b70221ab0c24e9ba888f11af830b4f554438ccd Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Wed, 26 Jul 2023 12:33:32 +0100 Subject: [PATCH 01/19] Initial concept --- src/Forms/Form.php | 34 +++++++++++++------ src/Forms/FormRepository.php | 22 ++++++++++++ .../Controllers/CP/Forms/FormsController.php | 17 +++++++--- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/Forms/Form.php b/src/Forms/Form.php index ed905535a2..9d9346eae4 100644 --- a/src/Forms/Form.php +++ b/src/Forms/Form.php @@ -7,6 +7,7 @@ use Statamic\Contracts\Data\Augmented; use Statamic\Contracts\Forms\Form as FormContract; use Statamic\Contracts\Forms\Submission; +use Statamic\Data\ContainsData; use Statamic\Data\HasAugmentedInstance; use Statamic\Events\FormBlueprintFound; use Statamic\Events\FormCreated; @@ -25,7 +26,7 @@ class Form implements FormContract, Augmentable, Arrayable { - use FluentlyGetsAndSets, HasAugmentedInstance; + use ContainsData, FluentlyGetsAndSets, HasAugmentedInstance; protected $handle; protected $title; @@ -37,6 +38,11 @@ class Form implements FormContract, Augmentable, Arrayable protected $afterSaveCallbacks = []; protected $withEvents = true; + public function __construct() + { + $this->data = collect(); + } + /** * Get or set the handle. * @@ -178,7 +184,7 @@ public function save() } } - $data = collect([ + $data = $this->data->merge(collect([ 'title' => $this->title, 'honeypot' => $this->honeypot, 'email' => collect(isset($this->email['to']) ? [$this->email] : $this->email)->map(function ($email) { @@ -188,7 +194,7 @@ public function save() return Arr::removeNullValues($email); })->all(), 'metrics' => $this->metrics, - ])->filter()->all(); + ]))->filter()->all(); if ($this->store === false) { $data['store'] = false; @@ -228,14 +234,20 @@ public function delete() */ public function hydrate() { - collect(YAML::parse(File::get($this->path()))) - ->filter(function ($value, $property) { - return in_array($property, [ - 'title', - 'honeypot', - 'store', - 'email', - ]); + $contents = YAML::parse(File::get($this->path())); + + $methods = [ + 'title', + 'honeypot', + 'store', + 'email', + ]; + + $this->merge(collect($contents)->except($methods)); + + collect($contents) + ->filter(function ($value, $property) use ($methods) { + return in_array($property, $methods); }) ->each(function ($value, $property) { $this->{$property}($value); diff --git a/src/Forms/FormRepository.php b/src/Forms/FormRepository.php index 154c926fd1..f5eea326cf 100644 --- a/src/Forms/FormRepository.php +++ b/src/Forms/FormRepository.php @@ -7,9 +7,12 @@ use Statamic\Contracts\Forms\Submission as SubmissionContract; use Statamic\Facades\File; use Statamic\Facades\Folder; +use Statamic\Support\Arr; class FormRepository implements Contract { + private $configs = []; + /** * Find a form. * @@ -66,6 +69,25 @@ public function make($handle = null) return $form; } + public function addConfig($handles, array $fields) + { + $this->configs[] = [ + 'handles' => Arr::wrap($handles), + 'fields' => $fields, + ]; + } + + public function getConfigFor($handle) + { + return collect($this->configs) + ->filter(function ($config) use ($handle) { + return in_array('*', $config['handles']) || in_array($handle, $config['handles']); + }) + ->flatMap(fn ($config) => $config['fields']) + ->except(['name', 'fields', 'submission', 'email']) // cant use reserved words + ->all(); + } + public static function bindings(): array { return [ diff --git a/src/Http/Controllers/CP/Forms/FormsController.php b/src/Http/Controllers/CP/Forms/FormsController.php index c1156ce9c5..3293558e53 100644 --- a/src/Http/Controllers/CP/Forms/FormsController.php +++ b/src/Http/Controllers/CP/Forms/FormsController.php @@ -139,13 +139,13 @@ public function edit($form) { $this->authorize('edit', $form); - $values = [ + $values = array_merge($form->data()->all(), [ 'handle' => $form->handle(), 'title' => $form->title(), 'honeypot' => $form->honeypot(), 'store' => $form->store(), 'email' => $form->email(), - ]; + ]); $fields = ($blueprint = $this->editFormBlueprint($form)) ->fields() @@ -170,11 +170,14 @@ public function update($form, Request $request) $values = $fields->process()->values()->all(); + $data = collect($values)->except(['title', 'honeypot', 'store', 'email']); + $form ->title($values['title']) ->honeypot($values['honeypot']) ->store($values['store']) - ->email($values['email']); + ->email($values['email']) + ->merge($data); $form->save(); @@ -190,7 +193,7 @@ public function destroy($form) protected function editFormBlueprint($form) { - return Blueprint::makeFromTabs([ + $fields = array_merge([ 'name' => [ 'display' => __('Name'), 'fields' => [ @@ -312,6 +315,10 @@ protected function editFormBlueprint($form) ], // metrics - ]); + // ... + + ], Form::getConfigFor($form->handle())); + + return Blueprint::makeFromTabs($fields); } } From 40c5da878726b7f7b4a90d8f5401f05131d6ea7c Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 1 Aug 2023 07:08:18 +0100 Subject: [PATCH 02/19] Add some test coverage --- tests/Feature/Forms/UpdateFormTest.php | 38 ++++++++++++++ tests/Forms/FormRepositoryTest.php | 69 ++++++++++++++++++++++++++ tests/Forms/FormTest.php | 10 +++- 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 tests/Forms/FormRepositoryTest.php diff --git a/tests/Feature/Forms/UpdateFormTest.php b/tests/Feature/Forms/UpdateFormTest.php index d987f5a6be..120a96c4fa 100644 --- a/tests/Feature/Forms/UpdateFormTest.php +++ b/tests/Feature/Forms/UpdateFormTest.php @@ -107,6 +107,44 @@ public function it_updates_emails() ], $updated->email()); } + /** @test */ + public function it_updates_data() + { + $form = tap(Form::make('test'))->save(); + $this->assertNull($form->email()); + + Form::addConfig('*', [ + 'config' => [ + 'display' => __('config'), + 'fields' => [ + 'another_config' => [ + 'handle' => 'another_config', + 'field' => [ + 'type' => 'text', + ] + ], + 'some_config' => [ + 'handle' => 'some_config', + 'field' => [ + 'type' => 'text', + ] + ], + ], + ], + ]); + + $this + ->actingAs($this->userWithPermission()) + ->update($form, ['some_config' => 'foo', 'another_config' => 'bar']) + ->assertOk(); + + $updated = Form::all()->first(); + $this->assertEquals([ + 'another_config' => 'bar', + 'some_config' => 'foo', + ], $updated->data()->all()); + } + private function userWithoutPermission() { $this->setTestRoles(['test' => ['access cp']]); diff --git a/tests/Forms/FormRepositoryTest.php b/tests/Forms/FormRepositoryTest.php new file mode 100644 index 0000000000..ec97aceb7e --- /dev/null +++ b/tests/Forms/FormRepositoryTest.php @@ -0,0 +1,69 @@ + [ + 'display' => __('config'), + 'fields' => [ + 'another_config' => [ + 'handle' => 'another_config', + 'field' => [ + 'type' => 'text', + ] + ], + 'some_config' => [ + 'handle' => 'some_config', + 'field' => [ + 'type' => 'text', + ] + ], + ], + ], + ]); + + $this->assertNotNull(Form::getConfigFor('test_form')); + $this->assertEmpty(Form::getConfigFor('another_form')); + } + + /** @test */ + public function it_registers_wildcard_config() + { + Form::addConfig('*', [ + 'config' => [ + 'display' => __('config'), + 'fields' => [ + 'another_config' => [ + 'handle' => 'another_config', + 'field' => [ + 'type' => 'text', + ] + ], + 'some_config' => [ + 'handle' => 'some_config', + 'field' => [ + 'type' => 'text', + ] + ], + ], + ], + ]); + + $this->assertNotNull(Form::getConfigFor('test_form')); + $this->assertNotNull(Form::getConfigFor('another_form')); + } +} diff --git a/tests/Forms/FormTest.php b/tests/Forms/FormTest.php index b8eff5b2a4..bae7a4f516 100644 --- a/tests/Forms/FormTest.php +++ b/tests/Forms/FormTest.php @@ -29,13 +29,21 @@ public function it_saves_a_form() $form = Form::make('contact_us') ->title('Contact Us') - ->honeypot('winnie'); + ->honeypot('winnie') + ->data([ + 'foo' => 'bar', + 'roo' => 'rar', + ]); $form->save(); $this->assertEquals('contact_us', $form->handle()); $this->assertEquals('Contact Us', $form->title()); $this->assertEquals('winnie', $form->honeypot()); + $this->assertEquals([ + 'foo' => 'bar', + 'roo' => 'rar', + ], $form->data()->all()); Event::assertDispatched(FormSaving::class, function ($event) use ($form) { return $event->form === $form; From 1df616ed34218dcc74494425e08400e48f68b11d Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 1 Aug 2023 07:09:15 +0100 Subject: [PATCH 03/19] Remove un-needed use statements --- tests/Forms/FormRepositoryTest.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/Forms/FormRepositoryTest.php b/tests/Forms/FormRepositoryTest.php index ec97aceb7e..dde3c8d39a 100644 --- a/tests/Forms/FormRepositoryTest.php +++ b/tests/Forms/FormRepositoryTest.php @@ -2,13 +2,7 @@ namespace Tests\Forms; -use Illuminate\Contracts\Support\Arrayable; -use Illuminate\Support\Facades\Event; -use Statamic\Events\FormCreated; -use Statamic\Events\FormSaved; -use Statamic\Events\FormSaving; use Statamic\Facades\Form; -use Statamic\Fields\Blueprint; use Tests\TestCase; class FormRepositoryTest extends TestCase From 3ecdeec2076912f88bd7562e744af4416ae8856f Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 1 Aug 2023 07:11:31 +0100 Subject: [PATCH 04/19] :beer: --- tests/Feature/Forms/UpdateFormTest.php | 4 ++-- tests/Forms/FormRepositoryTest.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Feature/Forms/UpdateFormTest.php b/tests/Feature/Forms/UpdateFormTest.php index 120a96c4fa..5afe0d3e09 100644 --- a/tests/Feature/Forms/UpdateFormTest.php +++ b/tests/Feature/Forms/UpdateFormTest.php @@ -121,13 +121,13 @@ public function it_updates_data() 'handle' => 'another_config', 'field' => [ 'type' => 'text', - ] + ], ], 'some_config' => [ 'handle' => 'some_config', 'field' => [ 'type' => 'text', - ] + ], ], ], ], diff --git a/tests/Forms/FormRepositoryTest.php b/tests/Forms/FormRepositoryTest.php index dde3c8d39a..cc5148eb1e 100644 --- a/tests/Forms/FormRepositoryTest.php +++ b/tests/Forms/FormRepositoryTest.php @@ -18,13 +18,13 @@ public function it_registers_config() 'handle' => 'another_config', 'field' => [ 'type' => 'text', - ] + ], ], 'some_config' => [ 'handle' => 'some_config', 'field' => [ 'type' => 'text', - ] + ], ], ], ], @@ -45,13 +45,13 @@ public function it_registers_wildcard_config() 'handle' => 'another_config', 'field' => [ 'type' => 'text', - ] + ], ], 'some_config' => [ 'handle' => 'some_config', 'field' => [ 'type' => 'text', - ] + ], ], ], ], From 174f0b4556ee554232c8265c5ca14f29a624be72 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 1 Aug 2023 08:34:20 +0100 Subject: [PATCH 05/19] Change method signature to make it more intuitive --- src/Forms/FormRepository.php | 19 +++++++++-- tests/Forms/FormRepositoryTest.php | 54 ++++++++++++------------------ 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/src/Forms/FormRepository.php b/src/Forms/FormRepository.php index f5eea326cf..43b6022d52 100644 --- a/src/Forms/FormRepository.php +++ b/src/Forms/FormRepository.php @@ -8,6 +8,7 @@ use Statamic\Facades\File; use Statamic\Facades\Folder; use Statamic\Support\Arr; +use Statamic\Support\Str; class FormRepository implements Contract { @@ -69,9 +70,10 @@ public function make($handle = null) return $form; } - public function addConfig($handles, array $fields) + public function addConfig($handles, string $display, array $fields) { $this->configs[] = [ + 'display' => $display, 'handles' => Arr::wrap($handles), 'fields' => $fields, ]; @@ -79,12 +81,23 @@ public function addConfig($handles, array $fields) public function getConfigFor($handle) { + $reserved = ['name', 'fields', 'submission', 'email']; + return collect($this->configs) ->filter(function ($config) use ($handle) { return in_array('*', $config['handles']) || in_array($handle, $config['handles']); }) - ->flatMap(fn ($config) => $config['fields']) - ->except(['name', 'fields', 'submission', 'email']) // cant use reserved words + ->flatMap(function ($config) use ($reserved) { + + return [ + Str::slugify($config['display']) => [ + 'display' => $config['display'], + 'fields' => collect($config['fields']) + ->filter(fn ($field, $index) => ! in_array($field['handle'] ?? $index, $reserved)) + ->all(), + ], + ]; + }) ->all(); } diff --git a/tests/Forms/FormRepositoryTest.php b/tests/Forms/FormRepositoryTest.php index cc5148eb1e..eebc262a59 100644 --- a/tests/Forms/FormRepositoryTest.php +++ b/tests/Forms/FormRepositoryTest.php @@ -10,22 +10,17 @@ class FormRepositoryTest extends TestCase /** @test */ public function it_registers_config() { - Form::addConfig('test_form', [ - 'config' => [ - 'display' => __('config'), - 'fields' => [ - 'another_config' => [ - 'handle' => 'another_config', - 'field' => [ - 'type' => 'text', - ], - ], - 'some_config' => [ - 'handle' => 'some_config', - 'field' => [ - 'type' => 'text', - ], - ], + Form::addConfig('test_form', 'Test Config', [ + 'another_config' => [ + 'handle' => 'another_config', + 'field' => [ + 'type' => 'text', + ], + ], + 'some_config' => [ + 'handle' => 'some_config', + 'field' => [ + 'type' => 'text', ], ], ]); @@ -37,22 +32,17 @@ public function it_registers_config() /** @test */ public function it_registers_wildcard_config() { - Form::addConfig('*', [ - 'config' => [ - 'display' => __('config'), - 'fields' => [ - 'another_config' => [ - 'handle' => 'another_config', - 'field' => [ - 'type' => 'text', - ], - ], - 'some_config' => [ - 'handle' => 'some_config', - 'field' => [ - 'type' => 'text', - ], - ], + Form::addConfig('*', 'Test Config', [ + 'another_config' => [ + 'handle' => 'another_config', + 'field' => [ + 'type' => 'text', + ], + ], + 'some_config' => [ + 'handle' => 'some_config', + 'field' => [ + 'type' => 'text', ], ], ]); From 96171a7fd833166420414be362f12f55a4dc905c Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 1 Aug 2023 08:39:30 +0100 Subject: [PATCH 06/19] Missed this test update --- tests/Feature/Forms/UpdateFormTest.php | 27 +++++++++++--------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/tests/Feature/Forms/UpdateFormTest.php b/tests/Feature/Forms/UpdateFormTest.php index 5afe0d3e09..99e5c19de6 100644 --- a/tests/Feature/Forms/UpdateFormTest.php +++ b/tests/Feature/Forms/UpdateFormTest.php @@ -113,22 +113,17 @@ public function it_updates_data() $form = tap(Form::make('test'))->save(); $this->assertNull($form->email()); - Form::addConfig('*', [ - 'config' => [ - 'display' => __('config'), - 'fields' => [ - 'another_config' => [ - 'handle' => 'another_config', - 'field' => [ - 'type' => 'text', - ], - ], - 'some_config' => [ - 'handle' => 'some_config', - 'field' => [ - 'type' => 'text', - ], - ], + Form::addConfig('*', 'Test Config', [ + 'another_config' => [ + 'handle' => 'another_config', + 'field' => [ + 'type' => 'text', + ], + ], + 'some_config' => [ + 'handle' => 'some_config', + 'field' => [ + 'type' => 'text', ], ], ]); From 77a36f14457c42e61d7fd4c208f47979ea88ccb0 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 1 Aug 2023 08:39:33 +0100 Subject: [PATCH 07/19] Use the correct reserved words --- src/Forms/FormRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Forms/FormRepository.php b/src/Forms/FormRepository.php index 43b6022d52..58bf893ad8 100644 --- a/src/Forms/FormRepository.php +++ b/src/Forms/FormRepository.php @@ -81,7 +81,7 @@ public function addConfig($handles, string $display, array $fields) public function getConfigFor($handle) { - $reserved = ['name', 'fields', 'submission', 'email']; + $reserved = ['title', 'honeypot', 'store', 'email']; return collect($this->configs) ->filter(function ($config) use ($handle) { From ef2ce6b4727c9c674e7146e92450d2ca825622c7 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Wed, 20 Sep 2023 11:00:11 +0100 Subject: [PATCH 08/19] Change method name to appendConfigFields for consistency --- src/Forms/FormRepository.php | 2 +- tests/Feature/Forms/UpdateFormTest.php | 2 +- tests/Forms/FormRepositoryTest.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Forms/FormRepository.php b/src/Forms/FormRepository.php index 58bf893ad8..173267452a 100644 --- a/src/Forms/FormRepository.php +++ b/src/Forms/FormRepository.php @@ -70,7 +70,7 @@ public function make($handle = null) return $form; } - public function addConfig($handles, string $display, array $fields) + public function appendConfigFields($handles, string $display, array $fields) { $this->configs[] = [ 'display' => $display, diff --git a/tests/Feature/Forms/UpdateFormTest.php b/tests/Feature/Forms/UpdateFormTest.php index 99e5c19de6..a109f6cc77 100644 --- a/tests/Feature/Forms/UpdateFormTest.php +++ b/tests/Feature/Forms/UpdateFormTest.php @@ -113,7 +113,7 @@ public function it_updates_data() $form = tap(Form::make('test'))->save(); $this->assertNull($form->email()); - Form::addConfig('*', 'Test Config', [ + Form::appendConfigFields('*', 'Test Config', [ 'another_config' => [ 'handle' => 'another_config', 'field' => [ diff --git a/tests/Forms/FormRepositoryTest.php b/tests/Forms/FormRepositoryTest.php index eebc262a59..2b0a8eb15c 100644 --- a/tests/Forms/FormRepositoryTest.php +++ b/tests/Forms/FormRepositoryTest.php @@ -10,7 +10,7 @@ class FormRepositoryTest extends TestCase /** @test */ public function it_registers_config() { - Form::addConfig('test_form', 'Test Config', [ + Form::appendConfigFields('test_form', 'Test Config', [ 'another_config' => [ 'handle' => 'another_config', 'field' => [ @@ -32,7 +32,7 @@ public function it_registers_config() /** @test */ public function it_registers_wildcard_config() { - Form::addConfig('*', 'Test Config', [ + Form::appendConfigFields('*', 'Test Config', [ 'another_config' => [ 'handle' => 'another_config', 'field' => [ From 9d88f0aa743dda9091a5f013a329d7c724b87cc4 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Mon, 4 Dec 2023 18:04:18 +0000 Subject: [PATCH 09/19] Add ability to add to existing sections --- .../Controllers/CP/Forms/FormsController.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Http/Controllers/CP/Forms/FormsController.php b/src/Http/Controllers/CP/Forms/FormsController.php index 3293558e53..e015b7372f 100644 --- a/src/Http/Controllers/CP/Forms/FormsController.php +++ b/src/Http/Controllers/CP/Forms/FormsController.php @@ -10,6 +10,7 @@ use Statamic\Facades\Form; use Statamic\Facades\User; use Statamic\Http\Controllers\CP\CpController; +use Statamic\Support\Arr; use Statamic\Support\Str; class FormsController extends CpController @@ -193,7 +194,7 @@ public function destroy($form) protected function editFormBlueprint($form) { - $fields = array_merge([ + $fields = [ 'name' => [ 'display' => __('Name'), 'fields' => [ @@ -317,7 +318,21 @@ protected function editFormBlueprint($form) // metrics // ... - ], Form::getConfigFor($form->handle())); + ]; + + foreach (Form::getConfigFor($form->handle()) as $handle => $config) { + $merged = false; + foreach ($fields as $fieldHandle => $fieldConfig) { + if ($fieldConfig['display'] == $config['display']) { + $fields[$fieldHandle]['fields'] += $config['fields']; + $merged = true; + } + } + + if (! $merged) { + $fields[] = $config; + } + } return Blueprint::makeFromTabs($fields); } From 7933ff0fb255001dd2d8a5251941b1c4810cb10f Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Mon, 4 Dec 2023 18:06:50 +0000 Subject: [PATCH 10/19] :beer: --- src/Http/Controllers/CP/Forms/FormsController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Http/Controllers/CP/Forms/FormsController.php b/src/Http/Controllers/CP/Forms/FormsController.php index e015b7372f..1cbbf79334 100644 --- a/src/Http/Controllers/CP/Forms/FormsController.php +++ b/src/Http/Controllers/CP/Forms/FormsController.php @@ -10,7 +10,6 @@ use Statamic\Facades\Form; use Statamic\Facades\User; use Statamic\Http\Controllers\CP\CpController; -use Statamic\Support\Arr; use Statamic\Support\Str; class FormsController extends CpController From 29dcafa57cbe5d3d646cc226f822eedbfb01e755 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Fri, 10 May 2024 10:53:48 +0100 Subject: [PATCH 11/19] :beer: --- tests/Forms/FormRepositoryTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Forms/FormRepositoryTest.php b/tests/Forms/FormRepositoryTest.php index 8dc08aeba2..fb770f419c 100644 --- a/tests/Forms/FormRepositoryTest.php +++ b/tests/Forms/FormRepositoryTest.php @@ -42,7 +42,7 @@ public function test_find_or_fail_throws_exception_when_form_does_not_exist() $this->repo->findOrFail('does-not-exist'); } - + /** @test */ public function it_registers_config() { From 69e40b5024e69f0ba578073f98134dc55d0d1202 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Fri, 10 May 2024 10:59:06 +0100 Subject: [PATCH 12/19] Yep --- tests/Forms/FormRepositoryTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Forms/FormRepositoryTest.php b/tests/Forms/FormRepositoryTest.php index fb770f419c..f8db211459 100644 --- a/tests/Forms/FormRepositoryTest.php +++ b/tests/Forms/FormRepositoryTest.php @@ -61,8 +61,8 @@ public function it_registers_config() ], ]); - $this->assertNotNull(Form::getConfigFor('test_form')); - $this->assertEmpty(Form::getConfigFor('another_form')); + $this->assertNotNull(FormAPI::getConfigFor('test_form')); + $this->assertEmpty(FormAPI::getConfigFor('another_form')); } /** @test */ @@ -83,7 +83,7 @@ public function it_registers_wildcard_config() ], ]); - $this->assertNotNull(Form::getConfigFor('test_form')); - $this->assertNotNull(Form::getConfigFor('another_form')); + $this->assertNotNull(FormAPI::getConfigFor('test_form')); + $this->assertNotNull(FormAPI::getConfigFor('another_form')); } } From 9e64231b0a70e68446974118ae563a3d0ae09855 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 29 Jul 2024 19:08:31 -0400 Subject: [PATCH 13/19] Add test to assert fields can be added to existing sections --- tests/Feature/Forms/EditFormTest.php | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/Feature/Forms/EditFormTest.php b/tests/Feature/Forms/EditFormTest.php index 0721917a9c..db856a869e 100644 --- a/tests/Feature/Forms/EditFormTest.php +++ b/tests/Feature/Forms/EditFormTest.php @@ -49,4 +49,38 @@ public function it_denies_access_if_you_dont_have_permission() ->assertRedirect('/original') ->assertSessionHas('error'); } + + #[Test] + public function fields_can_be_added() + { + $this->setTestRoles(['test' => ['access cp', 'configure forms']]); + $user = User::make()->assignRole('test')->save(); + $form = tap(Form::make('test'))->save(); + + Form::appendConfigFields('*', 'Fields', [ + 'a' => ['type' => 'text', 'display' => 'First injected into fields section'], + 'b' => ['type' => 'text', 'display' => 'Second injected into fields section'], + ]); + Form::appendConfigFields('*', 'Additional Section', [ + 'c' => ['type' => 'text', 'display' => 'First injected into additional section'], + 'd' => ['type' => 'text', 'display' => 'Second injected into additional section'], + ]); + + $this + ->actingAs($user) + ->get(cp_route('forms.edit', $form->handle())) + ->assertSuccessful() + ->assertViewHas('form', $form) + ->assertSeeInOrder([ + 'Title', + 'Blueprint', + 'Honeypot', + 'First injected into fields section', + 'Second injected into fields section', + 'Store Submissions', + 'Additional Section', + 'First injected into additional section', + 'Second injected into additional section', + ]); + } } From af065a68264d17ae9764e2c587ac17ce62b69c11 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 29 Jul 2024 19:10:27 -0400 Subject: [PATCH 14/19] method name --- src/Forms/FormRepository.php | 2 +- src/Http/Controllers/CP/Forms/FormsController.php | 2 +- tests/Forms/FormRepositoryTest.php | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Forms/FormRepository.php b/src/Forms/FormRepository.php index 5ac75a347e..7452593946 100644 --- a/src/Forms/FormRepository.php +++ b/src/Forms/FormRepository.php @@ -94,7 +94,7 @@ public function appendConfigFields($handles, string $display, array $fields) ]; } - public function getConfigFor($handle) + public function extraConfigFor($handle) { $reserved = ['title', 'honeypot', 'store', 'email']; diff --git a/src/Http/Controllers/CP/Forms/FormsController.php b/src/Http/Controllers/CP/Forms/FormsController.php index 6af087d9de..6f69c00f74 100644 --- a/src/Http/Controllers/CP/Forms/FormsController.php +++ b/src/Http/Controllers/CP/Forms/FormsController.php @@ -356,7 +356,7 @@ protected function editFormBlueprint($form) ]; - foreach (Form::getConfigFor($form->handle()) as $handle => $config) { + foreach (Form::extraConfigFor($form->handle()) as $handle => $config) { $merged = false; foreach ($fields as $fieldHandle => $fieldConfig) { if ($fieldConfig['display'] == $config['display']) { diff --git a/tests/Forms/FormRepositoryTest.php b/tests/Forms/FormRepositoryTest.php index e1bb84d7b6..e21404bbe0 100644 --- a/tests/Forms/FormRepositoryTest.php +++ b/tests/Forms/FormRepositoryTest.php @@ -62,8 +62,8 @@ public function it_registers_config() ], ]); - $this->assertNotNull(FormAPI::getConfigFor('test_form')); - $this->assertEmpty(FormAPI::getConfigFor('another_form')); + $this->assertNotNull(FormAPI::extraConfigFor('test_form')); + $this->assertEmpty(FormAPI::extraConfigFor('another_form')); } /** @test */ @@ -84,7 +84,7 @@ public function it_registers_wildcard_config() ], ]); - $this->assertNotNull(FormAPI::getConfigFor('test_form')); - $this->assertNotNull(FormAPI::getConfigFor('another_form')); + $this->assertNotNull(FormAPI::extraConfigFor('test_form')); + $this->assertNotNull(FormAPI::extraConfigFor('another_form')); } } From 1ae9b25bcb60845fdd9b577a6620e3dde9a37df7 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 29 Jul 2024 19:10:52 -0400 Subject: [PATCH 15/19] my brain wasnt braining --- src/Http/Controllers/CP/Forms/FormsController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Http/Controllers/CP/Forms/FormsController.php b/src/Http/Controllers/CP/Forms/FormsController.php index 6f69c00f74..75c1457a5c 100644 --- a/src/Http/Controllers/CP/Forms/FormsController.php +++ b/src/Http/Controllers/CP/Forms/FormsController.php @@ -358,9 +358,9 @@ protected function editFormBlueprint($form) foreach (Form::extraConfigFor($form->handle()) as $handle => $config) { $merged = false; - foreach ($fields as $fieldHandle => $fieldConfig) { - if ($fieldConfig['display'] == $config['display']) { - $fields[$fieldHandle]['fields'] += $config['fields']; + foreach ($fields as $sectionHandle => $section) { + if ($section['display'] == $config['display']) { + $fields[$sectionHandle]['fields'] += $config['fields']; $merged = true; } } From 5e9898789aa79bdf6f74b3986ddff98dc88e428e Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 29 Jul 2024 19:11:47 -0400 Subject: [PATCH 16/19] use the property --- tests/Forms/FormRepositoryTest.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/Forms/FormRepositoryTest.php b/tests/Forms/FormRepositoryTest.php index e21404bbe0..a10555ca8c 100644 --- a/tests/Forms/FormRepositoryTest.php +++ b/tests/Forms/FormRepositoryTest.php @@ -5,7 +5,6 @@ use PHPUnit\Framework\Attributes\Test; use Statamic\Contracts\Forms\Form; use Statamic\Exceptions\FormNotFoundException; -use Statamic\Facades\Form as FormAPI; use Statamic\Forms\FormRepository; use Statamic\Stache\Stache; use Tests\TestCase; @@ -47,7 +46,7 @@ public function test_find_or_fail_throws_exception_when_form_does_not_exist() /** @test */ public function it_registers_config() { - FormAPI::appendConfigFields('test_form', 'Test Config', [ + $this->repo->appendConfigFields('test_form', 'Test Config', [ 'another_config' => [ 'handle' => 'another_config', 'field' => [ @@ -62,14 +61,14 @@ public function it_registers_config() ], ]); - $this->assertNotNull(FormAPI::extraConfigFor('test_form')); - $this->assertEmpty(FormAPI::extraConfigFor('another_form')); + $this->assertNotNull($this->repo->extraConfigFor('test_form')); + $this->assertEmpty($this->repo->extraConfigFor('another_form')); } /** @test */ public function it_registers_wildcard_config() { - FormAPI::appendConfigFields('*', 'Test Config', [ + $this->repo->appendConfigFields('*', 'Test Config', [ 'another_config' => [ 'handle' => 'another_config', 'field' => [ @@ -84,7 +83,7 @@ public function it_registers_wildcard_config() ], ]); - $this->assertNotNull(FormAPI::extraConfigFor('test_form')); - $this->assertNotNull(FormAPI::extraConfigFor('another_form')); + $this->assertNotNull($this->repo->extraConfigFor('test_form')); + $this->assertNotNull($this->repo->extraConfigFor('another_form')); } } From 7b25e505c0d26716fe24c008d8afd18324ca103c Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 29 Jul 2024 21:09:45 -0400 Subject: [PATCH 17/19] adjust test and use snake case --- src/Forms/FormRepository.php | 2 +- tests/Forms/FormRepositoryTest.php | 54 +++++++++++++----------------- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/src/Forms/FormRepository.php b/src/Forms/FormRepository.php index 7452593946..dbef859b5a 100644 --- a/src/Forms/FormRepository.php +++ b/src/Forms/FormRepository.php @@ -105,7 +105,7 @@ public function extraConfigFor($handle) ->flatMap(function ($config) use ($reserved) { return [ - Str::slugify($config['display']) => [ + Str::snake($config['display']) => [ 'display' => $config['display'], 'fields' => collect($config['fields']) ->filter(fn ($field, $index) => ! in_array($field['handle'] ?? $index, $reserved)) diff --git a/tests/Forms/FormRepositoryTest.php b/tests/Forms/FormRepositoryTest.php index a10555ca8c..3f3011ad0e 100644 --- a/tests/Forms/FormRepositoryTest.php +++ b/tests/Forms/FormRepositoryTest.php @@ -47,43 +47,37 @@ public function test_find_or_fail_throws_exception_when_form_does_not_exist() public function it_registers_config() { $this->repo->appendConfigFields('test_form', 'Test Config', [ - 'another_config' => [ - 'handle' => 'another_config', - 'field' => [ - 'type' => 'text', - ], - ], - 'some_config' => [ - 'handle' => 'some_config', - 'field' => [ - 'type' => 'text', - ], - ], + 'alfa' => ['type' => 'text'], + 'bravo' => ['type' => 'text'], ]); - $this->assertNotNull($this->repo->extraConfigFor('test_form')); - $this->assertEmpty($this->repo->extraConfigFor('another_form')); - } + $this->repo->appendConfigFields('*', 'This Goes Everywhere', [ + ['charlie' => ['type' => 'text']], + ]); - /** @test */ - public function it_registers_wildcard_config() - { - $this->repo->appendConfigFields('*', 'Test Config', [ - 'another_config' => [ - 'handle' => 'another_config', - 'field' => [ - 'type' => 'text', + $this->assertEquals([ + 'test_config' => [ + 'display' => 'Test Config', + 'fields' => [ + 'alfa' => ['type' => 'text'], + 'bravo' => ['type' => 'text'], ], ], - 'some_config' => [ - 'handle' => 'some_config', - 'field' => [ - 'type' => 'text', + 'this_goes_everywhere' => [ + 'display' => 'This Goes Everywhere', + 'fields' => [ + ['charlie' => ['type' => 'text']], ], ], - ]); + ], $this->repo->extraConfigFor('test_form')); - $this->assertNotNull($this->repo->extraConfigFor('test_form')); - $this->assertNotNull($this->repo->extraConfigFor('another_form')); + $this->assertEquals([ + 'this_goes_everywhere' => [ + 'display' => 'This Goes Everywhere', + 'fields' => [ + ['charlie' => ['type' => 'text']], + ], + ], + ], $this->repo->extraConfigFor('another_form')); } } From eb4dbbdecf3ec21c538ad07e47e34fb435b1596d Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 29 Jul 2024 21:19:30 -0400 Subject: [PATCH 18/19] key by handle, it doesnt really matter, but the rest of it is. --- src/Http/Controllers/CP/Forms/FormsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Controllers/CP/Forms/FormsController.php b/src/Http/Controllers/CP/Forms/FormsController.php index 75c1457a5c..73b2c65cfb 100644 --- a/src/Http/Controllers/CP/Forms/FormsController.php +++ b/src/Http/Controllers/CP/Forms/FormsController.php @@ -366,7 +366,7 @@ protected function editFormBlueprint($form) } if (! $merged) { - $fields[] = $config; + $fields[$handle] = $config; } } From 31c284148fab32b5c69bf084a06316b0360d9d2c Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 29 Jul 2024 21:22:40 -0400 Subject: [PATCH 19/19] add hints to facade --- src/Facades/Form.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Facades/Form.php b/src/Facades/Form.php index 9842ae975e..6bc7a1cf44 100644 --- a/src/Facades/Form.php +++ b/src/Facades/Form.php @@ -10,6 +10,8 @@ * @method static \Statamic\Contracts\Forms\Form findOrFail($handle) * @method static \Illuminate\Support\Collection all() * @method static \Statamic\Contracts\Forms\Form make($handle = null) + * @method static array extraConfigFor($handle) + * @method static void appendConfigFields($handle, $display, $fields) * * @see \Statamic\Contracts\Forms\FormRepository */