Skip to content

Commit

Permalink
Merge pull request #78 from wol-soft/issue77_dynamicProperty
Browse files Browse the repository at this point in the history
Fix creation of dynamic property for composed item validators on properties
  • Loading branch information
wol-soft authored Sep 14, 2023
2 parents e560d20 + 0ff4f64 commit 85aa9b5
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 13 deletions.
1 change: 1 addition & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
convertErrorsToExceptions="true"
convertWarningsToExceptions="true"
convertNoticesToExceptions="true"
convertDeprecationsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
bootstrap="tests/bootstrap.php"
Expand Down
2 changes: 2 additions & 0 deletions src/Model/Validator/PropertyTemplateValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public function setScope(Schema $schema): void
if (isset($this->templateValues['schema'])) {
$this->templateValues['schema'] = $schema;
}

$this->templateValues['isBaseValidator'] = in_array($this, $schema->getBaseValidators());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,14 @@
namespace PHPModelGenerator\PropertyProcessor\ComposedValue;

use PHPModelGenerator\Exception\SchemaException;
use PHPModelGenerator\Model\MethodInterface;
use PHPModelGenerator\Model\Property\CompositionPropertyDecorator;
use PHPModelGenerator\Model\Property\Property;
use PHPModelGenerator\Model\Property\PropertyInterface;
use PHPModelGenerator\Model\Property\PropertyType;
use PHPModelGenerator\Model\Schema;
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
use PHPModelGenerator\Model\Validator;
use PHPModelGenerator\Model\Validator\ComposedPropertyValidator;
use PHPModelGenerator\Model\Validator\RequiredPropertyValidator;
use PHPModelGenerator\PropertyProcessor\Decorator\Property\ObjectInstantiationDecorator;
use PHPModelGenerator\PropertyProcessor\Decorator\SchemaNamespaceTransferDecorator;
use PHPModelGenerator\PropertyProcessor\Decorator\TypeHint\ClearTypeHintDecorator;
use PHPModelGenerator\PropertyProcessor\Decorator\TypeHint\CompositionTypeHintDecorator;
use PHPModelGenerator\PropertyProcessor\Property\AbstractValueProcessor;
Expand Down
20 changes: 11 additions & 9 deletions src/Templates/Validator/ComposedItem.phptpl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
$proposedValue = null;
$modifiedValues = [];

{% if not generatorConfiguration.isImmutable() %}
{% if viewHelper.isMutableBaseValidator(generatorConfiguration, isBaseValidator) %}
$originalPropertyValidationState = $this->_propertyValidationState ?? [];
{% endif %}

Expand All @@ -24,7 +24,7 @@

