Skip to content

Commit bd7ad1f

Browse files
authored
Merge pull request #892 from hydephp/cherry-pick-base-command-changes-from-publications-feature
Cherry pick base command changes from publications feature
2 parents 3684ce1 + 1d3476b commit bd7ad1f

File tree

4 files changed

+131
-2
lines changed

4 files changed

+131
-2
lines changed

packages/framework/src/Console/Commands/RebuildStaticSiteCommand.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public function handle(): int
4747
try {
4848
$this->validate();
4949
} catch (Exception $exception) {
50-
return $this->handleException($exception);
50+
return $this->withException($exception);
5151
}
5252

5353
(new RebuildService($this->path))->execute();
@@ -102,7 +102,7 @@ public function validate(): void
102102
*
103103
* @return int Error code
104104
*/
105-
public function handleException(Exception $exception): int
105+
public function withException(Exception $exception): int
106106
{
107107
$this->error('Something went wrong!');
108108
$this->warn($exception->getMessage());

packages/framework/src/Console/Concerns/Command.php

+55
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,69 @@
44

55
namespace Hyde\Console\Concerns;
66

7+
use function config;
8+
use Exception;
79
use Hyde\Hyde;
810
use LaravelZero\Framework\Commands\Command as BaseCommand;
11+
use function sprintf;
912

1013
/**
1114
* @see \Hyde\Framework\Testing\Feature\CommandTest
1215
*/
1316
abstract class Command extends BaseCommand
1417
{
18+
public const USER_EXIT = 130;
19+
20+
/**
21+
* The base handle method that can be overridden by child classes.
22+
*
23+
* Alternatively, implement the safeHandle method in your child class
24+
* to utilize the automatic exception handling provided by this method.
25+
*
26+
* @return int The exit code.
27+
*/
28+
public function handle(): int
29+
{
30+
try {
31+
return $this->safeHandle();
32+
} catch (Exception $exception) {
33+
return $this->handleException($exception);
34+
}
35+
}
36+
37+
/**
38+
* This method can be overridden by child classes to provide automatic exception handling.
39+
*
40+
* Existing code can be converted simply by renaming the handle() method to safeHandle().
41+
*
42+
* @return int The exit code.
43+
*/
44+
protected function safeHandle(): int
45+
{
46+
return Command::SUCCESS;
47+
}
48+
49+
/**
50+
* Handle an exception that occurred during command execution.
51+
*
52+
* @return int The exit code
53+
*/
54+
public function handleException(Exception $exception): int
55+
{
56+
// When testing it might be more useful to see the full stack trace, so we have an option to actually throw the exception.
57+
if (config('app.throw_on_console_exception', false)) {
58+
throw $exception;
59+
}
60+
61+
// If the exception was thrown from the same file as a command, then we don't need to show which file it was thrown from.
62+
$location = str_ends_with($exception->getFile(), 'Command.php') ? '' : sprintf(' at %s:%s',
63+
$exception->getFile(), $exception->getLine()
64+
);
65+
$this->error("Error: {$exception->getMessage()}".$location);
66+
67+
return Command::FAILURE;
68+
}
69+
1570
/**
1671
* Create a filepath that can be opened in the browser from a terminal.
1772
*/

packages/framework/tests/Feature/CommandTest.php

+63
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use Hyde\Console\Concerns\Command;
99
use Hyde\Hyde;
1010
use Hyde\Testing\TestCase;
11+
use Mockery;
12+
use RuntimeException;
1113
use Symfony\Component\Console\Style\OutputStyle;
1214

1315
/**
@@ -122,6 +124,46 @@ public function testIndentedLine()
122124
$command->setMockedOutput($output);
123125
$command->handle();
124126
}
127+
128+
public function testHandleCallsBaseSafeHandle()
129+
{
130+
$this->assertSame(0, (new TestCommand())->handle());
131+
}
132+
133+
public function testHandleCallsChildSafeHandle()
134+
{
135+
$this->assertSame(1, (new SafeHandleTestCommand())->handle());
136+
}
137+
138+
public function testSafeHandleException()
139+
{
140+
$command = new SafeThrowingTestCommand();
141+
$output = Mockery::mock(\Illuminate\Console\OutputStyle::class);
142+
$output->shouldReceive('writeln')->once()->withArgs(function (string $message) {
143+
return str_starts_with($message, '<error>Error: This is a test at '.__FILE__.':');
144+
});
145+
$command->setOutput($output);
146+
147+
$code = $command->handle();
148+
149+
$this->assertSame(1, $code);
150+
}
151+
152+
public function testCanEnableThrowOnException()
153+
{
154+
$this->throwOnConsoleException();
155+
$command = new SafeThrowingTestCommand();
156+
157+
$output = Mockery::mock(\Illuminate\Console\OutputStyle::class);
158+
159+
$this->expectException(RuntimeException::class);
160+
$this->expectExceptionMessage('This is a test');
161+
162+
$command->setOutput($output);
163+
$code = $command->handle();
164+
165+
$this->assertSame(1, $code);
166+
}
125167
}
126168

127169
class MockableTestCommand extends Command
@@ -140,3 +182,24 @@ public function setMockedOutput($output)
140182
$this->output = $output;
141183
}
142184
}
185+
186+
class TestCommand extends Command
187+
{
188+
//
189+
}
190+
191+
class SafeHandleTestCommand extends Command
192+
{
193+
public function safeHandle(): int
194+
{
195+
return 1;
196+
}
197+
}
198+
199+
class SafeThrowingTestCommand extends Command
200+
{
201+
public function safeHandle(): int
202+
{
203+
throw new RuntimeException('This is a test');
204+
}
205+
}

packages/testing/src/TestCase.php

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Hyde\Testing;
66

7+
use function config;
78
use function file_get_contents;
89
use Hyde\Facades\Features;
910
use Hyde\Hyde;
@@ -55,4 +56,14 @@ protected function assertFileEqualsString(string $string, string $path, bool $st
5556
$this->assertEquals(normalize_newlines($string), normalize_newlines(file_get_contents(Hyde::path($path))));
5657
}
5758
}
59+
60+
/**
61+
* Disable the throwing of exceptions on console commands for the duration of the test.
62+
*
63+
* Note that this only affects commands using the {@see \Hyde\Console\Concerns\Command::safeHandle()} method.
64+
*/
65+
protected function throwOnConsoleException(bool $throw = true): void
66+
{
67+
config(['app.throw_on_console_exception' => $throw]);
68+
}
5869
}

0 commit comments

Comments
 (0)