Skip to content

Commit e1968a0

Browse files
authored
Merge pull request #69 from wol-soft/65-recursive-reference-resolving
Fix regression introduced by #68
2 parents b3deda8 + adde3ad commit e1968a0

File tree

8 files changed

+135
-16
lines changed

8 files changed

+135
-16
lines changed

src/Model/Validator/PropertyTemplateValidator.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPMicroTemplate\Render;
99
use PHPModelGenerator\Exception\RenderException;
1010
use PHPModelGenerator\Model\Property\PropertyInterface;
11+
use PHPModelGenerator\Model\Schema;
1112

1213
/**
1314
* Class PropertyTemplateValidator
@@ -45,6 +46,13 @@ public function __construct(
4546
parent::__construct($property, $exceptionClass, $exceptionParams);
4647
}
4748

49+
public function setScope(Schema $schema): void
50+
{
51+
if (isset($this->templateValues['schema'])) {
52+
$this->templateValues['schema'] = $schema;
53+
}
54+
}
55+
4856
/**
4957
* Get the source code for the check to perform
5058
*

src/PropertyProcessor/Property/BaseProcessor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ protected function transferComposedPropertiesToSchema(PropertyInterface $propert
303303

304304
// If the transferred validator of the composed property is also a composed property strip the nested
305305
// composition validations from the added validator. The nested composition will be validated in the object
306-
// generated for the nested composition which will be executed via an instanciation. Consequently the
306+
// generated for the nested composition which will be executed via an instantiation. Consequently, the
307307
// validation must not be executed in the outer composition.
308308
$this->schema->addBaseValidator(
309309
($validator instanceof ComposedPropertyValidator)

src/SchemaProcessor/PostProcessor/Internal/AdditionalPropertiesPostProcessor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace PHPModelGenerator\SchemaProcessor\PostProcessor\Internal;
66

7-
use Exception;
7+
use PHPModelGenerator\Exception\Object\InvalidAdditionalPropertiesException;
88
use PHPModelGenerator\Exception\SchemaException;
99
use PHPModelGenerator\Model\GeneratorConfiguration;
1010
use PHPModelGenerator\Model\Property\Property;
@@ -114,7 +114,7 @@ public function __construct(Schema $schema)
114114
array_keys($schema->getJsonSchema()->getJson()['properties'] ?? [])
115115
),
116116
],
117-
Exception::class
117+
InvalidAdditionalPropertiesException::class
118118
);
119119
}
120120
}

src/Utils/RenderHelper.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPModelGenerator\Model\Property\PropertyInterface;
99
use PHPModelGenerator\Model\Schema;
1010
use PHPModelGenerator\Model\Validator\ExtractedMethodValidator;
11+
use PHPModelGenerator\Model\Validator\PropertyTemplateValidator;
1112
use PHPModelGenerator\Model\Validator\PropertyValidatorInterface;
1213

1314
/**
@@ -162,6 +163,12 @@ public function getTypeHintAnnotation(PropertyInterface $property, bool $outputT
162163

163164
public function renderValidator(PropertyValidatorInterface $validator, Schema $schema): string
164165
{
166+
// scoping of the validator might be required as validators from a composition might be transferred to a
167+
// different schema
168+
if ($validator instanceof PropertyTemplateValidator) {
169+
$validator->setScope($schema);
170+
}
171+
165172
if (!$validator instanceof ExtractedMethodValidator) {
166173
return "
167174
{$validator->getValidatorSetUp()}
@@ -184,7 +191,7 @@ public function renderMethods(Schema $schema): string
184191

185192
// don't change to a foreach loop as the render process of a method might add additional methods
186193
for ($i = 0; $i < count($schema->getMethods()); $i++) {
187-
$renderedMethods .= $schema->getMethods()[array_keys($schema->getMethods())[$i]]->getCode();
194+
$renderedMethods .= $schema->getMethods()[array_keys($schema->getMethods())[$i]]->getCode() . "\n\n";
188195
}
189196

190197
return $renderedMethods;

tests/AbstractPHPModelGeneratorTest.php

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ protected function generateClassFromFile(
138138
string $schemaProviderClass = RecursiveDirectoryProvider::class
139139
): string {
140140
return $this->generateClass(
141-
file_get_contents(__DIR__ . '/Schema/' . $this->getStaticClassName() . '/' . $file),
141+
file_get_contents($this->getSchemaFilePath($file)),
142142
$generatorConfiguration,
143143
$originalClassNames,
144144
$implicitNull,
@@ -171,16 +171,13 @@ protected function generateClassFromFileTemplate(
171171
string $schemaProviderClass = RecursiveDirectoryProvider::class
172172
): string {
173173
return $this->generateClass(
174-
call_user_func_array(
175-
'sprintf',
176-
array_merge(
177-
[file_get_contents(__DIR__ . '/Schema/' . $this->getStaticClassName() . '/' . $file)],
178-
array_map(
179-
static function (string $item) use ($escape): string {
180-
return $escape ? str_replace("'", '"', addcslashes($item, '"\\')) : $item;
181-
},
182-
$values
183-
)
174+
sprintf(
175+
file_get_contents($this->getSchemaFilePath($file)),
176+
...array_map(
177+
static function (string $item) use ($escape): string {
178+
return $escape ? str_replace("'", '"', addcslashes($item, '"\\')) : $item;
179+
},
180+
$values
184181
)
185182
),
186183
$generatorConfiguration,
@@ -517,6 +514,11 @@ protected function getGeneratedFiles(): array
517514
return $this->generatedFiles;
518515
}
519516

517+
protected function getSchemaFilePath(string $file): string
518+
{
519+
return __DIR__ . '/Schema/' . $this->getStaticClassName() . '/' . $file;
520+
}
521+
520522
/**
521523
* Generate a unique name for a class
522524
*
@@ -536,7 +538,7 @@ private function getClassName(): string
536538
return $name;
537539
}
538540

539-
private function getStaticClassName(): string
541+
protected function getStaticClassName(): string
540542
{
541543
$parts = explode('\\', static::class);
542544

tests/Issues/AbstractIssueTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PHPModelGenerator\Tests\Issues;
6+
7+
use PHPModelGenerator\Tests\AbstractPHPModelGeneratorTest;
8+
9+
abstract class AbstractIssueTest extends AbstractPHPModelGeneratorTest
10+
{
11+
protected function getSchemaFilePath(string $file): string
12+
{
13+
preg_match('/(?P<issue>\d+)/', $this->getStaticClassName(), $matches);
14+
15+
return __DIR__ . '/../Schema/Issues/' . $matches['issue'] . '/' . $file;
16+
}
17+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PHPModelGenerator\Tests\Issues\Regression;
6+
7+
use PHPModelGenerator\Exception\ComposedValue\AllOfException;
8+
use PHPModelGenerator\Tests\Issues\AbstractIssueTest;
9+
10+
class RegressionIssue65Test extends AbstractIssueTest
11+
{
12+
public function testValidInput(): void
13+
{
14+
$className = $this->generateClassFromFile('regression.json');
15+
16+
$object = new $className(['list' => [['id' => 10, 'name' => 'Hans']], 'label' => 'visitors']);
17+
18+
$this->assertSame('visitors', $object->getLabel());
19+
$this->assertCount(1, $object->getList());
20+
$this->assertSame(10, $object->getList()[0]->getId());
21+
$this->assertSame('Hans', $object->getList()[0]->getName());
22+
}
23+
24+
/**
25+
* @dataProvider invalidInputDataProvider
26+
*/
27+
public function testInvalidInput(array $input): void
28+
{
29+
$this->expectException(AllOfException::class);
30+
31+
$className = $this->generateClassFromFile('regression.json');
32+
33+
new $className($input);
34+
}
35+
36+
public function invalidInputDataProvider(): array
37+
{
38+
return [
39+
'invalid label' => [['label' => 10]],
40+
'invalid list element' => [['list' => [['id' => 10, 'name' => 'Hans'], 10]]],
41+
'invalid id in list element' => [['list' => [['id' => '10', 'name' => 'Hans']]]],
42+
'invalid name in list element' => [['list' => [['id' => 10, 'name' => false]]]],
43+
];
44+
}
45+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"allOf": [
3+
{
4+
"type": "object",
5+
"properties": {
6+
"list": {
7+
"type": "array",
8+
"items": {
9+
"allOf": [
10+
{
11+
"type": "object",
12+
"properties": {
13+
"id": {
14+
"type": "integer"
15+
}
16+
}
17+
},
18+
{
19+
"type": "object",
20+
"properties": {
21+
"name": {
22+
"type": "string"
23+
}
24+
}
25+
}
26+
]
27+
}
28+
}
29+
}
30+
},
31+
{
32+
"type": "object",
33+
"properties": {
34+
"label": {
35+
"type": "string"
36+
}
37+
}
38+
}
39+
]
40+
}

0 commit comments

Comments
 (0)