Skip to content

Commit 05be1d0

Browse files
committed
Validate required properties which aren't defined in the properties section of a schema (fixes #44)
1 parent f31b216 commit 05be1d0

File tree

6 files changed

+66
-14
lines changed

6 files changed

+66
-14
lines changed

docs/source/complexTypes/object.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,11 @@ Possible exceptions:
158158

159159
* Missing required value for name
160160

161-
.. warning::
161+
.. hint::
162+
163+
Properties defined in the `required` array but not defined in the `properties` will be added to the interface of the generated class.
162164

163-
Properties defined in the `required` array but not defined in the `properties` section of the object aren't validated. Consequently provided objects missing these fields may be considered valid.
165+
A schema defining only the required property `example` consequently will provide the methods `getExample(): mixed` and `setExample(mixed $value): self`.
164166

165167
Size
166168
----

src/PropertyProcessor/Property/BaseProcessor.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,14 @@ protected function addPropertiesToSchema(JsonSchema $propertySchema): void
262262
$json['dependencies'] ?? []
263263
);
264264

265-
foreach ($json['properties'] ?? [] as $propertyName => $propertyStructure) {
265+
$json['properties'] = $json['properties'] ?? [];
266+
// setup empty properties for required properties which aren't defined in the properties section of the schema
267+
$json['properties'] += array_fill_keys(
268+
array_diff($json['required'] ?? [], array_keys($json['properties'])),
269+
[]
270+
);
271+
272+
foreach ($json['properties'] as $propertyName => $propertyStructure) {
266273
$this->schema->addProperty(
267274
$propertyFactory->create(
268275
$propertyMetaDataCollection,

tests/Objects/EnumPropertyTest.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,13 @@ function ($item) {
392392

393393
return $this->generateClassFromFileTemplate(
394394
'EnumProperty.json',
395-
[$type, sprintf('[%s]', join(',', $enumValues)), $required ? 'property' : '']
395+
[
396+
$type,
397+
str_replace("'", '"', sprintf('[%s]', join(',', $enumValues))),
398+
$required ? ',"required": ["property"]' : '',
399+
],
400+
null,
401+
false
396402
);
397403
}
398404
}

tests/Objects/RequiredPropertyTest.php

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,41 +26,52 @@ class RequiredPropertyTest extends AbstractPHPModelGeneratorTest
2626
* @throws RenderException
2727
* @throws SchemaException
2828
*/
29-
public function testRequiredPropertyIsValidIfProvided(bool $implicitNull, string $propertyValue): void
29+
public function testRequiredPropertyIsValidIfProvided(bool $implicitNull, string $file, string $propertyValue): void
3030
{
31-
$className = $this->generateClassFromFile('RequiredStringProperty.json', null, false, $implicitNull);
31+
$className = $this->generateClassFromFile($file, null, false, $implicitNull);
3232

3333
$object = new $className(['property' => $propertyValue]);
3434
$this->assertSame($propertyValue, $object->getProperty());
3535
}
3636

37-
public function validStringPropertyValueProvider(): array
37+
public function requiredDefinitionsDataProvider(): array
3838
{
3939
return $this->combineDataProvider(
4040
$this->implicitNullDataProvider(),
41+
[
42+
'Defined property' => ['RequiredStringProperty.json'],
43+
'Undefined property' => ['RequiredUndefinedProperty.json'],
44+
]
45+
);
46+
}
47+
48+
public function validStringPropertyValueProvider(): array
49+
{
50+
return $this->combineDataProvider(
51+
$this->requiredDefinitionsDataProvider(),
4152
[
4253
'Hello' => ['Hello'],
43-
'Empty string' => ['']
54+
'Empty string' => [''],
4455
]
4556
);
4657
}
4758

4859
/**
49-
* @dataProvider implicitNullDataProvider
60+
* @dataProvider requiredDefinitionsDataProvider
5061
*
5162
* @param bool $implicitNull
5263
*
5364
* @throws FileSystemException
5465
* @throws RenderException
5566
* @throws SchemaException
5667
*/
57-
public function testNotProvidedRequiredPropertyThrowsAnException(bool $implicitNull): void
68+
public function testNotProvidedRequiredPropertyThrowsAnException(bool $implicitNull, string $file): void
5869
{
5970
$this->expectException(ValidationException::class);
6071
$this->expectExceptionMessage("Missing required value for property");
6172

6273
$className = $this->generateClassFromFile(
63-
'RequiredStringProperty.json',
74+
$file,
6475
(new GeneratorConfiguration())->setCollectErrors(false),
6576
false,
6677
$implicitNull
@@ -69,7 +80,6 @@ public function testNotProvidedRequiredPropertyThrowsAnException(bool $implicitN
6980
new $className([]);
7081
}
7182

72-
7383
/**
7484
* @dataProvider implicitNullDataProvider
7585
*
@@ -93,6 +103,27 @@ public function testRequiredPropertyType(bool $implicitNull): void
93103
$this->assertFalse($setType->allowsNull());
94104
}
95105

106+
/**
107+
* @dataProvider implicitNullDataProvider
108+
*
109+
* @param bool $implicitNull
110+
*/
111+
public function testUndefinedRequiredPropertyType(bool $implicitNull): void
112+
{
113+
$className = $this->generateClassFromFile(
114+
'RequiredUndefinedProperty.json',
115+
(new GeneratorConfiguration())->setImmutable(false),
116+
false,
117+
$implicitNull
118+
);
119+
120+
$this->assertNull($this->getReturnType($className, 'getProperty'));
121+
$this->assertSame('mixed', $this->getMethodReturnTypeAnnotation($className, 'getProperty'));
122+
123+
$this->assertNull($this->getParameterType($className, 'setProperty'));
124+
$this->assertSame('mixed', $this->getMethodParameterTypeAnnotation($className, 'setProperty'));
125+
}
126+
96127
/**
97128
* @dataProvider implicitNullDataProvider
98129
*

tests/Schema/EnumPropertyTest/EnumProperty.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
"type": "%s",
66
"enum": %s
77
}
8-
},
9-
"required": ["%s"]
8+
}
9+
%s
1010
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "object",
3+
"required": [
4+
"property"
5+
]
6+
}

0 commit comments

Comments
 (0)