Skip to content

Commit 37679a3

Browse files
committed
Add factory for string uuid value object - Close #8
1 parent 952bd0c commit 37679a3

File tree

3 files changed

+323
-0
lines changed

3 files changed

+323
-0
lines changed

src/ValueObject/UuidFactory.php

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
<?php
2+
3+
/**
4+
* @see https://github.com/open-code-modeling/json-schema-to-php-ast for the canonical source repository
5+
* @copyright https://github.com/open-code-modeling/json-schema-to-php-ast/blob/master/COPYRIGHT.md
6+
* @license https://github.com/open-code-modeling/json-schema-to-php-ast/blob/master/LICENSE.md MIT License
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace OpenCodeModeling\JsonSchemaToPhpAst\ValueObject;
12+
13+
use OpenCodeModeling\CodeAst\Builder\ClassBuilder;
14+
use OpenCodeModeling\CodeAst\Code\BodyGenerator;
15+
use OpenCodeModeling\CodeAst\Code\MethodGenerator;
16+
use OpenCodeModeling\CodeAst\Code\ParameterGenerator;
17+
use OpenCodeModeling\CodeAst\NodeVisitor\ClassMethod;
18+
use OpenCodeModeling\JsonSchemaToPhp\Type\StringType;
19+
use OpenCodeModeling\JsonSchemaToPhpAst\PropertyFactory;
20+
use PhpParser\NodeVisitor;
21+
use PhpParser\Parser;
22+
23+
/**
24+
* This file creates node visitors for a value object of type string.
25+
*
26+
* The following code will be generated:
27+
*
28+
* private UuidInterface $uuid;
29+
*
30+
* public static function fromString(string $uuid): self
31+
* {
32+
* return new self(Uuid::fromString($uuid));
33+
* }
34+
*
35+
* private function __construct(UuidInterface $uuid)
36+
* {
37+
* $this->uuid = $uuid;
38+
* }
39+
*
40+
* public function toString(): string
41+
* {
42+
* return $this->uuid;
43+
* }
44+
*
45+
* public function equals($other): bool
46+
* {
47+
* if(!$other instanceof self) {
48+
* return false;
49+
* }
50+
*
51+
* return $this->uuid === $other->uuid;
52+
* }
53+
*
54+
* public function __toString(): string
55+
* {
56+
* return $this->uuid;
57+
* }
58+
*/
59+
final class UuidFactory
60+
{
61+
private Parser $parser;
62+
private PropertyFactory $propertyFactory;
63+
private bool $typed;
64+
65+
public function __construct(Parser $parser, bool $typed)
66+
{
67+
$this->parser = $parser;
68+
$this->typed = $typed;
69+
$this->propertyFactory = new PropertyFactory($typed);
70+
}
71+
72+
/**
73+
* @param StringType $typeDefinition
74+
* @return array<NodeVisitor>
75+
*/
76+
public function nodeVisitors(StringType $typeDefinition): array
77+
{
78+
$name = $typeDefinition->name() ?: 'uuid';
79+
80+
return $this->nodeVisitorsFromNative($name);
81+
}
82+
83+
public function classBuilder(StringType $typeDefinition): ClassBuilder
84+
{
85+
$name = $typeDefinition->name() ?: 'uuid';
86+
87+
return $this->classBuilderFromNative($name);
88+
}
89+
90+
/**
91+
* @param string $name
92+
* @return array<NodeVisitor>
93+
*/
94+
public function nodeVisitorsFromNative(string $name): array
95+
{
96+
$nodeVisitors = $this->propertyFactory->nodeVisitorFromNative($name, 'UuidInterface');
97+
$nodeVisitors[] = new ClassMethod($this->methodFromString($name));
98+
$nodeVisitors[] = new ClassMethod($this->methodMagicConstruct($name));
99+
$nodeVisitors[] = new ClassMethod($this->methodToString($name));
100+
$nodeVisitors[] = new ClassMethod($this->methodEquals($name));
101+
$nodeVisitors[] = new ClassMethod($this->methodMagicToString($name));
102+
103+
return $nodeVisitors;
104+
}
105+
106+
public function classBuilderFromNative(string $name): ClassBuilder
107+
{
108+
return ClassBuilder::fromNodes(
109+
$this->propertyFactory->propertyGenerator($name, 'UuidInterface')->generate(),
110+
$this->methodFromString($name)->generate(),
111+
$this->methodMagicConstruct($name)->generate(),
112+
$this->methodToString($name)->generate(),
113+
$this->methodEquals($name)->generate(),
114+
$this->methodMagicToString($name)->generate(),
115+
)->setTyped($this->typed);
116+
}
117+
118+
public function methodFromString(string $argumentName): MethodGenerator
119+
{
120+
$method = new MethodGenerator(
121+
'fromString',
122+
[
123+
new ParameterGenerator($argumentName, 'string'),
124+
],
125+
MethodGenerator::FLAG_STATIC | MethodGenerator::FLAG_PUBLIC,
126+
new BodyGenerator($this->parser, 'return new self(Uuid::fromString($' . $argumentName . '));')
127+
);
128+
$method->setTyped($this->typed);
129+
$method->setReturnType('self');
130+
131+
return $method;
132+
}
133+
134+
public function methodMagicConstruct(string $argumentName): MethodGenerator
135+
{
136+
$method = new MethodGenerator(
137+
'__construct',
138+
[
139+
new ParameterGenerator($argumentName, 'UuidInterface'),
140+
],
141+
MethodGenerator::FLAG_PRIVATE,
142+
new BodyGenerator($this->parser, \sprintf('$this->%s = $%s;', $argumentName, $argumentName))
143+
);
144+
$method->setTyped($this->typed);
145+
146+
return $method;
147+
}
148+
149+
public function methodToString(string $argumentName): MethodGenerator
150+
{
151+
$method = new MethodGenerator(
152+
'toString',
153+
[],
154+
MethodGenerator::FLAG_PUBLIC,
155+
new BodyGenerator($this->parser, 'return $this->' . $argumentName . ';')
156+
);
157+
$method->setTyped($this->typed);
158+
$method->setReturnType('string');
159+
160+
return $method;
161+
}
162+
163+
public function methodEquals(string $propertyName, string $argumentName = 'other'): MethodGenerator
164+
{
165+
$body = <<<PHP
166+
if(!\$$argumentName instanceof self) {
167+
return false;
168+
}
169+
170+
return \$this->$propertyName === \$$argumentName->$propertyName;
171+
PHP;
172+
173+
$method = new MethodGenerator(
174+
'equals',
175+
[
176+
new ParameterGenerator($argumentName),
177+
],
178+
MethodGenerator::FLAG_PUBLIC,
179+
new BodyGenerator($this->parser, $body)
180+
);
181+
$method->setTyped($this->typed);
182+
$method->setReturnType('bool');
183+
184+
return $method;
185+
}
186+
187+
public function methodMagicToString(string $argumentName): MethodGenerator
188+
{
189+
$method = new MethodGenerator(
190+
'__toString',
191+
[],
192+
MethodGenerator::FLAG_PUBLIC,
193+
new BodyGenerator($this->parser, 'return $this->' . $argumentName . ';')
194+
);
195+
$method->setTyped($this->typed);
196+
$method->setReturnType('string');
197+
198+
return $method;
199+
}
200+
}

