diff --git a/composer.json b/composer.json index 78456e1cdcf9ea34e6130cc8b4710a12e82fa69e..dbba9aafeed81f0abb887130f3ae6ad31277fd5f 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "require": { "php": "^8.0", "dibi/dibi": "^4.0.2", - "grifart/scaffolder": "^0.5.3", + "grifart/scaffolder": "^0.6.0", "nette/utils": "^3.0.1" }, "require-dev": { diff --git a/src/Scaffolding/Builders.php b/src/Scaffolding/Builders.php deleted file mode 100644 index 439104dd77cd1623b452e38b20990689f316d9dd..0000000000000000000000000000000000000000 --- a/src/Scaffolding/Builders.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php declare(strict_types = 1); - -namespace Grifart\Tables\Scaffolding; - -use Grifart\ClassScaffolder\Definition\ClassDefinition; -use Grifart\ClassScaffolder\Definition\ClassDefinitionBuilder; - - -/** - * @implements \IteratorAggregate<ClassDefinition> - */ -final class Builders implements \IteratorAggregate -{ - private function __construct( - private ClassDefinitionBuilder $rowClass, - private ClassDefinitionBuilder $modificationsClass, - private ClassDefinitionBuilder $tableClass, - ) {} - - public static function from( - ClassDefinitionBuilder $rowClass, - ClassDefinitionBuilder $modificationsClass, - ClassDefinitionBuilder $tableClass, - ): self - { - return new self( - $rowClass, - $modificationsClass, - $tableClass, - ); - } - - public function getRowClass(): ClassDefinitionBuilder - { - return $this->rowClass; - } - - public function getModificationsClass(): ClassDefinitionBuilder - { - return $this->modificationsClass; - } - - public function getTableClass(): ClassDefinitionBuilder - { - return $this->tableClass; - } - - - public function getIterator(): \Traversable - { - yield $this->rowClass->build(); - yield $this->modificationsClass->build(); - yield $this->tableClass->build(); - } - -} diff --git a/src/Scaffolding/Definitions.php b/src/Scaffolding/Definitions.php new file mode 100644 index 0000000000000000000000000000000000000000..9b22139c3b9a8c13ee708471a1a578638a1b0ddd --- /dev/null +++ b/src/Scaffolding/Definitions.php @@ -0,0 +1,55 @@ +<?php declare(strict_types = 1); + +namespace Grifart\Tables\Scaffolding; + +use Grifart\ClassScaffolder\Definition\ClassDefinition; + + +/** + * @implements \IteratorAggregate<ClassDefinition> + */ +final class Definitions implements \IteratorAggregate +{ + private function __construct( + private ClassDefinition $rowClass, + private ClassDefinition $modificationsClass, + private ClassDefinition $tableClass, + ) {} + + public static function from( + ClassDefinition $rowClass, + ClassDefinition $modificationsClass, + ClassDefinition $tableClass, + ): self + { + return new self( + $rowClass, + $modificationsClass, + $tableClass, + ); + } + + public function getRowClass(): ClassDefinition + { + return $this->rowClass; + } + + public function getModificationsClass(): ClassDefinition + { + return $this->modificationsClass; + } + + public function getTableClass(): ClassDefinition + { + return $this->tableClass; + } + + + public function getIterator(): \Traversable + { + yield $this->rowClass; + yield $this->modificationsClass; + yield $this->tableClass; + } + +} diff --git a/src/Scaffolding/ModificationsDecorator.php b/src/Scaffolding/ModificationsImplementation.php similarity index 87% rename from src/Scaffolding/ModificationsDecorator.php rename to src/Scaffolding/ModificationsImplementation.php index ea97881d825264cbf0e88914944bdfae9cd8badf..43e578d115b08203852afe66366b0b05e19cb0ab 100644 --- a/src/Scaffolding/ModificationsDecorator.php +++ b/src/Scaffolding/ModificationsImplementation.php @@ -3,16 +3,15 @@ namespace Grifart\Tables\Scaffolding; -use Grifart\ClassScaffolder\Decorators\ClassDecorator; +use Grifart\ClassScaffolder\Capabilities\Capability; +use Grifart\ClassScaffolder\ClassInNamespace; use Grifart\ClassScaffolder\Definition\ClassDefinition; use Grifart\Tables\Modifications; use Grifart\Tables\ModificationsTrait; -use Nette\PhpGenerator\ClassType; use Nette\PhpGenerator\Parameter; use Nette\PhpGenerator\PhpLiteral; -use Nette\PhpGenerator\PhpNamespace; -final class ModificationsDecorator implements ClassDecorator +final class ModificationsImplementation implements Capability { private string $modificationsStorage; @@ -29,8 +28,15 @@ final class ModificationsDecorator implements ClassDecorator } - public function decorate(PhpNamespace $namespace, ClassType $classType, ClassDefinition $definition): void + public function applyTo( + ClassDefinition $definition, + ClassInNamespace $draft, + ?ClassInNamespace $current, + ): void { + $namespace = $draft->getNamespace(); + $classType = $draft->getClassType(); + $namespace->addUse(ModificationsTrait::class); $classType->addTrait(ModificationsTrait::class); diff --git a/src/Scaffolding/PrivateConstructorDecorator.php b/src/Scaffolding/PrivateConstructorDecorator.php deleted file mode 100644 index 10a36db4358c84eeb5e7071f5a96fec9bec3e91a..0000000000000000000000000000000000000000 --- a/src/Scaffolding/PrivateConstructorDecorator.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php declare(strict_types=1); - -namespace Grifart\Tables\Scaffolding; - -use Grifart\ClassScaffolder\Decorators\ClassDecorator; -use Grifart\ClassScaffolder\Definition\ClassDefinition; -use Nette\PhpGenerator\ClassType; -use Nette\PhpGenerator\PhpNamespace; - -final class PrivateConstructorDecorator implements ClassDecorator -{ - - public function decorate(PhpNamespace $namespace, ClassType $classType, ClassDefinition $definition): void - { - $classType->getMethod('__construct')->setPrivate(); - } -} diff --git a/src/Scaffolding/ReconstituteConstructor.php b/src/Scaffolding/ReconstituteConstructor.php new file mode 100644 index 0000000000000000000000000000000000000000..8059191e4fe3ed76b89887ddcfa8546443629141 --- /dev/null +++ b/src/Scaffolding/ReconstituteConstructor.php @@ -0,0 +1,32 @@ +<?php declare(strict_types=1); + +namespace Grifart\Tables\Scaffolding; + +use Grifart\ClassScaffolder\Capabilities\Capability; +use Grifart\ClassScaffolder\ClassInNamespace; +use Grifart\ClassScaffolder\Definition\ClassDefinition; +use Grifart\ClassScaffolder\Definition\Field; +use Nette\PhpGenerator as Code; + +final class ReconstituteConstructor implements Capability +{ + public function applyTo( + ClassDefinition $definition, + ClassInNamespace $draft, + ?ClassInNamespace $current, + ): void + { + $classType = $draft->getClassType(); + + $reconstitute = $classType->addMethod('reconstitute') + ->setReturnType('static') + ->setParameters([(new Code\Parameter('values'))->setTypeHint('array')]) + ->setStatic(); + + $fields = $definition->getFields(); + $questionMarks = \implode(', ', array_fill(0, \count($fields), '?')); + $literals = \array_map(function(Field $field): Code\PhpLiteral {return new Code\PhpLiteral("\$values['" . $field->getName() . "']");}, $fields); + + $reconstitute->addBody("return new static($questionMarks);", \array_values($literals)); + } +} diff --git a/src/Scaffolding/ReconstituteConstructorDecorator.php b/src/Scaffolding/ReconstituteConstructorDecorator.php deleted file mode 100644 index b2c2fb6fb8a6517f5b928e032d65f26889f1bd75..0000000000000000000000000000000000000000 --- a/src/Scaffolding/ReconstituteConstructorDecorator.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace Grifart\Tables\Scaffolding; - -use Grifart\ClassScaffolder\Decorators\ClassDecorator; -use Grifart\ClassScaffolder\Definition\ClassDefinition; -use Nette\PhpGenerator as Code; -use Nette\PhpGenerator\ClassType; -use Nette\PhpGenerator\Property; - -final class ReconstituteConstructorDecorator implements ClassDecorator -{ - - public function decorate(Code\PhpNamespace $namespace, ClassType $classType, ClassDefinition $definition): void - { - $reconstitute = $classType->addMethod('reconstitute') - ->setReturnType('static') - ->setParameters([(new Code\Parameter('values'))->setTypeHint('array')]) - ->setStatic(); - - // todo use class definition instead when https://gitlab.grifart.cz/grifart/class-scaffolder/issues/5 is resolved - $properties = \array_map(function(Property $property): string {return $property->getName();}, $classType->getProperties()); - $questionMarks = \implode(', ', array_fill(0, \count($properties), '?')); - $literals = \array_map(function(string $property): Code\PhpLiteral {return new Code\PhpLiteral("\$values['" . $property . "']");}, $properties); - - // todo: add array_keys that it contains just keys that are necessary - - $reconstitute->addBody("return new static($questionMarks);", \array_values($literals)); - } -} diff --git a/src/Scaffolding/Scaffolding.php b/src/Scaffolding/Scaffolding.php index b6a83674df17b75ecd47791ce71bfa89988719f4..1a8e8bdc053d204786d93265149488ab84b5b76e 100644 --- a/src/Scaffolding/Scaffolding.php +++ b/src/Scaffolding/Scaffolding.php @@ -2,13 +2,13 @@ namespace Grifart\Tables\Scaffolding; -use Grifart\ClassScaffolder\Decorators\GettersDecorator; -use Grifart\ClassScaffolder\Decorators\InitializingConstructorDecorator; -use Grifart\ClassScaffolder\Decorators\PropertiesDecorator; use Grifart\ClassScaffolder\Definition\ClassDefinition; -use Grifart\ClassScaffolder\Definition\ClassDefinitionBuilder; use Grifart\Tables\Row; use Grifart\Tables\TypeMapper; +use function Grifart\ClassScaffolder\Capabilities\constructorWithPromotedProperties; +use function Grifart\ClassScaffolder\Capabilities\getters; +use function Grifart\ClassScaffolder\Capabilities\implementedInterface; +use function Grifart\ClassScaffolder\Capabilities\privatizedConstructor; use function Grifart\ClassScaffolder\Definition\Types\nullable; use function Grifart\ClassScaffolder\Definition\Types\resolve; @@ -37,7 +37,7 @@ final class Scaffolding string $modificationsClassName, string $tableClassName, string $primaryKeyClass - ): Builders + ): Definitions { return self::buildersForPgTable( $pgReflector, @@ -69,7 +69,7 @@ final class Scaffolding string $modificationsClassName, string $tableClassName, string $primaryKeyClass - ): Builders + ): Definitions { $columnsNativeTypes = $pgReflector->retrieveColumnInfo($schema, $tableClass); if (\count($columnsNativeTypes) === 0) { @@ -86,30 +86,28 @@ final class Scaffolding $columnsPhpTypes[$column->getName()] = $column->isNullable() ? nullable($phpType) : $phpType; } - $addTableFields = function (ClassDefinitionBuilder $builder) use ($columnsPhpTypes): ClassDefinitionBuilder { - foreach ($columnsPhpTypes as $name => $type) { - $builder->field($name, $type); - } - return $builder; + $addTableFields = function (ClassDefinition $definition) use ($columnsPhpTypes): ClassDefinition { + return $definition->withFields($columnsPhpTypes); }; // row class - $rowClass = $addTableFields(new ClassDefinitionBuilder($rowClassName)) - ->implement(Row::class) - ->decorate(new PropertiesDecorator()) - ->decorate(new InitializingConstructorDecorator()) - ->decorate(new GettersDecorator()) - ->decorate(new PrivateConstructorDecorator()) - ->decorate(new ReconstituteConstructorDecorator()); + $rowClass = $addTableFields(new ClassDefinition($rowClassName)) + ->with( + implementedInterface(Row::class), + constructorWithPromotedProperties(), + privatizedConstructor(), + getters(), + new ReconstituteConstructor(), + ); // row modification class - $modificationsClass = $addTableFields(new ClassDefinitionBuilder($modificationsClassName)) - ->decorate(new ModificationsDecorator($tableClassName, $primaryKeyClass)); + $modificationsClass = $addTableFields(new ClassDefinition($modificationsClassName)) + ->with(new ModificationsImplementation($tableClassName, $primaryKeyClass)); // table class - $tableClass = (new ClassDefinitionBuilder($tableClassName)) - ->decorate(new TableDecorator( + $tableClass = (new ClassDefinition($tableClassName)) + ->with(new TableImplementation( $schema, $tableClass, $primaryKeyClass, @@ -119,7 +117,7 @@ final class Scaffolding $columnsPhpTypes, )); - return Builders::from($rowClass, $modificationsClass, $tableClass); + return Definitions::from($rowClass, $modificationsClass, $tableClass); } } diff --git a/src/Scaffolding/TableDecorator.php b/src/Scaffolding/TableImplementation.php similarity index 92% rename from src/Scaffolding/TableDecorator.php rename to src/Scaffolding/TableImplementation.php index 0615f55041c2e082a982a49627688ee223a49e94..40bbf08f1ec881d015f94d9ccca45a506ce0b5da 100644 --- a/src/Scaffolding/TableDecorator.php +++ b/src/Scaffolding/TableImplementation.php @@ -4,7 +4,8 @@ namespace Grifart\Tables\Scaffolding; -use Grifart\ClassScaffolder\Decorators\ClassDecorator; +use Grifart\ClassScaffolder\Capabilities\Capability; +use Grifart\ClassScaffolder\ClassInNamespace; use Grifart\ClassScaffolder\Definition\ClassDefinition; use Grifart\ClassScaffolder\Definition\Types\Type; use Grifart\Tables\CaseConvertion; @@ -12,9 +13,8 @@ use Grifart\Tables\RowNotFound; use Grifart\Tables\Table; use Grifart\Tables\TableManager; use Nette\PhpGenerator as Code; -use Webmozart\Assert\Assert; -final class TableDecorator implements ClassDecorator +final class TableImplementation implements Capability { private string $schema; @@ -46,14 +46,20 @@ final class TableDecorator implements ClassDecorator $this->rowClass = $rowClass; $this->modificationClass = $modificationClass; - Assert::allIsInstanceOf($columnInfo, Column::class); $this->columnInfo = $columnInfo; $this->columnPhpTypes = $columnPhpTypes; } - public function decorate(Code\PhpNamespace $namespace, Code\ClassType $classType, ClassDefinition $definition): void + public function applyTo( + ClassDefinition $definition, + ClassInNamespace $draft, + ?ClassInNamespace $current, + ): void { + $namespace = $draft->getNamespace(); + $classType = $draft->getClassType(); + // implements table $namespace->addUse(Table::class); $classType->addImplement(Table::class); @@ -90,11 +96,6 @@ final class TableDecorator implements ClassDecorator // Column references // todo add - use constants? Or references to Column class? - $namespace->addUse(TableManager::class); - $classType->addProperty('tableManager') - ->addComment('@var TableManager') - ->setVisibility('private'); - $classType->addMethod('find') ->setParameters([ (new Code\Parameter('primaryKey')) @@ -232,13 +233,11 @@ final class TableDecorator implements ClassDecorator '$this->tableManager->delete($this, $primaryKey);' ); + $namespace->addUse(TableManager::class); $classType->addMethod('__construct') - ->setParameters([ - (new Code\Parameter('tableManager'))->setTypeHint(TableManager::class) - ]) - ->setBody( - '$this->tableManager = $tableManager;' - ); + ->addPromotedParameter('tableManager') + ->setType(TableManager::class) + ->setPrivate();