Skip to content

Commit 6f49da4

Browse files
authored
v1.6.2 [improvement] XML reader refactoring. Implement validations: … (#12)
* v1.6.2 [improvement] XML reader refactoring. Implement validations: Choice, Expression * v1.6.2 [refactoring] Remove redunant code from XMLReader * v1.6.2 [statics] Fix psalm, phpstan, cs * v1.6.2 [dependencies] Remove ext-intl as required
1 parent 7766526 commit 6f49da4

25 files changed

+486
-956
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ test-coverage-report
77
phpunit.xml
88
coverage/
99
.php-cs-fixer.php
10-
phpstan.neon
10+
phpstan.neon
11+
tests/Unit/Out/

composer.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,9 @@
2222
"require": {
2323
"php": ">= 8.0",
2424
"ext-dom": "*",
25-
"ext-intl": "*",
2625
"ext-libxml": "*",
2726
"nette/php-generator": "^4",
2827
"psr/log": "^1 || ^2 || ^3",
29-
"symfony/intl": "^5.4 || ^6",
3028
"symfony/property-access": "^5.4 || ^6",
3129
"symfony/validator": "^5.4.15 || ^6"
3230
},
@@ -36,9 +34,16 @@
3634
"phpstan/phpstan": "^1.9",
3735
"phpunit/php-code-coverage": "^9.2",
3836
"phpunit/phpunit": "^9.5",
37+
"symfony/expression-language": "^5.4 || ^6",
38+
"symfony/intl": "^5.4 || ^6",
3939
"symfony/var-dumper": "^5.4 || ^6",
4040
"vimeo/psalm": "^5.2"
4141
},
42+
"suggest": {
43+
"ext-intl": "You need this PHP extension if you will be using `time_zone` alidator with option `intl_compatible`",
44+
"symfony/expression-language": "You need this package if you will be using `Expression` alidator",
45+
"symfony/intl": "You need this package if you will be using `time_zone` alidator with option `intl_compatible`"
46+
},
4247
"autoload": {
4348
"psr-4": {
4449
"Micro\\Library\\DTO\\": "src/"

example/example.php

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
require dirname(__FILE__) . '/../vendor/autoload.php';
4+
5+
/**
6+
* Create default class generator facade
7+
*/
8+
$classGenerator = new \Micro\Library\DTO\ClassGeneratorFacadeDefault(
9+
['./example.xml'],
10+
'./out',
11+
'Transfer',
12+
'Transfer',
13+
);
14+
15+
$classGenerator->generate();
16+
17+
/**
18+
* Require generated classes
19+
*/
20+
require_once 'out/Simple/SimpleObjectTransfer.php';
21+
require_once 'out/Simple/SimpleUserTransfer.php';
22+
require_once 'out/UserTransfer.php';
23+
24+
use Transfer\UserTransfer;
25+
use Transfer\Simple\SimpleObjectTransfer;
26+
use Micro\Library\DTO\SerializerFacadeDefault;
27+
use Micro\Library\DTO\ValidatorFacadeDefault;
28+
use Transfer\Simple\SimpleUserTransfer;
29+
30+
/**
31+
* Iterate DTO values
32+
*/
33+
$user = new UserTransfer();
34+
$user
35+
->setFirstName('Stas')
36+
->setUsername('Asisyas')
37+
->setUpdatedAt(new DateTime('11.08.1989'))
38+
->setBooks(
39+
[
40+
(new SimpleObjectTransfer())
41+
->setHeight(1)
42+
->setWeight(20)
43+
->setParent(
44+
(new SimpleObjectTransfer())
45+
->setHeight(100)
46+
->setWeight(2000)
47+
)
48+
])
49+
->setSomeclass(
50+
(new SimpleObjectTransfer())
51+
->setWeight(1)
52+
->setHeight(2)
53+
)
54+
;
55+
56+
foreach ($user as $key => $value) {
57+
print_r("\r\nPROPERTY: " . $key . " ==== " . (is_scalar($value) ? $value : (is_null($value) ? 'NULL' : serialize($value))));
58+
}
59+
60+
61+
/**
62+
* Array access example
63+
*/
64+
print_r("\r\n\r\nFISRT BOOK HEIGHT : " . $user['books'][0]['height'] . "\r\n");
65+
print_r('FISRT BOOK PARENT HEIGHT : ' . $user['books'][0]['parent']['height'] . "\r\n\r\n");
66+
// Allowed too
67+
$user['books'][0]['height'] = 12;
68+
69+
/**
70+
* Serialization example
71+
*/
72+
$classSerializerFacade = new SerializerFacadeDefault();
73+
$jsonDto = $classSerializerFacade->toJsonTransfer($user);
74+
$json = $classSerializerFacade->toJson($user);
75+
76+
print_r('Serialized DTO: ' . $jsonDto . "\r\n\r\n");
77+
print_r('Serialize DTO as JSON: ' . $json . "\r\n\r\n");
78+
79+
$deserialized = $classSerializerFacade->fromJsonTransfer($jsonDto);
80+
81+
$className = get_class($user);
82+
$okNo = get_class($deserialized) === $className ?'true' : 'false';
83+
print_r( "Deserialize $className: $okNo \r\n");
84+
85+
/**
86+
* Validate DTO example
87+
*/
88+
$simpleUserParent = new SimpleObjectTransfer();
89+
$simpleUserParent
90+
->setWeight(9)
91+
->setHeight(8);
92+
93+
$simpleUser = new SimpleUserTransfer();
94+
$simpleUser
95+
->setParent($simpleUserParent)
96+
->setIp('192.168.0.1')
97+
->setAge(19)
98+
->setEmail('test@example.com')
99+
->setHostname('localhost')
100+
->setUsername('Asisyas')
101+
->setSometext('azds')
102+
->setUrl('//abc')
103+
->setJson('{"test": 123}')
104+
->setUuid('ffd4ff99-33ed-4a13-88cf-47e22de29dcc')
105+
->setCreatedAt('2002-08-11 20:08:01')
106+
->setUpdatedAt('2002-08-11')
107+
->setTimezone('Europe/Minsk')
108+
->setCardScheme('5555555555554444')
109+
->setBic('MIDLGB22')
110+
->setCurrency('USD')
111+
->setIban('BY 13 NBRB 3600900000002Z00AB00')
112+
->setIsbn('978-0-545-01022-1')
113+
->setIssn('0378-5955')
114+
->setIsin('US0378331005')
115+
->setChoice('example')
116+
;
117+
118+
$validator = new ValidatorFacadeDefault();
119+
$constraints = $validator->validate($simpleUser);
120+
121+
$validationStatus = !count($constraints) ? 'Validated': 'Validation error';
122+
123+
print_r("Validation status: $validationStatus\r\n");
124+

example/example.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,19 @@
134134
<isin />
135135
</validation>
136136
</property>
137+
<property name="choice" type="string|int|float|array">
138+
<validation>
139+
<not_blank />
140+
<choice choices="1, example, 0.001, true" />
141+
</validation>
142+
</property>
143+
<property name="expression" type="string|int">
144+
<validation>
145+
<expression expression="this.getChoice() === excepted">
146+
<variable name="excepted" value="example" />
147+
</expression>
148+
</validation>
149+
</property>
137150
</class>
138151

139152
<class name="User" description="Example class description" deprecated="Please, use gSON">

tests/Unit/Out/Simple/SimpleObjectTransfer.php renamed to example/out/Simple/SimpleObjectTransfer.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
declare(strict_types=1);
88

9-
namespace Micro\Library\DTO\Tests\Unit\Out\Simple;
9+
namespace Transfer\Simple;
1010

1111
use DateTimeInterface;
12-
use Micro\Library\DTO\Tests\Unit\Out\Simple\SimpleObjectTransfer as SimpleObjectTransfer1;
12+
use Transfer\Simple\SimpleObjectTransfer as SimpleObjectTransfer1;
1313

1414
final class SimpleObjectTransfer extends \Micro\Library\DTO\Object\AbstractDto
1515
{
@@ -18,8 +18,6 @@ final class SimpleObjectTransfer extends \Micro\Library\DTO\Object\AbstractDto
1818

1919
#[\Symfony\Component\Validator\Constraints\LessThan(groups: ['Default'], propertyPath: 'weight')]
2020
protected int|null $height = null;
21-
22-
/** Parent object */
2321
protected SimpleObjectTransfer|null $parent = null;
2422

2523
public function getWeight(): int|null
@@ -85,7 +83,7 @@ protected static function attributesMetadata(): array
8583
array (
8684
'type' =>
8785
array (
88-
0 => 'Micro\\Library\\DTO\\Tests\\Unit\\Out\\Simple\\SimpleObjectTransfer',
86+
0 => 'Transfer\\Simple\\SimpleObjectTransfer',
8987
1 => 'null',
9088
),
9189
'required' => false,

tests/Unit/Out/Simple/SimpleUserTransfer.php renamed to example/out/Simple/SimpleUserTransfer.php

Lines changed: 57 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
declare(strict_types=1);
88

9-
namespace Micro\Library\DTO\Tests\Unit\Out\Simple;
9+
namespace Transfer\Simple;
1010

1111
use DateTimeInterface;
1212

@@ -31,7 +31,6 @@ final class SimpleUserTransfer extends \Micro\Library\DTO\Object\AbstractDto
3131
protected string|null $ip = null;
3232

3333
#[\Symfony\Component\Validator\Constraints\Hostname(groups: ['Default'], requireTld: false)]
34-
#[\Symfony\Component\Validator\Constraints\Hostname(groups: ['test'], requireTld: true)]
3534
protected string|null $hostname = null;
3635

3736
#[\Symfony\Component\Validator\Constraints\Regex(groups: ['Default'], pattern: '/^(.[a-z])+$/', match: true)]
@@ -54,10 +53,6 @@ final class SimpleUserTransfer extends \Micro\Library\DTO\Object\AbstractDto
5453
#[\Symfony\Component\Validator\Constraints\Date(groups: ['Default'])]
5554
protected string|null $updated_at = null;
5655

57-
#[\Symfony\Component\Validator\Constraints\NotBlank(groups: ['Default'], allowNull: false)]
58-
#[\Symfony\Component\Validator\Constraints\Time(groups: ['Default'])]
59-
protected string|null $time = null;
60-
6156
#[\Symfony\Component\Validator\Constraints\Timezone(groups: ['Default'], countryCode: 'BY', intlCompatible: true, zone: 4096)]
6257
protected string|null $timezone = null;
6358

@@ -90,6 +85,13 @@ final class SimpleUserTransfer extends \Micro\Library\DTO\Object\AbstractDto
9085
#[\Symfony\Component\Validator\Constraints\Isin(groups: ['Default'])]
9186
protected string|null $isin = null;
9287

88+
#[\Symfony\Component\Validator\Constraints\NotBlank(groups: ['Default'], allowNull: false)]
89+
#[\Symfony\Component\Validator\Constraints\Choice(groups: ['Default'], choices: [1, 'example', 0.001, true])]
90+
protected string|int|float|array|null $choice = null;
91+
92+
#[\Symfony\Component\Validator\Constraints\Expression(groups: ['Default'], expression: 'this.getChoice() === excepted', values: ['excepted' => 'example'])]
93+
protected string|int|null $expression = null;
94+
9395
public function getParent(): SimpleObjectTransfer|null
9496
{
9597
return $this->parent;
@@ -150,11 +152,6 @@ public function getUpdatedAt(): string|null
150152
return $this->updated_at;
151153
}
152154

153-
public function getTime(): string|null
154-
{
155-
return $this->time;
156-
}
157-
158155
public function getTimezone(): string|null
159156
{
160157
return $this->timezone;
@@ -195,6 +192,16 @@ public function getIsin(): string|null
195192
return $this->isin;
196193
}
197194

195+
public function getChoice(): string|int|float|array|null
196+
{
197+
return $this->choice;
198+
}
199+
200+
public function getExpression(): string|int|null
201+
{
202+
return $this->expression;
203+
}
204+
198205
public function setParent(SimpleObjectTransfer|null $parent): self
199206
{
200207
$this->parent = $parent;
@@ -279,13 +286,6 @@ public function setUpdatedAt(string|null $updated_at): self
279286
return $this;
280287
}
281288

282-
public function setTime(string|null $time): self
283-
{
284-
$this->time = $time;
285-
286-
return $this;
287-
}
288-
289289
public function setTimezone(string|null $timezone): self
290290
{
291291
$this->timezone = $timezone;
@@ -342,14 +342,28 @@ public function setIsin(string|null $isin): self
342342
return $this;
343343
}
344344

345+
public function setChoice(string|int|float|array|null $choice): self
346+
{
347+
$this->choice = $choice;
348+
349+
return $this;
350+
}
351+
352+
public function setExpression(string|int|null $expression): self
353+
{
354+
$this->expression = $expression;
355+
356+
return $this;
357+
}
358+
345359
protected static function attributesMetadata(): array
346360
{
347361
return array (
348362
'parent' =>
349363
array (
350364
'type' =>
351365
array (
352-
0 => 'Micro\\Library\\DTO\\Tests\\Unit\\Out\\Simple\\SimpleObjectTransfer',
366+
0 => 'Transfer\\Simple\\SimpleObjectTransfer',
353367
1 => 'null',
354368
),
355369
'required' => false,
@@ -465,16 +479,6 @@ protected static function attributesMetadata(): array
465479
'required' => false,
466480
'actionName' => 'updatedAt',
467481
),
468-
'time' =>
469-
array (
470-
'type' =>
471-
array (
472-
0 => 'string',
473-
1 => 'null',
474-
),
475-
'required' => false,
476-
'actionName' => 'time',
477-
),
478482
'timezone' =>
479483
array (
480484
'type' =>
@@ -555,6 +559,30 @@ protected static function attributesMetadata(): array
555559
'required' => false,
556560
'actionName' => 'isin',
557561
),
562+
'choice' =>
563+
array (
564+
'type' =>
565+
array (
566+
0 => 'string',
567+
1 => 'int',
568+
2 => 'float',
569+
3 => 'array',
570+
4 => 'null',
571+
),
572+
'required' => false,
573+
'actionName' => 'choice',
574+
),
575+
'expression' =>
576+
array (
577+
'type' =>
578+
array (
579+
0 => 'string',
580+
1 => 'int',
581+
2 => 'null',
582+
),
583+
'required' => false,
584+
'actionName' => 'expression',
585+
),
558586
);
559587
}
560588
}

tests/Unit/Out/UserTransfer.php renamed to example/out/UserTransfer.php

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

77
declare(strict_types=1);
88

9-
namespace Micro\Library\DTO\Tests\Unit\Out;
9+
namespace Transfer;
1010

1111
use DateTimeInterface;
1212
use Micro\Library\DTO\Object\AbstractDto;

0 commit comments

Comments
 (0)