Skip to content

Commit 9e8901a

Browse files
authored
Merge pull request #26 from wol-soft/RefactorPropertyLateBinding
Resolve properties during rendering instead of processing for correct usage of the PropertyProxy
2 parents 8097b0c + 9f326ae commit 9e8901a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+403
-180
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ php:
1010
- 7.2
1111
- 7.3
1212
- 7.4
13+
- 8.0
1314
- nightly
1415

1516
install:
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PHPModelGenerator\Model\Property;
6+
7+
use PHPModelGenerator\Exception\SchemaException;
8+
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
9+
use PHPModelGenerator\Model\SchemaDefinition\JsonSchemaTrait;
10+
11+
/**
12+
* Class AbstractProperty
13+
*
14+
* @package PHPModelGenerator\Model\Property
15+
*/
16+
abstract class AbstractProperty implements PropertyInterface
17+
{
18+
use JsonSchemaTrait;
19+
20+
/** @var string */
21+
protected $name = '';
22+
/** @var string */
23+
protected $attribute = '';
24+
25+
/**
26+
* Property constructor.
27+
*
28+
* @param string $name
29+
* @param JsonSchema $jsonSchema
30+
*
31+
* @throws SchemaException
32+
*/
33+
public function __construct(string $name, JsonSchema $jsonSchema)
34+
{
35+
$this->name = $name;
36+
$this->jsonSchema = $jsonSchema;
37+
38+
$this->attribute = $this->processAttributeName($name);
39+
}
40+
41+
/**
42+
* @inheritdoc
43+
*/
44+
public function getName(): string
45+
{
46+
return $this->name;
47+
}
48+
49+
/**
50+
* @inheritdoc
51+
*/
52+
public function getAttribute(): string
53+
{
54+
return ($this->isInternal() ? '_' : '') . $this->attribute;
55+
}
56+
57+
/**
58+
* Convert a name of a JSON-field into a valid PHP variable name to be used as class attribute
59+
*
60+
* @param string $name
61+
*
62+
* @return string
63+
*
64+
* @throws SchemaException
65+
*/
66+
protected function processAttributeName(string $name): string
67+
{
68+
$attributeName = preg_replace_callback(
69+
'/([a-z][a-z0-9]*)([A-Z])/',
70+
function ($matches) {
71+
return "{$matches[1]}-{$matches[2]}";
72+
},
73+
$name
74+
);
75+
76+
$elements = array_map(
77+
function ($element) {
78+
return ucfirst(strtolower($element));
79+
},
80+
preg_split('/[^a-z0-9]/i', $attributeName)
81+
);
82+
83+
$attributeName = lcfirst(join('', $elements));
84+
85+
if (empty($attributeName)) {
86+
throw new SchemaException(
87+
sprintf(
88+
"Property name '%s' results in an empty attribute name in file %s",
89+
$name,
90+
$this->jsonSchema->getFile()
91+
)
92+
);
93+
}
94+
95+
return $attributeName;
96+
}
97+
}

src/Model/Property/CompositionPropertyDecorator.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace PHPModelGenerator\Model\Property;
66

7+
use PHPModelGenerator\Exception\SchemaException;
8+
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
79
use PHPModelGenerator\Model\SchemaDefinition\ResolvedDefinitionsCollection;
810

911
/**
@@ -26,11 +28,20 @@ class CompositionPropertyDecorator extends PropertyProxy
2628
/**
2729
* CompositionPropertyDecorator constructor.
2830
*
31+
* @param string $propertyName
32+
* @param JsonSchema $jsonSchema
2933
* @param PropertyInterface $property
34+
*
35+
* @throws SchemaException
3036
*/
31-
public function __construct(PropertyInterface $property)
37+
public function __construct(string $propertyName, JsonSchema $jsonSchema, PropertyInterface $property)
3238
{
33-
parent::__construct(new ResolvedDefinitionsCollection([self::PROPERTY_KEY => $property]), self::PROPERTY_KEY);
39+
parent::__construct(
40+
$propertyName,
41+
$jsonSchema,
42+
new ResolvedDefinitionsCollection([self::PROPERTY_KEY => $property]),
43+
self::PROPERTY_KEY
44+
);
3445
}
3546