src/ValueObjectFactory.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use OpenCodeModeling\JsonSchemaToPhpAst\ValueObject\IntegerFactory;
2323
use OpenCodeModeling\JsonSchemaToPhpAst\ValueObject\NumberFactory;
2424
use OpenCodeModeling\JsonSchemaToPhpAst\ValueObject\StringFactory;
25+
use OpenCodeModeling\JsonSchemaToPhpAst\ValueObject\UuidFactory;
2526
use PhpParser\NodeVisitor;
2627
use PhpParser\Parser;
2728

@@ -33,6 +34,7 @@ final class ValueObjectFactory
3334
private NumberFactory $numberFactory;
3435
private DateTimeFactory $dateTimeFactory;
3536
private EnumFactory $enumFactory;
37+
private UuidFactory $uuidFactory;
3638

3739
/**
3840
* @param Parser $parser
@@ -52,6 +54,7 @@ public function __construct(
5254
$this->numberFactory = new NumberFactory($parser, $typed);
5355
$this->dateTimeFactory = new DateTimeFactory($parser, $typed);
5456
$this->enumFactory = new EnumFactory($parser, $typed, $constNameFilter, $constValueFilter);
57+
$this->uuidFactory = new UuidFactory($parser, $typed);
5558
}
5659

5760
/**
@@ -68,6 +71,8 @@ public function nodeVisitors(TypeDefinition $typeDefinition): array
6871
switch ($typeDefinition->format()) {
6972
case TypeDefinition::FORMAT_DATETIME:
7073
return $this->dateTimeFactory->nodeVisitors($typeDefinition);
74+
case 'uuid':
75+
return $this->uuidFactory->nodeVisitors($typeDefinition);
7176
default:
7277
return $this->stringFactory->nodeVisitors($typeDefinition);
7378
}
@@ -94,6 +99,8 @@ public function classBuilder(TypeDefinition $typeDefinition): ClassBuilder
9499
switch ($typeDefinition->format()) {
95100
case TypeDefinition::FORMAT_DATETIME:
96101
return $this->dateTimeFactory->classBuilder($typeDefinition);
102+
case 'uuid':
103+
return $this->uuidFactory->classBuilder($typeDefinition);
97104
default:
98105
return $this->stringFactory->classBuilder($typeDefinition);
99106
}

tests/ValueObject/UuidFactoryTest.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenCodeModelingTest\JsonSchemaToPhpAst\ValueObject;
6+
7+
use OpenCodeModeling\JsonSchemaToPhp\Type\StringType;
8+
use OpenCodeModeling\JsonSchemaToPhpAst\ValueObject\UuidFactory;
9+
use PhpParser\NodeTraverser;
10+
use PhpParser\NodeVisitor;
11+
12+
final class UuidFactoryTest extends BaseTestCase
13+
{
14+
private UuidFactory $uuidFactory;
15+
16+
public function setUp(): void
17+
{
18+
parent::setUp();
19+
$this->uuidFactory = new UuidFactory($this->parser, true);
20+
}
21+
22+
/**
23+
* @test
24+
*/
25+
public function it_generates_code_from_native(): void
26+
{
27+
$this->assertCode($this->uuidFactory->nodeVisitorsFromNative('uuid'));
28+
}
29+
30+
/**
31+
* @test
32+
*/
33+
public function it_generates_code_via_value_object_factory(): void
34+
{
35+
$this->assertCode(
36+
$this->voFactory->nodeVisitors(
37+
StringType::fromDefinition(
38+
[
39+
'type' => 'string',
40+
'name' => 'uuid',
41+
'format' => 'uuid',
42+
]
43+
)
44+
)
45+
);
46+
}
47+
48+
/**
49+
* @test
50+
*/
51+
public function it_generates_code_via_value_object_factory_with_class_builder(): void
52+
{
53+
$classBuilder = $this->voFactory->classBuilder(
54+
StringType::fromDefinition(
55+
[
56+
'type' => 'string',
57+
'name' => 'uuid',
58+
'format' => 'uuid',
59+
]
60+
)
61+
);
62+
$classBuilder->setName('UuidVO');
63+
64+
$this->assertCode(
65+
$classBuilder->generate($this->parser)
66+
);
67+
}
68+
69+
/**
70+
* @param array<NodeVisitor> $nodeVisitors
71+
*/
72+
private function assertCode(array $nodeVisitors): void
73+
{
74+
$ast = $this->parser->parse('<?php final class UuidVO {}');
75+
76+
$nodeTraverser = new NodeTraverser();
77+
78+
foreach ($nodeVisitors as $nodeVisitor) {
79+
$nodeTraverser->addVisitor($nodeVisitor);
80+
}
81+
82+
$expected = <<<'EOF'
83+
<?php
84+
85+
final class UuidVO
86+
{
87+
private UuidInterface $uuid;
88+
public static function fromString(string $uuid) : self
89+
{
90+
return new self(Uuid::fromString($uuid));
91+
}
92+
private function __construct(UuidInterface $uuid)
93+
{
94+
$this->uuid = $uuid;
95+
}
96+
public function toString() : string
97+
{
98+
return $this->uuid;
99+
}
100+
public function equals($other) : bool
101+
{
102+
if (!$other instanceof self) {
103+
return false;
104+
}
105+
return $this->uuid === $other->uuid;
106+
}
107+
public function __toString() : string
108+
{
109+
return $this->uuid;
110+
}
111+
}
112+
EOF;
113+
114+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
115+
}
116+
}

0 commit comments

Comments
 (0)