Skip to content

Type every first-level schema field on all response DTOs#5

Merged
loevgaard merged 1 commit into
1.xfrom
add-first-level-dto-properties
Jun 10, 2026
Merged

Type every first-level schema field on all response DTOs#5
loevgaard merged 1 commit into
1.xfrom
add-first-level-dto-properties

Conversation

@loevgaard

Copy link
Copy Markdown
Member

Summary

  • Type all first-level properties from the e-conomic JSON schemas on every response DTO: Customer (+13), Product (+9), Inventory (+5), Order (+24), BookedInvoice (+24), Line (+14, union of order/invoice line schemas), Self_ (+12)
  • Add 25 small all-nullable final readonly nested DTOs: Response\Reference\* (shared foreign-key refs, each keeping its ?string $self link), Response\Document\* (Recipient, Delivery, Notes, References, Pdf — shared by orders and invoices), ProductGroup, Line\Accrual, and 8 Self_ sub-DTOs
  • Pure HATEOAS/meta link fields (self, metaData, soap, templates, totals, contacts, deliveryLocations, invoices, attachment, sent) deliberately stay raw-only; pdf is typed because consumers feed its download URL to Client::request()
  • All date/timestamp fields map to ?\DateTimeImmutable; new public Client::configureMapperBuilder() wires supportDateFormats() with e-conomic's timestamp shape and date-only !Y-m-d (the ! pins time to midnight UTC — deterministic). README/CLAUDE.md updated, custom-builder examples now wrap with the helper
  • customer references map into the full Customer DTO (precedent: Line::$product); RawStamper stamps nested Resources, so $order->customer->raw['self'] works

Behavioural note

Object fields that previously sat inert in $raw now pass through Valinor — a malformed nested object in a 2xx body fails the response with MappingException instead of being silently reachable-but-garbage. Real API responses conform; hand-built test doubles downstream may not.

Test plan

  • composer phpunit — 187 tests / 736 assertions (14 new tests: five kitchen-sink full-mapping tests asserting every new field incl. nested DTOs, recursive Customer → CustomerContact → Customer graph, and a date-format matrix proving date-only fields map to exactly midnight UTC)
  • composer analyse — PHPStan level max, no errors
  • composer check-style + vendor/bin/rector --dry-run — clean
  • vendor/bin/infection — MSI 68% (floor 53.85), covered MSI ≥ 79.25, exit 0

Customer, Product, Order, BookedInvoice, Self_, Line and Inventory now
expose all first-level properties from the e-conomic JSON schemas as
typed fields instead of raw-only access. Object-valued fields map into
25 new all-nullable `final readonly` nested DTOs under
Response\Reference (shared FK refs), Response\Document (order/invoice
sub-objects incl. Pdf) and Response\Self_. Pure HATEOAS/meta link
fields (self, metaData, soap, templates, totals, …) deliberately stay
in $raw.

Date handling: all new date/timestamp fields are ?\DateTimeImmutable.
The new public Client::configureMapperBuilder() helper (mirroring
registerNormalizerTransformers()) wires supportDateFormats() with both
e-conomic shapes — timestamps and date-only `!Y-m-d`, where the `!`
pins the time to midnight UTC so mapped dates are deterministic.
supportDateFormats() replaces Valinor's defaults, so the stock formats
are re-declared. README's custom-builder examples now use the helper.

`customer` references map into the full Customer DTO (the
Line::$product precedent); RawStamper fires polymorphically, so nested
Resources carry their slice of the body on $raw.

Covered by five kitchen-sink full-mapping tests (one per resource) and
a date-format matrix: 187 tests / 736 assertions, PHPStan level max,
ECS, Rector and Infection (MSI 68%, covered 79%+) all green.
@loevgaard loevgaard merged commit ea6062d into 1.x Jun 10, 2026
7 checks passed
@loevgaard loevgaard deleted the add-first-level-dto-properties branch June 10, 2026 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant