Skip to content

Migrate to STAB optics (Iso<S,T,A,B> / Lens<S,T,A,B>)#64

Merged
veewee merged 2 commits into
php-soap:mainfrom
veewee:feature/reflecta-stab-migration-main
May 27, 2026
Merged

Migrate to STAB optics (Iso<S,T,A,B> / Lens<S,T,A,B>)#64
veewee merged 2 commits into
php-soap:mainfrom
veewee:feature/reflecta-stab-migration-main

Conversation

@veewee
Copy link
Copy Markdown
Member

@veewee veewee commented May 26, 2026

Adopt the four-template profunctor STAB form from veewee/reflecta#31. Every Iso/Lens annotation and generic expands from <S, A> to <S, T, A, B>. Runtime behavior is unchanged; this is a structural / type-annotation migration.

Summary

  • Encoder interfaces (XmlEncoder, SoapMethodEncoder, ProvidesObject{En,De}coderLens, DecoratingEncoder) gain a 4-slot signature (TDataIn, TDataOut, TXmlOut, TXmlIn) and are marked @template-covariant to match reflecta's interface posture. Concrete encoder classes stay invariant.
  • Element-aware encoders declare their honest asymmetric shapes — from accepts Element|non-empty-string etc., reflecting the runtime fast path that was previously hidden behind 2-template unsoundness.
  • Simple-type encoders declare their narrow real outputs (DateTimeImmutable, numeric-string, scalar, list<mixed>, …) so psalm's body inference matches the declared shape.
  • Heterogeneous storage in EncoderRegistry, ObjectAccess, and the wrappers types its slots as IsoInterface/LensInterface/XmlEncoder<mixed, mixed, mixed, mixed>. Interface covariance lets concrete encoders flow into these slots without casts.
  • Wrappers (RepeatingElementEncoder<T>, OptionalElementEncoder<T>) accept XmlEncoder<T, T, mixed, mixed> in their constructor — T binds from the inner encoder's data slots, XML slots erased because the wrapper rewrites the XML representation regardless.

Variance posture

Mirrors reflecta's: interface covariant, concrete invariant. Concrete Iso<S, T, A, B> / Lens<S, T, A, B> construction and compose() chains still get full STAB invariance checking. IsoInterface<S, T, A, B> / LensInterface<S, T, A, B> typed slots widen polymorphically, same trade as IEnumerable<out T> in C#.

Requirements

  • Requires veewee/reflecta dev-feature/stab-optics (resolved via the as 0.19.0 alias in composer.json). Once that branch ships as a real release, drop the alias.

Test plan

  • vendor/bin/psalm --no-cache green (no errors)
  • vendor/bin/phpunit --no-coverage green (564 tests, 1156 assertions)
  • CI green
  • Downstream check: php-soap/psr18-attachments-middleware migration on top of this branch (linked PR)

Comment thread src/Encoder/Feature/DecoratingEncoder.php Outdated
Comment thread src/Encoder/SimpleType/AttributeValueEncoder.php Outdated
Comment thread src/Encoder/SimpleType/EncoderDetector.php Outdated
Comment thread src/Encoder/SimpleType/SimpleListEncoder.php Outdated
Comment thread src/Encoder/EncoderDetector.php Outdated
Comment thread src/Encoder/ObjectEncoder.php
Comment thread src/Encoder/OptionalElementEncoder.php Outdated
@veewee veewee force-pushed the feature/reflecta-stab-migration-main branch from 194f684 to 573d218 Compare May 27, 2026 12:52
@veewee veewee requested a review from Copilot May 27, 2026 13:21
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request migrates the encoding layer to Reflecta’s 4-template “STAB” optics (Iso<S,T,A,B> / Lens<S,T,A,B>), threading the expanded generic shape through encoder interfaces, implementations, and related helpers while keeping runtime behavior the same.

Changes:

  • Expand XmlEncoder / SoapMethodEncoder (and related feature interfaces) from 2-slot generics to 4-slot STAB generics and switch return types to IsoInterface where appropriate.
  • Tighten encoder XML/data shapes across simple-type, element-aware, and wrapper encoders to reflect asymmetric input/output behavior.
  • Update registry/detector and storage sites to accept heterogeneous encoders via covariant interfaces; adjust dependency to Reflecta’s STAB optics branch.

Reviewed changes

