Skip to content

Commit e9a6e69

Browse files
author
Mitchell Macpherson
authored
Support for artisan serve (built-in php dev server) (#4)
* Support `artisan serve` output forwarding * Update readme
1 parent ee0bda2 commit e9a6e69

File tree

8 files changed

+79
-51
lines changed

8 files changed

+79
-51
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ Unit tests ensure type-compatibility, expected behaviour is met & compatibility
9494
---
9595
# Features
9696

97+
## Artisan serve supported
98+
Logger output will be shown in your local development server console.
99+
97100
## Literally Effortless
98101

99102
Your application **will not be coupled** with ConsoleLogg.

src/Binder/LogOutputBinder.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66

77
use DevThis\ConsoleLogg\Interfaces\Binder\LogOutputBindedInterface;
88
use DevThis\ConsoleLogg\Interfaces\Factories\FilterableConsoleLoggerFactoryInterface;
9-
use Illuminate\Console\Events\CommandFinished;
10-
use Illuminate\Console\Events\CommandStarting;
119
use Illuminate\Contracts\Config\Repository;
1210
use Illuminate\Log\LogManager;
11+
use Symfony\Component\Console\Output\OutputInterface;
1312

1413
/**
1514
* Responsible for binding a ConsoleLogger instance with the built-in Laravel Logger, and removing
@@ -39,12 +38,12 @@ public function __construct(FilterableConsoleLoggerFactoryInterface $consoleLogg
3938
$this->consoleLoggerFactory = $consoleLoggerFactory;
4039
}
4140

42-
public function attach(CommandStarting $commandEvent, LogManager $logManager): void
41+
public function attach(OutputInterface $output, LogManager $logManager): void
4342
{
4443
$this->defaultDriver = $logManager->getDefaultDriver();
4544
$logManager->setDefaultDriver('console-logg');
4645

47-
$consoleLogger = $this->consoleLoggerFactory->create($commandEvent->output, $this->isFiltered);
46+
$consoleLogger = $this->consoleLoggerFactory->create($output, $this->isFiltered);
4847

4948
$logManager->extend(
5049
'console-logg',
@@ -54,7 +53,7 @@ function () use ($consoleLogger) {
5453
);
5554
}
5655

57-
public function detach(CommandFinished $commandFinished, LogManager $logManager): void
56+
public function detach(LogManager $logManager): void
5857
{
5958
$logManager->forgetChannel('console-logg');
6059
$logManager->setDefaultDriver($this->defaultDriver);

src/Interfaces/Binder/LogOutputBindedInterface.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44

55
namespace DevThis\ConsoleLogg\Interfaces\Binder;
66

7-
use Illuminate\Console\Events\CommandFinished;
8-
use Illuminate\Console\Events\CommandStarting;
97
use Illuminate\Log\LogManager;
8+
use Symfony\Component\Console\Output\OutputInterface;
109

1110
interface LogOutputBindedInterface
1211
{
13-
public function attach(CommandStarting $commandEvent, LogManager $logManager): void;
12+
public function attach(OutputInterface $output, LogManager $logManager): void;
1413

15-
public function detach(CommandFinished $commandFinished, LogManager $logManager): void;
14+
public function detach(LogManager $logManager): void;
1615
}

src/Listeners/LogManagerResolverListener.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Illuminate\Contracts\Events\Dispatcher as EventDispatcher;
1212
use Illuminate\Contracts\Foundation\Application;
1313
use Illuminate\Log\LogManager;
14+
use Symfony\Component\Console\Output\StreamOutput;
1415

1516
class LogManagerResolverListener implements LogManagerResolverListenerInterface
1617
{
@@ -35,18 +36,31 @@ public function __construct(EventDispatcher $eventDispatcher, LogOutputBindedInt
3536
*/
3637
public function handle(LogManager $logManager, Application $application): void
3738
{
39+
if ($this->isCliServer() === true) {
40+
// Parent process forwards standard output
41+
$output = new StreamOutput(\fopen('php://stdout', 'wb'));
42+
$this->logOutputBinder->attach($output, $logManager);
43+
44+
return;
45+
}
46+
3847
$this->eventDispatcher->listen(
3948
CommandStarting::class,
4049
function (CommandStarting $event) use ($logManager) {
41-
$this->logOutputBinder->attach($event, $logManager);
50+
$this->logOutputBinder->attach($event->output, $logManager);
4251
}
4352
);
4453

4554
$this->eventDispatcher->listen(
4655
CommandFinished::class,
4756
function (CommandFinished $event) use ($logManager) {
48-
$this->logOutputBinder->detach($event, $logManager);
57+
$this->logOutputBinder->detach($logManager);
4958
}
5059
);
5160
}
61+
62+
protected function isCliServer(): bool
63+
{
64+
return PHP_SAPI === 'cli-server';
65+
}
5266
}

