> */ private array $entries = []; /** @var array */ private array $resourceIds = []; /** @var array */ private array $bundleMeta = []; /** @var array|null */ private ?array $composition = null; public function buildBundleMeta(string $identifierValue, string $timestamp): self { $this->bundleMeta = [ 'resourceType' => 'Bundle', 'identifier' => [ 'system' => 'https://hms.local/fhir/document', 'value' => $identifierValue, ], 'type' => 'document', 'timestamp' => $timestamp, ]; return $this; } /** * @param array $composition */ public function buildComposition(array $composition): self { $this->composition = $composition; return $this; } /** * @param array $resource */ public function addPatient(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addEncounter(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addPractitioner(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addOrganization(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addCondition(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addObservation(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addServiceRequest(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addAllergyIntolerance(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addCarePlan(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addDiagnosticReport(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addMedicationRequest(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addProcedure(array $resource): self { return $this->addResource($resource); } /** @param array $resource */ public function addClaim(array $resource): self { return $this->addResource($resource); } /** * @return array */ public function toBundle(): array { $bundle = $this->bundleMeta; $entries = []; if (is_array($this->composition)) { $entries[] = $this->wrapEntry($this->composition); } foreach ($this->entries as $entry) { $entries[] = $entry; } $bundle['entry'] = $entries; return $this->stripNulls($bundle); } /** * @param array $resource */ private function addResource(array $resource): self { $id = (string) ($resource['id'] ?? ''); if ($id === '') { $resource['id'] = $this->newId((string) ($resource['resourceType'] ?? 'resource')); $id = (string) $resource['id']; } $fullRef = (string) ($resource['resourceType'] ?? '') . '/' . $id; if (isset($this->resourceIds[$fullRef])) { return $this; } $this->resourceIds[$fullRef] = true; $this->entries[] = $this->wrapEntry($resource); return $this; } /** * @param array $resource * @return array */ private function wrapEntry(array $resource): array { $id = (string) ($resource['id'] ?? $this->newId((string) ($resource['resourceType'] ?? 'resource'))); $resource['id'] = $id; return [ 'fullUrl' => 'urn:uuid:' . $id, 'resource' => $this->stripNulls($resource), ]; } /** * @param array $data * @return array */ private function stripNulls(array $data): array { $out = []; foreach ($data as $key => $value) { if ($value === null || $value === '') { continue; } if (is_array($value)) { $clean = $this->stripNested($value); if ($clean === [] || $clean === null) { continue; } $out[$key] = $clean; continue; } $out[$key] = $value; } return $out; } /** * @param array $value * @return array|null */ private function stripNested(array $value): ?array { $clean = []; foreach ($value as $k => $v) { if ($v === null || $v === '') { continue; } if (is_array($v)) { $nested = $this->stripNested($v); if ($nested === null || $nested === []) { continue; } $clean[$k] = $nested; continue; } $clean[$k] = $v; } return $clean === [] ? null : $clean; } private function newId(string $prefix): string { $prefix = strtolower(preg_replace('/[^a-z0-9]/i', '-', $prefix) ?: 'resource'); $bytes = bin2hex(random_bytes(6)); return $prefix . '-' . $bytes; } }