*/ public function rules(): array { return [ 'values' => ['required', 'array'], ]; } public function withValidator($validator): void { $validator->after(function ($validator) { $values = $this->input('values', []); $event = $this->route('event'); if (!$event || !is_array($values)) { return; } $fields = RegistrationFormField::where('event_id', $event->id) ->get() ->keyBy('slug'); $orgId = $event->organisation_id; foreach ($values as $slug => $value) { $field = $fields->get($slug); if ($field === null) { $validator->errors()->add("values.{$slug}", "Unknown field: {$slug}"); continue; } if ($field->is_required && ($value === null || $value === '' || $value === [])) { $validator->errors()->add("values.{$slug}", "The {$slug} field is required."); continue; } if ($value === null || $value === '') { continue; } match ($field->field_type) { RegistrationFieldType::TEXT, RegistrationFieldType::TEXTAREA => $this->validateString($validator, $slug, $value), RegistrationFieldType::NUMBER => $this->validateNumber($validator, $slug, $value), RegistrationFieldType::BOOLEAN => $this->validateBoolean($validator, $slug, $value), RegistrationFieldType::SELECT, RegistrationFieldType::RADIO => $this->validateSingleOption($validator, $slug, $value, $field), RegistrationFieldType::MULTISELECT, RegistrationFieldType::CHECKBOX => $this->validateMultiOption($validator, $slug, $value, $field), RegistrationFieldType::TAG_PICKER => $this->validateTagPicker($validator, $slug, $value, $orgId), }; } }); } private function validateString($validator, string $slug, mixed $value): void { if (!is_string($value) || mb_strlen($value) > 5000) { $validator->errors()->add("values.{$slug}", "Must be a string (max 5000 characters)."); } } private function validateNumber($validator, string $slug, mixed $value): void { if (!is_numeric($value)) { $validator->errors()->add("values.{$slug}", "Must be a number."); } } private function validateBoolean($validator, string $slug, mixed $value): void { if (!in_array($value, [true, false, 0, 1, '0', '1'], true)) { $validator->errors()->add("values.{$slug}", "Must be a boolean."); } } private function validateSingleOption($validator, string $slug, mixed $value, RegistrationFormField $field): void { if (!is_string($value) || !in_array($value, $field->options ?? [], true)) { $validator->errors()->add("values.{$slug}", "Must be one of the defined options."); } } private function validateMultiOption($validator, string $slug, mixed $value, RegistrationFormField $field): void { if (!is_array($value)) { $validator->errors()->add("values.{$slug}", "Must be an array."); return; } $options = $field->options ?? []; foreach ($value as $item) { if (!in_array($item, $options, true)) { $validator->errors()->add("values.{$slug}", "Invalid option: {$item}"); } } } private function validateTagPicker($validator, string $slug, mixed $value, string $orgId): void { if (!is_array($value)) { $validator->errors()->add("values.{$slug}", "Must be an array of tag IDs."); return; } $validTagIds = PersonTag::where('organisation_id', $orgId) ->where('is_active', true) ->pluck('id') ->all(); foreach ($value as $tagId) { if (!in_array($tagId, $validTagIds, true)) { $validator->errors()->add("values.{$slug}", "Invalid tag ID: {$tagId}"); } } } }