Skip to content

Commit

Permalink
[10.x] Move Symfony events dispatcher registration to Console\Kernel (
Browse files Browse the repository at this point in the history
#46508)

* [10.x] Move Symfony events dispatcher registration to `Console\Kernel`

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* formatting

---------

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
crynobone and taylorotwell authored Mar 18, 2023
1 parent c3e679c commit 287b02d
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 48 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
"league/flysystem-read-only": "^3.3",
"league/flysystem-sftp-v3": "^3.0",
"mockery/mockery": "^1.5.1",
"orchestra/testbench-core": "^8.0",
"orchestra/testbench-core": "^8.1",
"pda/pheanstalk": "^4.0",
"phpstan/phpdoc-parser": "^1.15",
"phpstan/phpstan": "^1.4.7",
Expand Down
39 changes: 0 additions & 39 deletions src/Illuminate/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,18 @@

use Closure;
use Illuminate\Console\Events\ArtisanStarting;
use Illuminate\Console\Events\CommandFinished;
use Illuminate\Console\Events\CommandStarting;
use Illuminate\Contracts\Console\Application as ApplicationContract;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\ProcessUtils;
use Symfony\Component\Console\Application as SymfonyApplication;
use Symfony\Component\Console\Command\Command as SymfonyCommand;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Process\PhpExecutableFinder;

class Application extends SymfonyApplication implements ApplicationContract
Expand Down Expand Up @@ -80,42 +74,9 @@ public function __construct(Container $laravel, Dispatcher $events, $version)

$this->events->dispatch(new ArtisanStarting($this));

$this->rerouteSymfonyCommandEvents();

$this->bootstrap();
}

/**
* Re-route the Symfony command events to their Laravel counterparts.
*
* @return void
*/
protected function rerouteSymfonyCommandEvents()
{
$this->setDispatcher($dispatcher = new EventDispatcher);

$dispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
$this->events->dispatch(
new CommandStarting(
$event->getCommand()->getName(),
$event->getInput(),
$event->getOutput(),
)
);
});

$dispatcher->addListener(ConsoleEvents::TERMINATE, function (ConsoleTerminateEvent $event) {
$this->events->dispatch(
new CommandFinished(
$event->getCommand()->getName(),
$event->getInput(),
$event->getOutput(),
$event->getExitCode(),
)
);
});
}

/**
* Determine the proper PHP executable.
*
Expand Down
49 changes: 49 additions & 0 deletions src/Illuminate/Foundation/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use DateTimeInterface;
use Illuminate\Console\Application as Artisan;
use Illuminate\Console\Command;
use Illuminate\Console\Events\CommandFinished;
use Illuminate\Console\Events\CommandStarting;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Contracts\Console\Kernel as KernelContract;
use Illuminate\Contracts\Debug\ExceptionHandler;
Expand All @@ -18,6 +20,10 @@
use Illuminate\Support\InteractsWithTime;
use Illuminate\Support\Str;
use ReflectionClass;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Finder\Finder;
use Throwable;

Expand All @@ -39,6 +45,13 @@ class Kernel implements KernelContract
*/
protected $events;

/**
* The Symfony event dispatcher implementation.
*
* @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface|null
*/
protected $symfonyDispatcher;

/**
* The Artisan application instance.
*
Expand Down Expand Up @@ -105,11 +118,43 @@ public function __construct(Application $app, Dispatcher $events)
$this->app = $app;
$this->events = $events;

if (! $this->app->runningUnitTests()) {
$this->rerouteSymfonyCommandEvents();
}

$this->app->booted(function () {
$this->defineConsoleSchedule();
});
}

/**
* Re-route the Symfony command events to their Laravel counterparts.
*
* @internal
*
* @return $this
*/
public function rerouteSymfonyCommandEvents()
{
if (is_null($this->symfonyDispatcher)) {
$this->symfonyDispatcher = new EventDispatcher;

$this->symfonyDispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
$this->events->dispatch(
new CommandStarting($event->getCommand()->getName(), $event->getInput(), $event->getOutput())
);
});

$this->symfonyDispatcher->addListener(ConsoleEvents::TERMINATE, function (ConsoleTerminateEvent $event) {
$this->events->dispatch(
new CommandFinished($event->getCommand()->getName(), $event->getInput(), $event->getOutput(), $event->getExitCode())
);
});
}

return $this;
}

/**
* Define the application's command schedule.
*
Expand Down Expand Up @@ -417,6 +462,10 @@ protected function getArtisan()
$this->artisan = (new Artisan($this->app, $this->events, $this->app->version()))
->resolveCommands($this->commands)
->setContainerCommandLoader();

if ($this->symfonyDispatcher instanceof EventDispatcher) {
$this->artisan->setDispatcher($this->symfonyDispatcher);
}
}

return $this->artisan;
Expand Down
28 changes: 20 additions & 8 deletions tests/Integration/Console/CommandEventsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@

use Illuminate\Console\Events\CommandFinished;
use Illuminate\Console\Events\CommandStarting;
use Illuminate\Contracts\Console\Kernel as ConsoleKernel;
use Illuminate\Events\Dispatcher;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Process;
use Illuminate\Support\Str;
use Orchestra\Testbench\TestCase;
use Symfony\Component\Process\PhpExecutableFinder;

class CommandEventsTest extends TestCase
{
Expand Down Expand Up @@ -65,14 +68,27 @@ protected function tearDown(): void
parent::tearDown();
}

/**
* Define environment setup.
*
* @param \Illuminate\Foundation\Application $app
* @return void
*/
protected function defineEnvironment($app)
{
$app->make(ConsoleKernel::class)->rerouteSymfonyCommandEvents();
}

/**
* @dataProvider commandEventsProvider
*/
public function testCommandEventsReceiveParsedInput($processType, $argumentType)
{
$phpBinary = (new PhpExecutableFinder)->find();

switch ($processType) {
case 'foreground':
$this->app[\Illuminate\Contracts\Console\Kernel::class]->registerCommand(new CommandEventsTestCommand);
$this->app[ConsoleKernel::class]->registerCommand(new CommandEventsTestCommand);
$this->app[Dispatcher::class]->listen(function (CommandStarting $event) {
array_map(fn ($e) => $this->fs->append($this->logfile, $e."\n"), [
'CommandStarting',
Expand Down Expand Up @@ -106,13 +122,8 @@ public function testCommandEventsReceiveParsedInput($processType, $argumentType)
case 'background':
// Initialize empty logfile.
$this->fs->append($this->logfile, '');
exec('php '.base_path('artisan').' command-events-test-command-'.$this->id.' taylor otwell --occupation=coding');
// Since our command is running in a separate process, we need to wait
// until it has finished executing before running our assertions.
$this->waitForLogMessages(
'CommandStarting', 'taylor', 'otwell', 'coding',
'CommandFinished', 'taylor', 'otwell', 'coding',
);

Process::run($phpBinary.' '.base_path('artisan').' command-events-test-command-'.$this->id.' taylor otwell --occupation=coding');
break;
}

Expand Down Expand Up @@ -185,6 +196,7 @@ protected function writeArtisanScript()
\$app = require_once __DIR__.'/bootstrap/app.php';
\$kernel = \$app->make(Illuminate\Contracts\Console\Kernel::class);
\$kernel->rerouteSymfonyCommandEvents();
class CommandEventsTestCommand extends Illuminate\Console\Command
{
Expand Down

0 comments on commit 287b02d

Please sign in to comment.