Skip to content

Commit 9891a4f

Browse files
committed
Import reused classes for objects nested in a combined schema
1 parent 9a35466 commit 9891a4f

File tree

7 files changed

+153
-31
lines changed

7 files changed

+153
-31
lines changed

src/Model/Schema.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44

55
namespace PHPModelGenerator\Model;
66

7-
use Exception;
8-
use PHPModelGenerator\Exception\SchemaException;
97
use PHPModelGenerator\Model\Property\Property;
108
use PHPModelGenerator\Model\Property\PropertyInterface;
119
use PHPModelGenerator\Model\SchemaDefinition\SchemaDefinitionDictionary;
1210
use PHPModelGenerator\Model\Validator\PropertyValidator;
1311
use PHPModelGenerator\Model\Validator\PropertyValidatorInterface;
12+
use PHPModelGenerator\PropertyProcessor\Decorator\SchemaNamespaceTransferDecorator;
1413

1514
/**
1615
* Class Schema
@@ -31,6 +30,8 @@ class Schema
3130
protected $baseValidators = [];
3231
/** @var array */
3332
protected $usedClasses = [];
33+
/** @var SchemaNamespaceTransferDecorator[] */
34+
protected $namespaceTransferDecorators = [];
3435

3536
/** @var SchemaDefinitionDictionary */
3637
protected $schemaDefinitionDictionary;
@@ -129,11 +130,29 @@ public function addUsedClass(string $path): self
129130
return $this;
130131
}
131132

133+
/**
134+
* @param SchemaNamespaceTransferDecorator $decorator
135+
*
136+
* @return $this
137+
*/
138+
public function addNamespaceTransferDecorator(SchemaNamespaceTransferDecorator $decorator): self
139+
{
140+
$this->namespaceTransferDecorators[] = $decorator;
141+
142+
return $this;
143+
}
144+
132145
/**
133146
* @return array
134147
*/
135148
public function getUsedClasses(): array
136149
{
137-
return $this->usedClasses;
150+
$usedClasses = $this->usedClasses;
151+
152+
foreach ($this->namespaceTransferDecorators as $decorator) {
153+
array_push($usedClasses, ...$decorator->resolve());
154+
}
155+
156+
return $usedClasses;
138157
}
139158
}

src/PropertyProcessor/ComposedValue/AbstractComposedValueProcessor.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use PHPModelGenerator\Model\Validator\ComposedPropertyValidator;
1414
use PHPModelGenerator\Model\Validator\RequiredPropertyValidator;
1515
use PHPModelGenerator\PropertyProcessor\Decorator\Property\ObjectInstantiationDecorator;
16+
use PHPModelGenerator\PropertyProcessor\Decorator\SchemaNamespaceTransferDecorator;
1617
use PHPModelGenerator\PropertyProcessor\Decorator\TypeHint\CompositionTypeHintDecorator;
1718
use PHPModelGenerator\PropertyProcessor\Property\AbstractValueProcessor;
1819
use PHPModelGenerator\PropertyProcessor\PropertyCollectionProcessor;
@@ -188,6 +189,8 @@ protected function transferPropertiesToMergedSchema(Schema $mergedPropertySchema
188189
})
189190
);
190191
}
192+
193+
$mergedPropertySchema->addNamespaceTransferDecorator(new SchemaNamespaceTransferDecorator($this->schema));
191194
}
192195
}
193196

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\PropertyProcessor\Decorator;
6+
7+
use PHPModelGenerator\Model\Property\PropertyInterface;
8+
use PHPModelGenerator\Model\Schema;
9+
10+
/**
11+
* Class SchemaNamespaceTransferDecorator
12+
*/
13+
class SchemaNamespaceTransferDecorator
14+
{
15+
/** @var Schema */
16+
private $schema;
17+
/** @var bool */
18+
private $fetchPropertyImports;
19+
20+
/**
21+
* SchemaNamespaceTransferDecorator constructor.
22+
*
23+
* @param Schema $schema
24+
* @param bool $fetchPropertyImports
25+
*/
26+
public function __construct(Schema $schema, bool $fetchPropertyImports = false)
27+
{
28+
$this->schema = $schema;
29+
$this->fetchPropertyImports = $fetchPropertyImports;
30+
}
31+
32+
/**
33+
* Get all used classes to use the referenced schema
34+
*
35+
* @return array
36+
*/
37+
public function resolve(): array
38+
{
39+
$usedClasses = $this->schema->getUsedClasses();
40+
41+
if ($this->fetchPropertyImports) {
42+
foreach ($this->schema->getProperties() as $property) {
43+
array_push($usedClasses, ...$this->getUsedClasses($property));
44+
}
45+
}
46+
47+
return $usedClasses;
48+
}
49+
50+
/**
51+
* Fetch required imports for handling a property
52+
*
53+
* @param PropertyInterface $property
54+
*
55+
* @return array
56+
*/
57+
private function getUsedClasses(PropertyInterface $property): array
58+
{
59+
$classes = array_filter(
60+
explode('|', str_replace('[]', '', $property->getTypeHint())),
61+
function (string $type): bool {
62+
return !in_array($type, ['null', 'mixed', 'string', 'int', 'bool', 'float', 'array']);
63+
}
64+
);
65+
66+
array_walk($classes, function (string &$class): void {
67+
$class = "{$this->schema->getClassPath()}\\$class";
68+
});
69+
70+
return $classes;
71+
}
72+
}

