false, 'error' => 'Head of household verification required.']); exit; } } /** * @param mixed $raw * @return array> */ function normalizePeopleList($raw): array { if (!is_array($raw) || !array_is_list($raw)) { return []; } $out = []; foreach ($raw as $row) { if (is_array($row) && !empty($row['id']) && is_string($row['id'])) { $out[] = $row; } } return $out; } /** * @param array $person * @return array */ function migrateLegacyPersonRow(array $person): array { if (!array_key_exists('nfc_submit_token_hash', $person) || !is_string($person['nfc_submit_token_hash'])) { $person['nfc_submit_token_hash'] = ''; } if (!array_key_exists('nfc_submit_token_updated_at', $person) || !is_string($person['nfc_submit_token_updated_at'])) { $person['nfc_submit_token_updated_at'] = ''; } return $person; } /** * @param array> $people * @return array> */ function migrateAllPeople(array $people): array { $out = []; foreach ($people as $person) { if (!is_array($person)) { continue; } $out[] = migrateLegacyPersonRow($person); } return $out; } /** * @param array> $people * @return array{index:int, person:array}|null */ function findPersonBySubmitToken(array $people, string $token): ?array { $token = trim($token); if ($token === '') { return null; } $candidateHash = hash('sha256', $token); foreach ($people as $index => $person) { $storedHash = trim((string) ($person['nfc_submit_token_hash'] ?? '')); if ($storedHash === '') { continue; } if (hash_equals($storedHash, $candidateHash)) { return ['index' => (int) $index, 'person' => $person]; } } return null; }