Skip to content

Commit 9247674

Browse files
authored
Merge pull request #84 from wol-soft/optionalConst
Optional const
2 parents 488f687 + c6ce299 commit 9247674

23 files changed

+595
-44
lines changed

src/Model/Validator/ExtractedMethodValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function __construct(
5959
public function getCode(): string
6060
{
6161
$renderHelper = new RenderHelper($this->generatorConfiguration);
62-
return "private function {$this->validator->getExtractedMethodName()}(&\$value): void {
62+
return "private function {$this->validator->getExtractedMethodName()}(&\$value, \$modelData): void {
6363
{$this->validator->getValidatorSetUp()}
6464
6565
if ({$this->validator->getCheck()}) {

src/Model/Validator/PropertyNamesValidator.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PHPModelGenerator\Model\Schema;
1111
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
1212
use PHPModelGenerator\Model\Validator;
13+
use PHPModelGenerator\PropertyProcessor\Property\ConstProcessor;
1314
use PHPModelGenerator\PropertyProcessor\Property\StringProcessor;
1415
use PHPModelGenerator\PropertyProcessor\PropertyMetaDataCollection;
1516
use PHPModelGenerator\SchemaProcessor\SchemaProcessor;
@@ -38,7 +39,15 @@ public function __construct(
3839
) {
3940
$this->isResolved = true;
4041

41-
$nameValidationProperty = (new StringProcessor(new PropertyMetaDataCollection(), $schemaProcessor, $schema))
42+
$processor = array_key_exists('const', $propertiesNames->getJson())
43+
? ConstProcessor::class
44+
: StringProcessor::class;
45+
46+
if ($processor === ConstProcessor::class && gettype($propertiesNames->getJson()['const']) !== 'string') {
47+
throw new SchemaException("Invalid const property name in file {$propertiesNames->getFile()}");
48+
}
49+
50+
$nameValidationProperty = (new $processor(new PropertyMetaDataCollection(), $schemaProcessor, $schema))
4251
->process('property name', $propertiesNames)
4352
// the property name validator doesn't need type checks or required checks so simply filter them out
4453
->filterValidators(static function (Validator $validator): bool {

src/PropertyProcessor/Property/AbstractPropertyProcessor.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,9 @@ protected function addComposedValueValidator(PropertyInterface $property, JsonSc
213213
$propertySchema->withJson([
214214
'type' => $composedValueKeyword,
215215
'propertySchema' => $propertySchema,
216-
'onlyForDefinedValues' => !($this instanceof BaseProcessor) && !$property->isRequired(),
216+
'onlyForDefinedValues' => !($this instanceof BaseProcessor) &&
217+
(!$property->isRequired()
218+
&& $this->schemaProcessor->getGeneratorConfiguration()->isImplicitNullAllowed()),
217219
]),
218220
);
219221

src/PropertyProcessor/Property/ArrayProcessor.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
use PHPModelGenerator\Model\Property\PropertyInterface;
1717
use PHPModelGenerator\Model\Property\PropertyType;
1818
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
19+
use PHPModelGenerator\Model\Validator;
1920
use PHPModelGenerator\Model\Validator\AdditionalItemsValidator;
2021
use PHPModelGenerator\Model\Validator\ArrayItemValidator;
2122
use PHPModelGenerator\Model\Validator\ArrayTupleValidator;
2223
use PHPModelGenerator\Model\Validator\PropertyTemplateValidator;
2324
use PHPModelGenerator\Model\Validator\PropertyValidator;
25+
use PHPModelGenerator\Model\Validator\RequiredPropertyValidator;
2426
use PHPModelGenerator\PropertyProcessor\Decorator\Property\DefaultArrayToEmptyArrayDecorator;
2527
use PHPModelGenerator\PropertyProcessor\PropertyMetaDataCollection;
2628
use PHPModelGenerator\PropertyProcessor\PropertyFactory;
@@ -253,16 +255,21 @@ private function addContainsValidation(PropertyInterface $property, JsonSchema $
253255
return;
254256
}
255257

258+
$name = "item of array {$property->getName()}";
256259
// an item of the array behaves like a nested property to add item-level validation
257260
$nestedProperty = (new PropertyFactory(new PropertyProcessorFactory()))
258261
->create(
259-
new PropertyMetaDataCollection(),
262+
new PropertyMetaDataCollection([$name]),
260263
$this->schemaProcessor,
261264
$this->schema,
262-
"item of array {$property->getName()}",
265+
$name,
263266
$propertySchema->withJson($propertySchema->getJson()[self::JSON_FIELD_CONTAINS]),
264267
);
265268

269+
$nestedProperty->filterValidators(static function (Validator $validator): bool {
270+
return !is_a($validator->getValidator(), RequiredPropertyValidator::class);
271+
});
272+
266273
$property->addValidator(
267274
new PropertyTemplateValidator(
268275
$property,

src/PropertyProcessor/Property/ConstProcessor.php

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
use PHPModelGenerator\Model\Property\PropertyType;
1111
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
1212
use PHPModelGenerator\Model\Validator\PropertyValidator;
13-
use PHPModelGenerator\PropertyProcessor\PropertyProcessorInterface;
13+
use PHPModelGenerator\Utils\RenderHelper;
1414
use PHPModelGenerator\Utils\TypeConverter;
1515

1616
/**
1717
* Class ConstProcessor
1818
*
1919
* @package PHPModelGenerator\PropertyProcessor\Property
2020
*/
21-
class ConstProcessor implements PropertyProcessorInterface
21+
class ConstProcessor extends AbstractPropertyProcessor
2222
{
2323
/**
2424
* @inheritdoc
@@ -34,13 +34,26 @@ public function process(string $propertyName, JsonSchema $propertySchema): Prope
3434
$json['description'] ?? '',
3535
);
3636

37-
return $property
38-
->setRequired(true)
39-
->addValidator(new PropertyValidator(
40-
$property,
41-
'$value !== ' . var_export($json['const'], true),
42-
InvalidConstException::class,
43-
[$json['const']],
44-
));
37+
$property->setRequired($this->propertyMetaDataCollection->isAttributeRequired($propertyName));
38+
39+
$check = match(true) {
40+
$property->isRequired()
41+
=> '$value !== ' . var_export($json['const'], true),
42+
$this->isImplicitNullAllowed($property)
43+
=> '!in_array($value, ' . RenderHelper::varExportArray([$json['const'], null]) . ', true)',
44+
default
45+
=> "array_key_exists('{$property->getName()}', \$modelData) && \$value !== " . var_export($json['const'], true),
46+
};
47+
48+
$property->addValidator(new PropertyValidator(
49+
$property,
50+
$check,
51+
InvalidConstException::class,
52+
[$json['const']],
53+
));
54+
55+
$this->generateValidators($property, $propertySchema);
56+
57+
return $property;
4558
}
4659
}

src/Templates/Validator/AdditionalProperties.phptpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(function () use ($properties, &$invalidProperties) {
1+
(function () use ($properties, &$invalidProperties, $modelData) {
22
{% if generatorConfiguration.collectErrors() %}
33
$originalErrorRegistry = $this->_errorRegistry;
44
{% endif %}

src/Templates/Validator/ArrayItem.phptpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
is_array($value) && (function (&$items) use (&$invalidItems{{ suffix }}) {
1+
is_array($value) && (function (&$items) use (&$invalidItems{{ suffix }}, $modelData) {
22
{% if generatorConfiguration.collectErrors() %}
33
$originalErrorRegistry = $this->_errorRegistry;
44
{% endif %}

src/Templates/Validator/ArrayTuple.phptpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
is_array($value) && (function (&$items) use (&$invalidTuples) {
1+
is_array($value) && (function (&$items) use (&$invalidTuples, $modelData) {
22
{% if generatorConfiguration.collectErrors() %}
33
$originalErrorRegistry = $this->_errorRegistry;
44
{% endif %}

src/Templates/Validator/PatternProperties.phptpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(function () use ($properties, &$invalidProperties) {
1+
(function () use ($properties, &$invalidProperties, $modelData) {
22
{% if generatorConfiguration.collectErrors() %}
33
$originalErrorRegistry = $this->_errorRegistry;
44
{% endif %}

src/Utils/RenderHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public function renderValidator(PropertyValidatorInterface $validator, Schema $s
182182
$schema->addMethod($validator->getExtractedMethodName(), $validator->getMethod());
183183
}
184184

185-
return "\$this->{$validator->getExtractedMethodName()}(\$value);";
185+
return "\$this->{$validator->getExtractedMethodName()}(\$value, \$modelData);";
186186
}
187187

188188
public function renderMethods(Schema $schema): string

tests/Basic/PropertyNamesTest.php

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

55
namespace PHPModelGenerator\Tests\Basic;
66

7+
use PHPModelGenerator\Exception\SchemaException;
78
use PHPModelGenerator\Model\GeneratorConfiguration;
89
use PHPModelGenerator\Tests\AbstractPHPModelGeneratorTestCase;
910

@@ -84,6 +85,12 @@ public function validPropertyNamesDataProvider(): array
8485
'test1298398717931793179317937197931' => 2,
8586
],
8687
],
88+
'const' => [
89+
'{"const": "test"}',
90+
[
91+
'test' => 1,
92+
],
93+
],
8794
],
8895
);
8996
}
@@ -166,6 +173,21 @@ public function invalidPropertyNamesDataProvider(): array
166173
* Value for property name doesn't match pattern ^test[0-9]+$
167174
- invalid property 'test'
168175
* Value for property name doesn't match pattern ^test[0-9]+$
176+
ERROR
177+
],
178+
'const violation' => [
179+
'{"const": "test"}',
180+
[
181+
'test1' => 1,
182+
'test' => 2,
183+
'bla' => 3,
184+
],
185+
<<<ERROR
186+
contains properties with invalid names.
187+
- invalid property 'test1'
188+
* Invalid value for property name declined by const constraint
189+
- invalid property 'bla'
190+
* Invalid value for property name declined by const constraint
169191
ERROR
170192
],
171193
],
@@ -211,4 +233,12 @@ public function invalidCombinedPropertyNamesDataProvider(): array
211233
],
212234
];
213235
}
236+
237+
public function testInvalidConstPropertyNamesThrowsAnException(): void
238+
{
239+
$this->expectException(SchemaException::class);
240+
$this->expectExceptionMessageMatches('/Invalid const property name in file/');
241+
242+
$this->generateClassFromFileTemplate('PropertyNames.json', ['{"const": false}'], escape: false);
243+
}
214244
}

tests/Objects/ArrayPropertyTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,6 @@ public function validArrayContainsDataProvider(): array
683683
return $this->combineDataProvider(
684684
$this->validationMethodDataProvider(),
685685
[
686-
'null' => [[3, null, true]],
687686
'empty string' => [[3, '', true]],
688687
'lowercase string' => [[3, 'abc', true]],
689688
'uppercase string' => [[3, 'AB', true]],

0 commit comments

Comments
 (0)