src/Providers/ConsoleLoggServiceProvider.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ public function boot()
4040
*/
4141
public function register()
4242
{
43-
if ($this->app->runningInConsole() === false) {
43+
// Support built-in PHP dev server or console kernel
44+
if (PHP_SAPI !== 'cli-server' && $this->app->runningInConsole() === false) {
4445
return;
4546
}
4647

tests/Doubles/Spies/Binder/LogOutputBinderFake.php

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,45 +5,38 @@
55
namespace Tests\Doubles\Spies\Binder;
66

77
use DevThis\ConsoleLogg\Interfaces\Binder\LogOutputBindedInterface;
8-
use Illuminate\Console\Events\CommandFinished;
9-
use Illuminate\Console\Events\CommandStarting;
108
use Illuminate\Log\LogManager;
9+
use Symfony\Component\Console\Output\OutputInterface;
1110

1211
class LogOutputBinderFake implements LogOutputBindedInterface
1312
{
14-
private $lastAttachEvent = null;
15-
1613
private $lastAttachLogManager = null;
1714

15+
private $lastAttachOutput = null;
16+
1817
private $lastDetachEvent = null;
1918

2019
private $lastDetachLogManager = null;
2120

22-
public function attach(CommandStarting $commandEvent, LogManager $logManager): void
21+
public function attach(OutputInterface $output, LogManager $logManager): void
2322
{
24-
$this->lastAttachEvent = $commandEvent;
23+
$this->lastAttachOutput = $output;
2524
$this->lastAttachLogManager = $logManager;
2625
}
2726

28-
public function detach(CommandFinished $commandFinished, LogManager $logManager): void
27+
public function detach(LogManager $logManager): void
2928
{
30-
$this->lastDetachEvent = $commandFinished;
3129
$this->lastDetachLogManager = $logManager;
3230
}
3331

34-
public function getLastAttachEvent(): ?CommandStarting
35-
{
36-
return $this->lastAttachEvent;
37-
}
38-
3932
public function getLastAttachLogManager(): ?LogManager
4033
{
4134
return $this->lastAttachLogManager;
4235
}
4336

44-
public function getLastDetachEvent(): ?CommandFinished
37+
public function getLastAttachOutput(): ?OutputInterface
4538
{
46-
return $this->lastDetachEvent;
39+
return $this->lastAttachOutput;
4740
}
4841

4942
public function getLastDetachLogManager(): ?LogManager

tests/Unit/Binder/LogOutputBinderTest.php

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@
55
namespace Tests\Unit\Binder;
66

77
use DevThis\ConsoleLogg\Binder\LogOutputBinder;
8-
use Illuminate\Console\Events\CommandFinished;
9-
use Illuminate\Console\Events\CommandStarting;
108
use Illuminate\Log\LogManager;
119
use PHPUnit\Framework\TestCase;
12-
use Symfony\Component\Console\Input\StringInput;
1310
use Symfony\Component\Console\Output\NullOutput;
1411
use Tests\Doubles\Fakes\vendor\Illuminate\ApplicationFake;
1512
use Tests\Doubles\Spies\Factories\FilterableConsoleLoggerFactorySpy;
@@ -26,13 +23,12 @@ public function testAttachSetsDefaultDriver(): void
2623
$config = new RepositoryStub();
2724
$filterableConsoleLoggerFactory = new FilterableConsoleLoggerFactorySpy();
2825
$logOutputBinder = new LogOutputBinder($filterableConsoleLoggerFactory, $config);
29-
$stringInput = new StringInput('some:command');
30-
$commandStarting = new CommandStarting('Some\Command', $stringInput, new NullOutput());
26+
$output = new NullOutput();
3127
$app = new ApplicationFake(['config' => ['logging.default' => ['driver' => 'the-default']]]);
3228
$logManager = new LogManager($app);
3329
$expectation = 'console-logg';
3430

35-
$logOutputBinder->attach($commandStarting, $logManager);
31+
$logOutputBinder->attach($output, $logManager);
3632

3733
self::assertSame($expectation, $logManager->getDefaultDriver());
3834
}
@@ -42,14 +38,12 @@ public function testAttachedConsoleLoggerRespectsFilteredOption(): void
4238
$config = new RepositoryStub();
4339
$filterableConsoleLoggerFactory = new FilterableConsoleLoggerFactorySpy();
4440
$logOutputBinder = new LogOutputBinder($filterableConsoleLoggerFactory, $config);
45-
$stringInput = new StringInput('some:command');
4641
$output = new NullOutput();
47-
$commandStarting = new CommandStarting('Some\Command', $stringInput, $output);
4842
$defaultDriver = ['driver' => 'the-default'];
4943
$app = new ApplicationFake(['config' => ['logging.default' => $defaultDriver]]);
5044
$logManager = new LogManagerSpy($app);
5145

52-
$logOutputBinder->attach($commandStarting, $logManager);
46+
$logOutputBinder->attach($output, $logManager);
5347

5448
self::assertEquals(
5549
$filterableConsoleLoggerFactory->getLastCreated(),
@@ -62,15 +56,13 @@ public function testDefaultDriverAfterDetachIsNotConsoleLogg(): void
6256
$config = new RepositoryStub();
6357
$filterableConsoleLoggerFactory = new FilterableConsoleLoggerFactorySpy();
6458
$logOutputBinder = new LogOutputBinder($filterableConsoleLoggerFactory, $config);
65-
$stringInput = new StringInput('some:command');
66-
$commandStarting = new CommandStarting('Some\Command', $stringInput, new NullOutput());
67-
$commandFinished = new CommandFinished('Some\Command', $stringInput, new NullOutput(), 0);
59+
$output = new NullOutput();
6860
$defaultDriver = ['driver' => 'the-default'];
6961
$app = new ApplicationFake(['config' => ['logging.default' => $defaultDriver]]);
7062
$logManager = new LogManager($app);
7163

72-
$logOutputBinder->attach($commandStarting, $logManager);
73-
$logOutputBinder->detach($commandFinished, $logManager);
64+
$logOutputBinder->attach($output, $logManager);
65+
$logOutputBinder->detach($logManager);
7466

7567
self::assertSame($defaultDriver, $logManager->getDefaultDriver());
7668
}

tests/Unit/Listeners/LogManagerResolverListenerTest.php

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PHPUnit\Framework\TestCase;
1313
use Symfony\Component\Console\Input\StringInput;
1414
use Symfony\Component\Console\Output\NullOutput;
15+
use Symfony\Component\Console\Output\StreamOutput;
1516
use Tests\Doubles\Fakes\vendor\Illuminate\ApplicationFake;
1617
use Tests\Doubles\Fakes\vendor\Illuminate\EventDispatcherFake;
1718
use Tests\Doubles\Spies\Binder\LogOutputBinderFake;
@@ -30,6 +31,35 @@ public function getInputsForEventDispatchListeningTo(): iterable
3031
yield 'CommandFinished' => [CommandFinished::class];
3132
}
3233

34+
public function testCliServerDetection(): void
35+
{
36+
$eventDispatcher = new EventDispatcherFake();
37+
$logOutputBinder = new LogOutputBinderFake();
38+
$logManagerResolverListener = new class($eventDispatcher, $logOutputBinder) extends LogManagerResolverListener {
39+
protected function isCliServer(): bool
40+
{
41+
return true;
42+
}
43+
};
44+
$app = new ApplicationFake();
45+
$logManager = new LogManager($app);
46+
$logManagerResolverListener->handle($logManager, $app);
47+
48+
self::assertInstanceOf(StreamOutput::class, $logOutputBinder->getLastAttachOutput());
49+
}
50+
51+
public function testCliServerSkips(): void
52+
{
53+
$eventDispatcher = new EventDispatcherFake();
54+
$logOutputBinder = new LogOutputBinderFake();
55+
$logManagerResolverListener = new LogManagerResolverListener($eventDispatcher, $logOutputBinder);
56+
$app = new ApplicationFake();
57+
$logManager = new LogManager($app);
58+
$logManagerResolverListener->handle($logManager, $app);
59+
60+
self::assertNotInstanceOf(StreamOutput::class, $logOutputBinder->getLastAttachOutput());
61+
}
62+
3363
/**
3464
* Slightly weak test
3565
* Testing the spy doesn't prove with certainty
@@ -69,16 +99,13 @@ public function testEventListenerAttachesLogManager(): void
6999
$app = new ApplicationFake();
70100
$logManager = new LogManager($app);
71101
$logManagerResolverListener->handle($logManager, $app);
72-
$event = new CommandStarting('some:command', new StringInput(''), new NullOutput());
73-
$actualBeforeEvent = $logOutputBinder->getLastAttachEvent();
74-
$expectedBeforeEvent = null;
75-
$expectedAfterEvent = $event;
102+
$output = new NullOutput();
103+
$event = new CommandStarting('some:command', new StringInput(''), $output);
76104
// @todo stubs with Input/Output interface
77105
$closure = $eventDispatcher->getListener(CommandStarting::class);
78106
$closure($event, new LogManagerStub());
79107

80-
self::assertSame($expectedAfterEvent, $logOutputBinder->getLastAttachEvent());
81-
self::assertSame($expectedBeforeEvent, $actualBeforeEvent);
108+
self::assertSame($output, $logOutputBinder->getLastAttachOutput());
82109
}
83110

84111
/**
@@ -95,13 +122,13 @@ public function testEventListenerDetachesLogManager(): void
95122
$logManager = new LogManager($app);
96123
$logManagerResolverListener->handle($logManager, $app);
97124
$event = new CommandFinished('some:command', new StringInput(''), new NullOutput(), 1);
98-
$actualBeforeEvent = $logOutputBinder->getLastDetachEvent();
125+
$actualBeforeEvent = $logOutputBinder->getLastDetachLogManager();
99126
$expectedBeforeEvent = null;
100-
$expectedAfterEvent = $event;
127+
$expectedAfterEvent = $logManager;
101128
$closure = $eventDispatcher->getListener(CommandFinished::class);
102-
$closure($event, new LogManagerStub());
129+
$closure($event, $logManager);
103130

104-
self::assertSame($expectedAfterEvent, $logOutputBinder->getLastDetachEvent());
105131
self::assertSame($expectedBeforeEvent, $actualBeforeEvent);
132+
self::assertSame($expectedAfterEvent, $logOutputBinder->getLastDetachLogManager());
106133
}
107134
}

0 commit comments

Comments
 (0)