Skip to content

Commit 67ee47a

Browse files
authored
Merge pull request #1247 from phpDocumentor/feature/simplify-serve-command
Feature/simplify serve command
2 parents 4077508 + 987a78b commit 67ee47a

File tree

6 files changed

+129
-73
lines changed

6 files changed

+129
-73
lines changed

packages/dev-server/src/Internal/HttpHandler.php

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Ratchet\Http\HttpServerInterface;
2424
use Throwable;
2525

26+
use function is_array;
2627
use function str_replace;
2728
use function strlen;
2829
use function trim;
@@ -33,9 +34,10 @@ final class HttpHandler implements HttpServerInterface
3334

3435
private ExtensionMimeTypeDetector $detector;
3536

37+
/** @param string|string[] $indexFile */
3638
public function __construct(
3739
private FlySystemAdapter $files,
38-
private string $indexFile = 'index.html',
40+
private string|array $indexFile = 'index.html',
3941
) {
4042
$this->detector = new ExtensionMimeTypeDetector();
4143
}
@@ -53,13 +55,17 @@ public function onOpen(ConnectionInterface $conn, RequestInterface|null $request
5355
// Remove leading slash and any route parameters
5456
$requestPath = trim($path, '/');
5557

56-
// For empty path (root) serve index.html
57-
if ($requestPath === '') {
58-
$requestPath = $this->indexFile;
59-
}
60-
61-
if ($this->files->isDirectory($requestPath)) {
62-
$requestPath .= '/' . $this->indexFile;
58+
if ($requestPath === '' || $this->files->isDirectory($requestPath)) {
59+
if (is_array($this->indexFile)) {
60+
foreach ($this->indexFile as $indexFile) {
61+
if ($this->files->has(trim($requestPath . '/' . $indexFile, '/'))) {
62+
$requestPath = trim($requestPath . '/' . $indexFile, '/');
63+
break;
64+
}
65+
}
66+
} else {
67+
$requestPath .= '/' . $this->indexFile;
68+
}
6369
}
6470

6571
if ($this->files->has($requestPath)) {
@@ -81,7 +87,9 @@ public function onOpen(ConnectionInterface $conn, RequestInterface|null $request
8187
return;
8288
}
8389

84-
$content = '<!DOCTYPE html><html><body><h1>404 - Page Not Found</h1></body></html>';
90+
$content = '<!DOCTYPE html><html><body><h1>404 - Page Not Found</h1>
91+
<p>Path ' . $requestPath . ' does not exist</p>
92+
</body></html>';
8593
$headers = [
8694
'Content-Type' => 'text/html',
8795
'Content-Length' => strlen($content),
@@ -95,7 +103,7 @@ private function injectWebSocketClient(string $html): string
95103
{
96104
//Read html and inject script before closing body tag
97105
$injection = <<<'EOT'
98-
<script>
106+
<script>
99107
const socket = new WebSocket('ws://' + window.location.host + '/ws');
100108
socket.addEventListener('message', function (event) {
101109
if (event.data === 'update') {

packages/dev-server/src/Server.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public function watch(string $path): void
6060
$this->watcher->addPath($path);
6161
}
6262

63-
public function addListener(string $event, Closure $param): void
63+
public function addListener(string $event, Closure|callable $param): void
6464
{
6565
$this->eventDispatcher->addListener($event, $param);
6666
}

packages/dev-server/src/ServerFactory.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@ public function __construct(
2929
) {
3030
}
3131

32+
/** @param string|string[] $indexFile */
3233
public function createDevServer(
3334
string $soureDirectory,
3435
FlySystemAdapter $files,
3536
string $host,
3637
string $listen,
3738
int $port,
38-
string $indexFile = 'index.html',
39+
string|array $indexFile = 'index.html',
3940
): Server {
4041
$httpHandler = new HttpHandler($files, $indexFile);
4142
$wsServer = new WebSocketHandler($this->logger);

packages/guides-cli/src/Command/Serve.php

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,18 @@
1919
use phpDocumentor\DevServer\ServerFactory;
2020
use phpDocumentor\DevServer\Watcher\FileModifiedEvent;
2121
use phpDocumentor\FileSystem\FlySystemAdapter;
22+
use phpDocumentor\Guides\Cli\DevServer\RerenderListener;
2223
use phpDocumentor\Guides\Cli\Internal\RunCommand;
23-
use phpDocumentor\Guides\Compiler\CompilerContext;
2424
use phpDocumentor\Guides\Event\PostParseDocument;
25-
use phpDocumentor\Guides\Handlers\CompileDocumentsCommand;
26-
use phpDocumentor\Guides\Handlers\ParseFileCommand;
27-
use phpDocumentor\Guides\Handlers\RenderDocumentCommand;
2825
use phpDocumentor\Guides\Nodes\DocumentNode;
29-
use phpDocumentor\Guides\RenderContext;
30-
use phpDocumentor\Guides\Renderer\DocumentListIterator;
3126
use Symfony\Component\Console\Command\Command;
3227
use Symfony\Component\Console\Input\InputInterface;
3328
use Symfony\Component\Console\Input\InputOption;
3429
use Symfony\Component\Console\Output\OutputInterface;
3530

36-
use function assert;
3731
use function is_int;
3832
use function is_string;
3933
use function sprintf;
40-
use function substr;
4134

4235
final class Serve extends Command
4336
{
@@ -123,58 +116,7 @@ static function (PostParseDocument $event) use ($app): void {
123116

124117
$app->addListener(
125118
FileModifiedEvent::class,
126-
function (FileModifiedEvent $event) use ($documents, $sourceFileSystem, $projectNode, $settings, $app, $output): void {
127-
$output->writeln(
128-
sprintf(
129-
'File modified: %s, rerendering...',
130-
$event->path,
131-
),
132-
);
133-
$file = substr($event->path, 0, -4);
134-
135-
$document = $this->commandBus->handle(
136-
new ParseFileCommand(
137-
$sourceFileSystem,
138-
'',
139-
$file,
140-
$settings->getInputFormat(),
141-
1,
142-
$projectNode,
143-
true,
144-
),
145-
);
146-
assert($document instanceof DocumentNode);
147-
148-
$documents[$file] = $document;
149-
150-
/** @var array<string, DocumentNode> $documents */
151-
$documents = $this->commandBus->handle(new CompileDocumentsCommand($documents, new CompilerContext($projectNode)));
152-
$destinationFileSystem = FlySystemAdapter::createForPath($settings->getOutput());
153-
154-
$documentIterator = DocumentListIterator::create(
155-
$projectNode->getRootDocumentEntry(),
156-
$documents,
157-
);
158-
159-
$renderContext = RenderContext::forProject(
160-
$projectNode,
161-
$documents,
162-
$sourceFileSystem,
163-
$destinationFileSystem,
164-
'/',
165-
'html',
166-
)->withIterator($documentIterator);
167-
168-
$this->commandBus->handle(
169-
new RenderDocumentCommand(
170-
$documents[$file],
171-
$renderContext->withDocument($documents[$file]),
172-
),
173-
);
174-
175-
$output->writeln('Rerendering completed.');
176-
$app->notifyClients();
177-
},
119+
new RerenderListener($output, $this->commandBus, $sourceFileSystem, $settings, $projectNode, $documents, $app),
178120
);
179121

180122
$output->writeln(
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link https://phpdoc.org
12+
*/
13+
14+
namespace phpDocumentor\Guides\Cli\DevServer;
15+
16+
use League\Tactician\CommandBus;
17+
use phpDocumentor\DevServer\Server;
18+
use phpDocumentor\DevServer\Watcher\FileModifiedEvent;
19+
use phpDocumentor\FileSystem\FileSystem;
20+
use phpDocumentor\FileSystem\FlySystemAdapter;
21+
use phpDocumentor\Guides\Compiler\CompilerContext;
22+
use phpDocumentor\Guides\Handlers\CompileDocumentsCommand;
23+
use phpDocumentor\Guides\Handlers\ParseFileCommand;
24+
use phpDocumentor\Guides\Handlers\RenderDocumentCommand;
25+
use phpDocumentor\Guides\Nodes\DocumentNode;
26+
use phpDocumentor\Guides\Nodes\ProjectNode;
27+
use phpDocumentor\Guides\RenderContext;
28+
use phpDocumentor\Guides\Renderer\DocumentListIterator;
29+
use phpDocumentor\Guides\Settings\ProjectSettings;
30+
use Symfony\Component\Console\Output\OutputInterface;
31+
32+
use function assert;
33+
use function sprintf;
34+
use function substr;
35+
36+
final class RerenderListener
37+
{
38+
/** @param array<string, DocumentNode> $documents */
39+
public function __construct(
40+
private readonly OutputInterface $output,
41+
private readonly CommandBus $commandBus,
42+
private readonly FileSystem $sourceFileSystem,
43+
private readonly ProjectSettings $settings,
44+
private readonly ProjectNode $projectNode,
45+
private array $documents,
46+
private readonly Server $server,
47+
) {
48+
}
49+
50+
public function __invoke(FileModifiedEvent $event): void
51+
{
52+
$this->output->writeln(
53+
sprintf(
54+
'File modified: %s, rerendering...',
55+
$event->path,
56+
),
57+
);
58+
$file = substr($event->path, 0, -4);
59+
60+
$document = $this->commandBus->handle(
61+
new ParseFileCommand(
62+
$this->sourceFileSystem,
63+
'',
64+
$file,
65+
$this->settings->getInputFormat(),
66+
1,
67+
$this->projectNode,
68+
true,
69+
),
70+
);
71+
assert($document instanceof DocumentNode);
72+
73+
$documents = $this->documents;
74+
$documents[$file] = $document;
75+
76+
/** @var array<string, DocumentNode> $documents */
77+
$documents = $this->commandBus->handle(new CompileDocumentsCommand($documents, new CompilerContext($this->projectNode)));
78+
$this->documents = $documents;
79+
$destinationFileSystem = FlySystemAdapter::createForPath($this->settings->getOutput());
80+
81+
$documentIterator = DocumentListIterator::create(
82+
$this->projectNode->getRootDocumentEntry(),
83+
$this->documents,
84+
);
85+
86+
$renderContext = RenderContext::forProject(
87+
$this->projectNode,
88+
$this->documents,
89+
$this->sourceFileSystem,
90+
$destinationFileSystem,
91+
'/',
92+
'html',
93+
)->withIterator($documentIterator);
94+
95+
$this->commandBus->handle(
96+
new RenderDocumentCommand(
97+
$this->documents[$file],
98+
$renderContext->withDocument($this->documents[$file]),
99+
),
100+
);
101+
102+
$this->output->writeln('Rerendering completed.');
103+
$this->server->notifyClients();
104+
}
105+
}

phpstan-baseline.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
parameters:
22
ignoreErrors:
33
-
4-
message: "#^Parameter \\#2 \\$headers of class GuzzleHttp\\\\Psr7\\\\Response constructor expects array\\<array\\<string\\>\\|string\\>, array\\<string, int\\|string\\> given\\.$#"
4+
message: "#^Parameter \\#2 \\$headers of class GuzzleHttp\\\\Psr7\\\\Response constructor expects array\\<array\\<string\\>\\|string\\>, array\\<string, int\\<1, max\\>\\|string\\> given\\.$#"
55
count: 1
66
path: packages/dev-server/src/Internal/HttpHandler.php
77

0 commit comments

Comments
 (0)