Skip to content

Commit 3c36713

Browse files
committed
refactor Console::run()
1 parent 3e14cd1 commit 3c36713

File tree

2 files changed

+84
-86
lines changed

2 files changed

+84
-86
lines changed

system/CLI/Console.php

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,61 @@
1616
use CodeIgniter\CodeIgniter;
1717
use Config\App;
1818
use Config\Services;
19-
use Exception;
2019

2120
/**
22-
* Console
23-
*
2421
* @see \CodeIgniter\CLI\ConsoleTest
2522
*/
2623
class Console
2724
{
25+
private const DEFAULT_COMMAND = 'list';
26+
27+
/**
28+
* @var array<string, string|null>
29+
*/
30+
private array $options = [];
31+
2832
/**
2933
* Runs the current command discovered on the CLI.
3034
*
31-
* @return int|void Exit code
35+
* @param list<string> $tokens
3236
*
33-
* @throws Exception
37+
* @return int|null Exit code or null for legacy commands that don't return an exit code.
3438
*/
35-
public function run()
39+
public function run(array $tokens = [])
3640
{
37-
// Create CLIRequest
38-
$appConfig = config(App::class);
39-
Services::createRequest($appConfig, true);
40-
// Load Routes
41-
service('routes')->loadRoutes();
41+
if ($tokens === []) {
42+
$tokens = service('superglobals')->server('argv', []);
43+
}
44+
45+
$parser = new CommandLineParser($tokens);
46+
47+
$arguments = $parser->getArguments();
48+
$this->options = $parser->getOptions();
49+
50+
$this->showHeader($this->hasParameterOption(['no-header']));
51+
unset($this->options['no-header']);
4252

43-
$params = array_merge(CLI::getSegments(), CLI::getOptions());
44-
$params = $this->parseParamsForHelpOption($params);
45-
$command = array_shift($params) ?? 'list';
53+
if ($this->hasParameterOption(['help'])) {
54+
unset($this->options['help']);
4655

47-
return service('commands')->run($command, $params);
56+
if ($arguments === []) {
57+
$arguments = ['help', self::DEFAULT_COMMAND];
58+
} elseif ($arguments[0] !== 'help') {
59+
array_unshift($arguments, 'help');
60+
}
61+
}
62+
63+
$command = array_shift($arguments) ?? self::DEFAULT_COMMAND;
64+
65+
return service('commands')->run($command, array_merge($arguments, $this->options));
66+
}
67+
68+
public function initialize(): static
69+
{
70+
Services::createRequest(config(App::class), true);
71+
service('routes')->loadRoutes();
72+
73+
return $this;
4874
}
4975

5076
/**
@@ -67,24 +93,18 @@ public function showHeader(bool $suppress = false)
6793
}
6894

6995
/**
70-
* Introspects the `$params` passed for presence of the
71-
* `--help` option.
96+
* Checks whether any of the options are present in the command line.
7297
*
73-
* If present, it will be found as `['help' => null]`.
74-
* We'll remove that as an option from `$params` and
75-
* unshift it as argument instead.
76-
*
77-
* @param array<int|string, string|null> $params
98+
* @param list<string> $options
7899
*/
79-
private function parseParamsForHelpOption(array $params): array
100+
private function hasParameterOption(array $options): bool
80101
{
81-
if (array_key_exists('help', $params)) {
82-
unset($params['help']);
83-
84-
$params = $params === [] ? ['list'] : $params;
85-
array_unshift($params, 'help');
102+
foreach ($options as $option) {
103+
if (array_key_exists($option, $this->options)) {
104+
return true;
105+
}
86106
}
87107

88-
return $params;
108+
return false;
89109
}
90110
}

tests/system/CLI/ConsoleTest.php

Lines changed: 35 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -39,53 +39,46 @@ protected function setUp(): void
3939
Services::injectMock('superglobals', new Superglobals());
4040
CLI::init();
4141

42-
$env = new DotEnv(ROOTPATH);
43-
$env->load();
44-
45-
// Set environment values that would otherwise stop the framework from functioning during tests.
46-
if (service('superglobals')->server('app.baseURL') === null) {
47-
service('superglobals')->setServer('app.baseURL', 'http://example.com/');
48-
}
42+
(new DotEnv(ROOTPATH))->load();
4943

5044
$this->app = new MockCodeIgniter(new MockCLIConfig());
5145
$this->app->initialize();
5246
}
5347

5448
protected function tearDown(): void
5549
{
56-
CLI::reset();
57-
5850
parent::tearDown();
51+
52+
CLI::reset();
5953
}
6054

