Files
crewli/api/app/Http/Requests/Api/V1/ReplacePersonSectionPreferencesRequest.php
bert.hausmans f6e3568011 feat: registration form fields, section preferences, tag sync & schema updates
Implement EAV system for dynamic event-specific registration fields
with organisation-level templates, person section preferences with
priority ranking, and TagSyncService for deferred tag_picker sync.

New tables: registration_field_templates, registration_form_fields,
person_field_values, person_section_preferences.
New columns: persons.remarks, events.registration_show_section_preferences,
events.registration_show_availability.

58 tests, 126 assertions — all 432 tests pass (zero regressions).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:10:16 +02:00

73 lines
2.4 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Requests\Api\V1;
use App\Models\FestivalSection;
use Illuminate\Foundation\Http\FormRequest;
final class ReplacePersonSectionPreferencesRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
/** @return array<string, mixed> */
public function rules(): array
{
return [
'preferences' => ['required', 'array', 'min:1', 'max:5'],
'preferences.*.festival_section_id' => ['required', 'ulid'],
'preferences.*.priority' => ['required', 'integer', 'min:1', 'max:5'],
];
}
public function withValidator($validator): void
{
$validator->after(function ($validator) {
$preferences = $this->input('preferences', []);
if (!is_array($preferences)) {
return;
}
// Priorities must be unique
$priorities = array_column($preferences, 'priority');
if (count($priorities) !== count(array_unique($priorities))) {
$validator->errors()->add('preferences', 'Priorities must be unique within the request.');
}
// Validate section IDs belong to the event
$event = $this->route('event');
$person = $this->route('person');
if (!$event || !$person) {
return;
}
// Valid sections: own event's sections + parent festival's cross_event sections
$validSectionIds = FestivalSection::where('event_id', $event->id)
->pluck('id');
if ($event->parent_event_id) {
$parentCrossEventSections = FestivalSection::where('event_id', $event->parent_event_id)
->where('type', 'cross_event')
->pluck('id');
$validSectionIds = $validSectionIds->merge($parentCrossEventSections);
}
foreach ($preferences as $index => $pref) {
$sectionId = $pref['festival_section_id'] ?? null;
if ($sectionId && !$validSectionIds->contains($sectionId)) {
$validator->errors()->add(
"preferences.{$index}.festival_section_id",
'Section does not belong to this event.'
);
}
}
});
}
}