Skip to content

Commit f33d181

Browse files
authored
refactor: migrate migrate and migrate:* commands as modern commands (#10265)
1 parent 84930c1 commit f33d181

11 files changed

Lines changed: 355 additions & 300 deletions

File tree

system/Commands/Database/Migrate.php

Lines changed: 47 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -13,81 +13,75 @@
1313

1414
namespace CodeIgniter\Commands\Database;
1515

16-
use CodeIgniter\CLI\BaseCommand;
16+
use CodeIgniter\CLI\AbstractCommand;
17+
use CodeIgniter\CLI\Attributes\Command;
1718
use CodeIgniter\CLI\CLI;
19+
use CodeIgniter\CLI\Input\Option;
1820
use CodeIgniter\CLI\SignalTrait;
21+
use CodeIgniter\Database\MigrationRunner;
1922
use Throwable;
2023

2124
/**
22-
* Runs all new migrations.
25+
* Locates and runs all new migrations against the database.
2326
*/
24-
class Migrate extends BaseCommand
27+
#[Command(
28+
name: 'migrate',
29+
description: 'Locates and runs all new migrations against the database.',
30+
group: 'Database',
31+
)]
32+
class Migrate extends AbstractCommand
2533
{
2634
use SignalTrait;
2735

28-
/**
29-
* The group the command is lumped under
30-
* when listing commands.
31-
*
32-
* @var string
33-
*/
34-
protected $group = 'Database';
35-
36-
/**
37-
* The Command's name
38-
*
39-
* @var string
40-
*/
41-
protected $name = 'migrate';
42-
43-
/**
44-
* the Command's short description
45-
*
46-
* @var string
47-
*/
48-
protected $description = 'Locates and runs all new migrations against the database.';
49-
50-
/**
51-
* the Command's usage
52-
*
53-
* @var string
54-
*/
55-
protected $usage = 'migrate [options]';
56-
57-
/**
58-
* the Command's Options
59-
*
60-
* @var array<string, string>
61-
*/
62-
protected $options = [
63-
'-n' => 'Set migration namespace',
64-
'-g' => 'Set database group',
65-
'--all' => 'Set for all namespaces, will ignore (-n) option',
66-
];
67-
68-
/**
69-
* Ensures that all migrations have been run.
70-
*/
71-
public function run(array $params)
36+
protected function configure(): void
7237
{
38+
$this
39+
->addOption(new Option(
40+
name: 'namespace',
41+
shortcut: 'n',
42+
description: 'Set migration namespace.',
43+
requiresValue: true,
44+
default: '',
45+
))
46+
->addOption(new Option(
47+
name: 'group',
48+
shortcut: 'g',
49+
description: 'Set database group.',
50+
requiresValue: true,
51+
default: '',
52+
))
53+
->addOption(new Option(
54+
name: 'all',
55+
description: 'Set for all namespaces. This will ignore the `--namespace` option.',
56+
));
57+
}
58+
59+
protected function execute(array $arguments, array $options): int
60+
{
61+
/** @var MigrationRunner $runner */
7362
$runner = service('migrations');
7463
$runner->clearCliMessages();
7564

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

78-
$namespace = $params['n'] ?? CLI::getOption('n');
79-
$group = $params['g'] ?? CLI::getOption('g');
67+
$namespace = $options['namespace'];
68+
assert(is_string($namespace));
69+
70+
$group = $options['group'];
71+
assert(is_string($group));
72+
73+
$group = $group !== '' ? $group : null;
8074

8175
try {
82-
if (array_key_exists('all', $params) || CLI::getOption('all')) {
76+
if ($options['all'] === true) {
8377
$runner->setNamespace(null);
84-
} elseif ($namespace) {
78+
} elseif ($namespace !== '') {
8579
$runner->setNamespace($namespace);
8680
}
8781

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

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

10296
return EXIT_SUCCESS;
103-
// @codeCoverageIgnoreStart
10497
} catch (Throwable $e) {
105-
$this->showError($e);
98+
$this->renderThrowable($e);
10699

107100
return EXIT_ERROR;
108-
// @codeCoverageIgnoreEnd
109101
}
110102
}
111103
}

system/Commands/Database/MigrateRefresh.php

Lines changed: 81 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -13,81 +13,102 @@
1313

1414
namespace CodeIgniter\Commands\Database;
1515

16-
use CodeIgniter\CLI\BaseCommand;
16+
use CodeIgniter\CLI\AbstractCommand;
17+
use CodeIgniter\CLI\Attributes\Command;
1718
use CodeIgniter\CLI\CLI;
19+
use CodeIgniter\CLI\Input\Option;
1820
use CodeIgniter\CLI\SignalTrait;
1921

2022
/**
21-
* Does a rollback followed by a latest to refresh the current state
22-
* of the database.
23+
* Does a rollback followed by a latest to refresh the current state of the database.
2324
*/
24-
class MigrateRefresh extends BaseCommand
25+
#[Command(
26+
name: 'migrate:refresh',
27+
description: 'Does a rollback followed by a latest to refresh the current state of the database.',
28+
group: 'Database',
29+
)]
30+
class MigrateRefresh extends AbstractCommand
2531
{
2632
use SignalTrait;
2733

28-
/**
29-
* The group the command is lumped under
30-
* when listing commands.
31-
*
32-
* @var string
33-
*/
34-
protected $group = 'Database';
35-
36-
/**
37-
* The Command's name
38-
*
39-
* @var string
40-
*/
41-
protected $name = 'migrate:refresh';
42-
43-
/**
44-
* the Command's short description
45-
*
46-
* @var string
47-
*/
48-
protected $description = 'Does a rollback followed by a latest to refresh the current state of the database.';
49-
50-
/**
51-
* the Command's usage
52-
*
53-
* @var string
54-
*/
55-
protected $usage = 'migrate:refresh [options]';
56-
57-
/**
58-
* the Command's Options
59-
*
60-
* @var array<string, string>
61-
*/
62-
protected $options = [
63-
'-n' => 'Set migration namespace',
64-
'-g' => 'Set database group',
65-
'--all' => 'Set latest for all namespace, will ignore (-n) option',
66-
'-f' => 'Force command - this option allows you to bypass the confirmation question when running this command in a production environment',
67-
];
68-
69-
/**
70-
* Does a rollback followed by a latest to refresh the current state
71-
* of the database.
72-
*/
73-
public function run(array $params)
34+
protected function configure(): void
7435
{
75-
$params['b'] = 0;
36+
$this
37+
->addOption(new Option(
38+
name: 'namespace',
39+
shortcut: 'n',
40+
description: 'Set migration namespace.',
41+
requiresValue: true,
42+
default: '',
43+
))
44+
->addOption(new Option(
45+
name: 'group',
46+
shortcut: 'g',
47+
description: 'Set database group.',
48+
requiresValue: true,
49+
default: '',
50+
))
51+
->addOption(new Option(
52+
name: 'all',
53+
description: 'Set latest for all namespaces. This will ignore the `--namespace` option.',
54+
))
55+
->addOption(new Option(
56+
name: 'force',
57+
shortcut: 'f',
58+
description: 'Bypass the confirmation question when running this command in a production environment.',
59+
));
60+
}
61+
62+
protected function interact(array &$arguments, array &$options): void
63+
{
64+
if (! service('environment')->isProduction()) {
65+
return;
66+
}
67+
68+
if ($this->hasUnboundOption('force', $options)) {
69+
return;
70+
}
7671

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

81-
if (! $force && CLI::prompt(lang('Migrations.refreshConfirm'), ['y', 'n']) === 'n') {
82-
return EXIT_ERROR;
83-
}
77+
protected function execute(array $arguments, array $options): int
78+
{
79+
if (service('environment')->isProduction() && $options['force'] === false) {
80+
return EXIT_ERROR;
81+
}
82+
83+
$namespace = $options['namespace'];
84+
assert(is_string($namespace));
85+
86+
$group = $options['group'];
87+
assert(is_string($group));
88+
89+
// A target batch of 0 rolls everything back before re-applying.
90+
$rollbackOptions = ['batch' => '0'];
91+
$migrateOptions = [];
92+
93+
if ($options['force'] === true) {
94+
$rollbackOptions['force'] = null;
95+
}
96+
97+
if ($namespace !== '') {
98+
$migrateOptions['namespace'] = $namespace;
99+
}
100+
101+
if ($group !== '') {
102+
$migrateOptions['group'] = $group;
103+
}
84104

85-
$params['f'] = null;
86-
// @codeCoverageIgnoreEnd
105+
if ($options['all'] === true) {
106+
$migrateOptions['all'] = null;
87107
}
88108

89109
return $this->withSignalsBlocked(
90-
fn (): int => $this->call('migrate:rollback', $params) | $this->call('migrate', $params),
110+
fn (): int => $this->call('migrate:rollback', options: $rollbackOptions)
111+
| $this->call('migrate', options: $migrateOptions),
91112
);
92113
}
93114
}

0 commit comments

Comments
 (0)