Skip to content

Commit 814bd79

Browse files
committed
feat(cmd-serve): improving the flexibility of the serve command with port detection
The command now supports starting a PHP server with the ability to automatically detect an available port. The user is prompted to specify a port, and if the provided port is already in use, the command will suggest an alternative available port. Users can also define custom scheme, host and port with optional arguments. This enhancement provides a more user-friendly experience when running the **serve** command. Asked by @eydun Refs: #6
1 parent 15f5522 commit 814bd79

File tree

1 file changed

+58
-4
lines changed

1 file changed

+58
-4
lines changed

src/Commands/Common/ServeCommand.php

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
use Symfony\Component\Console\Input\InputInterface;
44
use Symfony\Component\Console\Output\OutputInterface;
5+
use Symfony\Component\Console\Input\InputOption;
6+
use Symfony\Component\Console\Question\Question;
7+
58
use Wirecli\Helpers\PwConnector;
9+
use Wirecli\Helpers\WsTools as Tools;
610

711
/**
812
* Class ServeCommand
@@ -21,7 +25,10 @@ class ServeCommand extends PwConnector {
2125
protected function configure() {
2226
$this
2327
->setName('serve')
24-
->setDescription('Serve ProcessWire via built in PHP webserver');
28+
->setDescription('Serve ProcessWire via built in PHP webserver')
29+
->addOption('scheme', null, InputOption::VALUE_OPTIONAL, 'Scheme to serve on', 'http')
30+
->addOption('host', null, InputOption::VALUE_OPTIONAL, 'Host to serve on', 'localhost')
31+
->addOption('port', null, InputOption::VALUE_OPTIONAL, 'Port to serve on', '8080');
2532
}
2633

2734
/**
@@ -31,9 +38,56 @@ protected function configure() {
3138
*/
3239
protected function execute(InputInterface $input, OutputInterface $output) {
3340
$this->checkForProcessWire($output);
34-
$output->writeln("Starting PHP server at localhost:8000");
35-
passthru("php -S localhost:8000");
41+
42+
$scheme = $input->getOption('scheme');
43+
$host = $input->getOption('host');
44+
$port = $input->getOption('port');
45+
$url = "$scheme://$host:$port";
46+
$this->tools->writeComment("Starting PHP server at $url ...");
47+
$this->helper = $this->getHelper('question');
48+
49+
$port = (int)$port;
50+
$pf = @fsockopen($host, $port); // Try to open a socket
51+
if (is_resource($pf)) {
52+
fclose($pf); // Close the previous socket
53+
do {
54+
$this->tools->writeError("Port $port is already in use.");
55+
$this->tools->nl();
56+
57+
$port++; // Increment the port number and try again
58+
59+
$question = new Question($this->tools->getQuestion("Trying another one", (int)$port), $port);
60+
$question->setValidator(function ($answer) {
61+
if ($answer && !filter_var($answer, FILTER_VALIDATE_INT)) {
62+
throw new \RuntimeException('Please enter a valid port number.');
63+
}
64+
return $answer;
65+
});
66+
67+
$newPort = $this->helper->ask($input, $output, $question); // Ask for a new port number
68+
if (is_resource($pf)) { // If the previous socket is still open, close it
69+
fclose($pf);
70+
}
71+
$pf = @fsockopen($host, (int)$newPort);
72+
}
73+
while($pf !== false);
74+
75+
if (is_resource($pf)) { // If the previous socket is still open, close it
76+
fclose($pf);
77+
}
78+
$port = $newPort;
79+
}
80+
81+
$url = "$scheme://$host:$port";
82+
$this->tools->nl();
83+
$this->tools->writeSuccess("PHP server started, serving at $url. Press CTRL+C to stop the server.");
84+
$this->tools->nl();
85+
86+
if (passthru("php -S $host:$port") !== null) {
87+
$this->tools->writeError("Failed to start PHP server.");
88+
return static::FAILURE;
89+
}
3690

3791
return static::SUCCESS;
3892
}
39-
}
93+
}

0 commit comments

Comments
 (0)