diff --git a/CHANGELOG.md b/CHANGELOG.md index f0c6f393..520d5b8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ The format is based on Keep a Changelog. ### Changed - **BREAKING:** Converted the constant classes `ReservedKeys`, `AuthKeys`, `Pagination` and the database `Type`, `Key` and `Relation` to PHP enums, and moved the table actions of `Table` into the new `TableAction` enum (#612). An enum case is not its value, so code that needs the text or number reads `->value`, and text that comes from outside is turned into a case with `::from()` or `::tryFrom()`: - `ReservedKeys`, `AuthKeys`, `Pagination`, `Type`, `Key` and `Relation` are string-backed enums with the same case names and values, so `Relation::BELONGS_TO`, `Type::INT` and `Key::INDEX` are written as before. An application that uses a case as an array key, compares it with text, or passes it to a `string` parameter must add `->value`, for example `$this->keyFields[AuthKeys::USERNAME->value]`. Code that reads the constants with `ReflectionClass::getConstants()` uses `AuthKeys::cases()`. - - These methods take the enum and no longer accept text: `Table::addColumn()`, `Table::modifyColumn()` and `Column::__construct()` take `Type`, `Table::addIndex()` takes `Key` and `Table::setAction()` takes `TableAction`. A text value such as `addColumn('id', 'int')` throws a `TypeError`; write `Type::INT`. A subclass of `Table` or `Column` that overrides these methods must declare the enum types. + - `Table::addIndex()` takes `Key` and `Table::setAction()` takes `TableAction`, and no longer accept text: `addIndex('name', 'unique')` throws a `TypeError`; write `Key::UNIQUE`. A subclass of `Table` that overrides these methods must declare the enum types. + - `Table::addColumn()`, `Table::modifyColumn()` and `Column::__construct()` accept a `Type` case or the type as text. A text type is used as before, in upper case, so any SQL type name still works (`'integer'`, `'bigint'`, `'mediumtext'`), including those that `Type` has no case for. A subclass that overrides them must declare `Type|string`. - `Table::CREATE`, `Table::ALTER`, `Table::DROP` and `Table::RENAME` are removed: use `TableAction::CREATE`, `TableAction::ALTER`, `TableAction::DROP` and `TableAction::RENAME`. - The `type` of a model relation must be a `Relation` case. The text `'hasOne'` is rejected with the message "Relation type `hasOne` is not supported"; write `Relation::HAS_ONE`. `ModelException::unsupportedRelationType()` accepts a `Relation` or text. - `Pagination` keeps the four names (`PAGINATION_CLASS`, `PAGINATION_CLASS_ACTIVE`, `PER_PAGE`, `PAGE`) as a string-backed enum, read with `->value`. The numbers `FIRST_PAGE_NUMBER`, `MINIMUM_PAGE_ITEMS_COUNT` and `EDGE_PADDING` moved to `PaginationLimit`, an enum that holds them as constants, read without `->value`. diff --git a/src/Database/Schemas/Column.php b/src/Database/Schemas/Column.php index a991054b..2d5895a6 100644 --- a/src/Database/Schemas/Column.php +++ b/src/Database/Schemas/Column.php @@ -152,12 +152,12 @@ class Column * Column constructor. * @param mixed $constraint */ - public function __construct(string $name, ?Type $type = null, $constraint = null) + public function __construct(string $name, Type|string|null $type = null, $constraint = null) { $this->name = $name; - if ($type !== null) { - $this->type = strtoupper($type->value); + if ($type) { + $this->type = strtoupper($type instanceof Type ? $type->value : $type); $this->constraint = $constraint; } } diff --git a/src/Database/Schemas/Table.php b/src/Database/Schemas/Table.php index 4648e775..aa1eebbc 100644 --- a/src/Database/Schemas/Table.php +++ b/src/Database/Schemas/Table.php @@ -107,7 +107,7 @@ public function setAction(TableAction $action, ?array $data = null): Table * Adds column to the table * @param mixed $constraint */ - public function addColumn(string $name, Type $type, $constraint = null): Table + public function addColumn(string $name, Type|string $type, $constraint = null): Table { $this->columns[] = [ 'column' => new Column($name, $type, $constraint), @@ -121,7 +121,7 @@ public function addColumn(string $name, Type $type, $constraint = null): Table * Modifies the column * @param mixed $constraint */ - public function modifyColumn(string $name, Type $type, $constraint = null): Table + public function modifyColumn(string $name, Type|string $type, $constraint = null): Table { if ($this->action === TableAction::ALTER) { $this->columns[] = [ diff --git a/tests/Unit/Database/Schema/ColumnTest.php b/tests/Unit/Database/Schema/ColumnTest.php index 50bd580d..b2eada06 100644 --- a/tests/Unit/Database/Schema/ColumnTest.php +++ b/tests/Unit/Database/Schema/ColumnTest.php @@ -5,7 +5,6 @@ use Quantum\Database\Schemas\Column; use Quantum\Database\Enums\Type; use PHPUnit\Framework\TestCase; -use TypeError; class ColumnTest extends TestCase { @@ -14,11 +13,18 @@ public function testColumnConstructor(): void $this->assertInstanceOf(Column::class, new Column('test')); } - public function testColumnRejectsTheTypeAsText(): void + public function testColumnAcceptsAnySqlTypeAsText(): void { - $this->expectException(TypeError::class); + $this->assertSame('BIGINT', (new Column('test', 'bigint', 20))->get(Column::TYPE)); + $this->assertSame('INTEGER', (new Column('test', 'integer'))->get(Column::TYPE)); + } - new Column('test', 'int', 11); + public function testColumnTypeIsTheSameFromTheEnumAndFromText(): void + { + $this->assertSame( + (new Column('test', Type::VARCHAR, 255))->get(Column::TYPE), + (new Column('test', 'varchar', 255))->get(Column::TYPE) + ); } public function testColumnRename(): void diff --git a/tests/Unit/Database/Schema/TableTest.php b/tests/Unit/Database/Schema/TableTest.php index 913a55d7..7b422bbe 100644 --- a/tests/Unit/Database/Schema/TableTest.php +++ b/tests/Unit/Database/Schema/TableTest.php @@ -62,24 +62,28 @@ public function testAddColumn(): void $this->assertEquals($expectedSql, $table->getSql()); } - public function testAddColumnRejectsTheTypeAsText(): void + public function testAddColumnAcceptsAnySqlTypeAsText(): void { $table = new Table('test'); $table->setAction(TableAction::CREATE); + $table->addColumn('id', 'bigint', 20)->primary()->autoIncrement(); + $table->addColumn('code', 'integer'); + $table->addColumn('body', 'mediumtext'); - $this->expectException(TypeError::class); + $expectedSql = 'CREATE TABLE `test` (`id` BIGINT(20) NOT NULL AUTO_INCREMENT, `code` INTEGER NOT NULL, `body` MEDIUMTEXT NOT NULL, PRIMARY KEY (`id`));'; - $table->addColumn('id', 'int', 11); + $this->assertEquals($expectedSql, $table->getSql()); } - public function testModifyColumnRejectsTheTypeAsText(): void + public function testModifyColumnAcceptsTheTypeAsText(): void { $table = new Table('test'); $table->setAction(TableAction::ALTER); + $table->modifyColumn('name', 'varchar', 50); - $this->expectException(TypeError::class); + $expectedSql = 'ALTER TABLE `test` MODIFY COLUMN `name` VARCHAR(50) NOT NULL;'; - $table->modifyColumn('name', 'varchar', 50); + $this->assertEquals($expectedSql, $table->getSql()); } public function testAddColumnWithAttributes(): void