diff --git a/composer.lock b/composer.lock index 2808eb0d..5af1bb2c 100644 --- a/composer.lock +++ b/composer.lock @@ -943,16 +943,16 @@ }, { "name": "lion/database", - "version": "v9.1.2", + "version": "v9.2.0", "source": { "type": "git", "url": "https://github.com/lion-packages/database.git", - "reference": "97c6c0c1c11ab85b310395bfa6e418830f01eb0c" + "reference": "a651b0bf714ebbe39e1b6bfe8a6ca6b0c3f50f81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lion-packages/database/zipball/97c6c0c1c11ab85b310395bfa6e418830f01eb0c", - "reference": "97c6c0c1c11ab85b310395bfa6e418830f01eb0c", + "url": "https://api.github.com/repos/lion-packages/database/zipball/a651b0bf714ebbe39e1b6bfe8a6ca6b0c3f50f81", + "reference": "a651b0bf714ebbe39e1b6bfe8a6ca6b0c3f50f81", "shasum": "" }, "require": { @@ -976,9 +976,9 @@ "description": "package in charge of the generation and execution of processes with databases", "support": { "issues": "https://github.com/lion-packages/database/issues", - "source": "https://github.com/lion-packages/database/tree/v9.1.2" + "source": "https://github.com/lion-packages/database/tree/v9.2.0" }, - "time": "2024-02-19T15:50:21+00:00" + "time": "2024-03-02T20:36:58+00:00" }, { "name": "lion/dependency-injection", @@ -4799,16 +4799,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.11", + "version": "10.1.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "78c3b7625965c2513ee96569a4dbb62601784145" + "reference": "842f72662d6b9edda84c4b6f13885fd9cd53dc63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/78c3b7625965c2513ee96569a4dbb62601784145", - "reference": "78c3b7625965c2513ee96569a4dbb62601784145", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/842f72662d6b9edda84c4b6f13885fd9cd53dc63", + "reference": "842f72662d6b9edda84c4b6f13885fd9cd53dc63", "shasum": "" }, "require": { @@ -4865,7 +4865,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.11" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.12" }, "funding": [ { @@ -4873,7 +4873,7 @@ "type": "github" } ], - "time": "2023-12-21T15:38:30+00:00" + "time": "2024-03-02T07:22:05+00:00" }, { "name": "phpunit/php-file-iterator", @@ -5221,16 +5221,16 @@ }, { "name": "sebastian/cli-parser", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae" + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae", - "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", "shasum": "" }, "require": { @@ -5265,7 +5265,8 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.0" + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, "funding": [ { @@ -5273,7 +5274,7 @@ "type": "github" } ], - "time": "2023-02-03T06:58:15+00:00" + "time": "2024-03-02T07:12:49+00:00" }, { "name": "sebastian/code-unit", @@ -5523,16 +5524,16 @@ }, { "name": "sebastian/diff", - "version": "5.1.0", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f" + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/fbf413a49e54f6b9b17e12d900ac7f6101591b7f", - "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { @@ -5540,7 +5541,7 @@ }, "require-dev": { "phpunit/phpunit": "^10.0", - "symfony/process": "^4.2 || ^5" + "symfony/process": "^6.4" }, "type": "library", "extra": { @@ -5578,7 +5579,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.0" + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, "funding": [ { @@ -5586,7 +5587,7 @@ "type": "github" } ], - "time": "2023-12-22T10:55:06+00:00" + "time": "2024-03-02T07:15:17+00:00" }, { "name": "sebastian/environment", @@ -5654,16 +5655,16 @@ }, { "name": "sebastian/exporter", - "version": "5.1.1", + "version": "5.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc" + "reference": "955288482d97c19a372d3f31006ab3f37da47adf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/64f51654862e0f5e318db7e9dcc2292c63cdbddc", - "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf", "shasum": "" }, "require": { @@ -5720,7 +5721,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.1" + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" }, "funding": [ { @@ -5728,20 +5729,20 @@ "type": "github" } ], - "time": "2023-09-24T13:22:09+00:00" + "time": "2024-03-02T07:17:12+00:00" }, { "name": "sebastian/global-state", - "version": "6.0.1", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4" + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4", - "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { @@ -5775,14 +5776,14 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1" + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { @@ -5790,7 +5791,7 @@ "type": "github" } ], - "time": "2023-07-19T07:19:23+00:00" + "time": "2024-03-02T07:19:19+00:00" }, { "name": "sebastian/lines-of-code", diff --git a/src/LionBundle/Commands/Lion/DB/DBSeedCommand.php b/src/LionBundle/Commands/Lion/DB/DBSeedCommand.php index 5baf52a7..475a6d59 100644 --- a/src/LionBundle/Commands/Lion/DB/DBSeedCommand.php +++ b/src/LionBundle/Commands/Lion/DB/DBSeedCommand.php @@ -47,8 +47,17 @@ protected function configure(): void protected function execute(InputInterface $input, OutputInterface $output): int { + if (isError($this->store->exist('./database/Seed/'))) { + $output->writeln($this->errorOutput("\t>> SEED: there are no defined seeds")); + + return Command::FAILURE; + } + $end = (int) $input->getOption('run'); + /** @var array $files */ + $files = []; + foreach ($this->container->getFiles($this->container->normalizePath('./database/Seed/')) as $seed) { if (isSuccess($this->store->validate([$seed], ['php']))) { $class = $this->container->getNamespace( @@ -60,22 +69,53 @@ protected function execute(InputInterface $input, OutputInterface $output): int /** @var SeedInterface $seedInterface */ $seedInterface = new $class(); - for ($i = 0; $i < $end; $i++) { - $response = $seedInterface->run(); + $files[] = $seedInterface; + } + } + + foreach ($this->orderList($files) as $seedInterface) { + $output->writeln($this->warningOutput("\t>> SEED: " . $seedInterface::class)); - $output->writeln($this->warningOutput("\t>> SEED: " . $seedInterface::class)); + for ($i = 0; $i < $end; $i++) { + $response = $seedInterface->run(); - if (isError($response)) { - $output->writeln($this->errorOutput("\t>> SEED: {$response->message}")); - } else { - $output->writeln($this->successOutput("\t>> SEED: {$response->message}")); - } + if (isError($response)) { + $output->writeln($this->errorOutput("\t>> SEED: {$response->message}")); + } else { + $output->writeln($this->successOutput("\t>> SEED: {$response->message}")); } } } - $output->writeln($this->purpleOutput("\n\t>> SEED: seeds executed")); + $output->writeln($this->infoOutput("\n\t>> SEED: seeds executed")); return Command::SUCCESS; } + + /** + * Sorts the list of elements by the value defined in the INDEX constant + * + * @param array $files [Class List] + * + * @return array + */ + private function orderList(array $files): array + { + uasort($files, function($classA, $classB) { + $namespaceA = $classA::class; + $namespaceB = $classB::class; + + if (!defined($namespaceA . "::INDEX")) { + return -1; + } + + if (!defined($namespaceB . "::INDEX")) { + return -1; + } + + return $classA::INDEX <=> $classB::INDEX; + }); + + return $files; + } } diff --git a/src/LionBundle/Commands/Lion/DB/ShowDatabasesCommand.php b/src/LionBundle/Commands/Lion/DB/ShowDatabasesCommand.php index f9d85527..2acedc8a 100644 --- a/src/LionBundle/Commands/Lion/DB/ShowDatabasesCommand.php +++ b/src/LionBundle/Commands/Lion/DB/ShowDatabasesCommand.php @@ -61,7 +61,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int ->setHeaders(['DATABASE CONNECTION', 'DATABASE HOST', 'DATABASE PORT', 'DATABASE NAME', 'DATABASE USER']) ->setFooterTitle( $size > 1 - ? " Showing [" . $size . "] connections " + ? " Showing [{$size}] connections " : ($size === 1 ? ' showing a single connection ' : ' No connections available ' diff --git a/src/LionBundle/Commands/Lion/Migrations/EmptyMigrationsCommand.php b/src/LionBundle/Commands/Lion/Migrations/EmptyMigrationsCommand.php new file mode 100644 index 00000000..1193461b --- /dev/null +++ b/src/LionBundle/Commands/Lion/Migrations/EmptyMigrationsCommand.php @@ -0,0 +1,64 @@ +setName('migrate:empty') + ->setDescription('Empties all tables built with the migrations'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $connections = (object) Schema::getConnections(); + + foreach ($connections->connections as $connectionName => $connection) { + $tables = DB::connection($connectionName)->show()->tables()->getAll(); + + if (!is_array($tables) && isSuccess($tables)) { + $output->writeln($this->warningOutput("\t>> MIGRATION: no tables available")); + + continue; + } + + if (!is_array($tables) && isError($tables)) { + $output->writeln($this->errorOutput("\t>> MIGRATION: {$tables->message}")); + + continue; + } + + foreach ($tables as $table) { + $response = Schema::connection($connectionName) + ->truncateTable($table->{"Tables_in_{$connection['dbname']}"}) + ->execute(); + + $output->writeln( + $this->warningOutput( + "\t>> MIGRATION: {$connection['dbname']}." . $table->{"Tables_in_{$connection['dbname']}"} + ) + ); + + if (isError($response)) { + $output->writeln($this->errorOutput("\t>> MIGRATION: {$response->message}")); + } else { + $output->writeln($this->successOutput("\t>> MIGRATION: {$response->message}")); + } + } + } + + $output->writeln($this->infoOutput("\n\t>> All tables have been truncated")); + + return Command::SUCCESS; + } +} diff --git a/src/LionBundle/Commands/Lion/Migrations/FreshMigrationsCommand.php b/src/LionBundle/Commands/Lion/Migrations/FreshMigrationsCommand.php index f749106e..955c02e0 100644 --- a/src/LionBundle/Commands/Lion/Migrations/FreshMigrationsCommand.php +++ b/src/LionBundle/Commands/Lion/Migrations/FreshMigrationsCommand.php @@ -46,14 +46,19 @@ protected function configure(): void protected function execute(InputInterface $input, OutputInterface $output): int { - $this->dropTables($output); + if (isError($this->store->exist('./database/Migrations/'))) { + $output->writeln($this->errorOutput("\t>> MIGRATION: there are no defined migration routes")); + + return Command::FAILURE; + } + /** @var array $files */ $files = []; foreach ($this->container->getFiles('./database/Migrations/') as $file) { if (isSuccess($this->store->validate([$file], ['php']))) { $namespace = $this->container->getNamespace( - strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? str_replace('\\', '/', $file) : $file, + (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? str_replace('\\', '/', $file) : $file), 'Database\\Migrations\\', 'Migrations/' ); @@ -62,6 +67,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int } } + if (empty($files)) { + $output->writeln($this->warningOutput("\t>> MIGRATION: no migrations available")); + + return Command::INVALID; + } + + $this->dropTables($output); + foreach ($this->orderList($files) as $namespace => $classObject) { if ($classObject instanceof MigrationUpInterface) { /** @var MigrationUpInterface $classObject */ @@ -104,6 +117,13 @@ private function dropTables(OutputInterface $output): void } } + /** + * Sorts the list of elements by the value defined in the INDEX constant + * + * @param array $files [Class List] + * + * @return array + */ private function orderList(array $files): array { uasort($files, function($classA, $classB) { diff --git a/src/LionBundle/Commands/Lion/Migrations/NewMigrationCommand.php b/src/LionBundle/Commands/Lion/New/NewMigrationCommand.php similarity index 97% rename from src/LionBundle/Commands/Lion/Migrations/NewMigrationCommand.php rename to src/LionBundle/Commands/Lion/New/NewMigrationCommand.php index 4edb9ef8..8077c353 100644 --- a/src/LionBundle/Commands/Lion/Migrations/NewMigrationCommand.php +++ b/src/LionBundle/Commands/Lion/New/NewMigrationCommand.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Lion\Bundle\Commands\Lion\Migrations; +namespace Lion\Bundle\Commands\Lion\New; use Lion\Bundle\Helpers\Commands\ClassFactory; use Lion\Bundle\Helpers\Commands\Migrations\MigrationFactory; @@ -45,7 +45,7 @@ public function setMigration(MigrationFactory $migrationFactory): NewMigrationCo protected function configure(): void { $this - ->setName('migrate:new') + ->setName('new:migration') ->setDescription('Command to generate a new migration') ->addArgument('migration', InputArgument::REQUIRED, 'Migration name'); } diff --git a/src/LionBundle/Commands/Lion/New/SeedCommand.php b/src/LionBundle/Commands/Lion/New/SeedCommand.php index 38804554..40a249fa 100644 --- a/src/LionBundle/Commands/Lion/New/SeedCommand.php +++ b/src/LionBundle/Commands/Lion/New/SeedCommand.php @@ -72,6 +72,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int ->add($this->str->of("use Lion\Bundle\Interface\SeedInterface;")->ln()->get()) ->add($this->str->of("use Lion\Database\Drivers\MySQL as DB;")->ln()->ln()->get()) ->add($this->str->of("class ")->concat($class)->concat(' implements SeedInterface')->ln()->concat("{")->ln()->get()) + ->add($this->str->lt()->concat('const INDEX = null;')->ln()->ln()->get()) ->add("\t/**\n\t * {@inheritdoc}\n\t **/\n") ->add("\tpublic function run(): object\n\t{\n\t\treturn success('run seed');\n\t}\n}\n") ->close(); diff --git a/tests/Commands/Lion/Migrations/EmptyMigrationsCommandTest.php b/tests/Commands/Lion/Migrations/EmptyMigrationsCommandTest.php new file mode 100644 index 00000000..dccf706c --- /dev/null +++ b/tests/Commands/Lion/Migrations/EmptyMigrationsCommandTest.php @@ -0,0 +1,32 @@ +getApplication(); + $application->add((new Container())->injectDependencies(new EmptyMigrationsCommand())); + $this->commandTester = new CommandTester($application->find('migrate:empty')); + } + + public function testExecute(): void + { + $this->assertSame(Command::SUCCESS, $this->commandTester->execute([])); + $this->assertStringContainsString(self::OUTPUT_MESSAGE, $this->commandTester->getDisplay()); + } +} diff --git a/tests/Commands/Lion/Migrations/FreshMigrationsCommandTest.php b/tests/Commands/Lion/Migrations/FreshMigrationsCommandTest.php index 482db2e1..c20323fc 100644 --- a/tests/Commands/Lion/Migrations/FreshMigrationsCommandTest.php +++ b/tests/Commands/Lion/Migrations/FreshMigrationsCommandTest.php @@ -5,6 +5,7 @@ namespace Tests\Commands\Lion\Migrations; use Lion\Bundle\Commands\Lion\Migrations\FreshMigrationsCommand; +use Lion\Bundle\Commands\Lion\New\NewMigrationCommand; use Lion\Command\Command; use Lion\Command\Kernel; use Lion\DependencyInjection\Container; @@ -16,11 +17,14 @@ class FreshMigrationsCommandTest extends Test const OUTPUT_MESSAGE = 'Migrations executed successfully'; private CommandTester $commandTester; + private CommandTester $commandTesterFresh; protected function setUp(): void { $application = (new Kernel())->getApplication(); + $application->add((new Container())->injectDependencies(new NewMigrationCommand())); $application->add((new Container())->injectDependencies(new FreshMigrationsCommand())); + $this->commandTesterFresh = new CommandTester($application->find('new:migration')); $this->commandTester = new CommandTester($application->find('migrate:fresh')); $this->createDirectory('./database/Migrations/'); @@ -28,11 +32,12 @@ protected function setUp(): void protected function tearDown(): void { - $this->rmdirRecursively('./database/Migrations/'); + $this->rmdirRecursively('./database/'); } public function testExecute(): void { + $this->assertSame(Command::SUCCESS, $this->commandTesterFresh->execute(['migration' => 'test'])); $this->assertSame(Command::SUCCESS, $this->commandTester->execute([])); $this->assertStringContainsString(self::OUTPUT_MESSAGE, $this->commandTester->getDisplay()); } diff --git a/tests/Commands/Lion/Migrations/NewMigrationCommandTest.php b/tests/Commands/Lion/New/NewMigrationCommandTest.php similarity index 96% rename from tests/Commands/Lion/Migrations/NewMigrationCommandTest.php rename to tests/Commands/Lion/New/NewMigrationCommandTest.php index 0eee6268..e0d13bc8 100644 --- a/tests/Commands/Lion/Migrations/NewMigrationCommandTest.php +++ b/tests/Commands/Lion/New/NewMigrationCommandTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Tests\Commands\Lion\Migrations; +namespace Tests\Commands\Lion\New; -use Lion\Bundle\Commands\Lion\Migrations\NewMigrationCommand; +use Lion\Bundle\Commands\Lion\New\NewMigrationCommand; use Lion\Bundle\Interface\MigrationUpInterface; use Lion\Command\Command; use Lion\Command\Kernel; @@ -31,7 +31,7 @@ protected function setUp(): void { $application = (new Kernel())->getApplication(); $application->add((new Container())->injectDependencies(new NewMigrationCommand())); - $this->commandTester = new CommandTester($application->find('migrate:new')); + $this->commandTester = new CommandTester($application->find('new:migration')); } protected function tearDown(): void