Files
crewli/api/app/Http/Requests/Api/V1/FormBuilder/SubmitPublicSubmissionRequest.php
bert.hausmans 0cbdad70cd fix(api): accept submitter details on public draft PUT and submit POST
S3a PR 1 frontend sends public_submitter_name and public_submitter_email
on draft saves (PUT) and final submit (POST /submit), but the matching
SavePublicDraftRequest and SubmitPublicSubmissionRequest did not whitelist
these fields — Laravel's validated() silently stripped them, preventing
mid-form name/email updates from persisting.

Align both form requests with StartPublicDraftRequest to accept the same
submitter fields with identical rules (string, max:150 / email, max:255,
nullable). Controller copies present keys onto the submission model and
saves when dirty, matching standard Laravel update() semantics — missing
keys leave prior values untouched.

Closes the backend gap identified in PR 1 smoke test.
2026-04-23 16:36:31 +02:00

66 lines
1.8 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Requests\Api\V1\FormBuilder;
use App\Models\FormBuilder\FormSchema;
use App\Services\FormBuilder\FormFieldRuleBuilder;
use App\Services\FormBuilder\PublicFormTokenResolver;
use Illuminate\Foundation\Http\FormRequest;
/**
* Body for `POST /api/v1/public/forms/{public_token}/submissions/{id}/submit`.
*
* The FormRequest validates the request body in isolation using the
* *relaxed* rule set, because the controller merges the body with any
* values already saved via earlier PUT calls and runs the strict rule
* set on the merged value map before actually submitting.
*
* Upshot: a submit call with an empty body but all values auto-saved
* during drafting still passes at the request layer.
*/
final class SubmitPublicSubmissionRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
/**
* @return array<string, mixed>
*/
public function rules(): array
{
$base = [
'values' => ['sometimes', 'array'],
'captcha_token' => ['nullable', 'string', 'max:2000'],
'public_submitter_name' => ['nullable', 'string', 'max:150'],
'public_submitter_email' => ['nullable', 'email', 'max:255'],
];
$schema = $this->resolveSchema();
if (! $schema instanceof FormSchema) {
return $base;
}
return array_merge(
$base,
app(FormFieldRuleBuilder::class)->relaxed($schema),
);
}
private function resolveSchema(): ?FormSchema
{
$token = (string) $this->route('public_token');
if ($token === '') {
return null;
}
try {
return app(PublicFormTokenResolver::class)->resolve($token);
} catch (\Throwable) {
return null;
}
}
}