From 9ddcd9e828c1f9d5879bf4092f67688710b86d75 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 23 Apr 2025 15:16:37 -0400 Subject: [PATCH 1/5] Add test coverage for `get`, `only`, and `except` param support. --- tests/Tags/Form/FormCreateTest.php | 60 ++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/Tags/Form/FormCreateTest.php b/tests/Tags/Form/FormCreateTest.php index 987c5f2c064..cc920f0da10 100644 --- a/tests/Tags/Form/FormCreateTest.php +++ b/tests/Tags/Form/FormCreateTest.php @@ -260,6 +260,66 @@ public function it_dynamically_renders_fields_using_legacy_array() $this->assertEquals(['Full Name', 'Email Address', 'Message'], $fieldOrder[1]); } + #[Test] + public function it_dynamically_renders_specific_fields_using_params() + { + $this->createForm([ + 'tabs' => [ + 'main' => [ + 'sections' => [ + [ + 'display' => 'Section One', + 'fields' => [ + ['handle' => 'first_name', 'field' => ['type' => 'text']], + ['handle' => 'middle_name', 'field' => ['type' => 'text', 'display' => 'Middle Name']], + ['handle' => 'last_name', 'field' => ['type' => 'text', 'display' => 'Last Name']], + [ + 'handle' => 'group_one', + 'field' => [ + 'type' => 'group', + 'display' => 'Group One', + 'fields' => [ + ['handle' => 'nested_one', 'field' => ['type' => 'text', 'display' => 'Nested One']], + ['handle' => 'nested_two', 'field' => ['type' => 'text', 'display' => 'Nested Two']], + ], + ], + ], + [ + 'handle' => 'group_two', + 'field' => [ + 'type' => 'group', + 'display' => 'Group Two', + 'fields' => [ + ['handle' => 'nested_three', 'field' => ['type' => 'text', 'display' => 'Nested One']], + ['handle' => 'nested_four', 'field' => ['type' => 'text', 'display' => 'Nested Two']], + ], + ], + ], + ], + ], + ], + ], + ], + ], 'survey'); + + $output = $this->normalizeHtml($this->tag(<<<'EOT' +{{ form:survey }} +
{{ form:fields get="middle_name" }}{{ handle }},{{ /form:fields }}
+
{{ form:fields get="group_one" }}{{ handle }},{{ /form:fields }}
+
{{ form:fields get="group_one.nested_two" }}{{ handle }},{{ /form:fields }}
+
{{ form:fields only="middle_name|group_one" }}{{ handle }},{{ /form:fields }}
+
{{ form:fields except="middle_name|group_one" }}{{ handle }},{{ /form:fields }}
+{{ /form:survey }} +EOT + )); + + $this->assertStringContainsString('
middle_name,
', $output); + $this->assertStringContainsString('
group_one,
', $output); + $this->assertStringContainsString('
group_one.nested_two,
', $output); + $this->assertStringContainsString('
middle_name,group_one,
', $output); + $this->assertStringContainsString('
first_name,last_name,group_two,
', $output); + } + #[Test] public function it_dynamically_renders_fields_with_form_handle() { From 8b13954756e47290e827ca0f592b442719e525cf Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 23 Apr 2025 15:16:53 -0400 Subject: [PATCH 2/5] Implement params. --- src/Forms/Tags.php | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Forms/Tags.php b/src/Forms/Tags.php index 83bf34f3b52..6fae3ba2d2e 100644 --- a/src/Forms/Tags.php +++ b/src/Forms/Tags.php @@ -4,6 +4,7 @@ use DebugBar\DataCollector\ConfigCollector; use DebugBar\DebugBarException; +use Illuminate\Support\Collection; use Statamic\Contracts\Forms\Form as FormContract; use Statamic\Facades\Antlers; use Statamic\Facades\Blink; @@ -171,7 +172,19 @@ public function fields() $params = Html::attributes(['scope' => $scope]); } - return Antlers::parse('{{ fields '.$params.' }}'.$this->content.'{{ /fields }}', $this->context->all()); + $context = $this->context->all(); + + $fields = Arr::get($context, 'fields', []); + + if ($handle = $this->params->get('get')) { + $context['fields'] = $this->dottedContextFields($fields, recursive: true)->only($handle)->values()->all(); + } elseif ($only = $this->params->get('only')) { + $context['fields'] = $this->dottedContextFields($fields, recursive: false)->only(explode('|', $only))->values()->all(); + } elseif ($except = $this->params->get('except')) { + $context['fields'] = $this->dottedContextFields($fields, recursive: false)->except(explode('|', $except))->values()->all(); + } + + return Antlers::parse('{{ fields '.$params.' }}'.$this->content.'{{ /fields }}', $context); } /** @@ -427,4 +440,17 @@ public function eventUrl($url, $relative = true) config('statamic.routes.action').'/form/'.$url ); } + + private function dottedContextFields(array $fields, $recursive = false, array &$dotted = []): Collection + { + foreach ($fields as $field) { + $dotted[$field['handle']] = $field; + + if ($recursive && $fields = Arr::get($field, 'fields')) { + $this->dottedContextFields($fields, $recursive, $dotted); + } + } + + return collect($dotted); + } } From 6d4e5042fab4caa4f54c837eeff90817a6c9ed41 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 23 Apr 2025 15:24:50 -0400 Subject: [PATCH 3/5] These are implicit anyway. --- src/Forms/Tags.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Forms/Tags.php b/src/Forms/Tags.php index 6fae3ba2d2e..86f4be109d6 100644 --- a/src/Forms/Tags.php +++ b/src/Forms/Tags.php @@ -179,9 +179,9 @@ public function fields() if ($handle = $this->params->get('get')) { $context['fields'] = $this->dottedContextFields($fields, recursive: true)->only($handle)->values()->all(); } elseif ($only = $this->params->get('only')) { - $context['fields'] = $this->dottedContextFields($fields, recursive: false)->only(explode('|', $only))->values()->all(); + $context['fields'] = $this->dottedContextFields($fields)->only(explode('|', $only))->values()->all(); } elseif ($except = $this->params->get('except')) { - $context['fields'] = $this->dottedContextFields($fields, recursive: false)->except(explode('|', $except))->values()->all(); + $context['fields'] = $this->dottedContextFields($fields)->except(explode('|', $except))->values()->all(); } return Antlers::parse('{{ fields '.$params.' }}'.$this->content.'{{ /fields }}', $context); From a87a63032af5dfdcca6c253ca3ecae1b59f321b2 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 23 Apr 2025 15:41:19 -0400 Subject: [PATCH 4/5] Simplify. This is already defined above. --- src/Tags/Concerns/RendersForms.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tags/Concerns/RendersForms.php b/src/Tags/Concerns/RendersForms.php index f7809e616ff..91242bd6ef5 100644 --- a/src/Tags/Concerns/RendersForms.php +++ b/src/Tags/Concerns/RendersForms.php @@ -150,7 +150,7 @@ protected function getRenderableField($field, $errorBag = 'default', $manipulate 'id' => $this->generateFieldId($field->handle(), $formHandle), 'instructions' => $field->instructions(), 'error' => $errors->first($field->handle()) ?: null, - 'default' => $field->value() ?? $field->defaultValue(), + 'default' => $default, 'old' => old($field->handle()), 'value' => $value, ], $field->fieldtype()->extraRenderableFieldData()); From 04564d8224c73c3543f9a45db5bdd82b5f870dff Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 23 Apr 2025 17:05:57 -0400 Subject: [PATCH 5/5] Make sure `` gets same context. --- src/Forms/Tags.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Forms/Tags.php b/src/Forms/Tags.php index 86f4be109d6..a5f98d47e8b 100644 --- a/src/Forms/Tags.php +++ b/src/Forms/Tags.php @@ -162,16 +162,6 @@ public function fields() collect($this->context['fields']) ->each(fn ($field) => $field['field']->slot($slot)); - if ($isBlade) { - return $this->tagRenderer->render('@foreach($fields as $field)'.$this->content.'@endforeach', $this->context->all()); - } - - $params = ''; - - if ($scope) { - $params = Html::attributes(['scope' => $scope]); - } - $context = $this->context->all(); $fields = Arr::get($context, 'fields', []); @@ -184,6 +174,16 @@ public function fields() $context['fields'] = $this->dottedContextFields($fields)->except(explode('|', $except))->values()->all(); } + if ($isBlade) { + return $this->tagRenderer->render('@foreach($fields as $field)'.$this->content.'@endforeach', $context); + } + + $params = ''; + + if ($scope) { + $params = Html::attributes(['scope' => $scope]); + } + return Antlers::parse('{{ fields '.$params.' }}'.$this->content.'{{ /fields }}', $context); }