Skip to content

Commit

Permalink
Merge pull request #84 from wol-soft/optionalConst
Browse files Browse the repository at this point in the history
Optional const
  • Loading branch information
wol-soft authored Sep 19, 2024
2 parents 488f687 + c6ce299 commit 9247674
Show file tree
Hide file tree
Showing 23 changed files with 595 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/Model/Validator/ExtractedMethodValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function __construct(
public function getCode(): string
{
$renderHelper = new RenderHelper($this->generatorConfiguration);
return "private function {$this->validator->getExtractedMethodName()}(&\$value): void {
return "private function {$this->validator->getExtractedMethodName()}(&\$value, \$modelData): void {
{$this->validator->getValidatorSetUp()}
if ({$this->validator->getCheck()}) {
Expand Down
11 changes: 10 additions & 1 deletion src/Model/Validator/PropertyNamesValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use PHPModelGenerator\Model\Schema;
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
use PHPModelGenerator\Model\Validator;
use PHPModelGenerator\PropertyProcessor\Property\ConstProcessor;
use PHPModelGenerator\PropertyProcessor\Property\StringProcessor;
use PHPModelGenerator\PropertyProcessor\PropertyMetaDataCollection;
use PHPModelGenerator\SchemaProcessor\SchemaProcessor;
Expand Down Expand Up @@ -38,7 +39,15 @@ public function __construct(
) {
$this->isResolved = true;

$nameValidationProperty = (new StringProcessor(new PropertyMetaDataCollection(), $schemaProcessor, $schema))
$processor = array_key_exists('const', $propertiesNames->getJson())
? ConstProcessor::class
: StringProcessor::class;

if ($processor === ConstProcessor::class && gettype($propertiesNames->getJson()['const']) !== 'string') {
throw new SchemaException("Invalid const property name in file {$propertiesNames->getFile()}");
}

$nameValidationProperty = (new $processor(new PropertyMetaDataCollection(), $schemaProcessor, $schema))
->process('property name', $propertiesNames)
// the property name validator doesn't need type checks or required checks so simply filter them out
->filterValidators(static function (Validator $validator): bool {
Expand Down
4 changes: 3 additions & 1 deletion src/PropertyProcessor/Property/AbstractPropertyProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@ protected function addComposedValueValidator(PropertyInterface $property, JsonSc
$propertySchema->withJson([
'type' => $composedValueKeyword,
'propertySchema' => $propertySchema,
'onlyForDefinedValues' => !($this instanceof BaseProcessor) && !$property->isRequired(),
'onlyForDefinedValues' => !($this instanceof BaseProcessor) &&
(!$property->isRequired()
&& $this->schemaProcessor->getGeneratorConfiguration()->isImplicitNullAllowed()),
]),
);

Expand Down
11 changes: 9 additions & 2 deletions src/PropertyProcessor/Property/ArrayProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
use PHPModelGenerator\Model\Property\PropertyInterface;
use PHPModelGenerator\Model\Property\PropertyType;
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
use PHPModelGenerator\Model\Validator;
use PHPModelGenerator\Model\Validator\AdditionalItemsValidator;
use PHPModelGenerator\Model\Validator\ArrayItemValidator;
use PHPModelGenerator\Model\Validator\ArrayTupleValidator;
use PHPModelGenerator\Model\Validator\PropertyTemplateValidator;
use PHPModelGenerator\Model\Validator\PropertyValidator;
use PHPModelGenerator\Model\Validator\RequiredPropertyValidator;
use PHPModelGenerator\PropertyProcessor\Decorator\Property\DefaultArrayToEmptyArrayDecorator;
use PHPModelGenerator\PropertyProcessor\PropertyMetaDataCollection;
use PHPModelGenerator\PropertyProcessor\PropertyFactory;
Expand Down Expand Up @@ -253,16 +255,21 @@ private function addContainsValidation(PropertyInterface $property, JsonSchema $
return;
}

$name = "item of array {$property->getName()}";
// an item of the array behaves like a nested property to add item-level validation
$nestedProperty = (new PropertyFactory(new PropertyProcessorFactory()))
->create(
new PropertyMetaDataCollection(),
new PropertyMetaDataCollection([$name]),
$this->schemaProcessor,
$this->schema,
"item of array {$property->getName()}",
$name,
$propertySchema->withJson($propertySchema->getJson()[self::JSON_FIELD_CONTAINS]),
);

$nestedProperty->filterValidators(static function (Validator $validator): bool {
return !is_a($validator->getValidator(), RequiredPropertyValidator::class);
});

$property->addValidator(
new PropertyTemplateValidator(
$property,
Expand Down
33 changes: 23 additions & 10 deletions src/PropertyProcessor/Property/ConstProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
use PHPModelGenerator\Model\Property\PropertyType;
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
use PHPModelGenerator\Model\Validator\PropertyValidator;
use PHPModelGenerator\PropertyProcessor\PropertyProcessorInterface;
use PHPModelGenerator\Utils\RenderHelper;
use PHPModelGenerator\Utils\TypeConverter;

/**
* Class ConstProcessor
*
* @package PHPModelGenerator\PropertyProcessor\Property
*/
class ConstProcessor implements PropertyProcessorInterface
class ConstProcessor extends AbstractPropertyProcessor
{
/**
* @inheritdoc
Expand All @@ -34,13 +34,26 @@ public function process(string $propertyName, JsonSchema $propertySchema): Prope
$json['description'] ?? '',
);

return $property
->setRequired(true)
->addValidator(new PropertyValidator(
$property,
'$value !== ' . var_export($json['const'], true),
InvalidConstException::class,
[$json['const']],
));
$property->setRequired($this->propertyMetaDataCollection->isAttributeRequired($propertyName));

$check = match(true) {
$property->isRequired()
=> '$value !== ' . var_export($json['const'], true),
$this->isImplicitNullAllowed($property)
=> '!in_array($value, ' . RenderHelper::varExportArray([$json['const'], null]) . ', true)',
default
=> "array_key_exists('{$property->getName()}', \$modelData) && \$value !== " . var_export($json['const'], true),
};

$property->addValidator(new PropertyValidator(
$property,
$check,
InvalidConstException::class,
[$json['const']],
));

$this->generateValidators($property, $propertySchema);

return $property;
}
}
2 changes: 1 addition & 1 deletion src/Templates/Validator/AdditionalProperties.phptpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(function () use ($properties, &$invalidProperties) {
(function () use ($properties, &$invalidProperties, $modelData) {
{% if generatorConfiguration.collectErrors() %}
$originalErrorRegistry = $this->_errorRegistry;
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion src/Templates/Validator/ArrayItem.phptpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
is_array($value) && (function (&$items) use (&$invalidItems{{ suffix }}) {
is_array($value) && (function (&$items) use (&$invalidItems{{ suffix }}, $modelData) {
{% if generatorConfiguration.collectErrors() %}
$originalErrorRegistry = $this->_errorRegistry;
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion src/Templates/Validator/ArrayTuple.phptpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
is_array($value) && (function (&$items) use (&$invalidTuples) {
is_array($value) && (function (&$items) use (&$invalidTuples, $modelData) {
{% if generatorConfiguration.collectErrors() %}
$originalErrorRegistry = $this->_errorRegistry;
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion src/Templates/Validator/PatternProperties.phptpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(function () use ($properties, &$invalidProperties) {
(function () use ($properties, &$invalidProperties, $modelData) {
{% if generatorConfiguration.collectErrors() %}
$originalErrorRegistry = $this->_errorRegistry;
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion src/Utils/RenderHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ public function renderValidator(PropertyValidatorInterface $validator, Schema $s
$schema->addMethod($validator->getExtractedMethodName(), $validator->getMethod());
}

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

public function renderMethods(Schema $schema): string
Expand Down
30 changes: 30 additions & 0 deletions tests/Basic/PropertyNamesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace PHPModelGenerator\Tests\Basic;

use PHPModelGenerator\Exception\SchemaException;
use PHPModelGenerator\Model\GeneratorConfiguration;
use PHPModelGenerator\Tests\AbstractPHPModelGeneratorTestCase;

Expand Down Expand Up @@ -84,6 +85,12 @@ public function validPropertyNamesDataProvider(): array
'test1298398717931793179317937197931' => 2,
],
],
'const' => [
'{"const": "test"}',
[
'test' => 1,
],
],
],
);
}
Expand Down Expand Up @@ -166,6 +173,21 @@ public function invalidPropertyNamesDataProvider(): array
* Value for property name doesn't match pattern ^test[0-9]+$
- invalid property 'test'
* Value for property name doesn't match pattern ^test[0-9]+$
ERROR
],
'const violation' => [
'{"const": "test"}',
[
'test1' => 1,
'test' => 2,
'bla' => 3,
],
<<<ERROR
contains properties with invalid names.
- invalid property 'test1'
* Invalid value for property name declined by const constraint
- invalid property 'bla'
* Invalid value for property name declined by const constraint
ERROR
],
],
Expand Down Expand Up @@ -211,4 +233,12 @@ public function invalidCombinedPropertyNamesDataProvider(): array
],
];
}

public function testInvalidConstPropertyNamesThrowsAnException(): void
{
$this->expectException(SchemaException::class);
$this->expectExceptionMessageMatches('/Invalid const property name in file/');

$this->generateClassFromFileTemplate('PropertyNames.json', ['{"const": false}'], escape: false);
}
}
1 change: 0 additions & 1 deletion tests/Objects/ArrayPropertyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,6 @@ public function validArrayContainsDataProvider(): array
return $this->combineDataProvider(
$this->validationMethodDataProvider(),
[
'null' => [[3, null, true]],
'empty string' => [[3, '', true]],
'lowercase string' => [[3, 'abc', true]],
'uppercase string' => [[3, 'AB', true]],
Expand Down
Loading

0 comments on commit 9247674

Please sign in to comment.