Migrate to STAB optics (Iso<S,T,A,B> / Lens<S,T,A,B>)#64
Merged
veewee merged 2 commits intoMay 27, 2026
Conversation
3 tasks
veewee
commented
May 27, 2026
veewee
commented
May 27, 2026
veewee
commented
May 27, 2026
veewee
commented
May 27, 2026
veewee
commented
May 27, 2026
veewee
commented
May 27, 2026
veewee
commented
May 27, 2026
194f684 to
573d218
Compare
There was a problem hiding this comment.
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 toIsoInterfacewhere 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$complexTypeMapto avoid propagating the misspelling throughout the codebase and docs.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
424307f to
62027a5
Compare
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.
Adopt the four-template profunctor STAB form from veewee/reflecta#31. Every
Iso/Lensannotation and generic expands from<S, A>to<S, T, A, B>. Runtime behavior is unchanged; this is a structural / type-annotation migration.Summary
XmlEncoder,SoapMethodEncoder,ProvidesObject{En,De}coderLens,DecoratingEncoder) gain a 4-slot signature(TDataIn, TDataOut, TXmlOut, TXmlIn)and are marked@template-covariantto match reflecta's interface posture. Concrete encoder classes stay invariant.fromacceptsElement|non-empty-stringetc., reflecting the runtime fast path that was previously hidden behind 2-template unsoundness.DateTimeImmutable,numeric-string,scalar,list<mixed>, …) so psalm's body inference matches the declared shape.EncoderRegistry,ObjectAccess, and the wrappers types its slots asIsoInterface/LensInterface/XmlEncoder<mixed, mixed, mixed, mixed>. Interface covariance lets concrete encoders flow into these slots without casts.RepeatingElementEncoder<T>,OptionalElementEncoder<T>) acceptXmlEncoder<T, T, mixed, mixed>in their constructor —Tbinds 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 andcompose()chains still get full STAB invariance checking.IsoInterface<S, T, A, B>/LensInterface<S, T, A, B>typed slots widen polymorphically, same trade asIEnumerable<out T>in C#.Requirements
dev-feature/stab-optics(resolved via theas 0.19.0alias incomposer.json). Once that branch ships as a real release, drop the alias.Test plan
vendor/bin/psalm --no-cachegreen (no errors)vendor/bin/phpunit --no-coveragegreen (564 tests, 1156 assertions)php-soap/psr18-attachments-middlewaremigration on top of this branch (linked PR)