-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add factory for string uuid value object - Close #8
- Loading branch information
1 parent
952bd0c
commit 37679a3
Showing
3 changed files
with
323 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
<?php | ||
|
||
/** | ||
* @see https://github.com/open-code-modeling/json-schema-to-php-ast for the canonical source repository | ||
* @copyright https://github.com/open-code-modeling/json-schema-to-php-ast/blob/master/COPYRIGHT.md | ||
* @license https://github.com/open-code-modeling/json-schema-to-php-ast/blob/master/LICENSE.md MIT License | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenCodeModeling\JsonSchemaToPhpAst\ValueObject; | ||
|
||
use OpenCodeModeling\CodeAst\Builder\ClassBuilder; | ||
use OpenCodeModeling\CodeAst\Code\BodyGenerator; | ||
use OpenCodeModeling\CodeAst\Code\MethodGenerator; | ||
use OpenCodeModeling\CodeAst\Code\ParameterGenerator; | ||
use OpenCodeModeling\CodeAst\NodeVisitor\ClassMethod; | ||
use OpenCodeModeling\JsonSchemaToPhp\Type\StringType; | ||
use OpenCodeModeling\JsonSchemaToPhpAst\PropertyFactory; | ||
use PhpParser\NodeVisitor; | ||
use PhpParser\Parser; | ||
|
||
/** | ||
* This file creates node visitors for a value object of type string. | ||
* | ||
* The following code will be generated: | ||
* | ||
* private UuidInterface $uuid; | ||
* | ||
* public static function fromString(string $uuid): self | ||
* { | ||
* return new self(Uuid::fromString($uuid)); | ||
* } | ||
* | ||
* private function __construct(UuidInterface $uuid) | ||
* { | ||
* $this->uuid = $uuid; | ||
* } | ||
* | ||
* public function toString(): string | ||
* { | ||
* return $this->uuid; | ||
* } | ||
* | ||
* public function equals($other): bool | ||
* { | ||
* if(!$other instanceof self) { | ||
* return false; | ||
* } | ||
* | ||
* return $this->uuid === $other->uuid; | ||
* } | ||
* | ||
* public function __toString(): string | ||
* { | ||
* return $this->uuid; | ||
* } | ||
*/ | ||
final class UuidFactory | ||
{ | ||
private Parser $parser; | ||
private PropertyFactory $propertyFactory; | ||
private bool $typed; | ||
|
||
public function __construct(Parser $parser, bool $typed) | ||
{ | ||
$this->parser = $parser; | ||
$this->typed = $typed; | ||
$this->propertyFactory = new PropertyFactory($typed); | ||
} | ||
|
||
/** | ||
* @param StringType $typeDefinition | ||
* @return array<NodeVisitor> | ||
*/ | ||
public function nodeVisitors(StringType $typeDefinition): array | ||
{ | ||
$name = $typeDefinition->name() ?: 'uuid'; | ||
|
||
return $this->nodeVisitorsFromNative($name); | ||
} | ||
|
||
public function classBuilder(StringType $typeDefinition): ClassBuilder | ||
{ | ||
$name = $typeDefinition->name() ?: 'uuid'; | ||
|
||
return $this->classBuilderFromNative($name); | ||
} | ||
|
||
/** | ||
* @param string $name | ||
* @return array<NodeVisitor> | ||
*/ | ||
public function nodeVisitorsFromNative(string $name): array | ||
{ | ||
$nodeVisitors = $this->propertyFactory->nodeVisitorFromNative($name, 'UuidInterface'); | ||
$nodeVisitors[] = new ClassMethod($this->methodFromString($name)); | ||
$nodeVisitors[] = new ClassMethod($this->methodMagicConstruct($name)); | ||
$nodeVisitors[] = new ClassMethod($this->methodToString($name)); | ||
$nodeVisitors[] = new ClassMethod($this->methodEquals($name)); | ||
$nodeVisitors[] = new ClassMethod($this->methodMagicToString($name)); | ||
|
||
return $nodeVisitors; | ||
} | ||
|
||
public function classBuilderFromNative(string $name): ClassBuilder | ||
{ | ||
return ClassBuilder::fromNodes( | ||
$this->propertyFactory->propertyGenerator($name, 'UuidInterface')->generate(), | ||
$this->methodFromString($name)->generate(), | ||
$this->methodMagicConstruct($name)->generate(), | ||
$this->methodToString($name)->generate(), | ||
$this->methodEquals($name)->generate(), | ||
$this->methodMagicToString($name)->generate(), | ||
)->setTyped($this->typed); | ||
} | ||
|
||
public function methodFromString(string $argumentName): MethodGenerator | ||
{ | ||
$method = new MethodGenerator( | ||
'fromString', | ||
[ | ||
new ParameterGenerator($argumentName, 'string'), | ||
], | ||
MethodGenerator::FLAG_STATIC | MethodGenerator::FLAG_PUBLIC, | ||
new BodyGenerator($this->parser, 'return new self(Uuid::fromString($' . $argumentName . '));') | ||
); | ||
$method->setTyped($this->typed); | ||
$method->setReturnType('self'); | ||
|
||
return $method; | ||
} | ||
|
||
public function methodMagicConstruct(string $argumentName): MethodGenerator | ||
{ | ||
$method = new MethodGenerator( | ||
'__construct', | ||
[ | ||
new ParameterGenerator($argumentName, 'UuidInterface'), | ||
], | ||
MethodGenerator::FLAG_PRIVATE, | ||
new BodyGenerator($this->parser, \sprintf('$this->%s = $%s;', $argumentName, $argumentName)) | ||
); | ||
$method->setTyped($this->typed); | ||
|
||
return $method; | ||
} | ||
|
||
public function methodToString(string $argumentName): MethodGenerator | ||
{ | ||
$method = new MethodGenerator( | ||
'toString', | ||
[], | ||
MethodGenerator::FLAG_PUBLIC, | ||
new BodyGenerator($this->parser, 'return $this->' . $argumentName . ';') | ||
); | ||
$method->setTyped($this->typed); | ||
$method->setReturnType('string'); | ||
|
||
return $method; | ||
} | ||
|
||
public function methodEquals(string $propertyName, string $argumentName = 'other'): MethodGenerator | ||
{ | ||
$body = <<<PHP | ||
if(!\$$argumentName instanceof self) { | ||
return false; | ||
} | ||
return \$this->$propertyName === \$$argumentName->$propertyName; | ||
PHP; | ||
|
||
$method = new MethodGenerator( | ||
'equals', | ||
[ | ||
new ParameterGenerator($argumentName), | ||
], | ||
MethodGenerator::FLAG_PUBLIC, | ||
new BodyGenerator($this->parser, $body) | ||
); | ||
$method->setTyped($this->typed); | ||
$method->setReturnType('bool'); | ||
|
||
return $method; | ||
} | ||
|
||
public function methodMagicToString(string $argumentName): MethodGenerator | ||
{ | ||
$method = new MethodGenerator( | ||
'__toString', | ||
[], | ||
MethodGenerator::FLAG_PUBLIC, | ||
new BodyGenerator($this->parser, 'return $this->' . $argumentName . ';') | ||
); | ||
$method->setTyped($this->typed); | ||
$method->setReturnType('string'); | ||
|
||
return $method; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenCodeModelingTest\JsonSchemaToPhpAst\ValueObject; | ||
|
||
use OpenCodeModeling\JsonSchemaToPhp\Type\StringType; | ||
use OpenCodeModeling\JsonSchemaToPhpAst\ValueObject\UuidFactory; | ||
use PhpParser\NodeTraverser; | ||
use PhpParser\NodeVisitor; | ||
|
||
final class UuidFactoryTest extends BaseTestCase | ||
{ | ||
private UuidFactory $uuidFactory; | ||
|
||
public function setUp(): void | ||
{ | ||
parent::setUp(); | ||
$this->uuidFactory = new UuidFactory($this->parser, true); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function it_generates_code_from_native(): void | ||
{ | ||
$this->assertCode($this->uuidFactory->nodeVisitorsFromNative('uuid')); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function it_generates_code_via_value_object_factory(): void | ||
{ | ||
$this->assertCode( | ||
$this->voFactory->nodeVisitors( | ||
StringType::fromDefinition( | ||
[ | ||
'type' => 'string', | ||
'name' => 'uuid', | ||
'format' => 'uuid', | ||
] | ||
) | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function it_generates_code_via_value_object_factory_with_class_builder(): void | ||
{ | ||
$classBuilder = $this->voFactory->classBuilder( | ||
StringType::fromDefinition( | ||
[ | ||
'type' => 'string', | ||
'name' => 'uuid', | ||
'format' => 'uuid', | ||
] | ||
) | ||
); | ||
$classBuilder->setName('UuidVO'); | ||
|
||
$this->assertCode( | ||
$classBuilder->generate($this->parser) | ||
); | ||
} | ||
|
||
/** | ||
* @param array<NodeVisitor> $nodeVisitors | ||
*/ | ||
private function assertCode(array $nodeVisitors): void | ||
{ | ||
$ast = $this->parser->parse('<?php final class UuidVO {}'); | ||
|
||
$nodeTraverser = new NodeTraverser(); | ||
|
||
foreach ($nodeVisitors as $nodeVisitor) { | ||
$nodeTraverser->addVisitor($nodeVisitor); | ||
} | ||
|
||
$expected = <<<'EOF' | ||
<?php | ||
final class UuidVO | ||
{ | ||
private UuidInterface $uuid; | ||
public static function fromString(string $uuid) : self | ||
{ | ||
return new self(Uuid::fromString($uuid)); | ||
} | ||
private function __construct(UuidInterface $uuid) | ||
{ | ||
$this->uuid = $uuid; | ||
} | ||
public function toString() : string | ||
{ | ||
return $this->uuid; | ||
} | ||
public function equals($other) : bool | ||
{ | ||
if (!$other instanceof self) { | ||
return false; | ||
} | ||
return $this->uuid === $other->uuid; | ||
} | ||
public function __toString() : string | ||
{ | ||
return $this->uuid; | ||
} | ||
} | ||
EOF; | ||
|
||
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast))); | ||
} | ||
} |