From 196e76d4fe7ba7c0af594c592d16aed9daba0daa Mon Sep 17 00:00:00 2001 From: Christoph Kappestein Date: Sun, 18 Feb 2024 21:21:10 +0100 Subject: [PATCH 1/8] extend generator to also generate a column enum --- src/ColumnInterface.php | 32 ++++++++++++++++++ src/Generator/Generator.php | 56 +++++++++++++++++++++---------- src/TableAbstract.php | 9 +++-- tests/Generator/GeneratorTest.php | 2 ++ tests/TableQueryTestTrait.php | 19 ++++++----- 5 files changed, 89 insertions(+), 29 deletions(-) create mode 100644 src/ColumnInterface.php diff --git a/src/ColumnInterface.php b/src/ColumnInterface.php new file mode 100644 index 0000000..24295b5 --- /dev/null +++ b/src/ColumnInterface.php @@ -0,0 +1,32 @@ + + * + * Copyright 2010-2023 Christoph Kappestein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace PSX\Sql; + +/** + * Represents a class which describes a table + * + * @author Christoph Kappestein + * @license http://www.apache.org/licenses/LICENSE-2.0 + * @link https://phpsx.org + */ +interface ColumnInterface extends \BackedEnum +{ +} diff --git a/src/Generator/Generator.php b/src/Generator/Generator.php index c2a9370..a934839 100644 --- a/src/Generator/Generator.php +++ b/src/Generator/Generator.php @@ -26,6 +26,7 @@ use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types; use PhpParser\Builder; +use PhpParser\Builder\Declaration; use PhpParser\BuilderFactory; use PhpParser\Comment\Doc; use PhpParser\Node; @@ -38,6 +39,7 @@ use PSX\Record\Record; use PSX\Record\RecordableInterface; use PSX\Record\RecordInterface; +use PSX\Sql\ColumnInterface; use PSX\Sql\Condition; use PSX\Sql\Exception\GeneratorException; use PSX\Sql\Exception\ManipulationException; @@ -90,12 +92,16 @@ public function generate(): \Generator $modelClassName = $this->normalizeName($tableName) . 'Row'; $repositoryClassName = $this->normalizeName($tableName) . 'Table'; + $columnClassName = $this->normalizeName($tableName) . 'Column'; $class = $this->generateModel($modelClassName, $table); yield $modelClassName => $this->prettyPrint($class); - $class = $this->generateRepository($repositoryClassName, $modelClassName, $table); + $class = $this->generateRepository($repositoryClassName, $modelClassName, $columnClassName, $table); yield $repositoryClassName => $this->prettyPrint($class); + + $class = $this->generateColumn($columnClassName, $repositoryClassName, $table); + yield $columnClassName => $this->prettyPrint($class); } } @@ -272,13 +278,10 @@ private function buildFrom(\PhpParser\Builder\Class_ $class, array $columns): vo $class->addStmt($fromArray); } - private function generateRepository(string $className, string $rowClass, Table $table): Builder\Class_ + private function generateRepository(string $className, string $rowClass, string $columnClass, Table $table): Builder\Class_ { - if ($this->namespace !== null) { - $rowClass = '\\' . $this->namespace . '\\' . $rowClass; - } else { - $rowClass = '\\' . $rowClass; - } + $rowClass = $this->namespace !== null ? '\\' . $this->namespace . '\\' . $rowClass : '\\' . $rowClass; + $columnClass = $this->namespace !== null ? '\\' . $this->namespace . '\\' . $columnClass : '\\' . $columnClass; $class = $this->factory->class($className); $class->extend('\\' . TableAbstract::class); @@ -287,13 +290,13 @@ private function generateRepository(string $className, string $rowClass, Table $ $this->buildConstants($class, $table); $this->buildGetName($class, $table); $this->buildGetColumns($class, $table); - $this->buildFindAll($class, $rowClass); - $this->buildFindBy($class, $rowClass); + $this->buildFindAll($class, $rowClass, $columnClass); + $this->buildFindBy($class, $rowClass, $columnClass); $this->buildFindOneBy($class, $rowClass); $this->buildFind($class, $table, $rowClass); foreach ($table->getColumns() as $column) { - $this->buildFindByForColumn($class, $column, $rowClass); + $this->buildFindByForColumn($class, $column, $rowClass, $columnClass); $this->buildFindOneByForColumn($class, $column, $rowClass); $this->buildUpdateByForColumn($class, $column, $rowClass); $this->buildDeleteByForColumn($class, $column, $rowClass); @@ -387,7 +390,7 @@ private function buildFind(Builder\Class_ $class, Table $table, string $rowClass $class->addStmt($method); } - private function buildFindAll(Builder\Class_ $class, string $rowClass): void + private function buildFindAll(Builder\Class_ $class, string $rowClass, string $columnClass): void { $methodCall = new Node\Expr\MethodCall(new Node\Expr\Variable('this'), new Node\Identifier('doFindAll'), [ new Node\Arg(new Node\Expr\Variable('condition')), @@ -404,13 +407,13 @@ private function buildFindAll(Builder\Class_ $class, string $rowClass): void $method->addParam(new Node\Param(new Node\Expr\Variable('condition'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Name('\\' . Condition::class)))); $method->addParam(new Node\Param(new Node\Expr\Variable('startIndex'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Identifier('int')))); $method->addParam(new Node\Param(new Node\Expr\Variable('count'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Identifier('int')))); - $method->addParam(new Node\Param(new Node\Expr\Variable('sortBy'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Identifier('string')))); + $method->addParam(new Node\Param(new Node\Expr\Variable('sortBy'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Name($columnClass)))); $method->addParam(new Node\Param(new Node\Expr\Variable('sortOrder'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Name('\\' . OrderBy::class)))); $method->addStmt(new Node\Stmt\Return_($methodCall)); $class->addStmt($method); } - private function buildFindBy(Builder\Class_ $class, string $rowClass): void + private function buildFindBy(Builder\Class_ $class, string $rowClass, string $columnClass): void { $methodCall = new Node\Expr\MethodCall(new Node\Expr\Variable('this'), new Node\Identifier('doFindBy'), [ new Node\Arg(new Node\Expr\Variable('condition')), @@ -427,7 +430,7 @@ private function buildFindBy(Builder\Class_ $class, string $rowClass): void $method->addParam(new Node\Param(new Node\Expr\Variable('condition'), null, new Node\Name('\\' . Condition::class))); $method->addParam(new Node\Param(new Node\Expr\Variable('startIndex'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Identifier('int')))); $method->addParam(new Node\Param(new Node\Expr\Variable('count'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Identifier('int')))); - $method->addParam(new Node\Param(new Node\Expr\Variable('sortBy'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Identifier('string')))); + $method->addParam(new Node\Param(new Node\Expr\Variable('sortBy'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Name($columnClass)))); $method->addParam(new Node\Param(new Node\Expr\Variable('sortOrder'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Name('\\' . OrderBy::class)))); $method->addStmt(new Node\Stmt\Return_($methodCall)); $class->addStmt($method); @@ -448,7 +451,7 @@ private function buildFindOneBy(Builder\Class_ $class, string $rowClass): void $class->addStmt($method); } - private function buildFindByForColumn(Builder\Class_ $class, Column $column, string $rowClass): void + private function buildFindByForColumn(Builder\Class_ $class, Column $column, string $rowClass, string $columnClass): void { $methodCall = new Node\Expr\MethodCall(new Node\Expr\Variable('this'), new Node\Identifier('doFindBy'), [ new Node\Arg(new Node\Expr\Variable('condition')), @@ -467,7 +470,7 @@ private function buildFindByForColumn(Builder\Class_ $class, Column $column, str $method->addParam(new Node\Param(new Node\Expr\Variable('value'), null, new Node\Identifier($type))); $method->addParam(new Node\Param(new Node\Expr\Variable('startIndex'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Identifier('int')))); $method->addParam(new Node\Param(new Node\Expr\Variable('count'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Identifier('int')))); - $method->addParam(new Node\Param(new Node\Expr\Variable('sortBy'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Identifier('string')))); + $method->addParam(new Node\Param(new Node\Expr\Variable('sortBy'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Name($columnClass)))); $method->addParam(new Node\Param(new Node\Expr\Variable('sortOrder'), new Node\Expr\ConstFetch(new Node\Name('null')), new Node\NullableType(new Node\Name('\\' . OrderBy::class)))); $method->addStmt(new Node\Stmt\Expression(new Node\Expr\Assign(new Node\Expr\Variable('condition'), new Node\Expr\StaticCall(new Node\Name('\\' . Condition::class), new Node\Identifier('withAnd'))))); $method->addStmt(new Node\Stmt\Expression(new Node\Expr\MethodCall(new Node\Expr\Variable('condition'), new Node\Identifier($this->getOperatorForColumn($column)), [ @@ -636,6 +639,25 @@ private function buildNewRecord(Builder\Class_ $class, string $rowClass): void $class->addStmt($method); } + private function generateColumn(string $className, string $repositoryClass, Table $table): Builder\Enum_ + { + $tableClass = $this->namespace !== null ? '\\' . $this->namespace . '\\' . $repositoryClass : '\\' . $repositoryClass; + + $enum = $this->factory->enum($className); + $enum->implement('\\' . ColumnInterface::class); + $enum->setScalarType('string'); + + $columns = $table->getColumns(); + foreach ($columns as $column) { + $caseName = strtoupper($column->getName()); + $constName = 'COLUMN_' . strtoupper($column->getName()); + + $enum->addStmt(new Node\Stmt\EnumCase(new Node\Identifier($caseName), new Node\Expr\ClassConstFetch(new Node\Name($tableClass), new Node\Identifier($constName)))); + } + + return $enum; + } + private function normalizeName(string $name): string { return str_replace(' ', '', ucwords(str_replace('_', ' ', $name))); @@ -661,7 +683,7 @@ private function buildComment(array $tags): string return '/**' . "\n" . implode("\n", $lines) . "\n" . ' */'; } - private function prettyPrint(Builder\Class_ $class): string + private function prettyPrint(Builder\Declaration $class): string { if ($this->namespace !== null) { $namespace = $this->factory->namespace($this->namespace); diff --git a/src/TableAbstract.php b/src/TableAbstract.php index 1f2f468..c084fcb 100644 --- a/src/TableAbstract.php +++ b/src/TableAbstract.php @@ -185,7 +185,7 @@ protected function serializeType(mixed $value, int $type): string * @throws QueryException * @return array */ - protected function doFindAll(?Condition $condition = null, ?int $startIndex = null, ?int $count = null, ?string $sortBy = null, ?OrderBy $sortOrder = null): array + protected function doFindAll(?Condition $condition = null, ?int $startIndex = null, ?int $count = null, string|ColumnInterface|null $sortBy = null, ?OrderBy $sortOrder = null): array { $startIndex = $startIndex !== null ? $startIndex : 0; $count = $count !== null && $count > 0 ? $count : $this->limit(); @@ -193,7 +193,10 @@ protected function doFindAll(?Condition $condition = null, ?int $startIndex = nu $sortOrder = $sortOrder !== null ? $sortOrder : $this->sortOrder(); $columns = array_keys($this->getColumns()); - if (!in_array($sortBy, $columns)) { + + if ($sortBy instanceof ColumnInterface) { + $sortBy = $sortBy->value; + } elseif (!in_array($sortBy, $columns)) { $sortBy = $this->getPrimaryKeys()[0] ?? null; } @@ -220,7 +223,7 @@ protected function doFindAll(?Condition $condition = null, ?int $startIndex = nu * @throws QueryException * @return array */ - protected function doFindBy(Condition $condition, ?int $startIndex = null, ?int $count = null, ?string $sortBy = null, ?OrderBy $sortOrder = null): array + protected function doFindBy(Condition $condition, ?int $startIndex = null, ?int $count = null, string|ColumnInterface|null $sortBy = null, ?OrderBy $sortOrder = null): array { return $this->doFindAll($condition, $startIndex, $count, $sortBy, $sortOrder); } diff --git a/tests/Generator/GeneratorTest.php b/tests/Generator/GeneratorTest.php index 700e758..52e5963 100644 --- a/tests/Generator/GeneratorTest.php +++ b/tests/Generator/GeneratorTest.php @@ -20,6 +20,8 @@ namespace PSX\Sql\Tests\Generator; +use PhpParser\Error; +use PhpParser\ParserFactory; use PSX\DateTime\Date; use PSX\DateTime\DateTime; use PSX\DateTime\LocalDate; diff --git a/tests/TableQueryTestTrait.php b/tests/TableQueryTestTrait.php index a33f2b5..a8a9d46 100644 --- a/tests/TableQueryTestTrait.php +++ b/tests/TableQueryTestTrait.php @@ -23,6 +23,7 @@ use PSX\Sql\Condition; use PSX\Sql\Fields; use PSX\Sql\OrderBy; +use PSX\Sql\Tests\Generator\HandlerCommentColumn; use PSX\Sql\Tests\Generator\HandlerCommentRow; /** @@ -147,7 +148,7 @@ public function testFindAllStartIndexAndCountDefault() public function testFindAllStartIndexAndCountDesc() { $table = $this->getTable(); - $result = $table->findAll(startIndex: 2, count: 2, sortBy: 'id', sortOrder: OrderBy::DESC); + $result = $table->findAll(startIndex: 2, count: 2, sortBy: HandlerCommentColumn::ID, sortOrder: OrderBy::DESC); $this->assertEquals(true, is_array($result)); $this->assertEquals(2, count($result)); @@ -173,7 +174,7 @@ public function testFindAllStartIndexAndCountDesc() public function testFindAllStartIndexAndCountAsc() { $table = $this->getTable(); - $result = $table->findAll(startIndex: 2, count: 2, sortBy: 'id', sortOrder: OrderBy::ASC); + $result = $table->findAll(startIndex: 2, count: 2, sortBy: HandlerCommentColumn::ID, sortOrder: OrderBy::ASC); $this->assertEquals(true, is_array($result)); $this->assertEquals(2, count($result)); @@ -199,7 +200,7 @@ public function testFindAllStartIndexAndCountAsc() public function testFindAllSortDesc() { $table = $this->getTable(); - $result = $table->findAll(startIndex: 0, count: 2, sortBy: 'id', sortOrder: OrderBy::DESC); + $result = $table->findAll(startIndex: 0, count: 2, sortBy: HandlerCommentColumn::ID, sortOrder: OrderBy::DESC); $this->assertEquals(true, is_array($result)); $this->assertEquals(2, count($result)); @@ -234,7 +235,7 @@ public function testFindAllSortDesc() public function testFindAllSortAsc() { $table = $this->getTable(); - $result = $table->findAll(startIndex: 0, count: 2, sortBy: 'id', sortOrder: OrderBy::ASC); + $result = $table->findAll(startIndex: 0, count: 2, sortBy: HandlerCommentColumn::ID, sortOrder: OrderBy::ASC); $this->assertEquals(true, is_array($result)); $this->assertEquals(2, count($result)); @@ -261,7 +262,7 @@ public function testFindAllCondition() { $table = $this->getTable(); $con = Condition::withAnd()->equals('userId', 1); - $result = $table->findAll(condition: $con, startIndex: 0, count: 16, sortBy: 'id', sortOrder: OrderBy::DESC); + $result = $table->findAll(condition: $con, startIndex: 0, count: 16, sortBy: HandlerCommentColumn::ID, sortOrder: OrderBy::DESC); $this->assertEquals(true, is_array($result)); $this->assertEquals(2, count($result)); @@ -291,7 +292,7 @@ public function testFindAllConditionAndConjunction() $con = Condition::withAnd(); $con->equals('userId', 1); $con->equals('userId', 3); - $result = $table->findAll(condition: $con, startIndex: 0, count: 16, sortBy: 'id', sortOrder: OrderBy::DESC); + $result = $table->findAll(condition: $con, startIndex: 0, count: 16, sortBy: HandlerCommentColumn::ID, sortOrder: OrderBy::DESC); $this->assertEquals(true, is_array($result)); $this->assertEquals(0, count($result)); @@ -300,7 +301,7 @@ public function testFindAllConditionAndConjunction() $con = Condition::withAnd(); $con->equals('userId', 1); $con->equals('title', 'foo'); - $result = $table->findAll(condition: $con, startIndex: 0, count: 16, sortBy: 'id', sortOrder: OrderBy::DESC); + $result = $table->findAll(condition: $con, startIndex: 0, count: 16, sortBy: HandlerCommentColumn::ID, sortOrder: OrderBy::DESC); $this->assertEquals(true, is_array($result)); $this->assertEquals(1, count($result)); @@ -324,7 +325,7 @@ public function testFindAllConditionOrConjunction() $con = Condition::withOr(); $con->equals('userId', 1); $con->equals('userId', 3); - $result = $table->findAll(condition: $con, startIndex: 0, count: 16, sortBy: 'id', sortOrder: OrderBy::DESC); + $result = $table->findAll(condition: $con, startIndex: 0, count: 16, sortBy: HandlerCommentColumn::ID, sortOrder: OrderBy::DESC); $this->assertEquals(true, is_array($result)); $this->assertEquals(3, count($result)); @@ -382,7 +383,7 @@ public function testFindBy() public function testFindByStartIndexCountOrder() { $table = $this->getTable(); - $result = $table->findBy(condition: Condition::withAnd()->equals('userId', 1), startIndex: 0, count: 1, sortBy: 'id', sortOrder: OrderBy::ASC); + $result = $table->findBy(condition: Condition::withAnd()->equals('userId', 1), startIndex: 0, count: 1, sortBy: HandlerCommentColumn::ID, sortOrder: OrderBy::ASC); $this->assertEquals(true, is_array($result)); $this->assertEquals(1, count($result)); From 2528200171f1fc013b4fbb94978f6832aeccadf8 Mon Sep 17 00:00:00 2001 From: Christoph Kappestein Date: Sun, 18 Feb 2024 21:21:38 +0100 Subject: [PATCH 2/8] optimize uses --- src/Generator/Generator.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Generator/Generator.php b/src/Generator/Generator.php index a934839..f247d6d 100644 --- a/src/Generator/Generator.php +++ b/src/Generator/Generator.php @@ -26,7 +26,6 @@ use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types; use PhpParser\Builder; -use PhpParser\Builder\Declaration; use PhpParser\BuilderFactory; use PhpParser\Comment\Doc; use PhpParser\Node; From 0134c8956a3b64e7c6ebce378e4f0772d9119a25 Mon Sep 17 00:00:00 2001 From: Christoph Kappestein Date: Sun, 18 Feb 2024 21:22:27 +0100 Subject: [PATCH 3/8] update php doc --- src/ColumnInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ColumnInterface.php b/src/ColumnInterface.php index 24295b5..df74407 100644 --- a/src/ColumnInterface.php +++ b/src/ColumnInterface.php @@ -21,7 +21,7 @@ namespace PSX\Sql; /** - * Represents a class which describes a table + * Represents a column * * @author Christoph Kappestein * @license http://www.apache.org/licenses/LICENSE-2.0 From 5b1ee7cc434f81f10d1a92aae55b0a06f40c46aa Mon Sep 17 00:00:00 2001 From: Christoph Kappestein Date: Sun, 18 Feb 2024 21:23:41 +0100 Subject: [PATCH 4/8] optimize uses --- tests/Generator/GeneratorTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/Generator/GeneratorTest.php b/tests/Generator/GeneratorTest.php index 52e5963..fe3cc33 100644 --- a/tests/Generator/GeneratorTest.php +++ b/tests/Generator/GeneratorTest.php @@ -20,14 +20,11 @@ namespace PSX\Sql\Tests\Generator; -use PhpParser\Error; -use PhpParser\ParserFactory; use PSX\DateTime\Date; use PSX\DateTime\DateTime; use PSX\DateTime\LocalDate; use PSX\DateTime\LocalDateTime; use PSX\DateTime\LocalTime; -use PSX\Record\Record; use PSX\Sql\Generator\Generator; use PSX\Sql\TableManager; use PSX\Sql\TableManagerInterface; From 5886fb480d02977d86929a1d2316abd324b43d96 Mon Sep 17 00:00:00 2001 From: Christoph Kappestein Date: Sun, 18 Feb 2024 21:26:02 +0100 Subject: [PATCH 5/8] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c0542cb..6a00c8f 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ console app or you can also do this programmatically through the `PSX\Sql\Genera use PSX\Sql\Generator\Generator; -$connection = null; // a doctrine DBAL connection +$connection = null; // a doctrine DBAL connection $target = __DIR__; $generator = new Generator($connection, 'Acme\\Table'); @@ -58,7 +58,7 @@ $table->findAll(); $table->findAll(startIndex: 0, count: 12); // orders the entries after the column "id" descending -$table->findAll(startIndex: 0, count: 12, sortBy: 'id', sortOrder: OrderBy::DESC); +$table->findAll(startIndex: 0, count: 12, sortBy: \PSX\Sql\Tests\Generator\SqlTableTestColumn::ID, sortOrder: OrderBy::DESC); // returns all rows which match the specified title $table->findByTitle('foo%'); From 9c0182e578432bb3b6a0d543d9af149f20714dd5 Mon Sep 17 00:00:00 2001 From: Christoph Kappestein Date: Wed, 13 Mar 2024 20:36:12 +0100 Subject: [PATCH 6/8] add ResolvableInterface --- src/Test/Fixture.php | 6 ++++++ src/Test/ResolvableInterface.php | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 src/Test/ResolvableInterface.php diff --git a/src/Test/Fixture.php b/src/Test/Fixture.php index 8e76753..e380f53 100644 --- a/src/Test/Fixture.php +++ b/src/Test/Fixture.php @@ -67,6 +67,12 @@ public static function insert(Connection $connection, array $data): void { foreach ($data as $tableName => $rows) { foreach ($rows as $row) { + foreach ($row as $key => $value) { + if ($value instanceof ResolvableInterface) { + $row[$key] = $value->resolve($connection); + } + } + $connection->insert($tableName, $row); } } diff --git a/src/Test/ResolvableInterface.php b/src/Test/ResolvableInterface.php new file mode 100644 index 0000000..cc11158 --- /dev/null +++ b/src/Test/ResolvableInterface.php @@ -0,0 +1,35 @@ + + * + * Copyright 2010-2023 Christoph Kappestein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace PSX\Sql\Test; + +use Doctrine\DBAL\Connection; + +/** + * ResolvableInterface + * + * @author Christoph Kappestein + * @license http://www.apache.org/licenses/LICENSE-2.0 + * @link https://phpsx.org + */ +interface ResolvableInterface +{ + public function resolve(Connection $connection): int; +} From f610051673ca0e8f6778ed4f587375d12317ed52 Mon Sep 17 00:00:00 2001 From: Christoph Kappestein Date: Sun, 2 Feb 2025 12:36:51 +0100 Subject: [PATCH 7/8] update namespace --- src/Generator/Generator.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Generator/Generator.php b/src/Generator/Generator.php index 1efbbbc..b0a8024 100644 --- a/src/Generator/Generator.php +++ b/src/Generator/Generator.php @@ -26,6 +26,8 @@ use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types; use PhpParser\Builder\Class_; +use PhpParser\Builder\Declaration; +use PhpParser\Builder\Enum_; use PhpParser\BuilderFactory; use PhpParser\Comment\Doc; use PhpParser\Modifiers; @@ -638,7 +640,7 @@ private function buildNewRecord(Class_ $class, string $rowClass): void $class->addStmt($method); } - private function generateColumn(string $className, string $repositoryClass, Table $table): Builder\Enum_ + private function generateColumn(string $className, string $repositoryClass, Table $table): Enum_ { $tableClass = $this->namespace !== null ? '\\' . $this->namespace . '\\' . $repositoryClass : '\\' . $repositoryClass; @@ -682,15 +684,15 @@ private function buildComment(array $tags): string return '/**' . "\n" . implode("\n", $lines) . "\n" . ' */'; } - private function prettyPrint(Class_ $class): string + private function prettyPrint(Declaration $declaration): string { if ($this->namespace !== null) { $namespace = $this->factory->namespace($this->namespace); - $namespace->addStmt($class); + $namespace->addStmt($declaration); return $this->printer->prettyPrint([$namespace->getNode()]); } else { - return $this->printer->prettyPrint([$class->getNode()]); + return $this->printer->prettyPrint([$declaration->getNode()]); } } From 176b01cb117edd2a56efb8f697f946f6cdcd7c36 Mon Sep 17 00:00:00 2001 From: Christoph Kappestein Date: Sun, 2 Feb 2025 12:41:07 +0100 Subject: [PATCH 8/8] update readme --- README.md | 109 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 6a00c8f..fabc2b0 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,15 @@ The following are basic examples how you can work with a generated table class. use PSX\Sql\Condition; use PSX\Sql\OrderBy; use PSX\Sql\TableManager; +use PSX\Sql\Tests\Generator\SqlTableTestTable; +use PSX\Sql\Tests\Generator\SqlTableTestColumn; +use PSX\Sql\Tests\Generator\SqlTableTestRow; $connection = null; // a doctrine DBAL connection $tableManager = new TableManager($connection); -/** @var \PSX\Sql\Tests\Generator\SqlTableTestTable $table */ -$table = $tableManager->getTable(\PSX\Sql\Tests\Generator\SqlTableTestTable::class); +/** @var SqlTableTestTable $table */ +$table = $tableManager->getTable(SqlTableTestTable::class); // returns by default 16 entries from the table ordered by the primary column descending $table->findAll(); @@ -58,7 +61,7 @@ $table->findAll(); $table->findAll(startIndex: 0, count: 12); // orders the entries after the column "id" descending -$table->findAll(startIndex: 0, count: 12, sortBy: \PSX\Sql\Tests\Generator\SqlTableTestColumn::ID, sortOrder: OrderBy::DESC); +$table->findAll(startIndex: 0, count: 12, sortBy: SqlTableTestColumn::ID, sortOrder: OrderBy::DESC); // returns all rows which match the specified title $table->findByTitle('foo%'); @@ -70,7 +73,7 @@ $table->find(1); $table->getCount(); // creates a new row -$row = new \PSX\Sql\Tests\Generator\SqlTableTestRow(); +$row = new SqlTableTestRow(); $row->setTitle('foo'); $table->create($row); @@ -103,19 +106,19 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract public const COLUMN_ID = 'id'; public const COLUMN_TITLE = 'title'; public const COLUMN_DATE = 'date'; - public function getName() : string + public function getName(): string { return self::NAME; } - public function getColumns() : array + public function getColumns(): array { - return array(self::COLUMN_ID => 0x3020000a, self::COLUMN_TITLE => 0xa00020, self::COLUMN_DATE => 0x800000); + return [self::COLUMN_ID => 0x3020000a, self::COLUMN_TITLE => 0xa00020, self::COLUMN_DATE => 0x800000]; } /** * @return array<\PSX\Sql\Tests\Generator\SqlTableTestRow> * @throws \PSX\Sql\Exception\QueryException */ - public function findAll(?\PSX\Sql\Condition $condition = null, ?int $startIndex = null, ?int $count = null, ?string $sortBy = null, ?\PSX\Sql\OrderBy $sortOrder = null) : array + public function findAll(?\PSX\Sql\Condition $condition = null, ?int $startIndex = null, ?int $count = null, ?\PSX\Sql\Tests\Generator\SqlTableTestColumn $sortBy = null, ?\PSX\Sql\OrderBy $sortOrder = null): array { return $this->doFindAll($condition, $startIndex, $count, $sortBy, $sortOrder); } @@ -123,21 +126,21 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract * @return array<\PSX\Sql\Tests\Generator\SqlTableTestRow> * @throws \PSX\Sql\Exception\QueryException */ - public function findBy(\PSX\Sql\Condition $condition, ?int $startIndex = null, ?int $count = null, ?string $sortBy = null, ?\PSX\Sql\OrderBy $sortOrder = null) : array + public function findBy(\PSX\Sql\Condition $condition, ?int $startIndex = null, ?int $count = null, ?\PSX\Sql\Tests\Generator\SqlTableTestColumn $sortBy = null, ?\PSX\Sql\OrderBy $sortOrder = null): array { return $this->doFindBy($condition, $startIndex, $count, $sortBy, $sortOrder); } /** * @throws \PSX\Sql\Exception\QueryException */ - public function findOneBy(\PSX\Sql\Condition $condition) : ?\PSX\Sql\Tests\Generator\SqlTableTestRow + public function findOneBy(\PSX\Sql\Condition $condition): ?\PSX\Sql\Tests\Generator\SqlTableTestRow { return $this->doFindOneBy($condition); } /** * @throws \PSX\Sql\Exception\QueryException */ - public function find(int $id) : ?\PSX\Sql\Tests\Generator\SqlTableTestRow + public function find(int $id): ?\PSX\Sql\Tests\Generator\SqlTableTestRow { $condition = \PSX\Sql\Condition::withAnd(); $condition->equals('id', $id); @@ -147,7 +150,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract * @return array<\PSX\Sql\Tests\Generator\SqlTableTestRow> * @throws \PSX\Sql\Exception\QueryException */ - public function findById(int $value, ?int $startIndex = null, ?int $count = null, ?string $sortBy = null, ?\PSX\Sql\OrderBy $sortOrder = null) : array + public function findById(int $value, ?int $startIndex = null, ?int $count = null, ?\PSX\Sql\Tests\Generator\SqlTableTestColumn $sortBy = null, ?\PSX\Sql\OrderBy $sortOrder = null): array { $condition = \PSX\Sql\Condition::withAnd(); $condition->equals('id', $value); @@ -156,7 +159,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract /** * @throws \PSX\Sql\Exception\QueryException */ - public function findOneById(int $value) : ?\PSX\Sql\Tests\Generator\SqlTableTestRow + public function findOneById(int $value): ?\PSX\Sql\Tests\Generator\SqlTableTestRow { $condition = \PSX\Sql\Condition::withAnd(); $condition->equals('id', $value); @@ -165,7 +168,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function updateById(int $value, \PSX\Sql\Tests\Generator\SqlTableTestRow $record) : int + public function updateById(int $value, \PSX\Sql\Tests\Generator\SqlTableTestRow $record): int { $condition = \PSX\Sql\Condition::withAnd(); $condition->equals('id', $value); @@ -174,7 +177,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function deleteById(int $value) : int + public function deleteById(int $value): int { $condition = \PSX\Sql\Condition::withAnd(); $condition->equals('id', $value); @@ -184,7 +187,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract * @return array<\PSX\Sql\Tests\Generator\SqlTableTestRow> * @throws \PSX\Sql\Exception\QueryException */ - public function findByTitle(string $value, ?int $startIndex = null, ?int $count = null, ?string $sortBy = null, ?\PSX\Sql\OrderBy $sortOrder = null) : array + public function findByTitle(string $value, ?int $startIndex = null, ?int $count = null, ?\PSX\Sql\Tests\Generator\SqlTableTestColumn $sortBy = null, ?\PSX\Sql\OrderBy $sortOrder = null): array { $condition = \PSX\Sql\Condition::withAnd(); $condition->like('title', $value); @@ -193,7 +196,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract /** * @throws \PSX\Sql\Exception\QueryException */ - public function findOneByTitle(string $value) : ?\PSX\Sql\Tests\Generator\SqlTableTestRow + public function findOneByTitle(string $value): ?\PSX\Sql\Tests\Generator\SqlTableTestRow { $condition = \PSX\Sql\Condition::withAnd(); $condition->like('title', $value); @@ -202,7 +205,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function updateByTitle(string $value, \PSX\Sql\Tests\Generator\SqlTableTestRow $record) : int + public function updateByTitle(string $value, \PSX\Sql\Tests\Generator\SqlTableTestRow $record): int { $condition = \PSX\Sql\Condition::withAnd(); $condition->like('title', $value); @@ -211,7 +214,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function deleteByTitle(string $value) : int + public function deleteByTitle(string $value): int { $condition = \PSX\Sql\Condition::withAnd(); $condition->like('title', $value); @@ -221,7 +224,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract * @return array<\PSX\Sql\Tests\Generator\SqlTableTestRow> * @throws \PSX\Sql\Exception\QueryException */ - public function findByDate(\PSX\DateTime\LocalDateTime $value, ?int $startIndex = null, ?int $count = null, ?string $sortBy = null, ?\PSX\Sql\OrderBy $sortOrder = null) : array + public function findByDate(\PSX\DateTime\LocalDateTime $value, ?int $startIndex = null, ?int $count = null, ?\PSX\Sql\Tests\Generator\SqlTableTestColumn $sortBy = null, ?\PSX\Sql\OrderBy $sortOrder = null): array { $condition = \PSX\Sql\Condition::withAnd(); $condition->equals('date', $value); @@ -230,7 +233,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract /** * @throws \PSX\Sql\Exception\QueryException */ - public function findOneByDate(\PSX\DateTime\LocalDateTime $value) : ?\PSX\Sql\Tests\Generator\SqlTableTestRow + public function findOneByDate(\PSX\DateTime\LocalDateTime $value): ?\PSX\Sql\Tests\Generator\SqlTableTestRow { $condition = \PSX\Sql\Condition::withAnd(); $condition->equals('date', $value); @@ -239,7 +242,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function updateByDate(\PSX\DateTime\LocalDateTime $value, \PSX\Sql\Tests\Generator\SqlTableTestRow $record) : int + public function updateByDate(\PSX\DateTime\LocalDateTime $value, \PSX\Sql\Tests\Generator\SqlTableTestRow $record): int { $condition = \PSX\Sql\Condition::withAnd(); $condition->equals('date', $value); @@ -248,7 +251,7 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function deleteByDate(\PSX\DateTime\LocalDateTime $value) : int + public function deleteByDate(\PSX\DateTime\LocalDateTime $value): int { $condition = \PSX\Sql\Condition::withAnd(); $condition->equals('date', $value); @@ -257,42 +260,42 @@ class SqlTableTestTable extends \PSX\Sql\TableAbstract /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function create(\PSX\Sql\Tests\Generator\SqlTableTestRow $record) : int + public function create(\PSX\Sql\Tests\Generator\SqlTableTestRow $record): int { return $this->doCreate($record->toRecord()); } /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function update(\PSX\Sql\Tests\Generator\SqlTableTestRow $record) : int + public function update(\PSX\Sql\Tests\Generator\SqlTableTestRow $record): int { return $this->doUpdate($record->toRecord()); } /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function updateBy(\PSX\Sql\Condition $condition, \PSX\Sql\Tests\Generator\SqlTableTestRow $record) : int + public function updateBy(\PSX\Sql\Condition $condition, \PSX\Sql\Tests\Generator\SqlTableTestRow $record): int { return $this->doUpdateBy($condition, $record->toRecord()); } /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function delete(\PSX\Sql\Tests\Generator\SqlTableTestRow $record) : int + public function delete(\PSX\Sql\Tests\Generator\SqlTableTestRow $record): int { return $this->doDelete($record->toRecord()); } /** * @throws \PSX\Sql\Exception\ManipulationException */ - public function deleteBy(\PSX\Sql\Condition $condition) : int + public function deleteBy(\PSX\Sql\Condition $condition): int { return $this->doDeleteBy($condition); } /** * @param array $row */ - protected function newRecord(array $row) : \PSX\Sql\Tests\Generator\SqlTableTestRow + protected function newRecord(array $row): \PSX\Sql\Tests\Generator\SqlTableTestRow { return \PSX\Sql\Tests\Generator\SqlTableTestRow::from($row); } @@ -313,49 +316,67 @@ class SqlTableTestRow implements \JsonSerializable, \PSX\Record\RecordableInterf private ?int $id = null; private ?string $title = null; private ?\PSX\DateTime\LocalDateTime $date = null; - public function setId(int $id) : void + public function setId(int $id): void { $this->id = $id; } - public function getId() : int + public function getId(): int { - return $this->id; + return $this->id ?? throw new \PSX\Sql\Exception\NoValueAvailable('No value for required column "id" was provided'); } - public function setTitle(string $title) : void + public function setTitle(string $title): void { $this->title = $title; } - public function getTitle() : string + public function getTitle(): string { - return $this->title; + return $this->title ?? throw new \PSX\Sql\Exception\NoValueAvailable('No value for required column "title" was provided'); } - public function setDate(\PSX\DateTime\LocalDateTime $date) : void + public function setDate(\PSX\DateTime\LocalDateTime $date): void { $this->date = $date; } - public function getDate() : \PSX\DateTime\LocalDateTime + public function getDate(): \PSX\DateTime\LocalDateTime { - return $this->date; + return $this->date ?? throw new \PSX\Sql\Exception\NoValueAvailable('No value for required column "date" was provided'); } - public function toRecord() : \PSX\Record\RecordInterface + public function toRecord(): \PSX\Record\RecordInterface { + /** @var \PSX\Record\Record $record */ $record = new \PSX\Record\Record(); $record->put('id', $this->id); $record->put('title', $this->title); $record->put('date', $this->date); return $record; } - public function jsonSerialize() : object + public function jsonSerialize(): object { return (object) $this->toRecord()->getAll(); } - public static function from(array|\ArrayAccess $data) : self + public static function from(array|\ArrayAccess $data): self { $row = new self(); - $row->id = $data['id'] ?? null; - $row->title = $data['title'] ?? null; - $row->date = isset($data['date']) ? \PSX\DateTime\LocalDateTime::from($data['date']) : null; + $row->id = isset($data['id']) && is_int($data['id']) ? $data['id'] : null; + $row->title = isset($data['title']) && is_string($data['title']) ? $data['title'] : null; + $row->date = isset($data['date']) && $data['date'] instanceof \DateTimeInterface ? \PSX\DateTime\LocalDateTime::from($data['date']) : null; return $row; } } ``` + +## Column + +The following is an example of a generated table column. + +```php +