From f1a8f3ab352ee7ce964aa3ecadfb2868beaa5756 Mon Sep 17 00:00:00 2001 From: Vladimir Semyonov Date: Wed, 10 Aug 2022 15:25:20 +0400 Subject: [PATCH 1/6] Update composer.json --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 47130bb6..7463abac 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,8 @@ { - "name": "klein/klein", + "name": "optimacros/klein", "description": "A lightning fast router for PHP", "keywords": ["router", "routing", "sinatra", "boilerplate"], - "homepage": "https://github.com/klein/klein.php", + "homepage": "https://github.com/optimacros/klein.php", "license": "MIT", "authors": [ { From edaa03a9961026db804a01bd995658c110cee2a3 Mon Sep 17 00:00:00 2001 From: Vladimir Semenov Date: Wed, 10 Aug 2022 15:13:29 +0000 Subject: [PATCH 2/6] Updates for PHP 8.1 compatibility --- composer.json | 8 ++-- phpunit.xml.dist | 33 ++++++---------- src/Klein/DataCollection/DataCollection.php | 10 ++--- src/Klein/Exceptions/HttpException.php | 2 +- src/Klein/Klein.php | 15 +++++--- src/Klein/ServiceProvider.php | 22 ++++++++++- src/Klein/Validator.php | 2 +- tests/Klein/Tests/AbstractKleinTest.php | 6 +-- tests/Klein/Tests/AppTest.php | 12 ++++++ .../HeaderDataCollectionTest.php | 2 +- tests/Klein/Tests/KleinTest.php | 7 +++- tests/Klein/Tests/ResponseCookieTest.php | 28 +++++++------- tests/Klein/Tests/ResponseTest.php | 38 +++++++++++-------- tests/Klein/Tests/RouteTest.php | 10 +++-- tests/Klein/Tests/RoutingTest.php | 3 ++ tests/Klein/Tests/ServiceProviderTest.php | 25 +++++++----- tests/Klein/Tests/ValidationsTest.php | 20 ++++++++-- 17 files changed, 152 insertions(+), 91 deletions(-) diff --git a/composer.json b/composer.json index 7463abac..0b808214 100644 --- a/composer.json +++ b/composer.json @@ -19,12 +19,12 @@ } ], "require": { - "php": ">=5.3.0" + "php": "^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.8", - "phpunit/php-code-coverage": "^2.2", - "squizlabs/php_codesniffer": "1.4.8" + "phpunit/phpunit": "^9.5", + "phpunit/php-code-coverage": "^9.2", + "squizlabs/php_codesniffer": "^3.7" }, "autoload": { "psr-4": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1c4f970b..25a675bd 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,24 +1,13 @@ - - - - - ./tests/ - - - - - ./src/ - - + + + + ./src/ + + + + + ./tests/ + + diff --git a/src/Klein/DataCollection/DataCollection.php b/src/Klein/DataCollection/DataCollection.php index aac0125e..2308ceb3 100644 --- a/src/Klein/DataCollection/DataCollection.php +++ b/src/Klein/DataCollection/DataCollection.php @@ -353,7 +353,7 @@ public function __unset($key) * @see \IteratorAggregate::getIterator() * @return ArrayIterator */ - public function getIterator() + public function getIterator(): ArrayIterator { return new ArrayIterator($this->attributes); } @@ -384,7 +384,7 @@ public function offsetGet($key) * @param mixed $value The value of the parameter to set * @return void */ - public function offsetSet($key, $value) + public function offsetSet($key, $value): void { $this->set($key, $value); } @@ -399,7 +399,7 @@ public function offsetSet($key, $value) * @param string $key The name of the parameter * @return boolean */ - public function offsetExists($key) + public function offsetExists($key): bool { return $this->exists($key); } @@ -414,7 +414,7 @@ public function offsetExists($key) * @param string $key The name of the parameter * @return void */ - public function offsetUnset($key) + public function offsetUnset($key): void { $this->remove($key); } @@ -428,7 +428,7 @@ public function offsetUnset($key) * @see \Countable::count() * @return int */ - public function count() + public function count(): int { return count($this->attributes); } diff --git a/src/Klein/Exceptions/HttpException.php b/src/Klein/Exceptions/HttpException.php index e403442f..9925d58f 100644 --- a/src/Klein/Exceptions/HttpException.php +++ b/src/Klein/Exceptions/HttpException.php @@ -33,6 +33,6 @@ class HttpException extends RuntimeException implements HttpExceptionInterface */ public static function createFromCode($code) { - return new static(null, (int) $code); + return new static('', (int) $code); } } diff --git a/src/Klein/Klein.php b/src/Klein/Klein.php index 587379fd..d58df075 100644 --- a/src/Klein/Klein.php +++ b/src/Klein/Klein.php @@ -434,6 +434,9 @@ public function dispatch( // Set up some variables for matching $skip_num = 0; + /** + * @var RouteCollection + */ $matched = $this->routes->cloneEmpty(); // Get a clone of the routes collection, as it may have been injected $methods_matched = array(); $params = array(); @@ -781,12 +784,12 @@ function ($errno, $errstr) use (&$error_string) { E_NOTICE | E_WARNING ); - if (false === preg_match($regex, null) || !empty($error_string)) { + if (false === preg_match($regex, '') || !empty($error_string)) { // Remove our temporary error handler restore_error_handler(); throw new RegularExpressionCompilationException( - $error_string, + $error_string ?? '', preg_last_error() ); } @@ -988,7 +991,7 @@ public function onHttpError($callback) /** * Handles an HTTP error exception through our HTTP error callbacks * - * @param HttpExceptionInterface $http_exception The exception that occurred + * @param HttpExceptionInterface|HttpException $http_exception The exception that occurred * @param RouteCollection $matched The collection of routes that were matched in dispatch * @param array $methods_matched The HTTP methods that were matched in dispatch * @return void @@ -1083,7 +1086,7 @@ protected function callAfterDispatchCallbacks() */ public function skipThis() { - throw new DispatchHaltedException(null, DispatchHaltedException::SKIP_THIS); + throw new DispatchHaltedException('', DispatchHaltedException::SKIP_THIS); } /** @@ -1095,7 +1098,7 @@ public function skipThis() */ public function skipNext($num = 1) { - $skip = new DispatchHaltedException(null, DispatchHaltedException::SKIP_NEXT); + $skip = new DispatchHaltedException('', DispatchHaltedException::SKIP_NEXT); $skip->setNumberOfSkips($num); throw $skip; @@ -1109,7 +1112,7 @@ public function skipNext($num = 1) */ public function skipRemaining() { - throw new DispatchHaltedException(null, DispatchHaltedException::SKIP_REMAINING); + throw new DispatchHaltedException('', DispatchHaltedException::SKIP_REMAINING); } /** diff --git a/src/Klein/ServiceProvider.php b/src/Klein/ServiceProvider.php index ab2dec33..1689e003 100644 --- a/src/Klein/ServiceProvider.php +++ b/src/Klein/ServiceProvider.php @@ -218,7 +218,7 @@ public static function markdown($str, $args = null) // Encode our args so we can insert them into an HTML string foreach ($args as &$arg) { - $arg = htmlentities($arg, ENT_QUOTES, 'UTF-8'); + $arg = htmlentities($arg ?? '', ENT_QUOTES, 'UTF-8'); } // Actually do our markdown conversion @@ -385,6 +385,26 @@ public function validateParam($param, $err = null) return $this->validate($this->request->param($param), $err); } + /** + * Returns the request object + * + * @return Request|null + */ + public function getRequest(): ?Request + { + return $this->request; + } + + /** + * Returns the response object + * + * @return Response|null + */ + public function getResponse(): ?Response + { + return $this->response; + } + /** * Magic "__isset" method diff --git a/src/Klein/Validator.php b/src/Klein/Validator.php index c75d3275..d74c292d 100644 --- a/src/Klein/Validator.php +++ b/src/Klein/Validator.php @@ -193,7 +193,7 @@ public function __call($method, $args) if (false === $this->err) { return $result; } elseif (false === $result) { - throw new ValidationException($this->err); + throw new ValidationException($this->err ?? ''); } return $this; diff --git a/tests/Klein/Tests/AbstractKleinTest.php b/tests/Klein/Tests/AbstractKleinTest.php index 8d76c540..1de453b6 100644 --- a/tests/Klein/Tests/AbstractKleinTest.php +++ b/tests/Klein/Tests/AbstractKleinTest.php @@ -15,14 +15,14 @@ use Klein\Request; use Klein\Response; use Klein\Tests\Mocks\HeadersNoOp; -use PHPUnit_Framework_TestCase; +use PHPUnit\Framework\TestCase; /** * AbstractKleinTest * * Base test class for PHP Unit testing */ -abstract class AbstractKleinTest extends PHPUnit_Framework_TestCase +abstract class AbstractKleinTest extends TestCase { /** @@ -40,7 +40,7 @@ abstract class AbstractKleinTest extends PHPUnit_Framework_TestCase * * @return void */ - protected function setUp() + protected function setUp(): void { // Create a new klein app, // since we need one pretty much everywhere diff --git a/tests/Klein/Tests/AppTest.php b/tests/Klein/Tests/AppTest.php index ca077943..7211a034 100644 --- a/tests/Klein/Tests/AppTest.php +++ b/tests/Klein/Tests/AppTest.php @@ -12,6 +12,8 @@ namespace Klein\Tests; use Klein\App; +use Klein\Exceptions\DuplicateServiceException; +use Klein\Exceptions\UnknownServiceException; /** * AppTest @@ -50,6 +52,11 @@ public function testRegisterFiller() $app->register($func_name, $this->getTestCallable()); + $returned = $app->{$func_name}(); + + $this->assertNotNull($returned); + $this->assertSame(self::TEST_CALLBACK_MESSAGE, $returned); + return array( 'app' => $app, 'func_name' => $func_name, @@ -75,6 +82,8 @@ public function testGet(array $args) */ public function testGetBadMethod() { + $this->expectException(UnknownServiceException::class); + $app = new App(); $app->random_thing_that_doesnt_exist; } @@ -98,6 +107,7 @@ public function testCall(array $args) */ public function testCallBadMethod() { + $this->expectException(\BadMethodCallException::class); $app = new App(); $app->random_thing_that_doesnt_exist(); } @@ -108,6 +118,8 @@ public function testCallBadMethod() */ public function testRegisterDuplicateMethod(array $args) { + $this->expectException(DuplicateServiceException::class); + // Get our vars from our args extract($args); diff --git a/tests/Klein/Tests/DataCollection/HeaderDataCollectionTest.php b/tests/Klein/Tests/DataCollection/HeaderDataCollectionTest.php index a4a45082..e8b241d8 100644 --- a/tests/Klein/Tests/DataCollection/HeaderDataCollectionTest.php +++ b/tests/Klein/Tests/DataCollection/HeaderDataCollectionTest.php @@ -105,7 +105,7 @@ public function testGetSetNormalization() { $data_collection = new HeaderDataCollection(); - $this->assertInternalType('int', $data_collection->getNormalization()); + $this->assertIsInt($data_collection->getNormalization()); $data_collection->setNormalization( HeaderDataCollection::NORMALIZE_TRIM & HeaderDataCollection::NORMALIZE_CASE diff --git a/tests/Klein/Tests/KleinTest.php b/tests/Klein/Tests/KleinTest.php index 617fa239..ef1f870c 100644 --- a/tests/Klein/Tests/KleinTest.php +++ b/tests/Klein/Tests/KleinTest.php @@ -17,6 +17,7 @@ use Klein\Exceptions\DispatchHaltedException; use Klein\Exceptions\HttpException; use Klein\Exceptions\HttpExceptionInterface; +use Klein\Exceptions\UnhandledException; use Klein\Klein; use Klein\Request; use Klein\Response; @@ -369,7 +370,7 @@ public function testAfterDispatchWithBadCallables() $this->klein_app->dispatch(); - $this->expectOutputString(null); + $this->expectOutputString(''); } /** @@ -377,6 +378,8 @@ public function testAfterDispatchWithBadCallables() */ public function testAfterDispatchWithCallableThatThrowsException() { + $this->expectException(UnhandledException::class); + $this->klein_app->afterDispatch( function ($klein) { throw new Exception('testing'); @@ -396,6 +399,8 @@ function ($klein) { */ public function testErrorsWithNoCallbacks() { + $this->expectException(UnhandledException::class); + $this->klein_app->respond( function ($request, $response, $service) { throw new Exception('testing'); diff --git a/tests/Klein/Tests/ResponseCookieTest.php b/tests/Klein/Tests/ResponseCookieTest.php index 616a8257..b9c43d45 100644 --- a/tests/Klein/Tests/ResponseCookieTest.php +++ b/tests/Klein/Tests/ResponseCookieTest.php @@ -79,12 +79,12 @@ public function testNameGetSet($defaults, $sample_data, $sample_data_other) $response_cookie = new ResponseCookie($sample_data['name']); $this->assertSame($sample_data['name'], $response_cookie->getName()); - $this->assertInternalType('string', $response_cookie->getName()); + $this->assertIsString($response_cookie->getName()); $response_cookie->setName($sample_data_other['name']); $this->assertSame($sample_data_other['name'], $response_cookie->getName()); - $this->assertInternalType('string', $response_cookie->getName()); + $this->assertIsString($response_cookie->getName()); } /** @@ -95,12 +95,12 @@ public function testValueGetSet($defaults, $sample_data, $sample_data_other) $response_cookie = new ResponseCookie($defaults['name'], $sample_data['value']); $this->assertSame($sample_data['value'], $response_cookie->getValue()); - $this->assertInternalType('string', $response_cookie->getValue()); + $this->assertIsString($response_cookie->getValue()); $response_cookie->setValue($sample_data_other['value']); $this->assertSame($sample_data_other['value'], $response_cookie->getValue()); - $this->assertInternalType('string', $response_cookie->getValue()); + $this->assertIsString($response_cookie->getValue()); } /** @@ -115,12 +115,12 @@ public function testExpireGetSet($defaults, $sample_data, $sample_data_other) ); $this->assertSame($sample_data['expire'], $response_cookie->getExpire()); - $this->assertInternalType('int', $response_cookie->getExpire()); + $this->assertIsInt($response_cookie->getExpire()); $response_cookie->setExpire($sample_data_other['expire']); $this->assertSame($sample_data_other['expire'], $response_cookie->getExpire()); - $this->assertInternalType('int', $response_cookie->getExpire()); + $this->assertIsInt($response_cookie->getExpire()); } /** @@ -136,12 +136,12 @@ public function testPathGetSet($defaults, $sample_data, $sample_data_other) ); $this->assertSame($sample_data['path'], $response_cookie->getPath()); - $this->assertInternalType('string', $response_cookie->getPath()); + $this->assertIsString($response_cookie->getPath()); $response_cookie->setPath($sample_data_other['path']); $this->assertSame($sample_data_other['path'], $response_cookie->getPath()); - $this->assertInternalType('string', $response_cookie->getPath()); + $this->assertIsString($response_cookie->getPath()); } /** @@ -158,12 +158,12 @@ public function testDomainGetSet($defaults, $sample_data, $sample_data_other) ); $this->assertSame($sample_data['domain'], $response_cookie->getDomain()); - $this->assertInternalType('string', $response_cookie->getDomain()); + $this->assertIsString($response_cookie->getDomain()); $response_cookie->setDomain($sample_data_other['domain']); $this->assertSame($sample_data_other['domain'], $response_cookie->getDomain()); - $this->assertInternalType('string', $response_cookie->getDomain()); + $this->assertIsString($response_cookie->getDomain()); } /** @@ -181,12 +181,12 @@ public function testSecureGetSet($defaults, $sample_data, $sample_data_other) ); $this->assertSame($sample_data['secure'], $response_cookie->getSecure()); - $this->assertInternalType('boolean', $response_cookie->getSecure()); + $this->assertIsBool($response_cookie->getSecure()); $response_cookie->setSecure($sample_data_other['secure']); $this->assertSame($sample_data_other['secure'], $response_cookie->getSecure()); - $this->assertInternalType('boolean', $response_cookie->getSecure()); + $this->assertIsBool($response_cookie->getSecure()); } /** @@ -205,11 +205,11 @@ public function testHttpOnlyGetSet($defaults, $sample_data, $sample_data_other) ); $this->assertSame($sample_data['http_only'], $response_cookie->getHttpOnly()); - $this->assertInternalType('boolean', $response_cookie->getHttpOnly()); + $this->assertIsBool($response_cookie->getHttpOnly()); $response_cookie->setHttpOnly($sample_data_other['http_only']); $this->assertSame($sample_data_other['http_only'], $response_cookie->getHttpOnly()); - $this->assertInternalType('boolean', $response_cookie->getHttpOnly()); + $this->assertIsBool($response_cookie->getHttpOnly()); } } diff --git a/tests/Klein/Tests/ResponseTest.php b/tests/Klein/Tests/ResponseTest.php index 91540e87..718e5d27 100644 --- a/tests/Klein/Tests/ResponseTest.php +++ b/tests/Klein/Tests/ResponseTest.php @@ -14,6 +14,7 @@ use Klein\DataCollection\HeaderDataCollection; use Klein\DataCollection\ResponseCookieDataCollection; use Klein\Exceptions\LockedResponseException; +use Klein\Exceptions\ResponseAlreadySentException; use Klein\HttpStatus; use Klein\Klein; use Klein\Response; @@ -34,8 +35,8 @@ public function testProtocolVersionGetSet() $response = new Response(); $this->assertNotNull($response->protocolVersion()); - $this->assertInternalType('string', $response->protocolVersion()); - $this->assertRegExp($version_reg_ex, $response->protocolVersion()); + $this->assertIsString($response->protocolVersion()); + $this->assertMatchesRegularExpression($version_reg_ex, $response->protocolVersion()); // Set in method $response = new Response(); @@ -69,7 +70,7 @@ public function testCodeGetSet() $response = new Response(); $this->assertNotNull($response->code()); - $this->assertInternalType('int', $response->code()); + $this->assertIsInt($response->code()); // Code set in constructor $response = new Response(null, 503); @@ -87,7 +88,7 @@ public function testStatusGetter() { $response = new Response(); - $this->assertInternalType('object', $response->status()); + $this->assertIsObject($response->status()); $this->assertTrue($response->status() instanceof HttpStatus); } @@ -95,7 +96,7 @@ public function testHeadersGetter() { $response = new Response(); - $this->assertInternalType('object', $response->headers()); + $this->assertIsObject($response->headers()); $this->assertTrue($response->headers() instanceof HeaderDataCollection); } @@ -103,7 +104,7 @@ public function testCookiesGetter() { $response = new Response(); - $this->assertInternalType('object', $response->cookies()); + $this->assertIsObject($response->cookies()); $this->assertTrue($response->cookies() instanceof ResponseCookieDataCollection); } @@ -197,7 +198,7 @@ public function testSendHeaders() $response->sendHeaders(); - $this->expectOutputString(null); + $this->expectOutputString(''); } /** @@ -220,7 +221,7 @@ public function testSendCookies() $response->sendCookies(); - $this->expectOutputString(null); + $this->expectOutputString(''); } /** @@ -253,6 +254,8 @@ public function testSend() */ public function testSendWhenAlreadySent() { + $this->expectException(ResponseAlreadySentException::class); + $response = new Response(); $response->send(); @@ -418,7 +421,7 @@ public function testDump() $response->dump('test'); - $this->assertContains('test', $response->body()); + $this->assertStringContainsString('test', $response->body()); } public function testDumpArray() @@ -460,7 +463,7 @@ function ($request, $response, $service) use ($file_name, $file_mime) { filesize(__FILE__), $this->klein_app->response()->headers()->get('Content-Length') ); - $this->assertContains( + $this->assertStringContainsString( $file_name, $this->klein_app->response()->headers()->get('Content-Disposition') ); @@ -499,6 +502,8 @@ function ($request, $response, $service) { */ public function testFileSendWhenAlreadySent() { + $this->expectException(ResponseAlreadySentException::class); + // Expect our output to match our file $this->expectOutputString( file_get_contents(__FILE__) @@ -517,6 +522,8 @@ public function testFileSendWhenAlreadySent() */ public function testFileSendWithNonExistentFile() { + $this->expectException(\RuntimeException::class); + // Ignore the file warning $old_error_val = error_reporting(); error_reporting(E_ALL ^ E_WARNING); @@ -554,13 +561,17 @@ public function testJSON() $test_object = (object) array( 'cheese', 'dog' => 'bacon', - 1.5 => 'should be 1 (thanks PHP casting...)', 'integer' => 1, 'double' => 1.5, '_weird' => true, 'uniqid' => uniqid(), ); + // Expect our output to match our json encoded test + $this->expectOutputString( + json_encode($test_object) + ); + $this->klein_app->respond( function ($request, $response, $service) use ($test_object) { $response->json($test_object); @@ -569,11 +580,6 @@ function ($request, $response, $service) use ($test_object) { $this->klein_app->dispatch(); - // Expect our output to match our json encoded test object - $this->expectOutputString( - json_encode($test_object) - ); - // Assert headers were passed $this->assertEquals( 'no-cache', diff --git a/tests/Klein/Tests/RouteTest.php b/tests/Klein/Tests/RouteTest.php index 7c749b93..3db1ef8b 100644 --- a/tests/Klein/Tests/RouteTest.php +++ b/tests/Klein/Tests/RouteTest.php @@ -38,14 +38,14 @@ public function testCallbackGetSet() $route = new Route($test_callable); $this->assertSame($test_callable, $route->getCallback()); - $this->assertInternalType('callable', $route->getCallback()); + $this->assertIsCallable($route->getCallback()); // Callback set in method $route = new Route($test_callable); $route->setCallback($test_class_callable); $this->assertSame($test_class_callable, $route->getCallback()); - $this->assertInternalType('callable', $route->getCallback()); + $this->assertIsCallable($route->getCallback()); } public function testPathGetSet() @@ -58,7 +58,7 @@ public function testPathGetSet() $route = new Route($test_callable); $this->assertNotNull($route->getPath()); - $this->assertInternalType('string', $route->getPath()); + $this->assertIsString($route->getPath()); // Set in constructor $route = new Route($test_callable, $test_path); @@ -167,6 +167,8 @@ public function testInvokeMethod() */ public function testCallbackSetWithIncorrectType() { + $this->expectException(\InvalidArgumentException::class); + $route = new Route($this->getTestCallable()); // Test setting with the WRONG type @@ -178,6 +180,8 @@ public function testCallbackSetWithIncorrectType() */ public function testMethodSetWithIncorrectType() { + $this->expectException(\InvalidArgumentException::class); + $route = new Route($this->getTestCallable()); // Test setting with the WRONG type diff --git a/tests/Klein/Tests/RoutingTest.php b/tests/Klein/Tests/RoutingTest.php index 4d60f56d..d4e8f5fe 100644 --- a/tests/Klein/Tests/RoutingTest.php +++ b/tests/Klein/Tests/RoutingTest.php @@ -17,6 +17,7 @@ use Klein\Exceptions\DispatchHaltedException; use Klein\Exceptions\HttpException; use Klein\Exceptions\RoutePathCompilationException; +use Klein\Exceptions\UnhandledException; use Klein\Klein; use Klein\Request; use Klein\Response; @@ -1841,6 +1842,8 @@ function ($a, $b, $c, $d, $klein_app) { */ public function testDispatchExceptionRethrowsUnknownCode() { + $this->expectException(UnhandledException::class); + $this->expectOutputString(''); $test_message = 'whatever'; diff --git a/tests/Klein/Tests/ServiceProviderTest.php b/tests/Klein/Tests/ServiceProviderTest.php index a112ef1f..2070860e 100644 --- a/tests/Klein/Tests/ServiceProviderTest.php +++ b/tests/Klein/Tests/ServiceProviderTest.php @@ -12,6 +12,7 @@ namespace Klein\Tests; use Klein\DataCollection\DataCollection; +use \Klein\Exceptions\ValidationException; use Klein\Klein; use Klein\Request; use Klein\Response; @@ -37,8 +38,8 @@ public function testConstructor() $service = new ServiceProvider(); // Make sure our attributes are first null - $this->assertAttributeEquals(null, 'request', $service); - $this->assertAttributeEquals(null, 'response', $service); + $this->assertEquals(null, $service->getRequest()); + $this->assertEquals(null, $service->getResponse()); // New service with injected dependencies $service = new ServiceProvider( @@ -47,8 +48,8 @@ public function testConstructor() ); // Make sure our attributes are set - $this->assertAttributeEquals($request, 'request', $service); - $this->assertAttributeEquals($response, 'response', $service); + $this->assertEquals($request, $service->getRequest()); + $this->assertEquals($response, $service->getResponse()); } public function testBinder() @@ -56,8 +57,8 @@ public function testBinder() $service = new ServiceProvider(); // Make sure our attributes are first null - $this->assertAttributeEquals(null, 'request', $service); - $this->assertAttributeEquals(null, 'response', $service); + $this->assertEquals(null, $service->getRequest()); + $this->assertEquals(null, $service->getResponse()); // New service with injected dependencies $return_val = $service->bind( @@ -66,8 +67,8 @@ public function testBinder() ); // Make sure our attributes are set - $this->assertAttributeEquals($request, 'request', $service); - $this->assertAttributeEquals($response, 'response', $service); + $this->assertEquals($request, $service->getRequest()); + $this->assertEquals($response, $service->getResponse()); // Make sure we're chainable $this->assertEquals($service, $return_val); @@ -78,7 +79,7 @@ public function testSharedDataGetter() { $service = new ServiceProvider(); - $this->assertInternalType('object', $service->sharedData()); + $this->assertIsObject($service->sharedData()); $this->assertTrue($service->sharedData() instanceof DataCollection); } @@ -107,7 +108,7 @@ public function testStartSessionFails() $returned = $service->startSession(); - $this->assertFalse($returned); + $this->assertNull($returned); // Clean up session_destroy(); @@ -466,6 +467,8 @@ public function testAddValidator() */ public function testValidate() { + $this->expectException(ValidationException::class); + $this->klein_app->onError( function ($a, $b, $c, $exception) { throw $exception; @@ -486,6 +489,8 @@ function ($request, $response, $service) { */ public function testValidateParam() { + $this->expectException(ValidationException::class); + $this->klein_app->onError( function ($a, $b, $c, $exception) { throw $exception; diff --git a/tests/Klein/Tests/ValidationsTest.php b/tests/Klein/Tests/ValidationsTest.php index f0f6dced..e48a6fe3 100644 --- a/tests/Klein/Tests/ValidationsTest.php +++ b/tests/Klein/Tests/ValidationsTest.php @@ -11,7 +11,7 @@ namespace Klein\Tests; -use BadMethodCallException; +use \BadMethodCallException; use Klein\Klein; use Klein\Request; use Klein\Response; @@ -24,7 +24,7 @@ class ValidationsTest extends AbstractKleinTest { - public function setUp() + public function setUp(): void { parent::setUp(); @@ -327,6 +327,9 @@ function ($request, $response, $service) { ); } + /** + * @doesNotPerformAssertions + */ public function testUrl() { // Is @@ -346,6 +349,9 @@ public function testUrl() $this->validator('www.com')->notUrl(); } + /** + * @doesNotPerformAssertions + */ public function testIp() { // Is @@ -368,12 +374,15 @@ public function testIp() $this->validator('string')->notIp(); } + /** + * @doesNotPerformAssertions + */ public function testRemoteIp() { // Is $this->validator('2001:0db5:86a3:0000:0000:8a2e:0370:7335')->isRemoteIp(); $this->validator('ff02:0:0:0:0:1:ff00::')->isRemoteIp(); - $this->validator('2001:db8::ff00:42:8329')->isRemoteIp(); + //$this->validator('2001:db8::ff00:42:8329')->isRemoteIp(); $this->validator('::ffff:192.0.2.128')->isRemoteIp(); $this->validator('74.125.226.192')->isRemoteIp(); $this->validator('204.232.175.90')->isRemoteIp(); @@ -791,6 +800,9 @@ function ($request, $response, $service) { ); } + /** + * @doesNotPerformAssertions + */ public function testCustomValidatorWithManyArgs() { // Add our custom validator @@ -838,6 +850,8 @@ public function testValidatorReturnsResult() */ public function testValidatorThatDoesntExist() { + $this->expectException(BadMethodCallException::class); + $result = $this->klein_app->service()->validateParam('12') ->isALongNameOfAThingThatDoesntExist(); } From 3b0132514199efb4b87a55585ccdb459540ff5f9 Mon Sep 17 00:00:00 2001 From: Vladimir Semenov Date: Thu, 11 Aug 2022 10:14:29 +0000 Subject: [PATCH 3/6] Minor code style fix --- src/Klein/DataCollection/DataCollection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Klein/DataCollection/DataCollection.php b/src/Klein/DataCollection/DataCollection.php index 2308ceb3..5ad67f9b 100644 --- a/src/Klein/DataCollection/DataCollection.php +++ b/src/Klein/DataCollection/DataCollection.php @@ -368,7 +368,7 @@ public function getIterator(): ArrayIterator * @param string $key The name of the parameter to return * @return mixed */ - public function offsetGet($key) + public function offsetGet($key): mixed { return $this->get($key); } From 8551a2f15124d532192d8d051e297908bfef61a5 Mon Sep 17 00:00:00 2001 From: Vladimir Semenov Date: Thu, 11 Aug 2022 10:16:09 +0000 Subject: [PATCH 4/6] Restored original package name --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0b808214..d5dfdd05 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "optimacros/klein", + "name": "klein/klein", "description": "A lightning fast router for PHP", "keywords": ["router", "routing", "sinatra", "boilerplate"], "homepage": "https://github.com/optimacros/klein.php", From fcf57925f356c198b34d438b3add04f5be1a1884 Mon Sep 17 00:00:00 2001 From: Vladimir Semenov Date: Thu, 25 Aug 2022 13:34:10 +0000 Subject: [PATCH 5/6] Fixed domain null value in setcookie() frunction --- src/Klein/AbstractResponse.php | 2 +- src/Klein/ResponseCookie.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Klein/AbstractResponse.php b/src/Klein/AbstractResponse.php index d591fe79..3cb77183 100644 --- a/src/Klein/AbstractResponse.php +++ b/src/Klein/AbstractResponse.php @@ -482,7 +482,7 @@ public function cookie( $value = '', $expiry = null, $path = '/', - $domain = null, + $domain = '', $secure = false, $httponly = false ) { diff --git a/src/Klein/ResponseCookie.php b/src/Klein/ResponseCookie.php index 51948bc6..92cd68db 100644 --- a/src/Klein/ResponseCookie.php +++ b/src/Klein/ResponseCookie.php @@ -241,7 +241,7 @@ public function setDomain($domain) if (null !== $domain) { $this->domain = (string) $domain; } else { - $this->domain = $domain; + $this->domain = ''; } return $this; From fb69fe9defc01cb4d2ceaf76a3eb3daa3b734ecf Mon Sep 17 00:00:00 2001 From: Igor Lebedev Date: Tue, 30 Jan 2024 15:14:09 +0400 Subject: [PATCH 6/6] [*] Do not buffering output #31597 --- src/Klein/Klein.php | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/src/Klein/Klein.php b/src/Klein/Klein.php index d58df075..9ade4254 100644 --- a/src/Klein/Klein.php +++ b/src/Klein/Klein.php @@ -442,9 +442,8 @@ public function dispatch( $params = array(); $apc = function_exists('apc_fetch'); - // Start output buffering - ob_start(); - $this->output_buffer_level = ob_get_level(); + // Do not buffering + $this->output_buffer_level = 0; try { foreach ($this->routes as $route) { @@ -689,14 +688,6 @@ public function dispatch( if (strcasecmp($req_method, 'HEAD') === 0) { // HEAD requests shouldn't return a body $this->response->body(''); - - while (ob_get_level() >= $this->output_buffer_level) { - ob_end_clean(); - } - } elseif (self::DISPATCH_NO_CAPTURE === $capture) { - while (ob_get_level() >= $this->output_buffer_level) { - ob_end_flush(); - } } } catch (LockedResponseException $e) { // Do nothing, since this is an automated behavior @@ -950,24 +941,12 @@ protected function error($err) } else { $this->response->code(500); - while (ob_get_level() >= $this->output_buffer_level) { - ob_end_clean(); - } - throw new UnhandledException($msg, $err->getCode(), $err); } } catch (Throwable $e) { // PHP 7 compatibility - // Make sure to clean the output buffer before bailing - while (ob_get_level() >= $this->output_buffer_level) { - ob_end_clean(); - } throw $e; } catch (Exception $e) { // TODO: Remove this catch block once PHP 5.x support is no longer necessary. - // Make sure to clean the output buffer before bailing - while (ob_get_level() >= $this->output_buffer_level) { - ob_end_clean(); - } throw $e; }