3647
/**

src/Model/Property/Property.php

Lines changed: 5 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use PHPModelGenerator\Exception\SchemaException;
88
use PHPModelGenerator\Model\Schema;
99
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
10-
use PHPModelGenerator\Model\SchemaDefinition\JsonSchemaTrait;
1110
use PHPModelGenerator\Model\Validator;
1211
use PHPModelGenerator\Model\Validator\PropertyValidatorInterface;
1312
use PHPModelGenerator\PropertyProcessor\Decorator\Property\PropertyDecoratorInterface;
@@ -18,14 +17,8 @@
1817
*
1918
* @package PHPModelGenerator\Model\Property
2019
*/
21-
class Property implements PropertyInterface
20+
class Property extends AbstractProperty
2221
{
23-
use JsonSchemaTrait;
24-
25-
/** @var string */
26-
protected $name = '';
27-
/** @var string */
28-
protected $attribute = '';
2922
/** @var string */
3023
protected $type = 'null';
3124
/** @var string|null */
@@ -62,28 +55,10 @@ class Property implements PropertyInterface
6255
*/
6356
public function __construct(string $name, string $type, JsonSchema $jsonSchema, string $description = '')
6457
{
65-
$this->name = $name;
58+
parent::__construct($name, $jsonSchema);
59+
6660
$this->type = $type;
67-
$this->jsonSchema = $jsonSchema;
6861
$this->description = $description;
69-
70-
$this->attribute = $this->processAttributeName($name);
71-
}
72-
73-
/**
74-
* @inheritdoc
75-
*/
76-
public function getName(): string
77-
{
78-
return $this->name;
79-
}
80-
81-
/**
82-
* @inheritdoc
83-
*/
84-
public function getAttribute(): string
85-
{
86-
return ($this->isInternal() ? '_' : '') . $this->attribute;
8762
}
8863

8964
/**
@@ -229,50 +204,9 @@ public function resolveDecorator(string $input, bool $nestedProperty): string
229204
/**
230205
* @inheritdoc
231206
*/
232-
public function hasDecorators(): bool
233-
{
234-
return count($this->decorators) > 0;
235-
}
236-
237-
/**
238-
* Convert a name of a JSON-field into a valid PHP variable name to be used as class attribute
239-
*
240-
* @param string $name
241-
*
242-
* @return string
243-
*
244-
* @throws SchemaException
245-
*/
246-
protected function processAttributeName(string $name): string
207+
public function getDecorators(): array
247208
{
248-
$attributeName = preg_replace_callback(
249-
'/([a-z][a-z0-9]*)([A-Z])/',
250-
function ($matches) {
251-
return "{$matches[1]}-{$matches[2]}";
252-
},
253-
$name
254-
);
255-
256-
$elements = array_map(
257-
function ($element) {
258-
return ucfirst(strtolower($element));
259-
},
260-
preg_split('/[^a-z0-9]/i', $attributeName)
261-
);
262-
263-
$attributeName = lcfirst(join('', $elements));
264-
265-
if (empty($attributeName)) {
266-
throw new SchemaException(
267-
sprintf(
268-
"Property name '%s' results in an empty attribute name in file %s",
269-
$name,
270-
$this->jsonSchema->getFile()
271-
)
272-
);
273-
}
274-
275-
return $attributeName;
209+
return $this->decorators;
276210
}
277211

278212
/**

src/Model/Property/PropertyInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ public function addDecorator(PropertyDecoratorInterface $decorator): PropertyInt
126126
public function resolveDecorator(string $input, bool $nestedProperty): string;
127127

128128
/**
129-
* @return bool
129+
* @return PropertyDecoratorInterface[]
130130
*/
131-
public function hasDecorators(): bool;
131+
public function getDecorators(): array;
132132

133133
/**
134134
* @param bool $isPropertyRequired

src/Model/Property/PropertyProxy.php

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

55
namespace PHPModelGenerator\Model\Property;
66

7+
use PHPModelGenerator\Exception\SchemaException;
78
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
89
use PHPModelGenerator\Model\SchemaDefinition\ResolvedDefinitionsCollection;
910
use PHPModelGenerator\Model\Schema;
@@ -16,21 +17,35 @@
1617
*
1718
* @package PHPModelGenerator\Model
1819
*/
19-
class PropertyProxy implements PropertyInterface
20+
class PropertyProxy extends AbstractProperty
2021
{
2122
/** @var string */
2223
protected $key;
24+
/** @var string */
25+
protected $name;
2326
/** @var ResolvedDefinitionsCollection */
2427
protected $definitionsCollection;
2528

2629
/**
2730
* PropertyProxy constructor.
2831
*
32+
* @param string $name The name must be provided separately as the name is not bound to the structure of a
33+
* referenced schema. Consequently two properties with different names can refer an identical schema utilizing the
34+
* PropertyProxy. By providing a name to each of the proxies the resulting properties will get the correct names.
35+
* @param JsonSchema $jsonSchema
2936
* @param ResolvedDefinitionsCollection $definitionsCollection
30-
* @param string $key
37+
* @param string $key
38+
*
39+
* @throws SchemaException
3140
*/
32-
public function __construct(ResolvedDefinitionsCollection $definitionsCollection, string $key)
33-
{
41+
public function __construct(
42+
string $name,
43+
JsonSchema $jsonSchema,
44+
ResolvedDefinitionsCollection $definitionsCollection,
45+
string $key
46+
) {
47+
parent::__construct($name, $jsonSchema);
48+
3449
$this->key = $key;
3550
$this->definitionsCollection = $definitionsCollection;
3651
}
@@ -45,22 +60,6 @@ protected function getProperty(): PropertyInterface
4560
return $this->definitionsCollection->offsetGet($this->key);
4661
}
4762

48-
/**
49-
* @inheritdoc
50-
*/
51-
public function getName(): string
52-
{
53-
return $this->getProperty()->getName();
54-
}
55-
56-
/**
57-
* @inheritdoc
58-
*/
59-
public function getAttribute(): string
60-
{
61-
return $this->getProperty()->getAttribute();
62-
}
63-
6463
/**
6564
* @inheritdoc
6665
*/
@@ -130,7 +129,9 @@ public function filterValidators(callable $filter): PropertyInterface
130129
*/
131130
public function getOrderedValidators(): array
132131
{
133-
return $this->getProperty()->getOrderedValidators();
132+
return array_map(function (PropertyValidatorInterface $propertyValidator): PropertyValidatorInterface {
133+
return $propertyValidator->withProperty($this);
134+
}, $this->getProperty()->getOrderedValidators());
134135
}
135136

136137
/**
@@ -146,15 +147,19 @@ public function addDecorator(PropertyDecoratorInterface $decorator): PropertyInt
146147
*/
147148
public function resolveDecorator(string $input, bool $nestedProperty): string
148149
{
149-
return $this->getProperty()->resolveDecorator($input, $nestedProperty);
150+
foreach ($this->getProperty()->getDecorators() as $decorator) {
151+
$input = $decorator->decorate($input, $this, $nestedProperty);
152+
}
153+
154+
return $input;
150155
}
151156

152157
/**
153158
* @inheritdoc
154159
*/
155-
public function hasDecorators(): bool
160+
public function getDecorators(): array
156161
{
157-
return $this->getProperty()->hasDecorators();
162+
return $this->getProperty()->getDecorators();
158163
}
159164

160165
/**

src/Model/SchemaDefinition/SchemaDefinition.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,6 @@ public function resolveReference(
107107
}
108108
}
109109

110-
return new PropertyProxy($this->resolvedPaths, $key);
110+
return new PropertyProxy($propertyName, $this->source, $this->resolvedPaths, $key);
111111
}
112112
}

0 commit comments

Comments
 (0)