src/PropertyProcessor/Property/ObjectProcessor.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPModelGenerator\Exception\SchemaException;
88
use PHPModelGenerator\Model\Property\PropertyInterface;
99
use PHPModelGenerator\PropertyProcessor\Decorator\Property\ObjectInstantiationDecorator;
10+
use PHPModelGenerator\PropertyProcessor\Decorator\SchemaNamespaceTransferDecorator;
1011

1112
/**
1213
* Class ObjectProcessor
@@ -42,6 +43,7 @@ public function process(string $propertyName, array $propertyData): PropertyInte
4243

4344
if ($schema->getClassPath() !== $this->schema->getClassPath()) {
4445
$this->schema->addUsedClass("{$schema->getClassPath()}\\{$schema->getClassName()}");
46+
$this->schema->addNamespaceTransferDecorator(new SchemaNamespaceTransferDecorator($schema, true));
4547
}
4648

4749
$property

tests/Basic/BasicSchemaGenerationTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,14 +276,16 @@ public function testIdenticalSchemasAreMappedToOneClassFromDifferentNamespaces()
276276
}
277277

278278
$subClass1FQCN = '\\Application\\SubFolder1\\SubSchema';
279-
$subObject1 = new $subClass1FQCN(['object1' => ['property1' => 'Hello']]);
279+
$subObject1 = new $subClass1FQCN(['object1' => ['property1' => 'Hello'], 'property3' => 3]);
280280

281281
$this->assertSame('Hello', $subObject1->getObject1()->getProperty1());
282+
$this->assertSame(3, $subObject1->getProperty3());
282283

283284
$subClass2FQCN = '\\Application\\SubFolder2\\SubSchema';
284-
$subObject2 = new $subClass2FQCN(['object1' => ['property1' => 'Goodbye']]);
285+
$subObject2 = new $subClass2FQCN(['object1' => ['property1' => 'Goodbye'], 'property3' => true]);
285286

286287
$this->assertSame('Goodbye', $subObject2->getObject1()->getProperty1());
288+
$this->assertSame(true, $subObject2->getProperty3());
287289

288290
$this->assertSame(get_class($subObject1->getObject1()), get_class($subObject2->getObject1()));
289291

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
{
2-
"type": "object",
3-
"properties": {
4-
"object1": {
2+
"allOf": [
3+
{
54
"type": "object",
65
"properties": {
7-
"property1": {
8-
"type": "string"
9-
},
10-
"property2": {
11-
"allOf": []
6+
"object1": {
7+
"type": "object",
8+
"properties": {
9+
"property1": {
10+
"type": "string"
11+
},
12+
"property2": {
13+
"allOf": []
14+
}
15+
},
16+
"required": [
17+
"property1"
18+
]
1219
}
13-
},
14-
"required": [
15-
"property1"
16-
]
20+
}
21+
},
22+
{
23+
"type": "object",
24+
"properties": {
25+
"property3": {
26+
"type": "integer"
27+
}
28+
}
1729
}
18-
}
30+
]
1931
}
Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
{
2-
"type": "object",
3-
"properties": {
4-
"object1": {
2+
"allOf": [
3+
{
54
"type": "object",
65
"properties": {
7-
"property1": {
8-
"type": "string"
9-
},
10-
"property2": {
11-
"allOf": []
6+
"object1": {
7+
"type": "object",
8+
"properties": {
9+
"property1": {
10+
"type": "string"
11+
},
12+
"property2": {
13+
"allOf": []
14+
}
15+
},
16+
"required": [
17+
"property1"
18+
]
1219
}
13-
},
14-
"required": [
15-
"property1"
16-
]
20+
}
21+
},
22+
{
23+
"type": "object",
24+
"properties": {
25+
"property3": {
26+
"type": "boolean"
27+
}
28+
}
1729
}
18-
}
30+
]
1931
}

0 commit comments

Comments
 (0)