77use GraphQL \SchemaGenerator \CodeGenerator \ArgumentsObjectClassBuilder ;
88use GraphQL \SchemaGenerator \CodeGenerator \EnumObjectBuilder ;
99use GraphQL \SchemaGenerator \CodeGenerator \InputObjectClassBuilder ;
10+ use GraphQL \SchemaGenerator \CodeGenerator \InterfaceObjectBuilder ;
1011use GraphQL \SchemaGenerator \CodeGenerator \ObjectBuilderInterface ;
1112use GraphQL \SchemaGenerator \CodeGenerator \QueryObjectClassBuilder ;
1213use GraphQL \SchemaGenerator \CodeGenerator \UnionObjectBuilder ;
@@ -44,7 +45,15 @@ class SchemaClassGenerator
4445 *AND complete covering the schema scanner class
4546 * @var array
4647 */
47- private $ generatedObjects ;
48+ private $ generatedObjects ;
49+
50+ /**
51+ * This array is used to remember the generated interfaces or store objects that implement the interface
52+ * Array structure: [$objectName] => string[] | InterfaceObjectBuilder
53+ *AND complete covering the schema scanner class
54+ * @var array
55+ */
56+ private $ generatedInterfaces ;
4857
4958 /**
5059 * SchemaClassGenerator constructor.
@@ -59,6 +68,7 @@ public function __construct(Client $client, string $writeDir = '', string $names
5968 $ this ->generatedObjects = [];
6069 $ this ->writeDir = $ writeDir ;
6170 $ this ->generationNamespace = $ namespace ;
71+ $ this ->generatedInterfaces = [];
6272 $ this ->setWriteDir ();
6373 }
6474
@@ -141,6 +151,7 @@ protected function generateObject(string $objectName, string $objectKind): bool
141151 {
142152 switch ($ objectKind ) {
143153 case FieldTypeKindEnum::OBJECT :
154+ case FieldTypeKindEnum::INTERFACE_OBJECT :
144155 return $ this ->generateQueryObject ($ objectName );
145156 case FieldTypeKindEnum::INPUT_OBJECT :
146157 return $ this ->generateInputObject ($ objectName );
@@ -168,11 +179,25 @@ protected function generateQueryObject(string $objectName): bool
168179 $ this ->generatedObjects [$ objectName ] = true ;
169180 $ objectArray = $ this ->schemaInspector ->getObjectSchema ($ objectName );
170181 $ objectName = $ objectArray ['name ' ];
171- $ objectBuilder = new QueryObjectClassBuilder ($ this ->writeDir , $ objectName , $ this ->generationNamespace );
182+
183+ if ($ objectArray ['kind ' ] === FieldTypeKindEnum::INTERFACE_OBJECT ) {
184+ $ objectBuilder = new InterfaceObjectBuilder ($ this ->writeDir , $ objectName , $ this ->generationNamespace );
185+ $ this ->registerInterface ($ objectName , $ objectBuilder );
186+ } else {
187+ $ objectBuilder = new QueryObjectClassBuilder ($ this ->writeDir , $ objectName , $ this ->generationNamespace );
188+ }
172189
173190 $ this ->appendQueryObjectFields ($ objectBuilder , $ objectName , $ objectArray ['fields ' ]);
174191 $ objectBuilder ->build ();
175192
193+ if (!empty ($ objectArray ['interfaces ' ])) {
194+ $ this ->registerInterfaces ($ objectName , array_column ($ objectArray ['interfaces ' ], 'name ' ));
195+ }
196+
197+ if ($ objectArray ['kind ' ] === FieldTypeKindEnum::INTERFACE_OBJECT ) {
198+ $ this ->registerInterface ($ objectName , $ objectBuilder );
199+ }
200+
176201 return true ;
177202 }
178203
@@ -274,6 +299,32 @@ protected function generateUnionObject(string $objectName): bool
274299 return true ;
275300 }
276301
302+ /**
303+ * @param string $objectName
304+ *
305+ * @return bool
306+ */
307+ protected function generateInterfaceObject (string $ objectName ): bool
308+ {
309+ if (array_key_exists ($ objectName , $ this ->generatedObjects )) {
310+ return true ;
311+ }
312+
313+ $ this ->generatedObjects [$ objectName ] = true ;
314+
315+ $ objectArray = $ this ->schemaInspector ->getObjectSchema ($ objectName );
316+ $ objectName = $ objectArray ['name ' ];
317+ $ objectBuilder = new UnionObjectBuilder ($ this ->writeDir , $ objectName , $ this ->generationNamespace );
318+
319+ foreach ($ objectArray ['possibleTypes ' ] as $ possibleType ) {
320+ $ this ->generateObject ($ possibleType ['name ' ], $ possibleType ['kind ' ]);
321+ $ objectBuilder ->addPossibleType ($ possibleType ['name ' ]);
322+ }
323+ $ objectBuilder ->build ();
324+
325+ return true ;
326+ }
327+
277328 /**
278329 * @param string $argsObjectName
279330 * @param array $arguments
@@ -367,4 +418,30 @@ public function getWriteDir(): string
367418
368419 return $ this ->writeDir ;
369420 }
421+
422+ private function registerInterfaces ($ objectName , array $ interfaceNames ): void
423+ {
424+ foreach ($ interfaceNames as $ interfaceName ) {
425+ if (isset ($ this ->generatedInterfaces [$ interfaceName ]) && is_object ($ this ->generatedInterfaces [$ interfaceName ])) {
426+ // The interface was already processed, add this implementation.
427+ $ this ->generatedInterfaces [$ interfaceName ]->addImplementation ($ objectName );
428+ $ this ->generatedInterfaces [$ interfaceName ]->build ();
429+ } else {
430+ // The interface is not yet processed, remember this implementation for later.
431+ $ this ->generatedInterfaces [$ interfaceName ][] = $ objectName ;
432+ }
433+ }
434+ }
435+
436+ private function registerInterface ($ interfaceName , InterfaceObjectBuilder $ objectBuilder ): void
437+ {
438+ // Check if any implementations were found before this interface was processed.
439+ if (isset ($ this ->generatedInterfaces [$ interfaceName ])) {
440+ foreach ($ this ->generatedInterfaces [$ interfaceName ] as $ implementation ) {
441+ $ objectBuilder ->addImplementation ($ implementation );
442+ }
443+ }
444+
445+ $ this ->generatedInterfaces [$ interfaceName ] = $ objectBuilder ;
446+ }
370447}
0 commit comments