Copilot reviewed 45 out of 45 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Xml/Writer/ElementValueBuilder.php Update XmlEncoder/Iso generics to STAB and switch to IsoInterface.
src/Xml/Reader/ElementValueReader.php Update XmlEncoder/Iso generics to STAB and switch to IsoInterface.
src/TypeInference/XsiTypeDetector.php Import XML node FQCNs and update FixedIsoEncoder STAB typing in cache/detector.
src/Normalizer/PhpPropertyNameNormalizer.php Import ucfirst and use it as a first-class callable.
src/Fault/Encoder/SoapFaultEncoder.php Update Iso generic annotation to STAB.
src/Fault/Encoder/Soap12FaultEncoder.php Update Iso generic annotation to STAB.
src/Fault/Encoder/Soap11FaultEncoder.php Update Iso generic annotation to STAB.
src/EncoderRegistry.php Retype simple/complex encoder maps and registry APIs with STAB XML shapes.
src/Encoder/XsiTypeEncoder.php Thread STAB types through xsi:type wrapper and align XML slot unions.
src/Encoder/XmlEncoder.php Expand encoder interface to 4 covariant templates and return IsoInterface.
src/Encoder/SoapEnc/SoapObjectEncoder.php Update XmlEncoder/Iso generics to STAB.
src/Encoder/SoapEnc/SoapArrayEncoder.php Update XmlEncoder/Iso generics to STAB.
src/Encoder/SoapEnc/SoapArrayAccess.php Update item encoder typing to STAB and honest XML slot unions.
src/Encoder/SoapEnc/ApacheMapEncoder.php Update XmlEncoder/Iso generics to STAB.
src/Encoder/SimpleType/StringTypeEncoder.php Update XmlEncoder/Iso generics to STAB.
src/Encoder/SimpleType/SimpleListEncoder.php Retype list encoder to STAB and remove now-unneeded psalm suppressions.
src/Encoder/SimpleType/ScalarTypeEncoder.php Tighten data out type to scalar and update STAB generics.
src/Encoder/SimpleType/IntTypeEncoder.php Update XmlEncoder/Iso generics to STAB.
src/Encoder/SimpleType/HexBinaryTypeEncoder.php Update XmlEncoder/Iso generics to STAB.
src/Encoder/SimpleType/FloatTypeEncoder.php Tighten XML out to numeric-string and update STAB generics.
src/Encoder/SimpleType/EncoderDetector.php Retype detector outputs and wrapper composition to STAB unions.
src/Encoder/SimpleType/DateTypeEncoder.php Tighten data out to DateTimeImmutable and update STAB generics.
src/Encoder/SimpleType/DateTimeTypeEncoder.php Tighten data out to DateTimeImmutable and update STAB generics.
src/Encoder/SimpleType/CDataTypeEncoder.php Update XmlEncoder/Iso generics to STAB.
src/Encoder/SimpleType/BoolTypeEncoder.php Update XmlEncoder/Iso generics to STAB.
src/Encoder/SimpleType/Base64BinaryTypeEncoder.php Update XmlEncoder/Iso generics to STAB.
src/Encoder/SimpleType/BackedEnumTypeEncoder.php Update XmlEncoder/Iso generics to STAB.
src/Encoder/SimpleType/AttributeValueEncoder.php Retype attribute wrapper to STAB with nullable XML slots and use IsoInterface internally.
src/Encoder/RepeatingElementEncoder.php Retype repeating wrapper to STAB and align XML slot unions.
src/Encoder/OptionalElementEncoder.php Retype optional wrapper to STAB and return IsoInterface.
src/Encoder/ObjectEncoder.php Retype object encoder to STAB and switch lens dependency to LensInterface.
src/Encoder/ObjectAccess.php Retype stored lenses/isos to STAB interfaces and narrow encoder/decoder lens subjects.
src/Encoder/Method/SoapMethodEncoder.php Expand method encoder interface to 4 covariant templates and return IsoInterface.
src/Encoder/Method/ResponseEncoder.php Update method encoder implementation to STAB generics.
src/Encoder/Method/RequestEncoder.php Update method encoder implementation to STAB generics.
src/Encoder/MatchingValueEncoder.php Retype matching encoder to STAB XML unions.
src/Encoder/FixedIsoEncoder.php Expand fixed-iso wrapper to STAB and store an IsoInterface.
src/Encoder/Feature/ProvidesObjectEncoderLens.php Expand provides-lens feature to LensInterface<S,T,A,B> with object constraints.
src/Encoder/Feature/ProvidesObjectDecoderLens.php Expand provides-lens feature to LensInterface<S,T,A,B> with array constraints.
src/Encoder/Feature/DecoratingEncoder.php Expand decorating feature to 4-slot STAB generics.
src/Encoder/ErrorHandlingEncoder.php Thread 4 STAB templates through the decorator and preserve asymmetry.
src/Encoder/EncoderDetector.php Retype detector cache/output to STAB unions.
src/Encoder/ElementEncoder.php Retype element wrapper to STAB and pass IsoInterface into builders/readers.
src/Encoder/AnyElementEncoder.php Retype any-element encoder and its provided lens to STAB.
composer.json Switch Reflecta dependency to STAB optics dev branch via version alias.
Comments suppressed due to low confidence (1)

src/EncoderRegistry.php:35

  • Typo in the parameter/property name $complextTypeMap (and corresponding docblock param). Since this is an internal/private field, consider renaming it consistently to $complexTypeMap to avoid propagating the misspelling throughout the codebase and docs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread composer.json Outdated
@veewee veewee force-pushed the feature/reflecta-stab-migration-main branch from 424307f to 62027a5 Compare May 27, 2026 13:42
@veewee veewee marked this pull request as ready for review May 27, 2026 14:19
@veewee veewee merged commit 0edbbb5 into php-soap:main May 27, 2026
11 checks passed
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.

2 participants