22
33use Symfony \Component \Console \Input \InputInterface ;
44use Symfony \Component \Console \Output \OutputInterface ;
5+ use Symfony \Component \Console \Input \InputOption ;
6+ use Symfony \Component \Console \Question \Question ;
7+
58use 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