From 888ff46d2683c05fb4a854f691c7cdfc2671fc12 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Sat, 27 Dec 2025 08:58:50 -0700 Subject: [PATCH] Fixed route and controller commands to accept old configs --- flight/commands/ControllerCommand.php | 21 +++++++---- flight/commands/RouteCommand.php | 19 ++++++---- flight/net/Request.php | 8 ++--- tests/UploadedFileTest.php | 4 +-- .../AiGenerateInstructionsCommandTest.php | 36 ++++++++++++------- tests/commands/ControllerCommandTest.php | 10 +++--- tests/commands/RouteCommandTest.php | 13 ++++--- 7 files changed, 71 insertions(+), 40 deletions(-) diff --git a/flight/commands/ControllerCommand.php b/flight/commands/ControllerCommand.php index 9706d97..a7c10bc 100644 --- a/flight/commands/ControllerCommand.php +++ b/flight/commands/ControllerCommand.php @@ -29,8 +29,16 @@ class ControllerCommand extends AbstractBaseCommand public function execute(string $controller) { $io = $this->app()->io(); - if (isset($this->config['app_root']) === false) { - $io->error('app_root not set in .runway-config.json', true); + + if (empty($this->config['runway'])) { + $io->warn('Using a .runway-config.json file is deprecated. Move your config values to app/config/config.php with `php runway config:migrate`.', true); // @codeCoverageIgnore + $runwayConfig = json_decode(file_get_contents($this->projectRoot . '/.runway-config.json'), true); // @codeCoverageIgnore + } else { + $runwayConfig = $this->config['runway']; + } + + if (isset($runwayConfig['app_root']) === false) { + $io->error('app_root not set in app/config/config.php', true); return; } @@ -38,7 +46,7 @@ class ControllerCommand extends AbstractBaseCommand $controller .= 'Controller'; } - $controllerPath = getcwd() . DIRECTORY_SEPARATOR . $this->config['app_root'] . 'controllers' . DIRECTORY_SEPARATOR . $controller . '.php'; + $controllerPath = $this->projectRoot . '/' . $runwayConfig['app_root'] . 'controllers/' . $controller . '.php'; if (file_exists($controllerPath) === true) { $io->error($controller . ' already exists.', true); return; @@ -70,7 +78,7 @@ class ControllerCommand extends AbstractBaseCommand $namespace->add($class); $file->addNamespace($namespace); - $this->persistClass($controller, $file); + $this->persistClass($controller, $file, $runwayConfig['app_root']); $io->ok('Controller successfully created at ' . $controllerPath, true); } @@ -80,12 +88,13 @@ class ControllerCommand extends AbstractBaseCommand * * @param string $controllerName Name of the Controller * @param PhpFile $file Class Object from Nette\PhpGenerator + * @param string $appRoot App Root from runway config * * @return void */ - protected function persistClass(string $controllerName, PhpFile $file) + protected function persistClass(string $controllerName, PhpFile $file, string $appRoot) { $printer = new \Nette\PhpGenerator\PsrPrinter(); - file_put_contents(getcwd() . DIRECTORY_SEPARATOR . $this->config['app_root'] . 'controllers' . DIRECTORY_SEPARATOR . $controllerName . '.php', $printer->printFile($file)); + file_put_contents($this->projectRoot . '/' . $appRoot . 'controllers/' . $controllerName . '.php', $printer->printFile($file)); } } diff --git a/flight/commands/RouteCommand.php b/flight/commands/RouteCommand.php index bbcf52e..d742708 100644 --- a/flight/commands/RouteCommand.php +++ b/flight/commands/RouteCommand.php @@ -41,16 +41,21 @@ class RouteCommand extends AbstractBaseCommand { $io = $this->app()->io(); - if (isset($this->config['index_root']) === false) { - $io->error('index_root not set in .runway-config.json', true); + if (empty($this->config['runway'])) { + $io->warn('Using a .runway-config.json file is deprecated. Move your config values to app/config/config.php with `php runway config:migrate`.', true); // @codeCoverageIgnore + $runwayConfig = json_decode(file_get_contents($this->projectRoot . '/.runway-config.json'), true); // @codeCoverageIgnore + } else { + $runwayConfig = $this->config['runway']; + } + + if (isset($runwayConfig['index_root']) === false) { + $io->error('index_root not set in app/config/config.php', true); return; } $io->bold('Routes', true); - $cwd = getcwd(); - - $index_root = $cwd . '/' . $this->config['index_root']; + $index_root = $this->projectRoot . '/' . $runwayConfig['index_root']; // This makes it so the framework doesn't actually execute Flight::map('start', function () { @@ -72,8 +77,8 @@ class RouteCommand extends AbstractBaseCommand } return preg_match("/^class@anonymous/", end($middleware_class_name)) ? 'Anonymous' : end($middleware_class_name); }, $route->middleware); - } catch (\TypeError $e) { - $middlewares[] = 'Bad Middleware'; + } catch (\TypeError $e) { // @codeCoverageIgnore + $middlewares[] = 'Bad Middleware'; // @codeCoverageIgnore } finally { if (is_string($route->middleware) === true) { $middlewares[] = $route->middleware; diff --git a/flight/net/Request.php b/flight/net/Request.php index 18d1692..6e9aa93 100644 --- a/flight/net/Request.php +++ b/flight/net/Request.php @@ -174,7 +174,7 @@ class Request } $base = dirname($base); if ($base === '\\') { - $base = '/'; + $base = '/'; // @codeCoverageIgnore } $config = [ 'url' => $url, @@ -243,8 +243,8 @@ class Request $this->data->setData($data); } } - // Check PUT, PATCH, DELETE for application/x-www-form-urlencoded data or multipart/form-data - } elseif (in_array($this->method, [ 'PUT', 'DELETE', 'PATCH' ], true) === true) { + // Check PUT, PATCH, DELETE for application/x-www-form-urlencoded data or multipart/form-data + } elseif (in_array($this->method, ['PUT', 'DELETE', 'PATCH'], true) === true) { $this->parseRequestBodyForHttpMethods(); } @@ -478,7 +478,7 @@ class Request /** * Retrieves the array of uploaded files. * - * @return array> Key is field name; value is either a single UploadedFile or an array of UploadedFile when multiple were uploaded. + * @return array> Key is field name; value is either a single UploadedFile or an array of UploadedFile when multiple were uploaded. */ public function getUploadedFiles(): array { diff --git a/tests/UploadedFileTest.php b/tests/UploadedFileTest.php index f64e155..9a531f5 100644 --- a/tests/UploadedFileTest.php +++ b/tests/UploadedFileTest.php @@ -25,8 +25,8 @@ class UploadedFileTest extends TestCase unlink('real_file'); } - // not found with file_exists...just delete it brute force - @unlink('tmp_symlink'); + // not found with file_exists...just delete it brute force + @unlink('tmp_symlink'); } public function testMoveToFalseSuccess(): void diff --git a/tests/commands/AiGenerateInstructionsCommandTest.php b/tests/commands/AiGenerateInstructionsCommandTest.php index 8e53444..c874a4b 100644 --- a/tests/commands/AiGenerateInstructionsCommandTest.php +++ b/tests/commands/AiGenerateInstructionsCommandTest.php @@ -9,12 +9,14 @@ use flight\commands\AiGenerateInstructionsCommand; use PHPUnit\Framework\TestCase; use tests\classes\NoExitInteractor; -class AiGenerateInstructionsCommandTest extends TestCase { +class AiGenerateInstructionsCommandTest extends TestCase +{ protected static $in; protected static $ou; protected $baseDir; - public function setUp(): void { + public function setUp(): void + { self::$in = __DIR__ . DIRECTORY_SEPARATOR . 'input.test' . uniqid('', true) . '.txt'; self::$ou = __DIR__ . DIRECTORY_SEPARATOR . 'output.test' . uniqid('', true) . '.txt'; file_put_contents(self::$in, ''); @@ -25,7 +27,8 @@ class AiGenerateInstructionsCommandTest extends TestCase { } } - public function tearDown(): void { + public function tearDown(): void + { if (file_exists(self::$in)) { unlink(self::$in); } @@ -35,7 +38,8 @@ class AiGenerateInstructionsCommandTest extends TestCase { $this->recursiveRmdir($this->baseDir); } - protected function recursiveRmdir($dir) { + protected function recursiveRmdir($dir) + { if (!is_dir($dir)) { return; } @@ -46,7 +50,8 @@ class AiGenerateInstructionsCommandTest extends TestCase { return rmdir($dir); } - protected function newApp($command): Application { + protected function newApp($command): Application + { $app = new Application('test', '0.0.1', function ($exitCode) { return $exitCode; }); @@ -55,11 +60,13 @@ class AiGenerateInstructionsCommandTest extends TestCase { return $app; } - protected function setInput(array $lines): void { + protected function setInput(array $lines): void + { file_put_contents(self::$in, implode("\n", $lines) . "\n"); } - protected function setProjectRoot($command, $path) { + protected function setProjectRoot($command, $path) + { $reflection = new \ReflectionClass(get_class($command)); $property = null; $currentClass = $reflection; @@ -79,7 +86,8 @@ class AiGenerateInstructionsCommandTest extends TestCase { } } - public function testFailsIfAiConfigMissing() { + public function testFailsIfAiConfigMissing() + { $this->setInput([ 'desc', 'none', @@ -107,7 +115,8 @@ class AiGenerateInstructionsCommandTest extends TestCase { $this->assertStringContainsString('Missing AI configuration', file_get_contents(self::$ou)); } - public function testWritesInstructionsToFiles() { + public function testWritesInstructionsToFiles() + { $creds = [ 'api_key' => 'key', 'model' => 'gpt-4o', @@ -154,7 +163,8 @@ class AiGenerateInstructionsCommandTest extends TestCase { $this->assertFileExists($this->baseDir . '.windsurfrules'); } - public function testNoInstructionsReturnedFromLlm() { + public function testNoInstructionsReturnedFromLlm() + { $creds = [ 'api_key' => 'key', 'model' => 'gpt-4o', @@ -196,7 +206,8 @@ class AiGenerateInstructionsCommandTest extends TestCase { $this->assertSame(1, $result); } - public function testLlmApiCallFails() { + public function testLlmApiCallFails() + { $creds = [ 'api_key' => 'key', 'model' => 'gpt-4o', @@ -234,7 +245,8 @@ class AiGenerateInstructionsCommandTest extends TestCase { $this->assertSame(1, $result); } - public function testUsesDeprecatedConfigFile() { + public function testUsesDeprecatedConfigFile() + { $creds = [ 'ai' => [ 'api_key' => 'key', diff --git a/tests/commands/ControllerCommandTest.php b/tests/commands/ControllerCommandTest.php index 510aaa2..c19b312 100644 --- a/tests/commands/ControllerCommandTest.php +++ b/tests/commands/ControllerCommandTest.php @@ -48,7 +48,7 @@ class ControllerCommandTest extends TestCase protected function newApp(string $name, string $version = '') { - $app = @new Application($name, $version ?: '0.0.1', fn () => false); + $app = @new Application($name, $version ?: '0.0.1', fn() => false); return @$app->io(new Interactor(static::$in, static::$ou)); } @@ -56,10 +56,10 @@ class ControllerCommandTest extends TestCase public function testConfigAppRootNotSet(): void { $app = $this->newApp('test', '0.0.1'); - $app->add(new ControllerCommand([])); + $app->add(new ControllerCommand(['runway' => ['something' => '']])); @$app->handle(['runway', 'make:controller', 'Test']); - $this->assertStringContainsString('app_root not set in .runway-config.json', file_get_contents(static::$ou)); + $this->assertStringContainsString('app_root not set in app/config/config.php', file_get_contents(static::$ou)); } public function testControllerAlreadyExists(): void @@ -67,7 +67,7 @@ class ControllerCommandTest extends TestCase $app = $this->newApp('test', '0.0.1'); mkdir(__DIR__ . '/controllers/'); file_put_contents(__DIR__ . '/controllers/TestController.php', 'add(new ControllerCommand(['app_root' => 'tests/commands/'])); + $app->add(new ControllerCommand(['runway' => ['app_root' => 'tests/commands/']])); $app->handle(['runway', 'make:controller', 'Test']); $this->assertStringContainsString('TestController already exists.', file_get_contents(static::$ou)); @@ -76,7 +76,7 @@ class ControllerCommandTest extends TestCase public function testCreateController(): void { $app = $this->newApp('test', '0.0.1'); - $app->add(new ControllerCommand(['app_root' => 'tests/commands/'])); + $app->add(new ControllerCommand(['runway' => ['app_root' => 'tests/commands/']])); $app->handle(['runway', 'make:controller', 'Test']); $this->assertFileExists(__DIR__ . '/controllers/TestController.php'); diff --git a/tests/commands/RouteCommandTest.php b/tests/commands/RouteCommandTest.php index 0d2aee7..11e39ce 100644 --- a/tests/commands/RouteCommandTest.php +++ b/tests/commands/RouteCommandTest.php @@ -23,6 +23,7 @@ class RouteCommandTest extends TestCase static::$ou = __DIR__ . DIRECTORY_SEPARATOR . 'output.test' . uniqid('', true) . '.txt'; file_put_contents(static::$in, ''); file_put_contents(static::$ou, ''); + $_SERVER = []; $_REQUEST = []; Flight::init(); @@ -91,21 +92,22 @@ PHP; public function testConfigIndexRootNotSet(): void { $app = @$this->newApp('test', '0.0.1'); - $app->add(new RouteCommand([])); + $app->add(new RouteCommand(['runway' => ['something' => 'else']])); @$app->handle(['runway', 'routes']); - $this->assertStringContainsString('index_root not set in .runway-config.json', file_get_contents(static::$ou)); + $this->assertStringContainsString('index_root not set in app/config/config.php', file_get_contents(static::$ou)); } public function testGetRoutes(): void { $app = @$this->newApp('test', '0.0.1'); $this->createIndexFile(); - $app->add(new RouteCommand(['index_root' => 'tests/commands/index.php'])); + $app->add(new RouteCommand(['runway' => ['index_root' => 'tests/commands/index.php']])); @$app->handle(['runway', 'routes']); $this->assertStringContainsString('Routes', file_get_contents(static::$ou)); $expected = <<<'output' + Routes +---------+--------------------+-------+----------+----------------+ | Pattern | Methods | Alias | Streamed | Middleware | +---------+--------------------+-------+----------+----------------+ @@ -127,12 +129,13 @@ PHP; { $app = @$this->newApp('test', '0.0.1'); $this->createIndexFile(); - $app->add(new RouteCommand(['index_root' => 'tests/commands/index.php'])); + $app->add(new RouteCommand(['runway' => ['index_root' => 'tests/commands/index.php']])); @$app->handle(['runway', 'routes', '--post']); $this->assertStringContainsString('Routes', file_get_contents(static::$ou)); $expected = <<<'output' + Routes +---------+---------------+-------+----------+------------+ | Pattern | Methods | Alias | Streamed | Middleware | +---------+---------------+-------+----------+------------+ @@ -140,6 +143,8 @@ PHP; +---------+---------------+-------+----------+------------+ output; // phpcs:ignore + $expected = str_replace(["\r\n", "\\n", "\n"], ["\n", "", "\n"], $expected); + $this->assertStringContainsString( $expected, $this->removeColors(file_get_contents(static::$ou))