diff --git a/composer.json b/composer.json index cfea8db..c8e93a7 100644 --- a/composer.json +++ b/composer.json @@ -28,19 +28,21 @@ "url": "https://github.com/sponsors/yiisoft" } ], + "minimum-stability": "dev", + "prefer-stable": true, "require": { "ext-pdo": "*", "php": "^8.1", "yiisoft/db": "^1.2", "yiisoft/db-migration": "^1.1", "yiisoft/friendly-exception": "^1.1", - "yiisoft/rbac": "^2.0" + "yiisoft/rbac": "dev-item-type-yii2-compatibility" }, "require-dev": { "ext-pdo_sqlite": "*", "ext-uopz": "*", "maglnet/composer-require-checker": "^4.3", - "phpunit/phpunit": "^10.5.5", + "phpunit/phpunit": "10.5.5", "rector/rector": "^1.0.0", "roave/infection-static-analysis-plugin": "^1.25", "slope-it/clock-mock": "0.4.0", diff --git a/migrations/M241008204900UpdateItemType.php b/migrations/M241008204900UpdateItemType.php new file mode 100644 index 0000000..0f6d560 --- /dev/null +++ b/migrations/M241008204900UpdateItemType.php @@ -0,0 +1,70 @@ +getDb() + ->createCommand() + ->update(table: self::ITEMS_TABLE, columns: ['type' => 1], condition: ['type' => 'role']) + ->execute(); + $b + ->getDb() + ->createCommand() + ->update(table: self::ITEMS_TABLE, columns: ['type' => 2], condition: ['type' => 'permission']) + ->execute(); + + if ($b->getDb()->getDriverName() !== 'sqlite') { + $b->alterColumn(self::ITEMS_TABLE, 'type', $b->smallInteger()->notNull()); + } else { + $b->execute('PRAGMA foreign_keys=off;'); + $b->dropIndex(self::ITEMS_TABLE, 'idx-' . self::ITEMS_TABLE . '-type'); + $b->renameTable(self::ITEMS_TABLE, self::ITEMS_TABLE . '_old'); + $b->createTable( + self::ITEMS_TABLE, + [ + 'name' => 'string(126) NOT NULL PRIMARY KEY', + 'type' => 'smallint NOT NULL', + 'description' => 'string(191)', + 'rule_name' => 'string(64)', + 'created_at' => 'integer NOT NULL', + 'updated_at' => 'integer NOT NULL', + ], + ); + $b->createIndex(self::ITEMS_TABLE, 'idx-' . self::ITEMS_TABLE . '-type', 'type'); + $newTableName = self::ITEMS_TABLE; + $oldTableName = self::ITEMS_TABLE . '_old'; + $b->execute( + "INSERT INTO $newTableName (name, type, description, rule_name, created_at, updated_at) + SELECT name, type, description, rule_name, created_at, updated_at + FROM $oldTableName;" + ); + $b->dropTable($oldTableName); + $b->execute('PRAGMA foreign_keys=on;'); + } + } + +// public function down(MigrationBuilder $b): void +// { +// $b->alterColumn(self::ITEMS_TABLE, 'type', $b->string(10)->notNull()); +// $b +// ->getDb() +// ->createCommand() +// ->update(table: self::ITEMS_TABLE, columns: ['type' => 'permission'], condition: ['type' => 2]) +// ->execute(); +// $b +// ->getDb() +// ->createCommand() +// ->update(table: self::ITEMS_TABLE, columns: ['type' => 'role'], condition: ['type' => 1]) +// ->execute(); +// } +} diff --git a/migrations/items/M240118192500CreateItemsTables.php b/migrations/items/M240118192500CreateItemsTables.php index 967b5a0..a7db7e6 100644 --- a/migrations/items/M240118192500CreateItemsTables.php +++ b/migrations/items/M240118192500CreateItemsTables.php @@ -30,7 +30,7 @@ private function createItemsTable(MigrationBuilder $b): void self::ITEMS_TABLE, [ 'name' => 'string(126) NOT NULL PRIMARY KEY', - 'type' => 'string(10) NOT NULL', + 'type' => 'smallint NOT NULL', 'description' => 'string(191)', 'rule_name' => 'string(64)', 'created_at' => 'integer NOT NULL', diff --git a/src/ItemsStorage.php b/src/ItemsStorage.php index 76d54c6..95a6819 100644 --- a/src/ItemsStorage.php +++ b/src/ItemsStorage.php @@ -421,13 +421,13 @@ public function removeChildren(string $parentName): void /** * Gets either all existing roles or permissions, depending on a specified type. * - * @param string $type Either {@see Item::TYPE_ROLE} or {@see Item::TYPE_PERMISSION}. + * @param int $type Either {@see Item::TYPE_ROLE} or {@see Item::TYPE_PERMISSION}. * @psalm-param Item::TYPE_* $type * * @return array A list of roles / permissions. * @psalm-return ($type is Item::TYPE_PERMISSION ? array : array) */ - private function getItemsByType(string $type): array + private function getItemsByType(int $type): array { /** @psalm-var RawPermission[] | RawRole[] $rawItems */ $rawItems = (new Query($this->database)) @@ -441,14 +441,14 @@ private function getItemsByType(string $type): array /** * Gets a single item by its type and name. * - * @param string $type Either {@see Item::TYPE_ROLE} or {@see Item::TYPE_PERMISSION}. + * @param int $type Either {@see Item::TYPE_ROLE} or {@see Item::TYPE_PERMISSION}. * @psalm-param Item::TYPE_* $type * * @return Permission|Role|null Either role or permission, depending on an initial type specified. `null` is * returned when no item was found by given condition. * @psalm-return ($type is Item::TYPE_PERMISSION ? Permission : Role)|null */ - private function getItemByTypeAndName(string $type, string $name): Permission|Role|null + private function getItemByTypeAndName(int $type, string $name): Permission|Role|null { /** * @psalm-var RawItem|null $row @@ -473,7 +473,7 @@ private function getItemByTypeAndName(string $type, string $name): Permission|Ro private function createItem(array $rawItem): Permission|Role { $item = $this - ->createItemByTypeAndName($rawItem['type'], $rawItem['name']) + ->createItemByTypeAndName((int) $rawItem['type'], $rawItem['name']) ->withCreatedAt((int) $rawItem['created_at']) ->withUpdatedAt((int) $rawItem['updated_at']); @@ -491,13 +491,13 @@ private function createItem(array $rawItem): Permission|Role /** * A basic factory method for creating a single item with name only. * - * @param string $type Either {@see Item::TYPE_ROLE} or {@see Item::TYPE_PERMISSION}. + * @param int $type Either {@see Item::TYPE_ROLE} or {@see Item::TYPE_PERMISSION}. * @psalm-param Item::TYPE_* $type * * @return Permission|Role Either role or permission, depending on an initial type specified. * @psalm-return ($type is Item::TYPE_PERMISSION ? Permission : Role) */ - private function createItemByTypeAndName(string $type, string $name): Permission|Role + private function createItemByTypeAndName(int $type, string $name): Permission|Role { return $type === Item::TYPE_PERMISSION ? new Permission($name) : new Role($name); } @@ -519,10 +519,10 @@ private function removeRelatedItemsChildren(ConnectionInterface $database, strin /** * Removes all existing items of a specified type. * - * @param string $type Either {@see Item::TYPE_ROLE} or {@see Item::TYPE_PERMISSION}. + * @param int $type Either {@see Item::TYPE_ROLE} or {@see Item::TYPE_PERMISSION}. * @psalm-param Item::TYPE_* $type */ - private function clearItemsByType(string $type): void + private function clearItemsByType(int $type): void { $itemsStorage = $this; $this->database->transaction(static function (ConnectionInterface $database) use ($itemsStorage, $type): void { diff --git a/tests/Base/SchemaTrait.php b/tests/Base/SchemaTrait.php index ef7cf80..6f4cbdd 100644 --- a/tests/Base/SchemaTrait.php +++ b/tests/Base/SchemaTrait.php @@ -170,8 +170,8 @@ private function checkItemsTable(): void $this->assertArrayHasKey('type', $columns); $type = $columns['type']; - $this->assertSame('string', $type->getType()); - $this->assertSame(10, $type->getSize()); + $this->assertSame('smallint', $type->getType()); + $this->assertNull($type->getSize()); $this->assertFalse($type->isAllowNull()); $this->assertArrayHasKey('description', $columns);