Skip to content

Commit 70cb7cf

Browse files
committed
Implement conditional compositions
1 parent 2b2cfe2 commit 70cb7cf

15 files changed

+281
-57
lines changed

src/Model/Schema.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,13 @@ public function getProperties(): array
5050
* @param PropertyInterface $property
5151
*
5252
* @return $this
53-
*
54-
* @throws SchemaException
5553
*/
5654
public function addProperty(PropertyInterface $property): self
5755
{
58-
if (isset($this->properties[$property->getName()])) {
59-
throw new SchemaException("Duplicate object property {$property->getName()}");
56+
if (!isset($this->properties[$property->getName()])) {
57+
$this->properties[$property->getName()] = $property;
6058
}
6159

62-
$this->properties[$property->getName()] = $property;
63-
6460
return $this;
6561
}
6662

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\Model\Validator;
6+
7+
use PHPModelGenerator\Model\Property\CompositionPropertyDecorator;
8+
9+
/**
10+
* Class AbstractComposedPropertyValidator
11+
*
12+
* @package PHPModelGenerator\Model\Validator
13+
*/
14+
abstract class AbstractComposedPropertyValidator extends PropertyTemplateValidator
15+
{
16+
/** @var string */
17+
protected $composedProcessor;
18+
/** @var CompositionPropertyDecorator[] */
19+
protected $composedProperties;
20+
21+
/**
22+
* @return string
23+
*/
24+
public function getComposedProcessor(): string
25+
{
26+
return $this->composedProcessor;
27+
}
28+
29+
/**
30+
* @return CompositionPropertyDecorator[]
31+
*/
32+
public function getComposedProperties(): array
33+
{
34+
return $this->composedProperties;
35+
}
36+
}

src/Model/Validator/ComposedPropertyValidator.php

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,8 @@
1313
*
1414
* @package PHPModelGenerator\Model\Validator
1515
*/
16-
class ComposedPropertyValidator extends PropertyTemplateValidator
16+
class ComposedPropertyValidator extends AbstractComposedPropertyValidator
1717
{
18-
/** @var string */
19-
protected $composedProcessor;
20-
/** @var CompositionPropertyDecorator[] */
21-
protected $composedProperties;
22-
2318
/**
2419
* ComposedPropertyValidator constructor.
2520
*
@@ -44,20 +39,4 @@ public function __construct(
4439
$this->composedProcessor = $composedProcessor;
4540
$this->composedProperties = $composedProperties;
4641
}
47-
48-
/**
49-
* @return string
50-
*/
51-
public function getComposedProcessor(): string
52-
{
53-
return $this->composedProcessor;
54-
}
55-
56-
/**
57-
* @return CompositionPropertyDecorator[]
58-
*/
59-
public function getComposedProperties(): array
60-
{
61-
return $this->composedProperties;
62-
}
6342
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\Model\Validator;
6+
7+
use PHPModelGenerator\Exception\InvalidArgumentException;
8+
use PHPModelGenerator\Model\Property\CompositionPropertyDecorator;
9+
use PHPModelGenerator\Model\Property\PropertyInterface;
10+
use PHPModelGenerator\PropertyProcessor\ComposedValue\IfProcessor;
11+
12+
/**
13+
* Class ConditionalPropertyValidator
14+
*
15+
* @package PHPModelGenerator\Model\Validator
16+
*/
17+
class ConditionalPropertyValidator extends AbstractComposedPropertyValidator
18+
{
19+
/**
20+
* ConditionalPropertyValidator constructor.
21+
*
22+
* @param PropertyInterface $property
23+
* @param CompositionPropertyDecorator[] $composedProperties
24+
* @param array $validatorVariables
25+
*/
26+
public function __construct(
27+
PropertyInterface $property,
28+
array $composedProperties,
29+
array $validatorVariables
30+
) {
31+
parent::__construct(
32+
InvalidArgumentException::class,
33+
"Invalid value for {$property->getName()} declined by conditional composition constraint",
34+
DIRECTORY_SEPARATOR . 'Validator' . DIRECTORY_SEPARATOR . 'ConditionalComposedItem.phptpl',
35+
$validatorVariables
36+
);
37+
38+
$this->composedProcessor = IfProcessor::class;
39+
$this->composedProperties = $composedProperties;
40+
}
41+
}

src/PropertyProcessor/ComposedValue/AbstractComposedValueProcessor.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use PHPModelGenerator\Model\Validator;
1010
use PHPModelGenerator\Model\Validator\ComposedPropertyValidator;
1111
use PHPModelGenerator\Model\Validator\RequiredPropertyValidator;
12-
use PHPModelGenerator\PropertyProcessor\Property\AbstractTypedValueProcessor;
12+
use PHPModelGenerator\PropertyProcessor\Property\AbstractValueProcessor;
1313
use PHPModelGenerator\PropertyProcessor\PropertyCollectionProcessor;
1414
use PHPModelGenerator\PropertyProcessor\PropertyFactory;
1515
use PHPModelGenerator\PropertyProcessor\PropertyProcessorFactory;
@@ -20,7 +20,7 @@
2020
*
2121
* @package PHPModelGenerator\PropertyProcessor\ComposedValue
2222
*/
23-
abstract class AbstractComposedValueProcessor extends AbstractTypedValueProcessor
23+
abstract class AbstractComposedValueProcessor extends AbstractValueProcessor
2424
{
2525
/**
2626
* @inheritdoc
@@ -31,7 +31,7 @@ protected function generateValidators(PropertyInterface $property, array $proper
3131

3232
$properties = [];
3333

34-
foreach ($propertyData['composition'] as $compositionElement) {
34+
foreach ($propertyData['propertyData'][$propertyData['type']] as $compositionElement) {
3535
$compositionProperty = new CompositionPropertyDecorator(
3636
$propertyFactory
3737
->create(
@@ -64,7 +64,7 @@ protected function generateValidators(PropertyInterface $property, array $proper
6464
'availableAmount' => $availableAmount,
6565
'composedValueValidation' => $this->getComposedValueValidation($availableAmount),
6666
'onlyForDefinedValues' => $propertyData['onlyForDefinedValues'] &&
67-
$this instanceof AbstractComposedPropertiesProcessor,
67+
$this instanceof ComposedPropertiesInterface,
6868
]
6969
),
7070
100

src/PropertyProcessor/ComposedValue/AllOfProcessor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
* @package PHPModelGenerator\PropertyProcessor\ComposedValue
99
*/
10-
class AllOfProcessor extends AbstractComposedPropertiesProcessor
10+
class AllOfProcessor extends AbstractComposedValueProcessor implements ComposedPropertiesInterface
1111
{
1212
/**
1313
* @inheritdoc

src/PropertyProcessor/ComposedValue/AnyOfProcessor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
* @package PHPModelGenerator\PropertyProcessor\ComposedValue
99
*/
10-
class AnyOfProcessor extends AbstractComposedPropertiesProcessor
10+
class AnyOfProcessor extends AbstractComposedValueProcessor implements ComposedPropertiesInterface
1111
{
1212
/**
1313
* @inheritdoc
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\PropertyProcessor\ComposedValue;
6+
7+
/**
8+
* Interface ComposedPropertiesInterface
9+
*
10+
* @package PHPModelGenerator\PropertyProcessor\ComposedValue
11+
*/
12+
interface ComposedPropertiesInterface
13+
{
14+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\PropertyProcessor\ComposedValue;
6+
7+
use PHPModelGenerator\Exception\SchemaException;
8+
use PHPModelGenerator\Model\Property\CompositionPropertyDecorator;
9+
use PHPModelGenerator\Model\Property\PropertyInterface;
10+
use PHPModelGenerator\Model\Validator;
11+
use PHPModelGenerator\Model\Validator\ComposedPropertyValidator;
12+
use PHPModelGenerator\Model\Validator\ConditionalPropertyValidator;
13+
use PHPModelGenerator\Model\Validator\RequiredPropertyValidator;
14+
use PHPModelGenerator\PropertyProcessor\Property\AbstractValueProcessor;
15+
use PHPModelGenerator\PropertyProcessor\PropertyCollectionProcessor;
16+
use PHPModelGenerator\PropertyProcessor\PropertyFactory;
17+
use PHPModelGenerator\PropertyProcessor\PropertyProcessorFactory;
18+
use PHPModelGenerator\Utils\RenderHelper;
19+
20+
/**
21+
* Class IfProcessor
22+
*
23+
* @package PHPModelGenerator\PropertyProcessor\ComposedValue
24+
*/
25+
class IfProcessor extends AbstractValueProcessor implements ComposedPropertiesInterface
26+
{
27+
/**
28+
* @inheritdoc
29+
*/
30+
protected function generateValidators(PropertyInterface $property, array $propertyData): void
31+
{
32+
echo print_r($propertyData, true);
33+
if (!isset($propertyData['propertyData']['then']) && !isset($propertyData['propertyData']['else'])) {
34+
throw new SchemaException('Incomplete conditional composition');
35+
}
36+
37+
$propertyFactory = new PropertyFactory(new PropertyProcessorFactory());
38+
39+
$properties = [];
40+
41+
foreach (['if', 'then', 'else'] as $compositionElement) {
42+
if (!isset($propertyData['propertyData'][$compositionElement])) {
43+
$properties[$compositionElement] = null;
44+
continue;
45+
}
46+
47+
$compositionProperty = new CompositionPropertyDecorator(
48+
$propertyFactory
49+
->create(
50+
new PropertyCollectionProcessor([$property->getName() => $property->isRequired()]),
51+
$this->schemaProcessor,
52+
$this->schema,
53+
$property->getName(),
54+
$propertyData['propertyData'][$compositionElement]
55+
)
56+
);
57+
58+
$compositionProperty->filterValidators(function (Validator $validator) {
59+
return !is_a($validator->getValidator(), RequiredPropertyValidator::class) &&
60+
!is_a($validator->getValidator(), ComposedPropertyValidator::class);
61+
});
62+
63+
$properties[$compositionElement] = $compositionProperty;
64+
}
65+
66+
print_r($propertyData['propertyData'], true);
67+
$property->addValidator(
68+
new ConditionalPropertyValidator(
69+
$property,
70+
$properties,
71+
[
72+
'ifProperty' => $properties['if'],
73+
'thenProperty' => $properties['then'],
74+
'elseProperty' => $properties['else'],
75+
'viewHelper' => new RenderHelper(),
76+
'onlyForDefinedValues' => $propertyData['onlyForDefinedValues'],
77+
]
78+
),
79+
100
80+
);
81+
82+
parent::generateValidators($property, $propertyData);
83+
}
84+
85+
/**
86+
* @inheritdoc
87+
*/
88+
protected function getComposedValueValidation(int $composedElements): string
89+
{
90+
return '$succeededCompositionElements === 0';
91+
}
92+
}

src/PropertyProcessor/ComposedValue/NotProcessor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class NotProcessor extends AbstractComposedValueProcessor
1717
protected function generateValidators(PropertyInterface $property, array $propertyData): void
1818
{
1919
// as the not composition only takes one schema nest it one level deeper to use the ComposedValueProcessor
20-
$propertyData['composition'] = [$propertyData['composition']];
20+
$propertyData['propertyData']['not'] = [$propertyData['propertyData']['not']];
2121
// strict type checks for not constraint to avoid issues with null
2222
$property->setRequired(true);
2323
parent::generateValidators($property, $propertyData);

0 commit comments

Comments
 (0)