Skip to content

Commit 1ca1182

Browse files
committed
Add new PreparesForValidation system to properly handle AutocompleteListFormatter validation errors
1 parent 420443f commit 1ca1182

6 files changed

Lines changed: 110 additions & 5 deletions

File tree

src/Form/Fields/Embeds/SharpFormEditorEmbed.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Code16\Sharp\Utils\Traits\HandleValidation;
1717
use Code16\Sharp\Utils\Transformers\WithCustomTransformers;
1818
use Illuminate\Support\Facades\Blade;
19+
use Illuminate\Support\Facades\Validator;
1920
use Illuminate\Support\HtmlString;
2021
use Illuminate\Support\Str;
2122
use Illuminate\View\View;
@@ -49,15 +50,15 @@ public function toConfigArray(bool $isForm): array
4950
'embedHeaderTitle' => $this->embedHeaderTitle ?: $this->label,
5051
];
5152

52-
$this->validate($config, [
53+
Validator::make($config, [
5354
'key' => ['required'],
5455
'label' => ['required'],
5556
'tag' => ['required', 'regex:/^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$/'],
5657
'attributes' => ['array'],
5758
], [
5859
'attributes.required' => 'Your Embed should at least have one form field',
5960
'tag.regex' => 'the tag name should only contain letters, figures and carets',
60-
]);
61+
])->validate();
6162

6263
return $config;
6364
}

src/Form/Fields/Formatters/AutocompleteListFormatter.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
namespace Code16\Sharp\Form\Fields\Formatters;
44

5+
use Code16\Sharp\Form\Fields\SharpFormAutocompleteListField;
56
use Code16\Sharp\Form\Fields\SharpFormField;
67

7-
class AutocompleteListFormatter extends SharpFieldFormatter
8+
class AutocompleteListFormatter extends SharpFieldFormatter implements PreparesForValidation
89
{
910
public function toFront(SharpFormField $field, $value)
1011
{
@@ -31,7 +32,9 @@ public function fromFront(SharpFormField $field, string $attribute, $value): arr
3132
$item = $item[$autocompleteField->key()] ?? null;
3233

3334
if ($item === null) {
34-
return null;
35+
return [
36+
$autocompleteField->itemIdAttribute() => null,
37+
];
3538
}
3639

3740
return [
@@ -40,7 +43,20 @@ public function fromFront(SharpFormField $field, string $attribute, $value): arr
4043
),
4144
];
4245
})
43-
->whereNotNull()
46+
->all();
47+
}
48+
49+
/**
50+
* @param SharpFormAutocompleteListField $field
51+
*/
52+
public function prepareForValidation(SharpFormField $field, string $key, $value): array
53+
{
54+
$autocompleteField = $field->autocompleteField();
55+
56+
return collect($value)
57+
->map(fn ($item) => [
58+
$autocompleteField->key() => $item[$autocompleteField->itemIdAttribute()],
59+
])
4460
->all();
4561
}
4662
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Code16\Sharp\Form\Fields\Formatters;
4+
5+
use Code16\Sharp\Form\Fields\SharpFormField;
6+
7+
interface PreparesForValidation
8+
{
9+
public function prepareForValidation(SharpFormField $field, string $key, $value): array;
10+
}

src/Utils/Traits/HandleValidation.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Code16\Sharp\Utils\Traits;
44

5+
use Code16\Sharp\Form\Fields\Formatters\PreparesForValidation;
56
use Illuminate\Contracts\Validation\Factory as Validator;
67
use Illuminate\Http\JsonResponse;
78
use Illuminate\Validation\ValidationException;
@@ -10,6 +11,22 @@ trait HandleValidation
1011
{
1112
final public function validate(array $params, array $rules, array $messages = []): void
1213
{
14+
$params = collect($params)
15+
->map(function ($value, $key) {
16+
if (! $field = $this->findFieldByKey($key)) {
17+
return $value;
18+
}
19+
20+
if ($field->formatter() instanceof PreparesForValidation) {
21+
return $field
22+
->formatter()
23+
->prepareForValidation($field, $key, $value);
24+
}
25+
26+
return $value;
27+
})
28+
->all();
29+
1330
$validator = app(Validator::class)->make($params, $rules, $messages);
1431

1532
if ($validator->fails()) {

tests/Http/Form/FormControllerTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
use Code16\Sharp\Enums\PageAlertLevel;
44
use Code16\Sharp\Exceptions\Form\SharpApplicativeException;
55
use Code16\Sharp\Exceptions\Form\SharpFormUpdateException;
6+
use Code16\Sharp\Form\Fields\SharpFormAutocompleteListField;
7+
use Code16\Sharp\Form\Fields\SharpFormAutocompleteLocalField;
68
use Code16\Sharp\Form\Fields\SharpFormCheckField;
79
use Code16\Sharp\Form\Fields\SharpFormEditorField;
810
use Code16\Sharp\Form\Fields\SharpFormTextField;
@@ -307,6 +309,40 @@ public function update($id, array $data)
307309
->assertSessionHasErrors('name');
308310
});
309311

312+
it('calls prepareForValidation() before validation on applicable fields', function () {
313+
fakeFormFor('person', new class() extends PersonForm
314+
{
315+
public function buildFormFields(FieldsContainer $formFields): void
316+
{
317+
$formFields->addField(
318+
SharpFormAutocompleteListField::make('jobs')
319+
->setItemField(
320+
SharpFormAutocompleteLocalField::make('job')
321+
->setLocalValues([
322+
1 => 'Physicist',
323+
2 => 'Chemist',
324+
])
325+
)
326+
);
327+
}
328+
329+
public function update($id, array $data)
330+
{
331+
$this->validate($data, ['jobs.*.job' => 'required']);
332+
}
333+
});
334+
335+
$this
336+
->post('/sharp/s-list/person/s-form/person', [
337+
'jobs' => [
338+
['id' => null, 'job' => ['id' => 1, 'label' => 'Physicist']],
339+
['id' => null],
340+
],
341+
])
342+
->assertSessionDoesntHaveErrors('jobs.0.job')
343+
->assertSessionHasErrors('jobs.1.job');
344+
});
345+
310346
it('handles application exception as 417', function () {
311347
fakeFormFor('person', new class() extends PersonForm
312348
{

tests/Unit/Form/Fields/Formatters/AutocompleteListFormatterTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,30 @@
6868
)->toBe([
6969
['id' => 'A'],
7070
['id' => 'B'],
71+
['id' => null],
72+
['id' => null],
73+
['id' => null],
74+
['id' => null],
75+
]);
76+
});
77+
78+
it('formats data in prepareForValidation()', function () {
79+
$formatter = new AutocompleteListFormatter();
80+
$field = SharpFormAutocompleteListField::make('list')
81+
->setItemField(SharpFormAutocompleteRemoteField::make('item')
82+
->setRemoteEndpoint('/endpoint'),
83+
);
84+
85+
expect(
86+
$formatter->prepareForValidation(
87+
$field,
88+
'attribute', [
89+
['id' => 'A'],
90+
['id' => 'B'],
91+
]
92+
)
93+
)->toBe([
94+
['item' => 'A'],
95+
['item' => 'B'],
7196
]);
7297
});

0 commit comments

Comments
 (0)