}> $items * @return array{items: list}>, duplicates: int} */ public function deduplicate(array $items): array { $uniqueItems = []; $duplicates = 0; foreach ($items as $item) { $key = trim((string) ($item['subject_type'] ?? '')).'|'.trim((string) ($item['subject_external_id'] ?? '')); if ($key === '|') { continue; } if (! array_key_exists($key, $uniqueItems)) { $uniqueItems[$key] = $item; continue; } $duplicates++; if ($this->shouldReplace($uniqueItems[$key], $item)) { $uniqueItems[$key] = $item; } } return [ 'items' => array_values($uniqueItems), 'duplicates' => $duplicates, ]; } /** * @param array{meta_jsonb?: array, baseline_hash?: string} $current * @param array{meta_jsonb?: array, baseline_hash?: string} $candidate */ private function shouldReplace(array $current, array $candidate): bool { $currentFidelity = $this->fidelityRank($current); $candidateFidelity = $this->fidelityRank($candidate); if ($candidateFidelity !== $currentFidelity) { return $candidateFidelity > $currentFidelity; } $currentObservedAt = $this->observedAt($current); $candidateObservedAt = $this->observedAt($candidate); if ($candidateObservedAt !== $currentObservedAt) { return $candidateObservedAt > $currentObservedAt; } return strcmp((string) ($candidate['baseline_hash'] ?? ''), (string) ($current['baseline_hash'] ?? '')) > 0; } /** * @param array{meta_jsonb?: array} $item */ private function fidelityRank(array $item): int { $fidelity = data_get($item, 'meta_jsonb.evidence.fidelity'); return match ($fidelity) { 'content' => 2, 'meta' => 1, default => 0, }; } /** * @param array{meta_jsonb?: array} $item */ private function observedAt(array $item): string { $observedAt = data_get($item, 'meta_jsonb.evidence.observed_at'); return is_string($observedAt) ? $observedAt : ''; } }