Skip to content

Commit

Permalink
Add schema manager
Browse files Browse the repository at this point in the history
  • Loading branch information
arogachev committed Apr 29, 2023
1 parent 3b4bdd2 commit 432476c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 90 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"php": "^8.0",
"symfony/console": "^5.3|^6.0",
"yiisoft/db": "^1.0",
"yiisoft/rbac": "^1.0.2"
"yiisoft/rbac": "dev-schema-manager"
},
"require-dev": {
"ext-pdo_sqlite": "*",
Expand Down
121 changes: 36 additions & 85 deletions src/Command/RbacDbInit.php → src/SchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,16 @@

declare(strict_types=1);

namespace Yiisoft\Rbac\Db\Command;
namespace Yiisoft\Rbac\Db;

use InvalidArgumentException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Schema\SchemaInterface;
use Yiisoft\Db\Sqlite\Column;
use Yiisoft\Rbac\SchemaManagerInterface;

/**
* Command for creating RBAC related database tables using Yii Database.
*/
final class RbacDbInit extends Command
final class SchemaManager implements SchemaManagerInterface
{
protected static $defaultName = 'rbac/db/init';

/**
* @var string A name of the table for storing RBAC items (roles and permissions).
* @psalm-var non-empty-string
Expand Down Expand Up @@ -67,43 +60,14 @@ public function __construct(
}

$this->itemsChildrenTable = $itemsChildrenTable ?? $this->itemsTable . '_child';

parent::__construct();
}

protected function configure(): void
{
$this
->setDescription('Create RBAC schemas')
->setHelp('This command creates schemas for RBAC using Yii Database')
->addOption(name: 'force', shortcut: 'f', description: 'Force recreation of schemas if they exist');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
/** @var bool $force */
$force = $input->getOption('force');
if ($force === true) {
$this->dropTable($this->itemsChildrenTable, $output);
$this->dropTable($this->assignmentsTable, $output);
$this->dropTable($this->itemsTable, $output);
}

$this->createTable($this->itemsTable, $output);
$this->createTable($this->itemsChildrenTable, $output);
$this->createTable($this->assignmentsTable, $output);

$output->writeln('<fg=green>DONE</>');

return Command::SUCCESS;
}

/**
* Creates table for storing RBAC items (roles and permissions).
*
* @see $itemsTable
*/
private function createItemsTable(): void
public function createItemsTable(): void
{
$this
->database
Expand Down Expand Up @@ -132,7 +96,7 @@ private function createItemsTable(): void
*
* @see $itemsChildrenTable
*/
private function createItemsChildrenTable(): void
public function createItemsChildrenTable(): void
{
$this
->database
Expand All @@ -155,7 +119,7 @@ private function createItemsChildrenTable(): void
*
* @see $assignmentsTable
*/
private function createAssignmentsTable(): void
public function createAssignmentsTable(): void
{
$this
->database
Expand All @@ -173,59 +137,46 @@ private function createAssignmentsTable(): void
->execute();
}

/**
* Basic method for creating RBAC related table. When a table already exists, creation is skipped. Operations are
* accompanied by explanations printed to console.
*
* @param string $tableName A name of created table.
* @psalm-param non-empty-string $tableName
*
* @param OutputInterface $output Output for writing messages.
*/
private function createTable(string $tableName, OutputInterface $output): void
public function tableExists(string $tableName): bool
{
$output->writeln("<fg=blue>Checking existence of `$tableName` table...</>");
return $this->database->getSchema()->getTableSchema($tableName) !== null;
}

if ($this->database->getSchema()->getTableSchema($tableName) !== null) {
$output->writeln("<bg=yellow>`$tableName` table already exists. Skipped creating.</>");
public function dropTable(string $tableName): void
{
$this->database->createCommand()->dropTable($tableName)->execute();
}

return;
public function createAll(bool $force = true): void

Check warning on line 150 in src/SchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/SchemaManager.php#L150

Added line #L150 was not covered by tests
{
if ($force === true) {
$this->dropAll();

Check warning on line 153 in src/SchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/SchemaManager.php#L152-L153

Added lines #L152 - L153 were not covered by tests
}

$output->writeln("<fg=blue>`$tableName` table doesn't exist. Creating...</>");

match ($tableName) {
$this->itemsTable => $this->createItemsTable(),
$this->assignmentsTable => $this->createAssignmentsTable(),
$this->itemsChildrenTable => $this->createItemsChildrenTable(),
};

$output->writeln("<bg=green>`$tableName` table has been successfully created.</>");
$this->createItemsTable();
$this->createItemsChildrenTable();
$this->createAssignmentsTable();

Check warning on line 158 in src/SchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/SchemaManager.php#L156-L158

Added lines #L156 - L158 were not covered by tests
}

/**
* Basic method for dropping RBAC related table. When a table doesn't exist, dropping is skipped. Operations are
* accompanied by explanations printed to console.
*
* @param string $tableName A name of created table.
* @psalm-param non-empty-string $tableName
*
* @param OutputInterface $output Output for writing messages.
*/
private function dropTable(string $tableName, OutputInterface $output): void
public function dropAll(): void

Check warning on line 161 in src/SchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/SchemaManager.php#L161

Added line #L161 was not covered by tests
{
$output->writeln("<fg=blue>Checking existence of `$tableName` table...</>");

if ($this->database->getSchema()->getTableSchema($tableName) === null) {
$output->writeln("<bg=yellow>`$tableName` table doesn't exist. Skipped dropping.</>");

return;
}
$this->dropTable($this->itemsChildrenTable);
$this->dropTable($this->assignmentsTable);
$this->dropTable($this->itemsTable);

Check warning on line 165 in src/SchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/SchemaManager.php#L163-L165

Added lines #L163 - L165 were not covered by tests
}

$output->writeln("<fg=blue>`$tableName` table exists. Dropping...</>");
public function getItemsTable(): string
{
return $this->itemsTable;
}

$this->database->createCommand()->dropTable($tableName)->execute();
public function getAssignmentsTable(): string
{
return $this->assignmentsTable;
}

$output->writeln("<bg=green>`$tableName` table has been successfully dropped.</>");
public function getItemsChildrenTable(): string
{
return $this->itemsChildrenTable;
}
}
4 changes: 2 additions & 2 deletions tests/Base/Command/RbacDbInitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\NullOutput;
use Yiisoft\Db\Constraint\IndexConstraint;
use Yiisoft\Rbac\Db\Command\RbacDbInit;
use Yiisoft\Rbac\Db\SchemaManager;
use Yiisoft\Rbac\Db\Tests\Base\TestCase;

abstract class RbacDbInitTest extends TestCase
Expand Down Expand Up @@ -54,7 +54,7 @@ public function testInitWithEmptyTableNames(array $tableNameArguments, $expected
$arguments = array_merge($tableNameArguments, $arguments);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("$expectedWrongTableName table name can't be empty.");
new RbacDbInit(...$arguments);
new SchemaManager(...$arguments);
}

public function dataExecute(): array
Expand Down
6 changes: 4 additions & 2 deletions tests/Base/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Rbac\Db\Command\RbacDbInit;
use Yiisoft\Rbac\Command\RbacDbInit;
use Yiisoft\Rbac\Db\SchemaManager;

abstract class TestCase extends \PHPUnit\Framework\TestCase
{
Expand Down Expand Up @@ -54,12 +55,13 @@ protected function createDatabaseTables(): void
protected function createApplication(string|null $itemsChildrenTable = self::ITEMS_CHILDREN_TABLE): Application
{
$app = new Application();
$command = new RbacDbInit(
$schemaManager = new SchemaManager(
itemsTable: self::ITEMS_TABLE,
assignmentsTable: self::ASSIGNMENTS_TABLE,
database: $this->getDatabase(),
itemsChildrenTable: $itemsChildrenTable,
);
$command = new RbacDbInit($schemaManager);
$app->add($command);

return $app;
Expand Down

0 comments on commit 432476c

Please sign in to comment.