Skip to content

Commit a2f6ae8

Browse files
Fixes CommandStarting and CommandFinished not working (#1272)
* Fixes `CommandStarting` and `CommandFinished` not working Signed-off-by: Mior Muhammad Zaki <[email protected]> * Apply fixes from StyleCI * wip Signed-off-by: Mior Muhammad Zaki <[email protected]> --------- Signed-off-by: Mior Muhammad Zaki <[email protected]> Co-authored-by: StyleCI Bot <[email protected]>
1 parent 7d9f5c4 commit a2f6ae8

File tree

4 files changed

+99
-1
lines changed

4 files changed

+99
-1
lines changed

src/Application.php

+1
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,7 @@ public function flush()
10061006
$this->router = null;
10071007
$this->dispatcher = null;
10081008
static::$instance = null;
1009+
static::$aliasesRegistered = false;
10091010
}
10101011

10111012
/**

src/Console/Kernel.php

+50-1
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,21 @@
33
namespace Laravel\Lumen\Console;
44

55
use Illuminate\Console\Application as Artisan;
6+
use Illuminate\Console\Events\CommandFinished;
7+
use Illuminate\Console\Events\CommandStarting;
68
use Illuminate\Console\Scheduling\Schedule;
79
use Illuminate\Console\Scheduling\ScheduleRunCommand;
810
use Illuminate\Contracts\Console\Kernel as KernelContract;
911
use Illuminate\Contracts\Debug\ExceptionHandler;
12+
use Illuminate\Contracts\Events\Dispatcher;
1013
use Illuminate\Http\Request;
1114
use Laravel\Lumen\Application;
1215
use Laravel\Lumen\Exceptions\Handler;
1316
use RuntimeException;
17+
use Symfony\Component\Console\ConsoleEvents;
18+
use Symfony\Component\Console\Event\ConsoleCommandEvent;
19+
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
20+
use Symfony\Component\EventDispatcher\EventDispatcher;
1421
use Throwable;
1522

1623
class Kernel implements KernelContract
@@ -22,6 +29,13 @@ class Kernel implements KernelContract
2229
*/
2330
protected $app;
2431

32+
/**
33+
* The Symfony event dispatcher implementation.
34+
*
35+
* @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface|null
36+
*/
37+
protected $symfonyDispatcher;
38+
2539
/**
2640
* The Artisan application instance.
2741
*
@@ -55,6 +69,8 @@ public function __construct(Application $app)
5569

5670
if ($this->app->runningInConsole()) {
5771
$this->setRequestForConsole($this->app);
72+
} else {
73+
$this->rerouteSymfonyCommandEvents();
5874
}
5975

6076
$this->app->prepareForConsoleCommand($this->aliases);
@@ -87,6 +103,34 @@ protected function setRequestForConsole(Application $app)
87103
));
88104
}
89105

106+
/**
107+
* Re-route the Symfony command events to their Laravel counterparts.
108+
*
109+
* @internal
110+
*
111+
* @return $this
112+
*/
113+
public function rerouteSymfonyCommandEvents()
114+
{
115+
if (is_null($this->symfonyDispatcher)) {
116+
$this->symfonyDispatcher = new EventDispatcher;
117+
118+
$this->symfonyDispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
119+
$this->app[Dispatcher::class]->dispatch(
120+
new CommandStarting($event->getCommand()->getName(), $event->getInput(), $event->getOutput())
121+
);
122+
});
123+
124+
$this->symfonyDispatcher->addListener(ConsoleEvents::TERMINATE, function (ConsoleTerminateEvent $event) {
125+
$this->app[Dispatcher::class]->dispatch(
126+
new CommandFinished($event->getCommand()->getName(), $event->getInput(), $event->getOutput(), $event->getExitCode())
127+
);
128+
});
129+
}
130+
131+
return $this;
132+
}
133+
90134
/**
91135
* Define the application's command schedule.
92136
*
@@ -212,9 +256,14 @@ public function output()
212256
protected function getArtisan()
213257
{
214258
if (is_null($this->artisan)) {
215-
return $this->artisan = (new Artisan($this->app, $this->app->make('events'), $this->app->version()))
259+
$this->artisan = (new Artisan($this->app, $this->app->make('events'), $this->app->version()))
216260
->resolveCommands($this->getCommands())
217261
->setContainerCommandLoader();
262+
263+
if ($this->symfonyDispatcher instanceof EventDispatcher) {
264+
$this->artisan->setDispatcher($this->symfonyDispatcher);
265+
$this->artisan->setSignalsToDispatchEvent();
266+
}
218267
}
219268

220269
return $this->artisan;

tests/Console/KernelTest.php

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
use Illuminate\Console\Events\CommandFinished;
4+
use Illuminate\Console\Events\CommandStarting;
5+
use Illuminate\Contracts\Console\Kernel as ConsoleKernelContract;
6+
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandlerContract;
7+
use Laravel\Lumen\Application;
8+
use Laravel\Lumen\Console\Kernel as ConsoleKernel;
9+
use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
10+
11+
class KernelTest extends \Laravel\Lumen\Testing\TestCase
12+
{
13+
/**
14+
* Creates the application.
15+
*
16+
* Needs to be implemented by subclasses.
17+
*
18+
* @return \Symfony\Component\HttpKernel\HttpKernelInterface
19+
*/
20+
public function createApplication()
21+
{
22+
$app = new Application();
23+
24+
$app->configure('app');
25+
26+
$app->singleton(ExceptionHandlerContract::class, fn () => new ExceptionHandler());
27+
$app->singleton(ConsoleKernelContract::class, function () use ($app) {
28+
return tap(new ConsoleKernel($app), function ($kernel) {
29+
$kernel->rerouteSymfonyCommandEvents();
30+
});
31+
});
32+
33+
return $app;
34+
}
35+
36+
public function testItCanRerouteToSymfonyEvent()
37+
{
38+
$this->expectsEvents([CommandStarting::class, CommandFinished::class]);
39+
40+
$this->artisan('cache:forget', ['key' => 'lumen']);
41+
}
42+
}

tests/FullApplicationTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use Illuminate\Contracts\Debug\ExceptionHandler;
55
use Illuminate\Contracts\Validation\Factory;
66
use Illuminate\Http\Response;
7+
use Illuminate\Support\Facades\Facade;
78
use Illuminate\View\ViewServiceProvider;
89
use Laravel\Lumen\Application;
910
use Laravel\Lumen\Console\ConsoleServiceProvider;
@@ -16,6 +17,11 @@
1617

1718
class FullApplicationTest extends TestCase
1819
{
20+
protected function setUp(): void
21+
{
22+
Facade::clearResolvedInstances();
23+
}
24+
1925
protected function tearDown(): void
2026
{
2127
m::close();

0 commit comments

Comments
 (0)