*/ public function toArray(Request $request): array { $this->resource->loadMissing(['schema', 'values.field']); $values = []; foreach ($this->values as $value) { $slug = $value->field?->slug; if ($slug === null) { continue; } $values[$slug] = [ 'value' => $value->value, 'value_anonymised' => (bool) $value->value_anonymised, ]; } $status = $this->status instanceof \BackedEnum ? $this->status->value : $this->status; $schemaDrift = $this->computeSchemaDrift(); $identityMatch = $this->formatIdentityMatch(); return [ 'id' => $this->id, 'form_schema_id' => $this->form_schema_id, 'status' => $status, 'auto_save_count' => (int) $this->auto_save_count, 'submitted_in_locale' => $this->submitted_in_locale, 'schema_version_at_submit' => $this->schema_version_at_submit, 'schema_drift' => $schemaDrift, 'values' => $values, 'identity_match' => $identityMatch, 'opened_at' => optional($this->opened_at)->toIso8601String(), 'first_interacted_at' => optional($this->first_interacted_at)->toIso8601String(), 'submitted_at' => optional($this->submitted_at)->toIso8601String(), 'submission_duration_seconds' => $this->submission_duration_seconds, 'created_at' => optional($this->created_at)->toIso8601String(), 'updated_at' => optional($this->updated_at)->toIso8601String(), ]; } private function computeSchemaDrift(): bool { // The draft was opened against version_at_open; at submit time the // schema's current version is frozen into version_at_submit. Drift // means the organiser edited the schema between the portal loading // the form and the user hitting submit. // // Drafts without a submit stamp keep the comparison live against // the current schema.version so an organiser edit during an open // draft also surfaces drift on subsequent PUT/GET calls. $atOpen = $this->schema_version_at_open; if ($atOpen === null) { return false; } $other = $this->schema_version_at_submit; if ($other === null) { $schema = $this->schema; if ($schema === null) { return false; } $other = (int) $schema->version; } return (int) $atOpen !== (int) $other; } /** * Identity-match signal per ARCH ยง31.1. Populated by the * TriggerPersonIdentityMatchOnFormSubmit listener on * FormSubmissionSubmitted. Read from the dedicated * form_submissions.identity_match_status column. * * @return array|null */ private function formatIdentityMatch(): ?array { $raw = $this->identity_match_status; if ($raw === null || $raw === '') { return null; } $status = $raw instanceof \BackedEnum ? $raw->value : (string) $raw; return [ 'status' => $status, 'message' => match ($status) { 'pending' => 'We controleren of je al bekend bent bij de organisator. Je gegevens worden gekoppeld zodra zij dit bevestigen.', 'matched' => 'Je account is gekoppeld aan een bekende deelnemer.', 'none' => 'Geen bestaand account gevonden โ€” je wordt als nieuwe deelnemer geregistreerd.', default => '', }, ]; } }