> $rows * @return list> */ public function attach(User $actor, PeopleProcess $record, array $rows): array { if ($rows === [] || ! Schema::hasTable('candidate_triage') || ! Schema::hasTable('candidate_submissions')) { return $rows; } $current = User::query()->where('tenant_id', $record->tenant_id)->whereKey($actor->id)->first(); if ($current === null || ! app(CandidateTriage::class)->canRead($current, $record)) { return $rows; } $sources = DB::table('candidate_triage as t')->join('candidate_submissions as s', function (JoinClause $join) { $join->on('s.id', '=', 't.candidate_submission_id')->on('s.tenant_id', '=', 't.tenant_id')->on('s.people_process_id', '=', 't.people_process_id'); })->where('t.tenant_id', $record->tenant_id)->where('t.people_process_id', $record->id)->where('t.outcome', 'accepted_for_analysis') ->whereIn('t.people_application_id', array_column($rows, 'id')) ->get(['t.people_application_id', 't.profile_version', 's.id', 's.reference', 's.snapshot'])->keyBy('people_application_id'); return array_map(function (array $row) use ($sources) { $source = $sources->get($row['id']); if ($source === null) { return $row; } $snapshot = json_decode($source->snapshot, true, 32, JSON_THROW_ON_ERROR); $data = $snapshot['profile']['data'] ?? []; $main = $this->location($data['availability'] ?? null); if ($main === null || ($snapshot['profile']['version'] ?? null) !== $source->profile_version) { return $row; } $additional = []; $references = []; foreach ($data['additional_availability'] ?? [] as $index => $location) { $value = $this->location($location); if ($value !== null) { $additional[] = $value; $references[] = $this->reference($data['additional_availability_references'][$index] ?? null); } } return [...$row, 'received_availability' => ['submission_id' => $source->id, 'reference' => $source->reference, 'profile_version' => $source->profile_version, 'availability' => $main, 'additional_availability' => $additional, 'availability_reference' => $this->reference($data['availability_reference'] ?? null), 'additional_availability_references' => $references]]; }, $rows); } /** @return array{province:string,district:string,locality:string}|null */ private function location(mixed $value): ?array { if (! is_array($value) || ! is_string($value['province'] ?? null) || ! is_string($value['district'] ?? null) || ! is_string($value['locality'] ?? null) || trim($value['province']) === '' || trim($value['district']) === '' || trim($value['locality']) === '') { return null; } return ['province' => $value['province'], 'district' => $value['district'], 'locality' => $value['locality']]; } /** @return array{country:string,catalogue:string,record_id:string}|null */ private function reference(mixed $value): ?array { if (! is_array($value) || ($value['country'] ?? null) !== 'MZ' || ! is_string($value['catalogue'] ?? null) || ! preg_match('/^[a-f0-9]{64}$/D', $value['catalogue']) || ! is_string($value['record_id'] ?? null) || ! preg_match('/^[0-9]{1,20}$/D', $value['record_id'])) { return null; } return ['country' => 'MZ', 'catalogue' => $value['catalogue'], 'record_id' => $value['record_id']]; } }