61-
public function testHeader(): void
55+
public function testHeaderShowsNormally(): void
6256
{
63-
$console = new Console();
64-
$console->showHeader();
65-
$this->assertGreaterThan(
66-
0,
67-
strpos(
68-
$this->getStreamFilterBuffer(),
69-
sprintf('CodeIgniter v%s Command Line Tool', CodeIgniter::CI_VERSION),
70-
),
57+
$this->initializeConsole();
58+
(new Console())->run();
59+
60+
$this->assertStringContainsString(
61+
sprintf('CodeIgniter v%s Command Line Tool', CodeIgniter::CI_VERSION),
62+
$this->getStreamFilterBuffer(),
7163
);
7264
}
7365

74-
public function testNoHeader(): void
66+
public function testHeaderDoesNotShowOnNoHeader(): void
7567
{
76-
$console = new Console();
77-
$console->showHeader(true);
78-
$this->assertSame('', $this->getStreamFilterBuffer());
68+
$this->initializeConsole('--no-header');
69+
(new Console())->run();
70+
71+
$this->assertStringNotContainsString(
72+
sprintf('CodeIgniter v%s Command Line Tool', CodeIgniter::CI_VERSION),
73+
$this->getStreamFilterBuffer(),
74+
);
7975
}
8076

8177
public function testRun(): void
8278
{
83-
$this->initCLI();
84-
85-
$console = new Console();
86-
$console->run();
79+
$this->initializeConsole();
80+
(new Console())->run();
8781

88-
// make sure the result looks like a command list
8982
$this->assertStringContainsString('Lists the available commands.', $this->getStreamFilterBuffer());
9083
$this->assertStringContainsString('Displays basic usage information.', $this->getStreamFilterBuffer());
9184
}
@@ -97,10 +90,8 @@ public function testRunEventsPreCommand(): void
9790
$result = 'fired';
9891
});
9992

100-
$this->initCLI();
101-
102-
$console = new Console();
103-
$console->run();
93+
$this->initializeConsole();
94+
(new Console())->run();
10495

10596
$this->assertEventTriggered('pre_command');
10697
$this->assertSame('fired', $result);
@@ -113,43 +104,34 @@ public function testRunEventsPostCommand(): void
113104
$result = 'fired';
114105
});
115106

116-
$this->initCLI();
117-
118-
$console = new Console();
119-
$console->run();
107+
$this->initializeConsole();
108+
(new Console())->run();
120109

121110
$this->assertEventTriggered('post_command');
122111
$this->assertSame('fired', $result);
123112
}
124113

125114
public function testBadCommand(): void
126115
{
127-
$this->initCLI('bogus');
128-
129-
$console = new Console();
130-
$console->run();
116+
$this->initializeConsole('bogus');
117+
(new Console())->run();
131118

132-
// make sure the result looks like a command list
133119
$this->assertStringContainsString('Command "bogus" not found', $this->getStreamFilterBuffer());
134120
}
135121

136122
public function testHelpCommandDetails(): void
137123
{
138-
$this->initCLI('help', 'make:migration');
139-
140-
$console = new Console();
141-
$console->run();
124+
$this->initializeConsole('help', 'make:migration');
125+
(new Console())->run();
142126

143-
// make sure the result looks like more detailed help
144127
$this->assertStringContainsString('Description:', $this->getStreamFilterBuffer());
145128
$this->assertStringContainsString('Usage:', $this->getStreamFilterBuffer());
146129
$this->assertStringContainsString('Options:', $this->getStreamFilterBuffer());
147130
}
148131

149132
public function testHelpCommandUsingHelpOption(): void
150133
{
151-
$this->initCLI('env', '--help');
152-
134+
$this->initializeConsole('env', '--help');
153135
(new Console())->run();
154136

155137
$this->assertStringContainsString('env [<environment>]', $this->getStreamFilterBuffer());
@@ -161,8 +143,7 @@ public function testHelpCommandUsingHelpOption(): void
161143

162144
public function testHelpOptionIsOnlyPassed(): void
163145
{
164-
$this->initCLI('--help');
165-
146+
$this->initializeConsole('--help');
166147
(new Console())->run();
167148

168149
// Since calling `php spark` is the same as calling `php spark list`,
@@ -172,21 +153,18 @@ public function testHelpOptionIsOnlyPassed(): void
172153

173154
public function testHelpArgumentAndHelpOptionCombined(): void
174155
{
175-
$this->initCLI('help', '--help');
176-
156+
$this->initializeConsole('help', '--help');
177157
(new Console())->run();
178158

179159
// Same as calling `php spark help` only
180160
$this->assertStringContainsString('Displays basic usage information.', $this->getStreamFilterBuffer());
181161
}
182162

183-
/**
184-
* @param string ...$command
185-
*/
186-
protected function initCLI(...$command): void
163+
private function initializeConsole(string ...$tokens): void
187164
{
188-
service('superglobals')->setServer('argv', ['spark', ...$command]);
189-
service('superglobals')->setServer('argc', count(service('superglobals')->server('argv')));
165+
service('superglobals')
166+
->setServer('argv', ['spark', ...$tokens])
167+
->setServer('argc', count($tokens) + 1);
190168

191169
CLI::init();
192170
}

0 commit comments

Comments
 (0)