Repository navigation
feat(factory): add public factories with shared mutability mode - #54
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #54 +/- ##
============================================
+ Coverage 99.40% 99.59% +0.18%
- Complexity 703 1116 +413
============================================
Files 132 277 +145
Lines 1525 2720 +1195
============================================
+ Hits 1516 2709 +1193
- Misses 9 11 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Alexandre-T
left a comment
There was a problem hiding this comment.
Independent review — READY FOR MERGE
Reviewed revision: b0d22bdefdb552ec286aea8c9c91fed8c0afe90d.
No blocking findings or unresolved gates remain.
Scope and acceptance criteria
Reviewed Story #46, parent Epic #38, the implementation diff, relevant constructor/hydration/component-guard code, tests and documentation against the repository instructions and shared LongitudeOne governance.
- The 84 factories cover all supported type/layout/family combinations. Their public signatures match immutable constructors, including named arguments and reference-first heterogeneous collections, in accordance with Alexandre's explicitly approved API decision.
- Each call reads the shared mode. Immutable is the process default; switching changes subsequent creation across factories and preserves earlier objects. Direct immutable construction remains independent of this mode.
- Dispatch delegates to existing constructors with the correct mutable argument order and namespace-selected family. Array-created descendants, EMPTY members, null ordinates, declared references, supplied identity and rejection of opposite representations are covered.
- Public consumer examples assemble heterogeneous and nested collections without internal infrastructure.
- Documentation covers selection, ownership, common read and separate copy/mutation contracts, explicit validation, transformation boundaries and sibling integration follow-up.
Independent verification
composer test-local: passed, 1,095 tests / 11,562 assertions, 99.61% local line coverage.composer quality: passed; PHP CS Fixer changed zero files, PHPStan level 9, PHPMD and PHP_CodeSniffer passed.git diff --check origin/main...HEAD: passed.- Executed all three PHP examples in
docs/public-factories.mdwith assertions enabled. - Independently audited namespace, family selection and dispatcher use across all 84 factories.
- GitHub checks on the reviewed SHA: PHP 8.4, PHP 8.5 and GitGuardian all successful.
- Working tree remains clean; reviewed head was rechecked before publication.
Local checks ran on PHP 8.5.11. PHP CS Fixer's first sandboxed attempt could not open its local worker socket; rerunning the same quality command outside the sandbox succeeded. Existing PHPMD/PDepend PHP 8.5 deprecation notices remain non-blocking and no quality rule was weakened.
Pre-merge Definition of Done
Applicable acceptance criteria, tests, quality, documentation, API approval, architecture boundaries and required CI are satisfied. This change adds constructor selection without introducing a new geometry-validity rule, serialization behavior, transformation or normative interpretation. No sibling repository implementation is included.
This independent agent verdict is recorded as a comment review. Merge remains Alexandre's decision; the PR is unmerged and the Story is not Done.
Pull Request
Closes #46
Summary
Applications and consuming libraries can now create every supported spatial type through 84 public static factories under
Factory\<dimension>\<family>\<type>Factory.SpatialFactory::immutable(),mutable()andisMutable()share one selection across subsequent calls; the initial mode is immutable. Earlier objects and direct constructors retain their behavior.Factories delegate to the existing constructors, preserving coordinate arrays, null ordinates, EMPTY members, declared context and supplied-component ownership. An internal constructor dispatcher selects the representation without cloning, conversion or validation.
Acceptance criteria
Coverage includes XY, XYZ, XYM and XYZM; both families; all supported types and heterogeneous collections; constructor-equivalent named arguments; nested descendants; shared identity; opposite-representation rejection; and explicit public-consumer examples.
Validation
Commands run
Final full suite: 1,095 tests, 11,562 assertions, including 109 new tests. Line coverage: 99.61%. Three documentation examples were executed with PHP assertions enabled; local Markdown link targets were checked.
PHP CS Fixer, PHPStan level 9, PHPMD and PHP_CodeSniffer passed on PHP 8.5.11. PHPMD/PDepend emit dependency deprecations on PHP 8.5; the quality command exits successfully without rule or configuration changes. GitHub Actions PHP 8.4 and PHP 8.5, plus GitGuardian Security Checks, passed on
b0d22bdefdb552ec286aea8c9c91fed8c0afe90d.Standards
Normative references
The existing distinction between technical representation and ISO/IEC 13249-3 / OGC geometric validity is preserved. Incomplete points remain representable. No automatic validation, repair, coordinate transformation, dimension conversion or new normative interpretation is introduced.
Architecture
Architecture decision
Follows #38–#46: factories construct domain objects; shared read interfaces and separate immutable/mutable contracts remain unchanged. Internal immutable hydration remains independent of the public mode. Sibling repositories are not modified.
Compatibility
API Gate resolved by Alexandre in this session:
create()mirrors the immutable constructor's parameter names, native types, order and defaults, adapting internally to mutable constructors. Specifically,MultiPointFactory::create(array $points, int|SpatialReference $srid = 0)retains$points, whileGeometryCollectionFactory::create(int|SpatialReference $srid = 0, array $elements = [])retains reference-first ordering. The same rule applies across the factory catalogue.The new factory APIs are additive. Existing constructors and internal hydration methods retain their signatures. Immutable classes are used under their renamed final symbols; no aliases, dependencies or supported environments change.
Documentation
Adds
docs/public-factories.mdwith selection, signatures, coverage, ownership and consumer follow-up for spatial-decoder, spatial-transformer and Doctrine. Updates the README, type reference, hierarchy and immutability guide.Developer handoff
Important implementation decisions
Each public factory has an explicit native signature and concrete immutable/mutable union return type. A shared internal dispatcher invokes the selected constructor with the appropriate argument order and namespace-selected family. Tests construct spatial fixtures explicitly; signature loops inspect metadata only.
Compatibility considerations
The mode is shared by all consumers in one execution. A switch affects future factory calls, not existing objects. Opposite-representation components continue to be rejected recursively without conversion.
Remaining risks or questions
Independent review is pending. The PR is not merged and the Story is not Done. No unresolved API, architecture or normative decision remains within the approved scope.