fix almost long lines phpcs warnings

pull/685/head
fadrian06 18 hours ago
parent ee00e5adbe
commit b55540068e

@ -267,7 +267,8 @@ class Engine
/** /**
* Registers the container handler * Registers the container handler
* *
* @param ContainerInterface|callable(class-string<T> $id, array<int|string, mixed> $params): ?T $containerHandler Callback function or PSR-11 Container object that sets the container and how it will inject classes * @param ContainerInterface|callable(class-string<T> $id, array<int|string, mixed> $params): ?T $containerHandler
* Callback function or PSR-11 Container object that sets the container and how it will inject classes
* *
* @template T of object * @template T of object
*/ */
@ -488,7 +489,14 @@ class Engine
// Which loosely translates to $class->$method($params) // Which loosely translates to $class->$method($params)
$start = microtime(true); $start = microtime(true);
$middlewareResult = $middlewareObject($params); $middlewareResult = $middlewareObject($params);
$this->triggerEvent('flight.middleware.executed', $route, $middleware, $eventName, microtime(true) - $start);
$this->triggerEvent(
'flight.middleware.executed',
$route,
$middleware,
$eventName,
microtime(true) - $start
);
if ($useV3OutputBuffering === true) { if ($useV3OutputBuffering === true) {
$this->response()->write(ob_get_clean()); $this->response()->write(ob_get_clean());
@ -860,7 +868,12 @@ class Engine
public function _methodNotFound(Route $route): void public function _methodNotFound(Route $route): void
{ {
$this->response()->setHeader('Allow', implode(', ', $route->methods)); $this->response()->setHeader('Allow', implode(', ', $route->methods));
$this->halt(405, 'Method Not Allowed. Allowed Methods are: ' . implode(', ', $route->methods), empty(getenv('PHPUNIT_TEST')));
$this->halt(
405,
'Method Not Allowed. Allowed Methods are: ' . implode(', ', $route->methods),
empty(getenv('PHPUNIT_TEST'))
);
} }
/** /**

@ -80,7 +80,8 @@ require_once __DIR__ . '/autoload.php';
* @phpstan-method static void jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0) * @phpstan-method static void jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0)
* @phpstan-method static void jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = "utf8", int $encodeOption = 0, int $encodeDepth = 512) * @phpstan-method static void jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = "utf8", int $encodeOption = 0, int $encodeDepth = 512)
* *
* Note: IDEs will use standard @method tags for autocompletion, while PHPStan will use @phpstan-* tags for advanced type checking. * Note: IDEs will use standard @method tags for autocompletion,
* while PHPStan will use @phpstan-* tags for advanced type checking.
*/ */
class Flight class Flight
{ {

@ -20,7 +20,13 @@ class AiGenerateInstructionsCommand extends AbstractBaseCommand
public function __construct(array $config) public function __construct(array $config)
{ {
parent::__construct('ai:generate-instructions', 'Generate project-specific AI coding instructions', $config); parent::__construct('ai:generate-instructions', 'Generate project-specific AI coding instructions', $config);
$this->option('--config-file', 'Path to .runway-config.json file (deprecated, use config.php instead)', null, '');
$this->option(
'--config-file',
'Path to .runway-config.json file (deprecated, use config.php instead)',
null,
''
);
} }
/** /**
@ -40,7 +46,12 @@ class AiGenerateInstructionsCommand extends AbstractBaseCommand
if (empty($this->config['runway'])) { if (empty($this->config['runway'])) {
$configFile = $this->configFile; $configFile = $this->configFile;
$io = $this->app()->io(); $io = $this->app()->io();
$io->warn('The --config-file option is deprecated. Move your config values to the \'runway\' key in the config.php file for configuration.', true);
$io->warn(
'The --config-file option is deprecated. '
. 'Move your config values to the \'runway\' key in the config.php file for configuration.',
true
);
$runwayConfig = json_decode(file_get_contents($configFile), true) ?? []; $runwayConfig = json_decode(file_get_contents($configFile), true) ?? [];
} else { } else {
$runwayConfig = $this->config['runway']; $runwayConfig = $this->config['runway'];
@ -56,12 +67,30 @@ class AiGenerateInstructionsCommand extends AbstractBaseCommand
// Ask questions // Ask questions
$projectDesc = $io->prompt('Please describe what your project is for?'); $projectDesc = $io->prompt('Please describe what your project is for?');
$database = $io->prompt('What database are you planning on using? (e.g. MySQL, SQLite, PostgreSQL, none)', 'none');
$templating = $io->prompt('What HTML templating engine will you plan on using (if any)? (recommend latte)', 'latte'); $database = $io->prompt(
'What database are you planning on using? (e.g. MySQL, SQLite, PostgreSQL, none)',
'none'
);
$templating = $io->prompt(
'What HTML templating engine will you plan on using (if any)? (recommend latte)',
'latte'
);
$security = $io->confirm('Is security an important element of this project?', 'y'); $security = $io->confirm('Is security an important element of this project?', 'y');
$performance = $io->confirm('Is performance and speed an important part of this project?', 'y'); $performance = $io->confirm('Is performance and speed an important part of this project?', 'y');
$composerLibs = $io->prompt('What major composer libraries will you be using if you know them right now?', 'none');
$envSetup = $io->prompt('How will you set up your development environment? (e.g. Docker, Vagrant, PHP dev server, other)', 'Docker'); $composerLibs = $io->prompt(
'What major composer libraries will you be using if you know them right now?',
'none'
);
$envSetup = $io->prompt(
'How will you set up your development environment? (e.g. Docker, Vagrant, PHP dev server, other)',
'Docker'
);
$teamSize = $io->prompt('How many developers will be working on this project?', '1'); $teamSize = $io->prompt('How many developers will be working on this project?', '1');
$api = $io->confirm('Will this project expose an API?', 'n'); $api = $io->confirm('Will this project expose an API?', 'n');
$other = $io->prompt('Any other important requirements or context? (optional)', 'no'); $other = $io->prompt('Any other important requirements or context? (optional)', 'no');
@ -107,7 +136,13 @@ class AiGenerateInstructionsCommand extends AbstractBaseCommand
$data = [ $data = [
'model' => $model, 'model' => $model,
'messages' => [ 'messages' => [
['role' => 'system', 'content' => 'You are a helpful AI coding assistant focused on the Flight Framework for PHP. You are up to date with all your knowledge from https://docs.flightphp.com. As an expert into the programming language PHP, you are top notch at architecting out proper instructions for FlightPHP projects.'], [
'role' => 'system',
'content' => 'You are a helpful AI coding assistant focused on the Flight Framework for PHP. '
. 'You are up to date with all your knowledge from https://docs.flightphp.com. '
. 'As an expert into the programming language PHP, '
. 'you are top notch at architecting out proper instructions for FlightPHP projects.'
],
['role' => 'user', 'content' => $prompt], ['role' => 'user', 'content' => $prompt],
], ],
'temperature' => 0.2, 'temperature' => 0.2,
@ -129,7 +164,11 @@ class AiGenerateInstructionsCommand extends AbstractBaseCommand
} }
// Write to files // Write to files
$io->info('Updating .github/copilot-instructions.md, .cursor/rules/project-overview.mdc, .gemini/GEMINI.md and .windsurfrules...', true); $io->info(
'Updating .github/copilot-instructions.md, .cursor/rules/project-overview.mdc, .gemini/GEMINI.md and .windsurfrules...',
true
);
if (!is_dir($this->projectRoot . '.github')) { if (!is_dir($this->projectRoot . '.github')) {
mkdir($this->projectRoot . '.github', 0755, true); mkdir($this->projectRoot . '.github', 0755, true);
} }

@ -79,7 +79,11 @@ class AiInitCommand extends AbstractBaseCommand
$defaultModel = 'claude-sonnet-4-5'; $defaultModel = 'claude-sonnet-4-5';
break; break;
} }
$model = trim($io->prompt('Enter the model name you want to use (e.g. gpt-5, claude-sonnet-4-5, etc)', $defaultModel));
$model = trim($io->prompt(
'Enter the model name you want to use (e.g. gpt-5, claude-sonnet-4-5, etc)',
$defaultModel
));
$runwayAiConfig = [ $runwayAiConfig = [
'provider' => $api, 'provider' => $api,

@ -31,8 +31,16 @@ class ControllerCommand extends AbstractBaseCommand
$io = $this->app()->io(); $io = $this->app()->io();
if (empty($this->config['runway'])) { 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 $io->warn(
$runwayConfig = json_decode(file_get_contents($this->projectRoot . '/.runway-config.json'), true); // @codeCoverageIgnore '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 { } else {
$runwayConfig = $this->config['runway']; $runwayConfig = $this->config['runway'];
} }
@ -95,6 +103,9 @@ class ControllerCommand extends AbstractBaseCommand
protected function persistClass(string $controllerName, PhpFile $file, string $appRoot) protected function persistClass(string $controllerName, PhpFile $file, string $appRoot)
{ {
$printer = new \Nette\PhpGenerator\PsrPrinter(); $printer = new \Nette\PhpGenerator\PsrPrinter();
file_put_contents($this->projectRoot . '/' . $appRoot . 'controllers/' . $controllerName . '.php', $printer->printFile($file)); file_put_contents(
$this->projectRoot . '/' . $appRoot . 'controllers/' . $controllerName . '.php',
$printer->printFile($file)
);
} }
} }

@ -58,7 +58,8 @@ class Dispatcher
* *
* @template T of object * @template T of object
* *
* @throws InvalidArgumentException If $containerHandler is not a `callable` or instance of `Psr\Container\ContainerInterface`. * @throws InvalidArgumentException
* If $containerHandler is not a `callable` or instance of `Psr\Container\ContainerInterface`.
*/ */
public function setContainerHandler($containerHandler): void public function setContainerHandler($containerHandler): void
{ {
@ -413,7 +414,10 @@ class Dispatcher
// Final check to make sure it's actually a class and a method, or throw an error // Final check to make sure it's actually a class and a method, or throw an error
if (is_object($class) === false && class_exists($class) === false) { if (is_object($class) === false && class_exists($class) === false) {
$exception = new Exception("Class '$class' not found. Is it being correctly autoloaded with Flight::path()?"); $exception = new Exception(
"Class '$class' not found. "
. "Is it being correctly autoloaded with Flight::path()?"
);
// If this tried to resolve a class in a container and failed somehow, throw the exception // If this tried to resolve a class in a container and failed somehow, throw the exception
} elseif (!$resolvedClass && $this->containerException !== null) { } elseif (!$resolvedClass && $this->containerException !== null) {

@ -439,7 +439,13 @@ class Request
*/ */
public static function getScheme(): string public static function getScheme(): string
{ {
if ((strtolower(self::getVar('HTTPS')) === 'on') || (self::getVar('HTTP_X_FORWARDED_PROTO') === 'https') || (self::getVar('HTTP_FRONT_END_HTTPS') === 'on') || (self::getVar('REQUEST_SCHEME') === 'https')) { if (strtolower(self::getVar('HTTPS')) === 'on') {
return 'https';
} elseif (self::getVar('HTTP_X_FORWARDED_PROTO') === 'https') {
return 'https';
} elseif (self::getVar('HTTP_FRONT_END_HTTPS') === 'on') {
return 'https';
} elseif (self::getVar('REQUEST_SCHEME') === 'https') {
return 'https'; return 'https';
} }
@ -470,7 +476,8 @@ class Request
/** /**
* Retrieves the array of uploaded files. * Retrieves the array of uploaded files.
* *
* @return array<string, UploadedFile|array<int, UploadedFile>> Key is field name; value is either a single UploadedFile or an array of UploadedFile when multiple were uploaded. * @return array<string, UploadedFile|array<int, UploadedFile>>
* Key is field name; value is either a single UploadedFile or an array of UploadedFile when multiple were uploaded.
*/ */
public function getUploadedFiles(): array public function getUploadedFiles(): array
{ {

@ -484,7 +484,8 @@ class Response
* Downloads a file. * Downloads a file.
* *
* @param string $filePath The path to the file to be downloaded. * @param string $filePath The path to the file to be downloaded.
* @param string $fileName The name the downloaded file should have. If not provided or is an empty string, the name of the file on disk will be used. * @param string $fileName The name the downloaded file should have.
* If not provided or is an empty string, the name of the file on disk will be used.
* *
* @throws Exception If the file cannot be found. * @throws Exception If the file cannot be found.
* *

@ -48,8 +48,14 @@ class UploadedFile
* @param int $error The error code associated with the uploaded file. * @param int $error The error code associated with the uploaded file.
* @param bool|null $isPostUploadedFile Indicates if the file was uploaded via POST method. * @param bool|null $isPostUploadedFile Indicates if the file was uploaded via POST method.
*/ */
public function __construct(string $name, string $mimeType, int $size, string $tmpName, int $error, ?bool $isPostUploadedFile = null) public function __construct(
{ string $name,
string $mimeType,
int $size,
string $tmpName,
int $error,
?bool $isPostUploadedFile = null
) {
$this->name = $name; $this->name = $name;
$this->mimeType = $mimeType; $this->mimeType = $mimeType;
$this->size = $size; $this->size = $size;

@ -152,7 +152,11 @@ class DispatcherTest extends TestCase
public function testInvalidCallback(): void public function testInvalidCallback(): void
{ {
$this->expectException(Exception::class); $this->expectException(Exception::class);
$this->expectExceptionMessage("Class 'NonExistentClass' not found. Is it being correctly autoloaded with Flight::path()?");
$this->expectExceptionMessage(
"Class 'NonExistentClass' not found. "
. "Is it being correctly autoloaded with Flight::path()?"
);
$this->dispatcher->execute(['NonExistentClass', 'nonExistentMethod']); $this->dispatcher->execute(['NonExistentClass', 'nonExistentMethod']);
} }
@ -279,7 +283,12 @@ class DispatcherTest extends TestCase
public function testExecuteStringClassBadConstructParams(): void public function testExecuteStringClassBadConstructParams(): void
{ {
$this->expectException(ArgumentCountError::class); $this->expectException(ArgumentCountError::class);
$this->expectExceptionMessageMatches('#Too few arguments to function tests\\\\classes\\\\TesterClass::__construct\(\), 1 passed .+ and exactly 6 expected#');
$this->expectExceptionMessageMatches(
'#Too few arguments to function tests\\\\classes\\\\TesterClass::__construct\(\), 1 passed'
. ' .+ and exactly 6 expected#'
);
$this->dispatcher->execute(TesterClass::class . '->instanceMethod'); $this->dispatcher->execute(TesterClass::class . '->instanceMethod');
} }
@ -331,7 +340,11 @@ class DispatcherTest extends TestCase
public function testExecuteStringClassDefaultContainerButForgotInjectingEngine(): void public function testExecuteStringClassDefaultContainerButForgotInjectingEngine(): void
{ {
$this->expectException(TypeError::class); $this->expectException(TypeError::class);
$this->expectExceptionMessageMatches('#tests\\\\classes\\\\ContainerDefault::__construct\(\).+flight\\\\Engine, null given#');
$this->expectExceptionMessageMatches(
'#tests\\\\classes\\\\ContainerDefault::__construct\(\).+flight\\\\Engine, null given#'
);
$this->dispatcher->execute([ContainerDefault::class, 'testTheContainer']); $this->dispatcher->execute([ContainerDefault::class, 'testTheContainer']);
} }

@ -232,13 +232,19 @@ class EventSystemTest extends TestCase
*/ */
public function testHasListeners(): void public function testHasListeners(): void
{ {
$this->assertFalse(Flight::eventDispatcher()->hasListeners('test.event'), 'Event should not have listeners before registration'); $this->assertFalse(
Flight::eventDispatcher()->hasListeners('test.event'),
'Event should not have listeners before registration'
);
Flight::onEvent('test.event', function () { Flight::onEvent('test.event', function () {
// //
}); });
$this->assertTrue(Flight::eventDispatcher()->hasListeners('test.event'), 'Event should have listeners after registration'); $this->assertTrue(
Flight::eventDispatcher()->hasListeners('test.event'),
'Event should have listeners after registration'
);
} }
/** /**
@ -253,7 +259,10 @@ class EventSystemTest extends TestCase
// //
}; };
$this->assertEmpty(Flight::eventDispatcher()->getListeners('test.event'), 'Event should have no listeners before registration'); $this->assertEmpty(
Flight::eventDispatcher()->getListeners('test.event'),
'Event should have no listeners before registration'
);
Flight::onEvent('test.event', $callback1); Flight::onEvent('test.event', $callback1);
Flight::onEvent('test.event', $callback2); Flight::onEvent('test.event', $callback2);
@ -279,7 +288,10 @@ class EventSystemTest extends TestCase
*/ */
public function testGetAllRegisteredEvents(): void public function testGetAllRegisteredEvents(): void
{ {
$this->assertEmpty(Flight::eventDispatcher()->getAllRegisteredEvents(), 'No events should be registered initially'); $this->assertEmpty(
Flight::eventDispatcher()->getAllRegisteredEvents(),
'No events should be registered initially'
);
Flight::onEvent('test.event1', function () { Flight::onEvent('test.event1', function () {
// //
@ -309,7 +321,11 @@ class EventSystemTest extends TestCase
Flight::onEvent('test.event', $callback1); Flight::onEvent('test.event', $callback1);
Flight::onEvent('test.event', $callback2); Flight::onEvent('test.event', $callback2);
$this->assertCount(2, Flight::eventDispatcher()->getListeners('test.event'), 'Event should have two listeners initially'); $this->assertCount(
2,
Flight::eventDispatcher()->getListeners('test.event'),
'Event should have two listeners initially'
);
Flight::eventDispatcher()->removeListener('test.event', $callback1); Flight::eventDispatcher()->removeListener('test.event', $callback1);
@ -333,13 +349,27 @@ class EventSystemTest extends TestCase
// //
}); });
$this->assertTrue(Flight::eventDispatcher()->hasListeners('test.event'), 'Event should have listeners before removal'); $this->assertTrue(
$this->assertTrue(Flight::eventDispatcher()->hasListeners('another.event'), 'Another event should have listeners'); Flight::eventDispatcher()->hasListeners('test.event'),
'Event should have listeners before removal'
);
$this->assertTrue(
Flight::eventDispatcher()->hasListeners('another.event'),
'Another event should have listeners'
);
Flight::eventDispatcher()->removeAllListeners('test.event'); Flight::eventDispatcher()->removeAllListeners('test.event');
$this->assertFalse(Flight::eventDispatcher()->hasListeners('test.event'), 'Event should have no listeners after removal'); $this->assertFalse(
$this->assertTrue(Flight::eventDispatcher()->hasListeners('another.event'), 'Another event should still have listeners'); Flight::eventDispatcher()->hasListeners('test.event'),
'Event should have no listeners after removal'
);
$this->assertTrue(
Flight::eventDispatcher()->hasListeners('another.event'),
'Another event should still have listeners'
);
} }
/** /**
@ -353,6 +383,9 @@ class EventSystemTest extends TestCase
}); });
Flight::eventDispatcher()->removeAllListeners('nonexistent.event'); Flight::eventDispatcher()->removeAllListeners('nonexistent.event');
$this->assertTrue(true, 'Removing listeners for nonexistent events should not throw errors'); $this->assertTrue(
true,
'Removing listeners for nonexistent events should not throw errors'
);
} }
} }

@ -178,7 +178,15 @@ class PdoWrapperTest extends TestCase
$queriesData = null; $queriesData = null;
$dispatcher = EventDispatcher::getInstance(); $dispatcher = EventDispatcher::getInstance();
$dispatcher->on('flight.db.queries', function ($conn, $queries) use (&$eventTriggered, &$connectionData, &$queriesData) {
$dispatcher->on('flight.db.queries', function (
$conn,
$queries
) use (
&$eventTriggered,
&$connectionData,
&$queriesData
) {
$eventTriggered = true; $eventTriggered = true;
$connectionData = $conn; $connectionData = $conn;
$queriesData = $queries; $queriesData = $queries;

@ -266,13 +266,13 @@ class RequestBodyParserTest extends TestCase
// Use PHP CLI with -d to set upload_max_filesize (ini_set can't change this setting in many SAPIs) // Use PHP CLI with -d to set upload_max_filesize (ini_set can't change this setting in many SAPIs)
$cases = [ $cases = [
// No unit yields default branch which returns 0 in current implementation // No unit yields default branch which returns 0 in current implementation
['1' , 0], // no unit and number too small ['1', 0], // no unit and number too small
['1K' , 1024], ['1K', 1024],
['2M' , 2 * 1024 * 1024], ['2M', 2 * 1024 * 1024],
['1G' , 1024 * 1024 * 1024], ['1G', 1024 * 1024 * 1024],
['1T' , 1024 * 1024 * 1024 * 1024], ['1T', 1024 * 1024 * 1024 * 1024],
['1Z' , 0 ], // Unknown unit and number too small ['1Z', 0], // Unknown unit and number too small
[ '1024', 1024 ] ['1024', 1024]
]; ];
foreach ($cases as [$iniVal, $expected]) { foreach ($cases as [$iniVal, $expected]) {
@ -321,7 +321,9 @@ class RequestBodyParserTest extends TestCase
$parts[] = "Content-Type: text/plain\r\n\r\nignoredvalue"; $parts[] = "Content-Type: text/plain\r\n\r\nignoredvalue";
// C: header too long (>16384) => skipped // C: header too long (>16384) => skipped
$longHeader = 'Content-Disposition: form-data; name="toolong"; filename="toolong.txt"; ' . str_repeat('x', 16500); $longHeader = 'Content-Disposition: form-data; name="toolong"; filename="toolong.txt"; '
. str_repeat('x', 16500);
$parts[] = $longHeader . "\r\n\r\nlongvalue"; $parts[] = $longHeader . "\r\n\r\nlongvalue";
// D: header line without colon gets skipped but rest processed; becomes non-file field // D: header line without colon gets skipped but rest processed; becomes non-file field
@ -334,14 +336,24 @@ class RequestBodyParserTest extends TestCase
$parts[] = "Content-Disposition: form-data; name=\"\"; filename=\"empty.txt\"\r\n\r\nemptyNameValue"; $parts[] = "Content-Disposition: form-data; name=\"\"; filename=\"empty.txt\"\r\n\r\nemptyNameValue";
// G: invalid filename triggers sanitized fallback // G: invalid filename triggers sanitized fallback
$parts[] = "Content-Disposition: form-data; name=\"filebad\"; filename=\"a*b?.txt\"\r\nContent-Type: text/plain\r\n\r\nFILEBAD"; $parts[] = "Content-Disposition: form-data; "
. "name=\"filebad\"; "
. "filename=\"a*b?.txt\"\r\nContent-Type: text/plain\r\n\r\nFILEBAD";
// H1 & H2: two files same key for aggregation logic (arrays) // H1 & H2: two files same key for aggregation logic (arrays)
$parts[] = "Content-Disposition: form-data; name=\"filemulti\"; filename=\"one.txt\"\r\nContent-Type: text/plain\r\n\r\nONE"; $parts[] = "Content-Disposition: form-data; "
$parts[] = "Content-Disposition: form-data; name=\"filemulti\"; filename=\"two.txt\"\r\nContent-Type: text/plain\r\n\r\nTWO"; . "name=\"filemulti\"; "
. "filename=\"one.txt\"\r\nContent-Type: text/plain\r\n\r\nONE";
$parts[] = "Content-Disposition: form-data; "
. "name=\"filemulti\"; "
. "filename=\"two.txt\"\r\nContent-Type: text/plain\r\n\r\nTWO";
// I: file exceeding total bytes triggers UPLOAD_ERR_INI_SIZE // I: file exceeding total bytes triggers UPLOAD_ERR_INI_SIZE
$parts[] = "Content-Disposition: form-data; name=\"filebig\"; filename=\"big.txt\"\r\nContent-Type: text/plain\r\n\r\n" . str_repeat('A', 10); $parts[] = "Content-Disposition: form-data; "
. "name=\"filebig\"; "
. "filename=\"big.txt\"\r\nContent-Type: text/plain\r\n\r\n"
. str_repeat('A', 10);
// Build full body // Build full body
$body = ''; $body = '';
@ -394,11 +406,31 @@ class RequestBodyParserTest extends TestCase
public function testMultipartEmptyArrayNameStripped(): void public function testMultipartEmptyArrayNameStripped(): void
{ {
// Covers line where keyName becomes empty after removing [] (name="[]") and header param extraction (preg_match_all) // Covers line where keyName becomes empty after removing [] (name="[]")
// and header param extraction (preg_match_all)
$boundary = 'BOUNDARYEMPTY'; $boundary = 'BOUNDARYEMPTY';
$validFilePart = "Content-Disposition: form-data; name=\"fileok\"; filename=\"ok.txt\"\r\nContent-Type: text/plain\r\n\r\nOK";
$emptyNameFilePart = "Content-Disposition: form-data; name=\"[]\"; filename=\"empty.txt\"\r\nContent-Type: text/plain\r\n\r\nSHOULD_SKIP"; $validFilePart = "Content-Disposition: form-data; "
$body = '--' . $boundary . "\r\n" . $validFilePart . "\r\n" . '--' . $boundary . "\r\n" . $emptyNameFilePart . "\r\n" . '--' . $boundary . "--\r\n"; . "name=\"fileok\"; "
. "filename=\"ok.txt\"\r\nContent-Type: text/plain\r\n\r\nOK";
$emptyNameFilePart = "Content-Disposition: form-data; "
. "name=\"[]\"; "
. "filename=\"empty.txt\"\r\nContent-Type: text/plain\r\n\r\nSHOULD_SKIP";
$body = '--'
. $boundary
. "\r\n"
. $validFilePart
. "\r\n"
. '--'
. $boundary
. "\r\n"
. $emptyNameFilePart
. "\r\n"
. '--'
. $boundary
. "--\r\n";
$tmp = tmpfile(); $tmp = tmpfile();
$path = stream_get_meta_data($tmp)['uri']; $path = stream_get_meta_data($tmp)['uri'];

@ -197,7 +197,7 @@ class RequestTest extends TestCase
'stream_path' => $stream_path, 'stream_path' => $stream_path,
'method' => 'POST' 'method' => 'POST'
]); ]);
$this->assertEquals([ 'foo' => 'bar' ], $request->data->getData()); $this->assertEquals(['foo' => 'bar'], $request->data->getData());
$this->assertEquals('{"foo":"bar"}', $request->getBody()); $this->assertEquals('{"foo":"bar"}', $request->getBody());
} }
@ -430,7 +430,12 @@ class RequestTest extends TestCase
// Find best match first // Find best match first
$_SERVER['HTTP_ACCEPT'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'; $_SERVER['HTTP_ACCEPT'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
$request = new Request(); $request = new Request();
$this->assertEquals('application/xml', $request->negotiateContentType(['application/xml', 'application/json', 'text/html']));
$this->assertEquals('application/xml', $request->negotiateContentType([
'application/xml',
'application/json',
'text/html'
]));
// Find the first match // Find the first match
$_SERVER['HTTP_ACCEPT'] = 'application/json,text/html'; $_SERVER['HTTP_ACCEPT'] = 'application/json,text/html';

@ -88,7 +88,13 @@ class SimplePdoTest extends TestCase
public function testRunQueryWithoutParamsWithMaxQueryMetrics(): void public function testRunQueryWithoutParamsWithMaxQueryMetrics(): void
{ {
$db = new class('sqlite::memory:', null, null, null, ['maxQueryMetrics' => 2, 'trackApmQueries' => true]) extends SimplePdo { $db = new class(
'sqlite::memory:',
null,
null,
null,
['maxQueryMetrics' => 2, 'trackApmQueries' => true]
) extends SimplePdo {
public function getQueryMetrics(): array public function getQueryMetrics(): array
{ {
return $this->queryMetrics; return $this->queryMetrics;

@ -42,7 +42,10 @@ class UploadedFileTest extends TestCase
{ {
return [ return [
[UPLOAD_ERR_INI_SIZE, 'The uploaded file exceeds the upload_max_filesize directive in php.ini.',], [UPLOAD_ERR_INI_SIZE, 'The uploaded file exceeds the upload_max_filesize directive in php.ini.',],
[UPLOAD_ERR_FORM_SIZE, 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',], [
UPLOAD_ERR_FORM_SIZE,
'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
],
[UPLOAD_ERR_PARTIAL, 'The uploaded file was only partially uploaded.',], [UPLOAD_ERR_PARTIAL, 'The uploaded file was only partially uploaded.',],
[UPLOAD_ERR_NO_FILE, 'No file was uploaded.',], [UPLOAD_ERR_NO_FILE, 'No file was uploaded.',],
[UPLOAD_ERR_NO_TMP_DIR, 'Missing a temporary folder.',], [UPLOAD_ERR_NO_TMP_DIR, 'Missing a temporary folder.',],

@ -33,6 +33,11 @@ class ContainerDefault
public function testUi(): void public function testUi(): void
{ {
echo '<span id="infotext">Route text:</span> The container successfully injected a value into the engine! Engine class: <b>' . get_class($this->app) . '</b> test_me_out Value: <b>' . $this->app->get('test_me_out') . '</b>'; echo '<span id="infotext">Route text:</span> '
. 'The container successfully injected a value into the engine! Engine class: <b>'
. get_class($this->app)
. '</b> test_me_out Value: <b>'
. $this->app->get('test_me_out')
. '</b>';
} }
} }

@ -21,7 +21,13 @@ class AiGenerateInstructionsCommandTest extends TestCase
self::$ou = __DIR__ . DIRECTORY_SEPARATOR . 'output.test' . uniqid('', true) . '.txt'; self::$ou = __DIR__ . DIRECTORY_SEPARATOR . 'output.test' . uniqid('', true) . '.txt';
file_put_contents(self::$in, ''); file_put_contents(self::$in, '');
file_put_contents(self::$ou, ''); file_put_contents(self::$ou, '');
$this->baseDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'flightphp-test-basedir-' . uniqid('', true) . DIRECTORY_SEPARATOR;
$this->baseDir = sys_get_temp_dir()
. DIRECTORY_SEPARATOR
. 'flightphp-test-basedir-'
. uniqid('', true)
. DIRECTORY_SEPARATOR;
if (!is_dir($this->baseDir)) { if (!is_dir($this->baseDir)) {
mkdir($this->baseDir, 0777, true); mkdir($this->baseDir, 0777, true);
} }

@ -95,7 +95,10 @@ PHP;
$app->add(new RouteCommand(['runway' => ['something' => 'else']])); $app->add(new RouteCommand(['runway' => ['something' => 'else']]));
@$app->handle(['runway', 'routes']); @$app->handle(['runway', 'routes']);
$this->assertStringContainsString('index_root not set in app/config/config.php', 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 public function testGetRoutes(): void

Loading…
Cancel
Save