Skip to content

Commit

Permalink
Improve compatibility of item's type with Yii 2
Browse files Browse the repository at this point in the history
  • Loading branch information
arogachev committed Oct 9, 2024
1 parent 0f2d25e commit 4588ad3
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 14 deletions.
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
70 changes: 70 additions & 0 deletions migrations/M241008204900UpdateItemType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

use Yiisoft\Db\Migration\MigrationBuilder;
use Yiisoft\Db\Migration\TransactionalMigrationInterface;

final class M241008204900UpdateItemType implements TransactionalMigrationInterface
{
private const TABLE_PREFIX = 'yii_rbac_';
private const ITEMS_TABLE = self::TABLE_PREFIX . 'item';

public function up(MigrationBuilder $b): void
{
$b
->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();
// }
}
2 changes: 1 addition & 1 deletion migrations/items/M240118192500CreateItemsTables.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
18 changes: 9 additions & 9 deletions src/ItemsStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, Permission> : array<string, Role>)
*/
private function getItemsByType(string $type): array
private function getItemsByType(int $type): array
{
/** @psalm-var RawPermission[] | RawRole[] $rawItems */
$rawItems = (new Query($this->database))
Expand All @@ -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
Expand All @@ -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'])

Check failure on line 476 in src/ItemsStorage.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

RedundantCastGivenDocblockType

src/ItemsStorage.php:476:39: RedundantCastGivenDocblockType: Redundant cast to int given docblock-provided type (see https://psalm.dev/263)
->withCreatedAt((int) $rawItem['created_at'])
->withUpdatedAt((int) $rawItem['updated_at']);

Expand All @@ -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);
}
Expand All @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions tests/Base/SchemaTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 4588ad3

Please sign in to comment.