refactor(form-builder): strict validator on save; strip rules.unique fallback

This commit is contained in:
2026-04-24 22:26:44 +02:00
parent 800b1b6c01
commit 64ec4bcc5c
12 changed files with 469 additions and 29 deletions

View File

@@ -27,6 +27,10 @@ use App\Models\FormBuilder\FormSchema;
*/
final class FormFieldRuleBuilder
{
public function __construct(
private readonly FormFieldValidationRuleService $validationRuleService,
) {}
/**
* @return array<string, array<int, string>>
*/
@@ -180,26 +184,36 @@ final class FormFieldRuleBuilder
}
/**
* Shortcuts picked up from form_fields.validation_rules JSON.
* Shortcuts picked up from the relational validation-rules table.
* Service-layer FormValueService does the deeper min/max/regex/unique
* enforcement these are quick boundary checks surfaced at the
* Request layer when cheap.
*
* Laravel's `min:N` / `max:N` already do the right thing for both
* numeric inputs (value comparison) and strings (length check), so
* `min_length`/`min_value` both emit the same `min:N` rule.
*
* @return array<int, string>
*/
private function validationRuleShortcuts(FormField $field): array
{
$rules = [];
$v = $field->validation_rules ?? null;
$v = $this->validationRuleService->toJsonShape($field->validationRules);
if (! is_array($v)) {
return $rules;
}
if (isset($v['min']) && is_numeric($v['min'])) {
$rules[] = 'min:'.(string) $v['min'];
if (isset($v['min_value']) && is_numeric($v['min_value'])) {
$rules[] = 'min:'.(string) $v['min_value'];
}
if (isset($v['max']) && is_numeric($v['max'])) {
$rules[] = 'max:'.(string) $v['max'];
if (isset($v['max_value']) && is_numeric($v['max_value'])) {
$rules[] = 'max:'.(string) $v['max_value'];
}
if (isset($v['min_length']) && is_numeric($v['min_length'])) {
$rules[] = 'min:'.(string) $v['min_length'];
}
if (isset($v['max_length']) && is_numeric($v['max_length'])) {
$rules[] = 'max:'.(string) $v['max_length'];
}
if (isset($v['regex']) && is_string($v['regex'])) {
$rules[] = 'regex:'.$v['regex'];