From 2bde7d59123383a904459a74a7a7a0fc8393b20f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pudil?= <me@jiripudil.cz> Date: Thu, 13 Feb 2025 13:40:19 +0100 Subject: [PATCH] add generated TableFactory that can create Tables with custom Connection or TableManager --- src/Scaffolding/Definitions.php | 18 +++++ .../TableFactoryImplementation.php | 73 +++++++++++++++++++ src/Scaffolding/TablesDefinitions.php | 6 +- src/TableFactory.php | 14 ++++ tests/Fixtures/ConfigTableFactory.php | 42 +++++++++++ tests/Fixtures/GeneratedTableFactory.php | 42 +++++++++++ tests/Fixtures/PackagesTableFactory.php | 42 +++++++++++ tests/Fixtures/TestsTableFactory.php | 42 +++++++++++ tests/Scaffolding/ScaffoldingTest.phpt | 2 +- 9 files changed, 278 insertions(+), 3 deletions(-) create mode 100644 src/Scaffolding/TableFactoryImplementation.php create mode 100644 src/TableFactory.php create mode 100644 tests/Fixtures/ConfigTableFactory.php create mode 100644 tests/Fixtures/GeneratedTableFactory.php create mode 100644 tests/Fixtures/PackagesTableFactory.php create mode 100644 tests/Fixtures/TestsTableFactory.php diff --git a/src/Scaffolding/Definitions.php b/src/Scaffolding/Definitions.php index 5fa50fa..35f5239 100644 --- a/src/Scaffolding/Definitions.php +++ b/src/Scaffolding/Definitions.php @@ -16,6 +16,7 @@ final class Definitions implements \IteratorAggregate private ClassDefinition $modificationsClass, private ?ClassDefinition $primaryKeyClass, private ClassDefinition $tableClass, + private ?ClassDefinition $factoryClass, ) {} public static function from( @@ -23,6 +24,7 @@ final class Definitions implements \IteratorAggregate ClassDefinition $modificationsClass, ClassDefinition $primaryKeyClass, ClassDefinition $tableClass, + ClassDefinition $factoryClass, ): self { return new self( @@ -30,6 +32,7 @@ final class Definitions implements \IteratorAggregate $modificationsClass, $primaryKeyClass, $tableClass, + $factoryClass, ); } @@ -63,6 +66,18 @@ final class Definitions implements \IteratorAggregate return $this; } + public function factoryClassWith(Capability $capability, Capability ...$capabilities): self + { + $this->factoryClass = $this->factoryClass?->with($capability, ...$capabilities); + return $this; + } + + public function withoutFactory(): self + { + $this->factoryClass = null; + return $this; + } + public function getIterator(): \Traversable { @@ -72,6 +87,9 @@ final class Definitions implements \IteratorAggregate if ($this->primaryKeyClass !== null) { yield $this->primaryKeyClass; } + if ($this->factoryClass !== null) { + yield $this->factoryClass; + } } } diff --git a/src/Scaffolding/TableFactoryImplementation.php b/src/Scaffolding/TableFactoryImplementation.php new file mode 100644 index 0000000..81bbede --- /dev/null +++ b/src/Scaffolding/TableFactoryImplementation.php @@ -0,0 +1,73 @@ +<?php + +declare(strict_types=1); + +namespace Grifart\Tables\Scaffolding; + +use Dibi\IConnection; +use Grifart\ClassScaffolder\Capabilities\Capability; +use Grifart\ClassScaffolder\ClassInNamespace; +use Grifart\ClassScaffolder\Definition\ClassDefinition; +use Grifart\Tables\SingleConnectionTableManager; +use Grifart\Tables\TableFactory; +use Grifart\Tables\TableManager; +use Grifart\Tables\TypeResolver; +use Nette\PhpGenerator\Literal; +use Nette\PhpGenerator\Parameter; +use Nette\PhpGenerator\PromotedParameter; + +final readonly class TableFactoryImplementation implements Capability +{ + public function __construct( + private string $tableClass, + ) {} + + public function applyTo( + ClassDefinition $definition, + ClassInNamespace $draft, + ?ClassInNamespace $current, + ): void + { + $namespace = $draft->getNamespace(); + $classType = $draft->getClassType(); + + $classType->addImplement(TableFactory::class); + $classType->setReadOnly(); + + $namespace->addUse(TypeResolver::class); + $namespace->addUse(TableManager::class); + + $classType->addMethod('__construct') + ->setPublic() + ->setParameters([ + (new PromotedParameter('tableManager')) + ->setPrivate() + ->setType(TableManager::class), + (new PromotedParameter('typeResolver')) + ->setPrivate() + ->setType(TypeResolver::class), + ]); + + $namespace->addUse($this->tableClass); + + $classType->addMethod('create') + ->setPublic() + ->setReturnType($this->tableClass) + ->setBody('return new ?($this->tableManager, $this->typeResolver);', [new Literal($namespace->simplifyName($this->tableClass))]); + + $classType->addMethod('withTableManager') + ->setPublic() + ->setReturnType($this->tableClass) + ->setParameters([(new Parameter('tableManager'))->setType(TableManager::class)]) + ->setBody('return new ?($tableManager, $this->typeResolver);', [new Literal($namespace->simplifyName($this->tableClass))]); + + $namespace->addUse(IConnection::class); + $namespace->addUse(SingleConnectionTableManager::class); + $classType->addMethod('withConnection') + ->setPublic() + ->setReturnType($this->tableClass) + ->setParameters([(new Parameter('connection'))->setType(IConnection::class)]) + ->addBody('$tableManager = new ?($connection);', [new Literal($namespace->simplifyName(SingleConnectionTableManager::class))]) + ->addBody('return new ?($tableManager, $this->typeResolver);', [new Literal($namespace->simplifyName($this->tableClass))]); + } +} diff --git a/src/Scaffolding/TablesDefinitions.php b/src/Scaffolding/TablesDefinitions.php index 0a5b629..805ac51 100644 --- a/src/Scaffolding/TablesDefinitions.php +++ b/src/Scaffolding/TablesDefinitions.php @@ -17,7 +17,6 @@ use function Grifart\ClassScaffolder\Capabilities\implementedInterface; use function Grifart\ClassScaffolder\Capabilities\namedConstructor; use function Grifart\ClassScaffolder\Capabilities\privatizedConstructor; use function Grifart\ClassScaffolder\Definition\Types\nullable; -use function Phun\map; use function Phun\mapWithKeys; final class TablesDefinitions @@ -101,6 +100,9 @@ final class TablesDefinitions $columnPhpTypes, )); - return Definitions::from($rowClass, $modificationsClass, $primaryKeyClass, $tableClass); + $factoryClass = (new ClassDefinition($tableClassName . 'Factory')) + ->with(new TableFactoryImplementation($tableClassName)); + + return Definitions::from($rowClass, $modificationsClass, $primaryKeyClass, $tableClass, $factoryClass); } } diff --git a/src/TableFactory.php b/src/TableFactory.php new file mode 100644 index 0000000..aa29745 --- /dev/null +++ b/src/TableFactory.php @@ -0,0 +1,14 @@ +<?php + +declare(strict_types=1); + +namespace Grifart\Tables; + +use Dibi\IConnection; + +interface TableFactory +{ + public function create(): Table; + public function withTableManager(TableManager $tableManager): Table; + public function withConnection(IConnection $connection): Table; +} diff --git a/tests/Fixtures/ConfigTableFactory.php b/tests/Fixtures/ConfigTableFactory.php new file mode 100644 index 0000000..de03067 --- /dev/null +++ b/tests/Fixtures/ConfigTableFactory.php @@ -0,0 +1,42 @@ +<?php + +/** + * Do not edit. This is generated file. Modify definition file instead. + */ + +declare(strict_types=1); + +namespace Grifart\Tables\Tests\Fixtures; + +use Dibi\IConnection; +use Grifart\Tables\SingleConnectionTableManager; +use Grifart\Tables\TableManager; +use Grifart\Tables\TypeResolver; + +final readonly class ConfigTableFactory implements \Grifart\Tables\TableFactory +{ + public function __construct( + private TableManager $tableManager, + private TypeResolver $typeResolver, + ) { + } + + + public function create(): ConfigTable + { + return new ConfigTable($this->tableManager, $this->typeResolver); + } + + + public function withTableManager(TableManager $tableManager): ConfigTable + { + return new ConfigTable($tableManager, $this->typeResolver); + } + + + public function withConnection(IConnection $connection): ConfigTable + { + $tableManager = new SingleConnectionTableManager($connection); + return new ConfigTable($tableManager, $this->typeResolver); + } +} diff --git a/tests/Fixtures/GeneratedTableFactory.php b/tests/Fixtures/GeneratedTableFactory.php new file mode 100644 index 0000000..ac9413d --- /dev/null +++ b/tests/Fixtures/GeneratedTableFactory.php @@ -0,0 +1,42 @@ +<?php + +/** + * Do not edit. This is generated file. Modify definition file instead. + */ + +declare(strict_types=1); + +namespace Grifart\Tables\Tests\Fixtures; + +use Dibi\IConnection; +use Grifart\Tables\SingleConnectionTableManager; +use Grifart\Tables\TableManager; +use Grifart\Tables\TypeResolver; + +final readonly class GeneratedTableFactory implements \Grifart\Tables\TableFactory +{ + public function __construct( + private TableManager $tableManager, + private TypeResolver $typeResolver, + ) { + } + + + public function create(): GeneratedTable + { + return new GeneratedTable($this->tableManager, $this->typeResolver); + } + + + public function withTableManager(TableManager $tableManager): GeneratedTable + { + return new GeneratedTable($tableManager, $this->typeResolver); + } + + + public function withConnection(IConnection $connection): GeneratedTable + { + $tableManager = new SingleConnectionTableManager($connection); + return new GeneratedTable($tableManager, $this->typeResolver); + } +} diff --git a/tests/Fixtures/PackagesTableFactory.php b/tests/Fixtures/PackagesTableFactory.php new file mode 100644 index 0000000..72bfcce --- /dev/null +++ b/tests/Fixtures/PackagesTableFactory.php @@ -0,0 +1,42 @@ +<?php + +/** + * Do not edit. This is generated file. Modify definition file instead. + */ + +declare(strict_types=1); + +namespace Grifart\Tables\Tests\Fixtures; + +use Dibi\IConnection; +use Grifart\Tables\SingleConnectionTableManager; +use Grifart\Tables\TableManager; +use Grifart\Tables\TypeResolver; + +final readonly class PackagesTableFactory implements \Grifart\Tables\TableFactory +{ + public function __construct( + private TableManager $tableManager, + private TypeResolver $typeResolver, + ) { + } + + + public function create(): PackagesTable + { + return new PackagesTable($this->tableManager, $this->typeResolver); + } + + + public function withTableManager(TableManager $tableManager): PackagesTable + { + return new PackagesTable($tableManager, $this->typeResolver); + } + + + public function withConnection(IConnection $connection): PackagesTable + { + $tableManager = new SingleConnectionTableManager($connection); + return new PackagesTable($tableManager, $this->typeResolver); + } +} diff --git a/tests/Fixtures/TestsTableFactory.php b/tests/Fixtures/TestsTableFactory.php new file mode 100644 index 0000000..7b7bf9d --- /dev/null +++ b/tests/Fixtures/TestsTableFactory.php @@ -0,0 +1,42 @@ +<?php + +/** + * Do not edit. This is generated file. Modify definition file instead. + */ + +declare(strict_types=1); + +namespace Grifart\Tables\Tests\Fixtures; + +use Dibi\IConnection; +use Grifart\Tables\SingleConnectionTableManager; +use Grifart\Tables\TableManager; +use Grifart\Tables\TypeResolver; + +final readonly class TestsTableFactory implements \Grifart\Tables\TableFactory +{ + public function __construct( + private TableManager $tableManager, + private TypeResolver $typeResolver, + ) { + } + + + public function create(): TestsTable + { + return new TestsTable($this->tableManager, $this->typeResolver); + } + + + public function withTableManager(TableManager $tableManager): TestsTable + { + return new TestsTable($tableManager, $this->typeResolver); + } + + + public function withConnection(IConnection $connection): TestsTable + { + $tableManager = new SingleConnectionTableManager($connection); + return new TestsTable($tableManager, $this->typeResolver); + } +} diff --git a/tests/Scaffolding/ScaffoldingTest.phpt b/tests/Scaffolding/ScaffoldingTest.phpt index 148d0c5..a956c07 100644 --- a/tests/Scaffolding/ScaffoldingTest.phpt +++ b/tests/Scaffolding/ScaffoldingTest.phpt @@ -34,5 +34,5 @@ $results = $fileProcessor->processFile( }, ); -Assert::count(16, $results->getDefinitions()); +Assert::count(20, $results->getDefinitions()); Assert::true($results->isSuccessful()); -- GitLab