Conversation
- Add SDC component for `Questionnaire/$populate` and `QuestionnaireResponse/$extract` operations. - Define `AbstractSdcConformanceTest` harness for structural output comparisons. - Implement `SafeExtensionReader` for tolerant extension reads. - Create initial test suites: `sdc-populate-spec` and `sdc-extract-spec`. - Update PHPUnit config, composer.json, and scripts to integrate new tests. - Add component documentation and conformance oracle guidelines.
- Add `ExtractResult` and `ExtractContext` classes to model extraction output and inputs. - Implement `FHIRQuestionnaireResponseExtractService` for observation- and definition-based `$extract`. - Add unit tests for `DefinitionPathWriteSpike` and `FHIRQuestionnaireResponseExtractService`. - Ensure tolerance for deserialization-origin objects via `SafeExtensionReader`.
- Add support for `extractAllocateId` to allocate `urn:uuid:` and expose it as a FHIRPath external constant. - Enable `definitionExtractValue` to write allocated IDs into cross-resource references. - Add integration test for `extractAllocateId` ensuring conformance with oracle reference Bundle. - Refactor resource extraction logic to handle `definitionExtractValue` and `fullUrl` resolution.
- Implement scalar-to-primitive coercion for `definitionExtractValue` to ensure type safety during extraction. - Enhance error handling for malformed FHIRPath expressions, surfacing diagnostic issues instead of crashing. - Add comprehensive unit and integration tests for `definitionExtractValue` behavior, including type coercion and error reporting. - Update `FHIRQuestionnaireResponseExtractService` and `DefinitionPathWriter` for reflective property handling and stricter type support.
…raction - Implement logic to generate `PUT Type/id` request for resources with logical `id` and `POST Type` for id-less resources per SDC specification. - Add `logicalIdOf` helper to identify resources with logical `id` to handle `PUT` directives. - Update `DefinitionPathWriter` to unwrap deserialized primitive wrappers for bare scalar properties. - Add unit and integration tests to validate `POST`/`PUT` behavior and ensure alignment with SDC conformance guidelines.
…ance - Update `FHIRQuestionnaireResponseExtractService` to support R4/R4B/R5 extraction by introducing version-generic models and type-tolerant inputs. - Replace type-guarding logic with clean handling of mismatched FHIR versions, yielding empty bundles and diagnostic issues instead of errors. - Add `ExtractModelFactory` for model construction based on specified FHIR version. - Refactor `collectObservations` and `collectDefinitionResources` methods to account for version-specific behaviors. - Introduce helper methods for tolerant property access across FHIR versions, including `childItems`, `itemCodings`, and `answerValue`. - Add unit test updates to validate behavior for unrecognized QuestionnaireResponses and enhance coverage across supported versions.
…d answer-bearing roots - Extend `FHIRQuestionnaireResponseExtractService` to handle choice-slice definitions (e.g., `value[x]:valueQuantity`) during extraction. - Add support for `fixed-value` in `definitionExtractValue` (e.g., complex/coded calculated values like `Coding` or `CodeableConcept`). - Enable processing of answer-bearing roots for `definitionExtract` (e.g., handling root items with answers directly written to resources). - Refactor `DefinitionPathWriter` for choice variant resolution, scalar-to-variant wrapping, and stricter type handling. - Improve handling of temporal and coded values with coercion and reduction (e.g., parse datetime strings or reduce `Coding` to scalar `code`). - Add unit and integration tests for choice slicing, fixed values, and cross-resource reference resolution.
…ExtractService` for focus-resource handling - Refactor `FHIRPathEvaluator` to align with FHIRPath semantics, separating `%context`, `%resource`, and `%rootResource` for precise evaluation focus and resource hierarchy handling. - Update `EvaluationContext` with `resourceNode` support, enabling stable resource binding during extraction. - Adjust `FHIRQuestionnaireResponseExtractService` for consistent use of `%resource` as the root QR and `%context` as the evaluation focus in `definitionExtractValue` expressions. - Add context-aware focus switching for FHIRPath evaluation during QR extraction. - Introduce `.gruff-php.yaml` for static analysis configuration. - Update tests and documentation to reflect new focus-resource behavior.
…eResponseExtractService` - Integrate `templateExtract` handling to clone and populate `contained` templates via `templateExtractContext` and `templateExtractValue`. - Add `TemplateExtractor` for version-agnostic processing of `templateExtract` elements at the array level. - Include `extract-complex-template` conformance test with vendored oracle fixtures. - Update documentation to detail template-based extraction workflow and limitations.
…generation - Add support for mixing observation-, definition-, and template-based extractions into a single merged Bundle. - Introduce opt-in `Provenance` generation in `$extract` via `ExtractContext::$emitProvenance`. - Update documentation to cover mixed-method extraction, `Provenance` details, and conformance corpus triage. - Add unit and integration tests for merging extraction results, `Provenance` output, and malformed expression handling.
- Add `FHIRQuestionnairePopulateService` for expression-based `$populate` implementation, enabling generation of `QuestionnaireResponse` from `Questionnaire` and contextual data. - Introduce `PopulateContext` and `PopulateResult` classes to handle operation inputs and outputs. - Add `PopulateModelFactory` for version-specific object construction in `$populate`. - Include initial support for `launchContext` resources and `initialExpression` evaluation with FHIRPath expressions. - Add unit tests and sample fixtures to validate `Questionnaire/$populate` behavior.
… item repetition, and observation-based population - Add support for resolving `variable` extensions as external constants in FHIRPath evaluation. - Implement `itemPopulationContext` handling for repeating group items based on context results. - Enable observation-based population using `observationLinkPeriod`, selecting the most recent matching `Observation`. - Add temporal coercion support (`date`, `dateTime`, `time`) and strengthen answer type compatibility checks. - Refactor `FHIRQuestionnairePopulateService` to modularize `item` population, improve error handling, and centralize value mismatches. - Update `PopulateModelFactory` with temporal wrapper methods, enabling version-specific date/time construction. - Enhance population logic with fallback handling for unresolved canonical URLs.
…uration warnings and expanded diagnostics - Introduce warnings for `Duration` units that cannot be mapped in `observationLinkPeriod`, treating look-back windows as unbounded but making diagnostic issues observable. - Expand test coverage to validate diagnostic issue generation for unmappable Duration units and no-match Observations. - Refactor internal population methods to support comprehensive result and issue inspection in test cases.
…bilities - Add documentation for expanded `$populate` operation, including updated handling for `launchContext`, `variable`, `itemPopulationContext`, and observation-based population (`observationLinkPeriod`). - Enhance complete phpdoc coverage for constructors and methods in public API files. - Expand test suite with new scenarios: malformed expressions, empty results, type mismatches, and nested group repetition. - Incorporate conformance corpus documentation and triage details for SDC IG example forms against implemented functionality. - Refactor test utilities for streamlined validation of population results and issues.
- Introduce `FhirPrimitiveReader` to handle primitive-wrapper-or-scalar value extraction across `Sdc` components. - Add `AnswerValueCoercer` for modular, reusable answer coercion in `FHIRQuestionnairePopulateService`. - Refactor `FHIRQuestionnairePopulateService` to delegate primitive handling and answer coercion to respective helpers. - Remove redundant coercion methods from `FHIRQuestionnairePopulateService`. - Improve type safety, error diagnostics, and code maintainability with centralized logic.
…based population logic - Moved observation-based population functionality from `FHIRQuestionnairePopulateService` to a new `ObservationSelector` class, centralizing handling of `observationLinkPeriod`. - Simplified `FHIRQuestionnairePopulateService` by delegating observation-based population to `ObservationSelector`, reducing duplication and improving maintainability. - Enhanced testability and modularity with clearly defined responsibilities for observation selection and diagnostics.
…ResponseReader` - Add `QuestionnaireResponseReader` for tolerant structural reads of `QuestionnaireResponse`/`Questionnaire` items and answers. - Remove redundant read methods and inline the new reader in `FHIRQuestionnaireResponseExtractService`. - Delegate QR-specific reads (e.g., `childItems`, `answersOf`, `answerValue`) to `QuestionnaireResponseReader`, improving modularity and maintainability. - Simplify `DefinitionExtractionWalker` initialization with shared reader dependency.
…g and extraction logic - Extract item processing into new private methods (`walkOneItem`, `writeAnswerLeaves`, `applyOneExtractValue`, `resolveExtractValue`) for improved readability and maintainability. - Simplify control flow and structure error handling with early returns, reducing nesting and duplication. - Enhance separation of concerns for path processing, value resolution, and answer extraction.
…pulation` - Implement strict subject matching in `ObservationSelector`, ensuring only `Observations` confirmably about the specified subject are eligible for population. - Raise warnings for mismatched or unconfirmable subjects when `PopulateContext::$subject` is set. - Update population logic, tests, and documentation to reflect subject-scoping behavior. - Prevent data leakage from mixed-subject Bundles, aligning with `observationLinkPeriod` intent.
… timestamp calculations` - Interpret timezone-less FHIR strings (e.g., date-only) as UTC for deterministic window comparisons. - Prevent race condition in `ObservationSelector` by capturing `time()` once, ensuring consistent window boundaries.
Implement optimized `$populate` operation with modular design
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Benchmark ResultsSerialization + FHIRPath benchmarks✅ Regression check passedComparison vs baselineRun |
❌ FHIR Model Generation Test OUT OF DATEThis automated test regenerates the R4B FHIR models and verifies that the generation functionality works correctly with the changes in this PR, then checks that the committed models are up to date. 📋 Click to view detailed outputM src/Component/Models/src/R4B/Profile/ExampleLipidProfile.php |
- Add `FHIRQuestionnairePopulateService::populate` for `Questionnaire/$populate` functionality. - Support expression-based and observation-based population mechanisms. - Update SDC docs and examples to reflect `$populate` capabilities alongside `$extract`.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Implement `$populate` operation for SDC and update documentation
Benchmark ResultsSerialization + FHIRPath benchmarks✅ Regression check passedComparison vs baselineRun |
…HIR server communication - Add `FHIRHttpClientInterface` to standardize FHIR REST server interaction. - Implement `FHIRHttpClient` for graceful, version-aware, and typed access to FHIR servers. - Add `NullFHIRHttpClient` for offline-first workflows, ensuring features degrade gracefully in the absence of a live server. - Integrate HTTP client functionality into `$populate` service with `XFhirQuery` support. - Update package-integrity workflow to include `fhir-http-client` repo.
A searchset Bundle from a live x-fhir-query fetch can carry _include'd resources and OperationOutcome entries alongside actual matches. XFhirQueryPopulationDataProvider took every entry.resource, so those would be bound as spurious %<name> context results in $populate.
Covers that evaluated launch-context values are always percent-encoded before substitution and that FHIRHttpClient always joins onto the configured base URL, so a resolved search string can never redirect a request to another host. Also adds an explicit timeout-to-null test and the end-to-end empty-substitution (all-holes-empty) case.
…berOf() ResolveFunction/MemberOfFunction previously hand-rolled PSR-18/17 HTTP calls with a duplicated fetch() helper. Relative Type/id and canonical searches now go through FHIRHttpClientInterface, matching the pattern HttpFHIRTerminologyClient already established; a raw PSR-18 client is kept only for resolve()'s absolute-URL case, which a base-URL-bound FHIRHttpClientInterface implementation cannot express. Removes FHIRPathEvaluator's setFhirServerUrl/setTerminologyUrl string setters (unused outside tests) in favour of setFhirHttpClient/ setTerminologyHttpClient, and wires an optional FHIRHttpClientInterface into FHIRPathService's constructor so the new DI alias in services.yaml is actually reachable.
FHIRHttpClient/XFhirQueryPopulationDataProvider previously fetched a single search page only. FHIRHttpClientInterface gains followLink(), which resolves a server-supplied Bundle.link.url to a same-origin relative path before dispatching through the existing baseUrl join -- rejecting the URL outright when its origin or path prefix doesn't match, since a next link (unlike a resolved search string) is absolute and server-supplied, so it isn't covered by the existing SSRF guarantee. XFhirQueryPopulationDataProvider follows next links via a plain FHIRPath expression (link.where(relation = 'next').url), which reads uniformly across FHIR versions despite Bundle.link.relation's type differing between R4/R4B and R5. Pagination is bounded to 50 pages; a page that fails to fetch for any reason (no further link, an off-host rejection, or a transport error) simply stops pagination, returning whatever pages were fetched successfully -- consistent with the graceful-degradation posture already used throughout this transport stack.
…-fhir-query transport sameOriginPath() matched a base path like "/fhir" against any path sharing that string prefix (e.g. "/fhir2/..."), which could misroute Bundle.link[next] pagination to the wrong path on a same-origin server. It now requires a whole path-segment match. evaluateAndFormat() kept an atom that formatted to an empty string (unsupported result type, empty CodeableConcept.coding, or a coding/identifier with neither system nor code) as a substituted value instead of treating it as empty per the resolver's own documented policy, producing malformed parameters like "subject=" instead of dropping them.
feat/x-fhir-query
Benchmark ResultsSerialization + FHIRPath benchmarks✅ Regression check passedComparison vs baselineRun |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This pull request introduces a new SDC (Structured Data Capture) component for extracting FHIR resources from a
QuestionnaireResponse, along with supporting infrastructure, documentation, and several enhancements to the FHIRPath evaluation context. The most important changes are summarized below.SDC (Structured Data Capture) Extraction Feature:
Added the
ardenexal/fhir-sdccomponent, implementingFHIRQuestionnaireResponseExtractService::extract($qr, new ExtractContext(...))forQuestionnaireResponse/$extract(observation-, definition-, and template-based extraction), returning anExtractResultwith a transactionBundleand optionalOperationOutcome. Supports R4, R4B, and R5, with advanced features like version-agnostic extraction, cross-resource references, fixed/calculated values, choice slices, and opt-in Provenance generation. [1] [2]SDC
$extractoutput is always atransactionBundle, with robust handling for empty or malformed extractions (yields an empty Bundle and/or warning OperationOutcome). [1] [2]FHIRPath Evaluation Context Enhancements:
EvaluationContext::withResourceNode()andgetResourceNode()to bind%resource/%rootResourceto a resource distinct from the evaluation focus, and updated context cloning methods to preserve this binding.%resource/%rootResourcenow resolve to this node when set, falling back to the focus otherwise. [1] [2] [3] [4] [5] [6] [7] [8] [9]Infrastructure & Testing:
Wired
ardenexal/fhir-sdcinto the workspace: added Composer autoloading, PHPUnit configuration for unit/integration and dedicated SDC conformance suites (sdc-extract-spec,sdc-populate-spec), and updated test runner scripts to include these. [1] [2] [3] [4] [5] [6] [7] [8]Added
blundergoat/gruff-phpas a dev dependency and its config, and updated.gitignorefor.gruff-cache/. [1] [2]Documentation Updates:
Other:
SafeExtensionReaderfor tolerant FHIR extension traversal, which degrades gracefully on deserialized objects.These changes significantly expand the library's support for SDC workflows, improve FHIRPath evaluation flexibility, and ensure robust testing and documentation for the new features.