@@ -48,6 +48,11 @@ final class ModelRegistry
48
48
*/
49
49
private array $ names = [];
50
50
51
+ /**
52
+ * @var array<string, array{'schema': string, 'model': Model}[]> List of schemas and Model per type
53
+ */
54
+ private array $ schemasPerType = [];
55
+
51
56
/**
52
57
* @var iterable<ModelDescriberInterface>
53
58
*/
@@ -82,13 +87,36 @@ public function __construct($modelDescribers, OA\OpenApi $api, array $alternativ
82
87
public function register (Model $ model ): string
83
88
{
84
89
$ hash = $ model ->getHash ();
85
- if (!isset ($ this ->models [$ hash ])) {
86
- $ this ->models [$ hash ] = $ model ;
87
- $ this ->unregistered [] = $ hash ;
88
- }
90
+ $ type = $ this ->getTypeShortName ($ model ->getType ());
91
+
92
+ $ schema = null ;
89
93
if (!isset ($ this ->names [$ hash ])) {
90
94
$ this ->names [$ hash ] = $ this ->generateModelName ($ model );
91
95
$ this ->registeredModelNames [$ this ->names [$ hash ]] = $ model ;
96
+
97
+ $ schema = $ this ->getSchemaWithoutRegistration ($ model );
98
+
99
+ // Only try to match schemas if we successfully got one
100
+ if (null !== $ schema ) {
101
+ foreach ($ this ->schemasPerType [$ type ] ?? [] as $ schemaAndModel ) {
102
+ if ($ schemaAndModel ['schema ' ] === json_encode ($ schema ->jsonSerialize ())) {
103
+ $ newHash = $ schemaAndModel ['model ' ]->getHash ();
104
+ unset($ this ->names [$ hash ], $ this ->registeredModelNames [$ hash ]);
105
+
106
+ return OA \Components::SCHEMA_REF .$ this ->names [$ newHash ];
107
+ }
108
+ }
109
+ }
110
+ }
111
+
112
+ if (!isset ($ this ->models [$ hash ])) {
113
+ $ this ->models [$ hash ] = $ model ;
114
+ $ this ->unregistered [] = $ hash ;
115
+ $ this ->unregistered = array_unique ($ this ->unregistered );
116
+ // Only store schema if it was successfully generated
117
+ if (null !== $ schema ) {
118
+ $ this ->schemasPerType [$ type ][] = ['schema ' => json_encode ($ schema ), 'model ' => $ model ];
119
+ }
92
120
}
93
121
94
122
// Reserve the name
@@ -97,6 +125,23 @@ public function register(Model $model): string
97
125
return OA \Components::SCHEMA_REF .$ this ->names [$ hash ];
98
126
}
99
127
128
+ private function getSchemaWithoutRegistration (Model $ model ): ?OA \Schema
129
+ {
130
+ foreach ($ this ->modelDescribers as $ modelDescriber ) {
131
+ if ($ modelDescriber instanceof ModelRegistryAwareInterface) {
132
+ $ modelDescriber ->setModelRegistry ($ this );
133
+ }
134
+ if ($ modelDescriber ->supports ($ model )) {
135
+ $ schema = new OA \Schema ([]);
136
+ $ modelDescriber ->describe ($ model , $ schema );
137
+
138
+ return $ schema ;
139
+ }
140
+ }
141
+
142
+ return null ;
143
+ }
144
+
100
145
/**
101
146
* @internal
102
147
*/
0 commit comments