Skip to content

Commit 8355302

Browse files
committed
Support nullable
1 parent 9779bff commit 8355302

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
lines changed

src/ClassGenerator.php

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use OpenCodeModeling\CodeAst\Builder\ClassMethodBuilder;
1717
use OpenCodeModeling\CodeAst\Builder\ClassPropertyBuilder;
1818
use OpenCodeModeling\CodeAst\Code\ClassConstGenerator;
19+
use OpenCodeModeling\CodeAst\Package\ClassInfo;
1920
use OpenCodeModeling\CodeAst\Package\ClassInfoList;
2021
use OpenCodeModeling\JsonSchemaToPhp\Type\ArrayType;
2122
use OpenCodeModeling\JsonSchemaToPhp\Type\ObjectType;
@@ -59,7 +60,7 @@ public function __construct(
5960
* @param ClassBuilderCollection $classBuilderCollection Collection for other classes
6061
* @param TypeSet $typeSet
6162
* @param string $srcFolder Source folder for namespace imports
62-
* @param string|null $className Class name of other classes
63+
* @param string|null $className Class name is used from $classBuilder if not set
6364
* @return void
6465
*/
6566
public function generateClasses(
@@ -79,6 +80,7 @@ public function generateClasses(
7980
) {
8081
$type = $refType->first();
8182
}
83+
$className = $className ?: $classBuilder->getName();
8284

8385
switch (true) {
8486
case $type instanceof ObjectType:
@@ -117,7 +119,12 @@ public function generateClasses(
117119
$propertyClassName
118120
);
119121
$classBuilder->addNamespaceImport($classNamespace . '\\' . $propertyClassName);
120-
$classBuilder->addProperty(ClassPropertyBuilder::fromScratch($propertyPropertyName, $propertyClassName));
122+
$classBuilder->addProperty(
123+
ClassPropertyBuilder::fromScratch(
124+
$propertyPropertyName,
125+
$propertyType->isNullable() ? ('?' . $propertyClassName) : $propertyClassName
126+
)
127+
);
121128
break;
122129
case $propertyType instanceof ReferenceType:
123130
if ($propertyRefType = $propertyType->resolvedType()) {
@@ -132,7 +139,10 @@ public function generateClasses(
132139
$classBuilder->addNamespaceImport($classNamespace . '\\' . $propertyClassName);
133140
}
134141
$classBuilder->addProperty(
135-
ClassPropertyBuilder::fromScratch($propertyPropertyName, $propertyClassName)
142+
ClassPropertyBuilder::fromScratch(
143+
$propertyPropertyName,
144+
$propertyType->isNullable() ? ('?' . $propertyClassName) : $propertyClassName
145+
)
136146
);
137147
break;
138148
case $propertyType instanceof ScalarType:
@@ -143,7 +153,7 @@ public function generateClasses(
143153
$classBuilder->addProperty(
144154
ClassPropertyBuilder::fromScratch(
145155
$propertyPropertyName,
146-
$propertyClassName
156+
$propertyType->isNullable() ? ('?' . $propertyClassName) : $propertyClassName
147157
)
148158
);
149159
break;
@@ -246,15 +256,23 @@ public function generateValueObject(string $className, string $classNamespace, T
246256
* @param ClassBuilderCollection $classBuilderCollection
247257
* @param Parser $parser
248258
* @param PrettyPrinterAbstract $printer
259+
* @param callable|null $currentFileAst Callable to return current file AST, if null, file will be overwritten
249260
* @return array<string, string> List of filename => code
250261
*/
251262
public function generateFiles(
252263
ClassBuilderCollection $classBuilderCollection,
253264
Parser $parser,
254-
PrettyPrinterAbstract $printer
265+
PrettyPrinterAbstract $printer,
266+
callable $currentFileAst = null
255267
): array {
256268
$files = [];
257269

270+
if ($currentFileAst === null) {
271+
$currentFileAst = static function (ClassBuilder $classBuilder, ClassInfo $classInfo) {
272+
return [];
273+
};
274+
}
275+
258276
$previousNamespace = '__invalid//namespace__';
259277

260278
foreach ($classBuilderCollection as $classBuilder) {
@@ -269,7 +287,10 @@ public function generateFiles(
269287
$nodeTraverser = new NodeTraverser();
270288
$classBuilder->injectVisitors($nodeTraverser, $parser);
271289

272-
$files[$filename] = $printer->prettyPrintFile($nodeTraverser->traverse([]));
290+
$files[$filename] = $printer->prettyPrintFile(
291+
// @phpstan-ignore-next-line
292+
$nodeTraverser->traverse($currentFileAst($classBuilder, $classInfo))
293+
);
273294
}
274295

275296
return $files;

tests/ClassGeneratorTest.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ private function assertBillingAddress(ClassBuilder $classBuilder): void
185185
$this->assertArrayHasKey('federalState', $properties);
186186
$this->assertArrayHasKey('streetAddress', $properties);
187187

188+
$this->assertSame('?City', $properties['city']->getType());
189+
$this->assertSame('State', $properties['federalState']->getType());
190+
$this->assertSame('StreetAddress', $properties['streetAddress']->getType());
191+
188192
$this->assertCount(3, $classBuilder->getNamespaceImports());
189193
$this->assertSame(
190194
['Acme\\StreetAddress' => 'Acme\\StreetAddress', 'Acme\\City' => 'Acme\\City', 'Acme\\State' => 'Acme\\State'],
@@ -230,6 +234,10 @@ private function assertAddress(ClassBuilder $classBuilder): void
230234
$this->assertArrayHasKey('federalState', $properties);
231235
$this->assertArrayHasKey('streetAddress', $properties);
232236

237+
$this->assertSame('?City', $properties['city']->getType());
238+
$this->assertSame('State', $properties['federalState']->getType());
239+
$this->assertSame('StreetAddress', $properties['streetAddress']->getType());
240+
233241
$this->assertCount(3, $classBuilder->getNamespaceImports());
234242
$this->assertSame(
235243
['Acme\\StreetAddress' => 'Acme\\StreetAddress', 'Acme\\City' => 'Acme\\City', 'Acme\\State' => 'Acme\\State'],
@@ -477,13 +485,13 @@ final class Address
477485
public const CITY = 'city';
478486
public const FEDERAL_STATE = 'federal_state';
479487
private StreetAddress $streetAddress;
480-
private City $city;
488+
private ?City $city;
481489
private State $federalState;
482490
public function streetAddress() : StreetAddress
483491
{
484492
return $this->streetAddress;
485493
}
486-
public function city() : City
494+
public function city() : ?City
487495
{
488496
return $this->city;
489497
}
@@ -513,13 +521,13 @@ final class BillingAddress
513521
public const CITY = 'city';
514522
public const FEDERAL_STATE = 'federal_state';
515523
private StreetAddress $streetAddress;
516-
private City $city;
524+
private ?City $city;
517525
private State $federalState;
518526
public function streetAddress() : StreetAddress
519527
{
520528
return $this->streetAddress;
521529
}
522-
public function city() : City
530+
public function city() : ?City
523531
{
524532
return $this->city;
525533
}

tests/_files/schema_with_objects.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"type": "string"
99
},
1010
"city": {
11-
"type": "string"
11+
"type": ["string", "null"]
1212
},
1313
"federal_state": {
1414
"$ref": "#/definitions/state"

0 commit comments

Comments
 (0)