Skip to content

Commit 1c5a9bb

Browse files
committed
Fix regression introduced by #70
The getModifiedValues method must be scoped to be added to the correct model. Additionally, it must be added with a unique key per validator as multiple composed validators in a single model might occur.
1 parent a9bda3c commit 1c5a9bb

18 files changed

+149
-145
lines changed

src/Model/Validator/ComposedPropertyValidator.php

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use PHPModelGenerator\Exception\ComposedValue\InvalidComposedValueException;
88
use PHPModelGenerator\Model\GeneratorConfiguration;
9+
use PHPModelGenerator\Model\MethodInterface;
910
use PHPModelGenerator\Model\Property\CompositionPropertyDecorator;
1011
use PHPModelGenerator\Model\Property\PropertyInterface;
1112
use PHPModelGenerator\Model\Validator;
@@ -17,20 +18,23 @@
1718
*/
1819
class ComposedPropertyValidator extends AbstractComposedPropertyValidator
1920
{
21+
private $modifiedValuesMethod;
22+
2023
public function __construct(
2124
GeneratorConfiguration $generatorConfiguration,
2225
PropertyInterface $property,
2326
array $composedProperties,
2427
string $compositionProcessor,
2528
array $validatorVariables
2629
) {
30+
$this->modifiedValuesMethod = '_getModifiedValues_' . substr(md5(spl_object_hash($this)), 0, 5);
2731
$this->isResolved = true;
2832

2933
parent::__construct(
3034
$generatorConfiguration,
3135
$property,
3236
DIRECTORY_SEPARATOR . 'Validator' . DIRECTORY_SEPARATOR . 'ComposedItem.phptpl',
33-
$validatorVariables,
37+
array_merge($validatorVariables, ['modifiedValuesMethod' => $this->modifiedValuesMethod]),
3438
$this->getExceptionByProcessor($compositionProcessor),
3539
['&$succeededCompositionElements', '&$compositionErrorCollection']
3640
);
@@ -39,6 +43,74 @@ public function __construct(
3943
$this->composedProperties = $composedProperties;
4044
}
4145

46+
/**
47+
* TODO: add method only if nested objects contain filter (else also skip method call)
48+
*/
49+
public function getCheck(): string
50+
{
51+
/**
52+
* Add a method to the schema to gather values from a nested object which are modified.
53+
* This is required to adopt filter changes to the values which are passed into a merged property
54+
*/
55+
$this->scope->addMethod(
56+
$this->modifiedValuesMethod,
57+
new class ($this->composedProperties, $this->modifiedValuesMethod) implements MethodInterface {
58+
/** @var CompositionPropertyDecorator[] $compositionProperties */
59+
private $compositionProperties;
60+
/** @var string */
61+
private $modifiedValuesMethod;
62+
63+
public function __construct(array $compositionProperties, string $modifiedValuesMethod)
64+
{
65+
$this->compositionProperties = $compositionProperties;
66+
$this->modifiedValuesMethod = $modifiedValuesMethod;
67+
}
68+
69+
public function getCode(): string
70+
{
71+
$defaultValueMap = [];
72+
$propertyAccessors = [];
73+
foreach ($this->compositionProperties as $compositionProperty) {
74+
if (!$compositionProperty->getNestedSchema()) {
75+
continue;
76+
}
77+
78+
foreach ($compositionProperty->getNestedSchema()->getProperties() as $property) {
79+
$propertyAccessors[$property->getName()] = 'get' . ucfirst($property->getAttribute());
80+
81+
if ($property->getDefaultValue() !== null) {
82+
$defaultValueMap[] = $property->getName();
83+
}
84+
}
85+
}
86+
87+
return sprintf('
88+
private function %s(array $originalModelData, object $nestedCompositionObject): array {
89+
$modifiedValues = [];
90+
$defaultValueMap = %s;
91+
92+
foreach (%s as $key => $accessor) {
93+
if ((isset($originalModelData[$key]) || in_array($key, $defaultValueMap))
94+
&& method_exists($nestedCompositionObject, $accessor)
95+
&& ($modifiedValue = $nestedCompositionObject->$accessor()) !== ($originalModelData[$key] ?? !$modifiedValue)
96+
) {
97+
$modifiedValues[$key] = $modifiedValue;
98+
}
99+
}
100+
101+
return $modifiedValues;
102+
}',
103+
$this->modifiedValuesMethod,
104+
var_export($defaultValueMap, true),
105+
var_export($propertyAccessors, true)
106+
);
107+
}
108+
}
109+
);
110+
111+
return parent::getCheck();
112+
}
113+
42114
/**
43115
* Initialize all variables which are required to execute a composed property validator
44116
*

src/Model/Validator/PatternPropertiesValidator.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@ public function __construct(
7070
'patternHash' => $this->key,
7171
'pattern' => base64_encode('/' . addcslashes($this->pattern, '/') . '/'),
7272
'validationProperty' => $this->validationProperty,
73+
'schema' => $schema,
7374
'generatorConfiguration' => $schemaProcessor->getGeneratorConfiguration(),
7475
'viewHelper' => new RenderHelper($schemaProcessor->getGeneratorConfiguration()),
75-
'schemaProperties' => $schema->getProperties(),
76+
# 'schemaProperties' => $schema->getProperties(),
7677
],
7778
InvalidPatternPropertiesException::class,
7879
[$this->pattern, '&$invalidProperties']

src/Model/Validator/PropertyNamesValidator.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public function __construct(
5353
'nameValidationProperty' => $nameValidationProperty,
5454
'generatorConfiguration' => $schemaProcessor->getGeneratorConfiguration(),
5555
'viewHelper' => new RenderHelper($schemaProcessor->getGeneratorConfiguration()),
56+
'schema' => $schema,
5657
],
5758
InvalidPropertyNamesException::class,
5859
['&$invalidProperties']

src/Model/Validator/PropertyTemplateValidator.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ class PropertyTemplateValidator extends AbstractPropertyValidator
2121
protected $template;
2222
/** @var array */
2323
protected $templateValues;
24+
/** @var Schema|null */
25+
protected $scope = null;
26+
2427
/** @var Render */
2528
static private $renderer;
2629

@@ -48,6 +51,8 @@ public function __construct(
4851

4952
public function setScope(Schema $schema): void
5053
{
54+
$this->scope = $schema;
55+
5156
if (isset($this->templateValues['schema'])) {
5257
$this->templateValues['schema'] = $schema;
5358
}

src/PropertyProcessor/ComposedValue/AbstractComposedValueProcessor.php

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ function () use (&$resolvedCompositions, $property, $compositionProperties, $pro
102102
static::class,
103103
[
104104
'compositionProperties' => $compositionProperties,
105+
'schema' => $this->schema,
105106
'generatorConfiguration' => $this->schemaProcessor->getGeneratorConfiguration(),
106107
'viewHelper' => new RenderHelper($this->schemaProcessor->getGeneratorConfiguration()),
107108
'availableAmount' => $availableAmount,
@@ -118,10 +119,6 @@ function () use (&$resolvedCompositions, $property, $compositionProperties, $pro
118119
),
119120
100
120121
);
121-
122-
if (!$this->schema->hasMethod('_getModifiedValues')) {
123-
$this->addGetModifiedValuesMethodToSchema($compositionProperties);
124-
}
125122
}
126123

127124
/**
@@ -344,64 +341,6 @@ function () use ($property, $mergedPropertySchema): void {
344341
}
345342
}
346343

347-
/**
348-
* Add a method to the schema to gather values from a nested object which are modified. This is required to adopt
349-
* filter changes to the values which are passed into a merged property
350-
*
351-
* @param CompositionPropertyDecorator[] $compositionProperties
352-
*/
353-
private function addGetModifiedValuesMethodToSchema(array $compositionProperties): void
354-
{
355-
$this->schema->addMethod('_getModifiedValues', new class ($compositionProperties) implements MethodInterface {
356-
/** @var CompositionPropertyDecorator[] $compositionProperties */
357-
private $compositionProperties;
358-
359-
public function __construct(array $compositionProperties)
360-
{
361-
$this->compositionProperties = $compositionProperties;
362-
}
363-
364-
public function getCode(): string
365-
{
366-
$defaultValueMap = [];
367-
$propertyAccessors = [];
368-
foreach ($this->compositionProperties as $compositionProperty) {
369-
if (!$compositionProperty->getNestedSchema()) {
370-
continue;
371-
}
372-
373-
foreach ($compositionProperty->getNestedSchema()->getProperties() as $property) {
374-
$propertyAccessors[$property->getName()] = 'get' . ucfirst($property->getAttribute());
375-
376-
if ($property->getDefaultValue() !== null) {
377-
$defaultValueMap[] = $property->getName();
378-
}
379-
}
380-
}
381-
382-
return sprintf('
383-
private function _getModifiedValues(array $originalModelData, object $nestedCompositionObject): array {
384-
$modifiedValues = [];
385-
$defaultValueMap = %s;
386-
387-
foreach (%s as $key => $accessor) {
388-
if ((isset($originalModelData[$key]) || in_array($key, $defaultValueMap))
389-
&& method_exists($nestedCompositionObject, $accessor)
390-
&& ($modifiedValue = $nestedCompositionObject->$accessor()) !== ($originalModelData[$key] ?? !$modifiedValue)
391-
) {
392-
$modifiedValues[$key] = $modifiedValue;
393-
}
394-
}
395-
396-
return $modifiedValues;
397-
}',
398-
var_export($defaultValueMap, true),
399-
var_export($propertyAccessors, true)
400-
);
401-
}
402-
});
403-
}
404-
405344
/**
406345
* @param int $composedElements The amount of elements which are composed together
407346
*

src/PropertyProcessor/ComposedValue/IfProcessor.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ protected function generateValidators(PropertyInterface $property, JsonSchema $p
8686
'ifProperty' => $properties['if'],
8787
'thenProperty' => $properties['then'],
8888
'elseProperty' => $properties['else'],
89+
'schema' => $this->schema,
8990
'generatorConfiguration' => $this->schemaProcessor->getGeneratorConfiguration(),
9091
'viewHelper' => new RenderHelper($this->schemaProcessor->getGeneratorConfiguration()),
9192
'onlyForDefinedValues' => $propertySchema->getJson()['onlyForDefinedValues'],

src/PropertyProcessor/Property/ArrayProcessor.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ private function addContainsValidation(PropertyInterface $property, JsonSchema $
269269
DIRECTORY_SEPARATOR . 'Validator' . DIRECTORY_SEPARATOR . 'ArrayContains.phptpl',
270270
[
271271
'property' => $nestedProperty,
272+
'schema' => $this->schema,
272273
'viewHelper' => new RenderHelper($this->schemaProcessor->getGeneratorConfiguration()),
273274
'generatorConfiguration' => $this->schemaProcessor->getGeneratorConfiguration(),
274275
],

src/SchemaProcessor/PostProcessor/Internal/CompositionValidationPostProcessor.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ private function generateValidatorPropertyMap(Schema $schema, GeneratorConfigura
8080
}
8181
}
8282

83-
if (!empty($validatorPropertyMap) && !$generatorConfiguration->isImmutable()) {
83+
if (!empty($validatorPropertyMap)) {
8484
$schema->addProperty(
8585
(new Property(
8686
'propertyValidationState',
@@ -114,14 +114,20 @@ private function addValidationMethods(
114114
array $validatorPropertyMap
115115
): void {
116116
foreach (array_unique(array_merge(...array_values($validatorPropertyMap))) as $validatorIndex) {
117+
/** @var AbstractComposedPropertyValidator $compositionValidator */
118+
$compositionValidator = $schema->getBaseValidators()[$validatorIndex];
119+
120+
$compositionValidator->setScope($schema);
121+
117122
$schema->addMethod(
118123
"validateComposition_$validatorIndex",
119124
new RenderedMethod(
120125
$schema,
121126
$generatorConfiguration,
122127
'CompositionValidation.phptpl',
123128
[
124-
'validator' => $schema->getBaseValidators()[$validatorIndex],
129+
'validator' => $compositionValidator,
130+
'schema' => $schema,
125131
'index' => $validatorIndex,
126132
'viewHelper' => new RenderHelper($generatorConfiguration),
127133
]

src/Templates/Model.phptpl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,7 @@ class {{ class }} {% if schema.getInterfaces() %}implements {{ viewHelper.joinCl
8181
$value = &$modelData;
8282

8383
{% foreach baseValidatorsWithoutCompositions as validator %}
84-
{{ validator.getValidatorSetUp() }}
85-
if ({{ validator.getCheck() }}) {
86-
{{ viewHelper.validationError(validator) }}
87-
}
84+
{{ viewHelper.renderValidator(validator, schema) }}
8885
{% endforeach %}
8986

9087
{% foreach schema.getCompositionValidatorKeys() as compositionValidatorKey %}

src/Templates/Validator/AdditionalProperties.phptpl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@
2525
{{ viewHelper.resolvePropertyDecorator(validationProperty) }}
2626

2727
{% foreach validationProperty.getOrderedValidators() as validator %}
28-
{{ validator.getValidatorSetUp() }}
29-
if ({{ validator.getCheck() }}) {
30-
{{ viewHelper.validationError(validator) }}
31-
}
28+
{{ viewHelper.renderValidator(validator, schema) }}
3229
{% endforeach %}
3330

3431
{% if generatorConfiguration.collectErrors() %}

0 commit comments

Comments
 (0)