{% foreach compositionProperties as compositionProperty %}
try {
{% if not generatorConfiguration.isImmutable() %}
{% if viewHelper.isMutableBaseValidator(generatorConfiguration, isBaseValidator) %}
// check if the state of the validator is already known.
// If none of the properties affected by the validator are changed the validator must not be re-evaluated
if (isset($validatorIndex) &&
Expand Down Expand Up @@ -71,7 +71,7 @@
{% if generatorConfiguration.collectErrors() %}
$compositionErrorCollection[] = $this->_errorRegistry;

{% if not generatorConfiguration.isImmutable() %}
{% if viewHelper.isMutableBaseValidator(generatorConfiguration, isBaseValidator) %}
if (isset($validatorIndex)) {
$this->_propertyValidationState[$validatorIndex][$validatorComponentIndex] = $this->_errorRegistry;
}
Expand All @@ -91,7 +91,7 @@
if (is_object($value)) {
$modifiedValues = array_merge($modifiedValues, $this->{{ modifiedValuesMethod }}($originalModelData, $value));
}
{% if not generatorConfiguration.isImmutable() %}
{% if viewHelper.isMutableBaseValidator(generatorConfiguration, isBaseValidator) %}
{% if not generatorConfiguration.collectErrors() %}
if (isset($validatorIndex)) {
$this->_propertyValidationState[$validatorIndex][$validatorComponentIndex] = true;
Expand All @@ -100,10 +100,12 @@
}
{% endif %}
} catch (\Exception $e) {
{% if not generatorConfiguration.collectErrors() %}
if (isset($validatorIndex)) {
$this->_propertyValidationState[$validatorIndex][$validatorComponentIndex] = false;
}
{% if viewHelper.isMutableBaseValidator(generatorConfiguration, isBaseValidator) %}
{% if not generatorConfiguration.collectErrors() %}
if (isset($validatorIndex)) {
$this->_propertyValidationState[$validatorIndex][$validatorComponentIndex] = false;
}
{% endif %}
{% endif %}

{% foreach compositionProperty.getAffectedObjectProperties() as affectedObjectProperty %}
Expand Down Expand Up @@ -137,7 +139,7 @@

$result = !({{ composedValueValidation }});

{% if not generatorConfiguration.isImmutable() %}
{% if viewHelper.isMutableBaseValidator(generatorConfiguration, isBaseValidator) %}
if ($result) {
$this->_propertyValidationState = $originalPropertyValidationState;
}
Expand Down
5 changes: 5 additions & 0 deletions src/Utils/RenderHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ public function renderMethods(Schema $schema): string
return $renderedMethods;
}

public function isMutableBaseValidator(GeneratorConfiguration $generatorConfiguration, bool $isBaseValidator): bool
{
return !$generatorConfiguration->isImmutable() && $isBaseValidator;
}

public static function varExportArray(array $values): string
{
return preg_replace('(\d+\s=>)', '', var_export($values, true));
Expand Down
27 changes: 27 additions & 0 deletions tests/Issues/Issue/Issue77Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace PHPModelGenerator\Tests\Issues\Issue;

use PHPModelGenerator\Model\GeneratorConfiguration;
use PHPModelGenerator\Tests\Issues\AbstractIssueTest;

class Issue77Test extends AbstractIssueTest
{
public function testCompositionValidatorOnPropertyGeneratesNoDynamicProperty(): void
{
$className = $this->generateClassFromFile('dynamicProperty.json', (new GeneratorConfiguration())->setImmutable(false));

$object = new $className(['values' => [1, 10, 1000], 'pet' => ['type' => 'dog', 'age' => 0, 'name' => 'Hans']]);

$this->assertSame([1, 10, 1000], $object->getValues());
$this->assertSame('dog', $object->getPet()->getType());
$this->assertSame(0, $object->getPet()->getAge());
$this->assertSame('Hans', $object->getPet()->getName());

$this->expectExceptionMessage('Value for item of array values must not be smaller than 1');

new $className(['values' => [0]]);
}
}
79 changes: 79 additions & 0 deletions tests/Schema/Issues/77/dynamicProperty.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"type": "object",
"definitions": {
"number": {
"type": "integer",
"minimum": 0,
"maximum": 1000
},
"values": {
"type": "array",
"items": {
"allOf": [
{
"$ref": "#/definitions/number"
},
{
"type": "integer",
"minimum": 1
}
]
}
},
"pet": {
"oneOf": [
{
"$ref": "#/definitions/pets/dog"
},
{
"$ref": "#/definitions/pets/spider"
}
]
},
"pets": {
"dog": {
"type": "object",
"$id": "dog",
"properties": {
"age": {
"$ref": "#/definitions/number"
},
"name": {
"type": "string"
},
"type": {
"const": "dog"
}
},
"required": [
"type"
]
},
"spider": {
"type": "object",
"properties": {
"age": {
"$ref": "#/definitions/number"
},
"weight": {
"type": "number"
},
"type": {
"const": "spider"
}
},
"required": [
"type"
]
}
}
},
"properties": {
"values": {
"$ref": "#/definitions/values"
},
"pet": {
"$ref": "#/definitions/pet"
}
}
}

0 comments on commit 85aa9b5

Please sign in to comment.