Skip to content

Commit

Permalink
feat(cmd-serve): improving the flexibility of the serve command wit…
Browse files Browse the repository at this point in the history
…h 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
  • Loading branch information
flydev-fr committed Jul 20, 2023
1 parent 15f5522 commit 814bd79
Showing 1 changed file with 58 additions and 4 deletions.
62 changes: 58 additions & 4 deletions src/Commands/Common/ServeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Question\Question;

use Wirecli\Helpers\PwConnector;
use Wirecli\Helpers\WsTools as Tools;

/**
* Class ServeCommand
Expand All @@ -21,7 +25,10 @@ class ServeCommand extends PwConnector {
protected function configure() {
$this
->setName('serve')
->setDescription('Serve ProcessWire via built in PHP webserver');
->setDescription('Serve ProcessWire via built in PHP webserver')
->addOption('scheme', null, InputOption::VALUE_OPTIONAL, 'Scheme to serve on', 'http')
->addOption('host', null, InputOption::VALUE_OPTIONAL, 'Host to serve on', 'localhost')
->addOption('port', null, InputOption::VALUE_OPTIONAL, 'Port to serve on', '8080');
}

/**
Expand All @@ -31,9 +38,56 @@ protected function configure() {
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$this->checkForProcessWire($output);
$output->writeln("Starting PHP server at localhost:8000");
passthru("php -S localhost:8000");

$scheme = $input->getOption('scheme');
$host = $input->getOption('host');
$port = $input->getOption('port');
$url = "$scheme://$host:$port";
$this->tools->writeComment("Starting PHP server at $url ...");
$this->helper = $this->getHelper('question');

$port = (int)$port;
$pf = @fsockopen($host, $port); // Try to open a socket
if (is_resource($pf)) {
fclose($pf); // Close the previous socket
do {
$this->tools->writeError("Port $port is already in use.");
$this->tools->nl();

$port++; // Increment the port number and try again

$question = new Question($this->tools->getQuestion("Trying another one", (int)$port), $port);
$question->setValidator(function ($answer) {
if ($answer && !filter_var($answer, FILTER_VALIDATE_INT)) {
throw new \RuntimeException('Please enter a valid port number.');
}
return $answer;
});

$newPort = $this->helper->ask($input, $output, $question); // Ask for a new port number
if (is_resource($pf)) { // If the previous socket is still open, close it
fclose($pf);
}
$pf = @fsockopen($host, (int)$newPort);
}
while($pf !== false);

if (is_resource($pf)) { // If the previous socket is still open, close it
fclose($pf);
}
$port = $newPort;
}

$url = "$scheme://$host:$port";
$this->tools->nl();
$this->tools->writeSuccess("PHP server started, serving at $url. Press CTRL+C to stop the server.");
$this->tools->nl();

if (passthru("php -S $host:$port") !== null) {
$this->tools->writeError("Failed to start PHP server.");
return static::FAILURE;
}

return static::SUCCESS;
}
}
}

0 comments on commit 814bd79

Please sign in to comment.