-
Notifications
You must be signed in to change notification settings - Fork 0
Implement optimized $populate operation with modular design
#95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
85d5ebc
feat(sdc): implement `$populate` operation foundation
Ardenexal df3954c
feat(sdc): extend `$populate` with variable resolution, context-based…
Ardenexal d296657
feat(sdc): enhance `observationLinkPeriod` handling with unmappable D…
Ardenexal b5b9d33
docs(sdc): update `$populate` docs and tests to reflect expanded capa…
Ardenexal e79f296
feat(sdc): centralize primitive handling and answer coercion logic
Ardenexal 7213d07
refactor(sdc): extract `ObservationSelector` for modular observation-…
Ardenexal a6ca9a1
refactor(sdc): encapsulate QR item/response reads with `Questionnaire…
Ardenexal 877c3f3
refactor(sdc): modularize `DefinitionExtractionWalker` item processin…
Ardenexal 4aff110
`refactor(sdc): moved internal classes to sub folders
Ardenexal 5ce5069
`refactor(sdc): remove unused classes and legacy `Sdc` implementation…
Ardenexal 863a509
`fix(fhir): correct match default case to increment primitiveType count`
Ardenexal 1a5d8ee
`feat(sdc): enforce subject-scoped selection for observation-based po…
Ardenexal 1136e0d
`fix(sdc): ensure timezone consistency and prevent race conditions in…
Ardenexal File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Ardenexal\FHIRTools\Component\Sdc; | ||
|
|
||
| use Ardenexal\FHIRTools\Component\Sdc\Contract\PopulationDataProviderInterface; | ||
|
|
||
| /** | ||
| * In-memory {@see PopulationDataProviderInterface} backed by a pre-fetched FHIR `Bundle`. | ||
| * | ||
| * The caller supplies a `Bundle` (a `searchset`/`collection` of the resources relevant to population); | ||
| * this provider surfaces its `Observation` entries. Reads are tolerant of deserializer-origin objects | ||
| * (uninitialized typed properties read via `isset`), so a Bundle straight from the serializer is safe. | ||
| */ | ||
| final class BundlePopulationDataProvider implements PopulationDataProviderInterface | ||
| { | ||
| /** | ||
| * @param object $bundle a pre-fetched FHIR `Bundle` (any version) whose entries hold the resources | ||
| * relevant to population; only its `Observation` entries are surfaced | ||
| */ | ||
| public function __construct( | ||
| private readonly object $bundle, | ||
| ) { | ||
| } | ||
|
|
||
| /** | ||
| * Every `Observation` resource found among the Bundle's entries (deserializer-origin objects tolerated), | ||
| * in entry order. Returns an empty list when the Bundle has no entries or none are Observations. | ||
| * | ||
| * @return list<object> | ||
| */ | ||
| public function observations(): array | ||
| { | ||
| $entries = $this->bundle->entry ?? null; | ||
| if (!\is_array($entries)) { | ||
| return []; | ||
| } | ||
|
|
||
| $observations = []; | ||
| foreach ($entries as $entry) { | ||
| if (!\is_object($entry)) { | ||
| continue; | ||
| } | ||
|
|
||
| $resource = $entry->resource ?? null; | ||
| if (\is_object($resource) && $this->isObservation($resource)) { | ||
| $observations[] = $resource; | ||
| } | ||
| } | ||
|
|
||
| return $observations; | ||
| } | ||
|
|
||
| /** | ||
| * Whether a resource object is an `Observation`, by class basename (version-agnostic — matches | ||
| * `Models\R4\...\ObservationResource`, R4B, R5) rather than a hardcoded FQCN. | ||
| */ | ||
| private function isObservation(object $resource): bool | ||
| { | ||
| $class = $resource::class; | ||
| $short = ($pos = strrpos($class, '\\')) !== false ? substr($class, $pos + 1) : $class; | ||
|
|
||
| return $short === 'ObservationResource' || $short === 'Observation'; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
src/Component/Sdc/src/Contract/PopulateServiceInterface.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Ardenexal\FHIRTools\Component\Sdc\Contract; | ||
|
|
||
| use Ardenexal\FHIRTools\Component\Sdc\PopulateContext; | ||
| use Ardenexal\FHIRTools\Component\Sdc\PopulateResult; | ||
|
|
||
| /** | ||
| * Generates a pre-filled `QuestionnaireResponse` from a `Questionnaire` plus contextual data, per the | ||
| * SDC `$populate` operation. | ||
| * | ||
| * The Questionnaire is typed as `object` (not a version-specific class) so a single interface spans | ||
| * R4/R4B/R5 — implementations narrow to {@see PopulateContext::$fhirVersion}. This mirrors the | ||
| * version-agnostic signature the toolkit's validator and `$extract` service already use. | ||
| */ | ||
| interface PopulateServiceInterface | ||
| { | ||
| /** | ||
| * Populate a QuestionnaireResponse from a Questionnaire and its launch context. | ||
| * | ||
| * @param object|string $questionnaire a version-specific Questionnaire model carrying the SDC | ||
| * population directives (`launchContext`, `initialExpression`), OR | ||
| * a canonical URL string resolved via a configured | ||
| * `FHIRQuestionnaireResolverInterface` | ||
| * @param PopulateContext $context target version + launch-context resources + subject | ||
| * | ||
| * @return PopulateResult the generated QuestionnaireResponse plus any informational/warning issues | ||
| */ | ||
| public function populate(object|string $questionnaire, PopulateContext $context): PopulateResult; | ||
| } |
33 changes: 33 additions & 0 deletions
33
src/Component/Sdc/src/Contract/PopulationDataProviderInterface.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Ardenexal\FHIRTools\Component\Sdc\Contract; | ||
|
|
||
| use Ardenexal\FHIRTools\Component\Sdc\FHIRQuestionnairePopulateService; | ||
| use Ardenexal\FHIRTools\Component\Sdc\PopulateContext; | ||
|
|
||
| /** | ||
| * Supplies the candidate resources observation-based population draws on. | ||
| * | ||
| * This is the named data seam that keeps population **offline-first**: the caller pre-fetches the | ||
| * relevant `Observation`s (e.g. into a `data` Bundle) and hands them over, so no live FHIR server or | ||
| * `x-fhir-query` fetching happens inside the library. A future live-fetch provider can implement this | ||
| * same interface without any change to {@see FHIRQuestionnairePopulateService} or {@see PopulateContext}. | ||
| */ | ||
| interface PopulationDataProviderInterface | ||
| { | ||
| /** | ||
| * All candidate `Observation` resources available for population. Order is not significant — the | ||
| * populate service filters by code, status, link period, and (when a subject is stated) `subject`, | ||
| * and selects the most recent itself. | ||
| * | ||
| * A subject filter is applied only when {@see PopulateContext::$subject} is set: the service then | ||
| * excludes any Observation not confirmably about that subject, so a broad or mixed-subject Bundle | ||
| * cannot leak another patient's value. When no subject is stated the caller remains responsible for | ||
| * supplying only relevant Observations. | ||
| * | ||
| * @return list<object> version-specific `Observation` model objects | ||
| */ | ||
| public function observations(): array; | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.