44
55namespace Patchlevel \Hydrator ;
66
7- use Patchlevel \Hydrator \Guesser \BuiltInGuesser ;
87use Patchlevel \Hydrator \Guesser \ChainGuesser ;
98use Patchlevel \Hydrator \Guesser \Guesser ;
109use Patchlevel \Hydrator \Metadata \AttributeMetadataFactory ;
1110use Patchlevel \Hydrator \Metadata \ClassMetadata ;
1211use Patchlevel \Hydrator \Metadata \ClassNotFound ;
12+ use Patchlevel \Hydrator \Metadata \MetadataEnricher ;
1313use Patchlevel \Hydrator \Metadata \MetadataFactory ;
1414use Patchlevel \Hydrator \Middleware \Middleware ;
1515use Patchlevel \Hydrator \Middleware \Stack ;
16- use Patchlevel \Hydrator \Middleware \TransformMiddleware ;
1716use Patchlevel \Hydrator \Normalizer \HydratorAwareNormalizer ;
1817use ReflectionClass ;
1918
2019use function array_key_exists ;
20+ use function array_merge ;
21+ use function krsort ;
2122
2223use const PHP_VERSION_ID ;
2324
@@ -26,10 +27,14 @@ final class MetadataHydrator implements Hydrator
2627 /** @var array<class-string, ClassMetadata> */
2728 private array $ classMetadata = [];
2829
29- /** @param list<Middleware> $middlewares */
30+ /**
31+ * @param list<Middleware> $middlewares
32+ * @param list<MetadataEnricher> $metadataEnrichers
33+ */
3034 public function __construct (
3135 private readonly MetadataFactory $ metadataFactory = new AttributeMetadataFactory (),
3236 private readonly array $ middlewares = [],
37+ private readonly array $ metadataEnrichers = [],
3338 private readonly bool $ defaultLazy = false ,
3439 ) {
3540 }
@@ -110,32 +115,68 @@ private function metadata(string $class): ClassMetadata
110115 $ property ->normalizer ->setHydrator ($ this );
111116 }
112117
118+ foreach ($ this ->metadataEnrichers as $ enricher ) {
119+ $ enricher ->enrich ($ metadata );
120+ }
121+
113122 return $ metadata ;
114123 }
115124
116- /**
117- * @param list<Middleware> $additionalMiddleware
118- * @param iterable<Guesser> $guessers
119- */
125+ /** @param iterable<MiddlewareProvider|MetadataEnricherProvider|GuesserProvider> $extensions */
120126 public static function create (
121- array $ additionalMiddleware = [],
122- iterable $ guessers = [],
127+ iterable $ extensions = [],
123128 bool $ defaultLazy = false ,
124129 ): self {
125- $ guesser = new BuiltInGuesser ();
130+ $ extensions = [...$ extensions , new CoreExtension ()];
131+
132+ $ middlewares = [];
133+ $ enrichers = [];
134+ $ guessers = [];
135+
136+ foreach ($ extensions as $ extension ) {
137+ if ($ extension instanceof MiddlewareProvider) {
138+ foreach ($ extension ->middlewares () as $ entry ) {
139+ if ($ entry instanceof Middleware) {
140+ $ middlewares [0 ][] = $ entry ;
141+ } else {
142+ $ middlewares [$ entry [1 ] ?? 0 ][] = $ entry [0 ];
143+ }
144+ }
145+ }
126146
127- if ($ guessers !== []) {
128- $ guesser = new ChainGuesser ([
129- ...$ guessers ,
130- $ guesser ,
131- ]);
147+ if ($ extension instanceof MetadataEnricherProvider) {
148+ foreach ($ extension ->metadataEnrichers () as $ entry ) {
149+ if ($ entry instanceof MetadataEnricher) {
150+ $ enrichers [0 ][] = $ entry ;
151+ } else {
152+ $ enrichers [$ entry [1 ] ?? 0 ][] = $ entry [0 ];
153+ }
154+ }
155+ }
156+
157+ if (!($ extension instanceof GuesserProvider)) {
158+ continue ;
159+ }
160+
161+ foreach ($ extension ->guesser () as $ entry ) {
162+ if ($ entry instanceof Guesser) {
163+ $ guessers [0 ][] = $ entry ;
164+ } else {
165+ $ guessers [$ entry [1 ] ?? 0 ][] = $ entry [0 ];
166+ }
167+ }
132168 }
133169
170+ krsort ($ middlewares );
171+ krsort ($ enrichers );
172+ krsort ($ guessers );
173+
134174 return new self (
135175 new AttributeMetadataFactory (
136- guesser: $ guesser ,
176+ guesser: new ChainGuesser ([... array_merge (... $ guessers )]) ,
137177 ),
138- [...$ additionalMiddleware , new TransformMiddleware ()],
178+ [...array_merge (...$ middlewares )],
179+ [...array_merge (...$ enrichers )],
139180 $ defaultLazy ,
140181 );
141182 }
0 commit comments