Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 47 additions & 55 deletions system/Commands/Database/Migrate.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,81 +13,75 @@

namespace CodeIgniter\Commands\Database;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\AbstractCommand;
use CodeIgniter\CLI\Attributes\Command;
use CodeIgniter\CLI\CLI;
use CodeIgniter\CLI\Input\Option;
use CodeIgniter\CLI\SignalTrait;
use CodeIgniter\Database\MigrationRunner;
use Throwable;

/**
* Runs all new migrations.
* Locates and runs all new migrations against the database.
*/
class Migrate extends BaseCommand
#[Command(
name: 'migrate',
description: 'Locates and runs all new migrations against the database.',
group: 'Database',
)]
class Migrate extends AbstractCommand
{
use SignalTrait;

/**
* The group the command is lumped under
* when listing commands.
*
* @var string
*/
protected $group = 'Database';

/**
* The Command's name
*
* @var string
*/
protected $name = 'migrate';

/**
* the Command's short description
*
* @var string
*/
protected $description = 'Locates and runs all new migrations against the database.';

/**
* the Command's usage
*
* @var string
*/
protected $usage = 'migrate [options]';

/**
* the Command's Options
*
* @var array<string, string>
*/
protected $options = [
'-n' => 'Set migration namespace',
'-g' => 'Set database group',
'--all' => 'Set for all namespaces, will ignore (-n) option',
];

/**
* Ensures that all migrations have been run.
*/
public function run(array $params)
protected function configure(): void
{
$this
->addOption(new Option(
name: 'namespace',
shortcut: 'n',
description: 'Set migration namespace.',
requiresValue: true,
default: '',
))
->addOption(new Option(
name: 'group',
shortcut: 'g',
description: 'Set database group.',
requiresValue: true,
default: '',
))
->addOption(new Option(
name: 'all',
description: 'Set for all namespaces. This will ignore the `--namespace` option.',
));
}

protected function execute(array $arguments, array $options): int
{
/** @var MigrationRunner $runner */
$runner = service('migrations');
$runner->clearCliMessages();

CLI::write(lang('Migrations.latest'), 'yellow');

$namespace = $params['n'] ?? CLI::getOption('n');
$group = $params['g'] ?? CLI::getOption('g');
$namespace = $options['namespace'];
assert(is_string($namespace));

$group = $options['group'];
assert(is_string($group));

$group = $group !== '' ? $group : null;

try {
if (array_key_exists('all', $params) || CLI::getOption('all')) {
if ($options['all'] === true) {
$runner->setNamespace(null);
} elseif ($namespace) {
} elseif ($namespace !== '') {
$runner->setNamespace($namespace);
}

$this->withSignalsBlocked(static function () use ($runner, $group): void {
if (! $runner->latest($group)) {
CLI::error(lang('Migrations.generalFault'), 'light_gray', 'red'); // @codeCoverageIgnore
CLI::error(lang('Migrations.generalFault'), 'light_gray', 'red');
}
});

Expand All @@ -100,12 +94,10 @@ public function run(array $params)
CLI::write(lang('Migrations.migrated'), 'green');

return EXIT_SUCCESS;
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
$this->showError($e);
$this->renderThrowable($e);

return EXIT_ERROR;
// @codeCoverageIgnoreEnd
}
}
}
141 changes: 81 additions & 60 deletions system/Commands/Database/MigrateRefresh.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,81 +13,102 @@

namespace CodeIgniter\Commands\Database;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\AbstractCommand;
use CodeIgniter\CLI\Attributes\Command;
use CodeIgniter\CLI\CLI;
use CodeIgniter\CLI\Input\Option;
use CodeIgniter\CLI\SignalTrait;

/**
* Does a rollback followed by a latest to refresh the current state
* of the database.
* Does a rollback followed by a latest to refresh the current state of the database.
*/
class MigrateRefresh extends BaseCommand
#[Command(
name: 'migrate:refresh',
description: 'Does a rollback followed by a latest to refresh the current state of the database.',
group: 'Database',
)]
class MigrateRefresh extends AbstractCommand
{
use SignalTrait;

/**
* The group the command is lumped under
* when listing commands.
*
* @var string
*/
protected $group = 'Database';

/**
* The Command's name
*
* @var string
*/
protected $name = 'migrate:refresh';

/**
* the Command's short description
*
* @var string
*/
protected $description = 'Does a rollback followed by a latest to refresh the current state of the database.';

/**
* the Command's usage
*
* @var string
*/
protected $usage = 'migrate:refresh [options]';

/**
* the Command's Options
*
* @var array<string, string>
*/
protected $options = [
'-n' => 'Set migration namespace',
'-g' => 'Set database group',
'--all' => 'Set latest for all namespace, will ignore (-n) option',
'-f' => 'Force command - this option allows you to bypass the confirmation question when running this command in a production environment',
];

/**
* Does a rollback followed by a latest to refresh the current state
* of the database.
*/
public function run(array $params)
protected function configure(): void
{
$params['b'] = 0;
$this
->addOption(new Option(
name: 'namespace',
shortcut: 'n',
description: 'Set migration namespace.',
requiresValue: true,
default: '',
))
->addOption(new Option(
name: 'group',
shortcut: 'g',
description: 'Set database group.',
requiresValue: true,
default: '',
))
->addOption(new Option(
name: 'all',
description: 'Set latest for all namespaces. This will ignore the `--namespace` option.',
))
->addOption(new Option(
name: 'force',
shortcut: 'f',
description: 'Bypass the confirmation question when running this command in a production environment.',
));
}

protected function interact(array &$arguments, array &$options): void
{
if (! service('environment')->isProduction()) {
return;
}

if ($this->hasUnboundOption('force', $options)) {
return;
}

if (service('environment')->isProduction()) {
// @codeCoverageIgnoreStart
$force = array_key_exists('f', $params) || CLI::getOption('f');
if (CLI::prompt(lang('Migrations.refreshConfirm'), ['y', 'n']) === 'y') {
$options['force'] = null; // simulate the presence of the --force option
}
}

if (! $force && CLI::prompt(lang('Migrations.refreshConfirm'), ['y', 'n']) === 'n') {
return EXIT_ERROR;
}
protected function execute(array $arguments, array $options): int
{
if (service('environment')->isProduction() && $options['force'] === false) {
return EXIT_ERROR;
}

$namespace = $options['namespace'];
assert(is_string($namespace));

$group = $options['group'];
assert(is_string($group));

// A target batch of 0 rolls everything back before re-applying.
$rollbackOptions = ['batch' => '0'];
$migrateOptions = [];

if ($options['force'] === true) {
$rollbackOptions['force'] = null;
}

if ($namespace !== '') {
$migrateOptions['namespace'] = $namespace;
}

if ($group !== '') {
$migrateOptions['group'] = $group;
}

$params['f'] = null;
// @codeCoverageIgnoreEnd
if ($options['all'] === true) {
$migrateOptions['all'] = null;
}

return $this->withSignalsBlocked(
fn (): int => $this->call('migrate:rollback', $params) | $this->call('migrate', $params),
fn (): int => $this->call('migrate:rollback', options: $rollbackOptions)
| $this->call('migrate', options: $migrateOptions),
);
}
}
Loading
Loading