From b0583e4bbaf4f03c45f4135d56b349d558d7b823 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 19 Jul 2022 21:15:48 +0300 Subject: [PATCH] Fix #142, fix #157: Add config for `serve` command --- CHANGELOG.md | 2 +- README.md | 26 ++++++++++++++++++++++++++ config/console.php | 9 +++++++++ config/params.php | 9 +++++++++ psalm.xml | 3 +++ src/Command/Serve.php | 36 ++++++++++++++++++++++++++---------- tests/ServeCommandTest.php | 37 +++++++++++++++++++++++++++++++++++++ 7 files changed, 111 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0b70681..844b1421 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 1.1.2 under development -- no changes in this release. +- Enh #157: Add config for `serve` command (@dood-) ## 1.1.1 July 04, 2022 diff --git a/README.md b/README.md index 0c9022ee..b3a08e74 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,32 @@ The command can be marked as hidden by prefixing its name with `|`. ], ``` +### Runs PHP built-in web server + +You can start local built-in web development server using the command: +``` +./yii serve +``` +Your application will be accessible in your web browser at http://localhost:8080 by default. +To configure default settings, set the options in `\Yiisoft\Yii\Console\CommandLoader` configuration. + +```php +'yiisoft/yii-console' => [ + 'serve' => [ + 'appRootPath' => null, + 'options' => [ + 'address' => '127.0.0.1', + 'port' => '8080', + 'docroot' => 'public', + 'router' => 'public/index.php', + ], + ], +], +``` + +Alternatively, you can pass the settings through the console options. To see the available options, run +`./yii serve --help` + ## Testing ### Unit testing diff --git a/config/console.php b/config/console.php index a178618a..336678ae 100644 --- a/config/console.php +++ b/config/console.php @@ -6,6 +6,7 @@ use Symfony\Component\Console\Input\InputOption; use Yiisoft\Definitions\Reference; use Yiisoft\Yii\Console\Application; +use Yiisoft\Yii\Console\Command\Serve; use Yiisoft\Yii\Console\CommandLoader; use Yiisoft\Yii\Console\SymfonyEventDispatcher; @@ -19,6 +20,14 @@ ], ], + Serve::class => [ + 'class' => Serve::class, + '__construct()' => [ + 'appRootPath' => $params['yiisoft/yii-console']['serve']['appRootPath'], + 'options' => $params['yiisoft/yii-console']['serve']['options'], + ], + ], + Application::class => [ '__construct()' => [ $params['yiisoft/yii-console']['name'], diff --git a/config/params.php b/config/params.php index c2a830d5..dadd7645 100644 --- a/config/params.php +++ b/config/params.php @@ -13,5 +13,14 @@ 'commands' => [ 'serve' => Serve::class, ], + 'serve' => [ + 'appRootPath' => null, + 'options' => [ + 'address' => '127.0.0.1', + 'port' => '8080', + 'docroot' => 'public', + 'router' => 'public/index.php', + ], + ], ], ]; diff --git a/psalm.xml b/psalm.xml index 5a95a3aa..3f815b4d 100644 --- a/psalm.xml +++ b/psalm.xml @@ -7,5 +7,8 @@ > + + + diff --git a/src/Command/Serve.php b/src/Command/Serve.php index 23dcc128..fa9e0a79 100644 --- a/src/Command/Serve.php +++ b/src/Command/Serve.php @@ -27,15 +27,31 @@ final class Serve extends Command public const EXIT_CODE_NO_ROUTING_FILE = 3; public const EXIT_CODE_ADDRESS_TAKEN_BY_ANOTHER_PROCESS = 5; - private const DEFAULT_PORT = '8080'; - private const DEFAULT_DOCROOT = 'public'; - private const DEFAULT_ROUTER = 'public/index.php'; + private string $defaultAddress; + private string $defaultPort; + private string $defaultDocroot; + private string $defaultRouter; protected static $defaultName = 'serve'; protected static $defaultDescription = 'Runs PHP built-in web server'; - public function __construct(private ?string $appRootPath = null) + /** + * @param string|null $appRootPath + * @param array|null $options + * @psalm-param array{ + * address?:non-empty-string, + * port?:non-empty-string, + * docroot?:string, + * router?:string + * } $options + */ + public function __construct(private ?string $appRootPath = null, ?array $options = []) { + $this->defaultAddress = $options['address'] ?? '127.0.0.1'; + $this->defaultPort = $options['port'] ?? '8080'; + $this->defaultDocroot = $options['docroot'] ?? 'public'; + $this->defaultRouter = $options['router'] ?? 'public/index.php'; + parent::__construct(); } @@ -43,10 +59,10 @@ public function configure(): void { $this ->setHelp('In order to access server from remote machines use 0.0.0.0:8000. That is especially useful when running server in a virtual machine.') - ->addArgument('address', InputArgument::OPTIONAL, 'Host to serve at', '127.0.0.1') - ->addOption('port', 'p', InputOption::VALUE_OPTIONAL, 'Port to serve at', self::DEFAULT_PORT) - ->addOption('docroot', 't', InputOption::VALUE_OPTIONAL, 'Document root to serve from', self::DEFAULT_DOCROOT) - ->addOption('router', 'r', InputOption::VALUE_OPTIONAL, 'Path to router script', self::DEFAULT_ROUTER) + ->addArgument('address', InputArgument::OPTIONAL, 'Host to serve at', $this->defaultAddress) + ->addOption('port', 'p', InputOption::VALUE_OPTIONAL, 'Port to serve at', $this->defaultPort) + ->addOption('docroot', 't', InputOption::VALUE_OPTIONAL, 'Document root to serve from', $this->defaultDocroot) + ->addOption('router', 'r', InputOption::VALUE_OPTIONAL, 'Path to router script', $this->defaultRouter) ->addOption('env', 'e', InputOption::VALUE_OPTIONAL, 'It is only used for testing.'); } @@ -74,8 +90,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int /** @var string $docroot */ $docroot = $input->getOption('docroot'); - if ($router === self::DEFAULT_ROUTER && !file_exists(self::DEFAULT_ROUTER)) { - $io->warning('Default router "' . self::DEFAULT_ROUTER . '" does not exist. Serving without router. URLs with dots may fail.'); + if ($router === $this->defaultRouter && !file_exists($this->defaultRouter)) { + $io->warning('Default router "' . $this->defaultRouter . '" does not exist. Serving without router. URLs with dots may fail.'); $router = null; } diff --git a/tests/ServeCommandTest.php b/tests/ServeCommandTest.php index 216b4482..9cfa4733 100644 --- a/tests/ServeCommandTest.php +++ b/tests/ServeCommandTest.php @@ -71,6 +71,43 @@ public function testServeCommandExecuteWithDocRoot(): void ); } + public function testServeCommandExecuteWithConfig(): void + { + $command = new Serve(null, [ + 'address' => '127.0.0.2', + 'port' => '8081', + 'docroot' => 'tests', + 'router' => 'public/index.php', + ]); + + $commandCreate = new CommandTester($command); + + $commandCreate->setInputs(['yes']); + + $commandCreate->execute([ + '--env' => 'test', + ]); + + $output = $commandCreate->getDisplay(true); + + $this->assertSame(ExitCode::OK, $commandCreate->getStatusCode()); + + $this->assertStringContainsString( + 'Server started on http://127.0.0.2:8081/', + $output + ); + + $this->assertStringContainsString( + 'Document root is', + $output + ); + + $this->assertStringContainsString( + 'Quit the server with CTRL-C or COMMAND-C.', + $output + ); + } + public function testErrorWhenAddressIsTaken(): void { $command = $this