From af70bee654d7f896474c8e4ab9d8eed6b8cf7d87 Mon Sep 17 00:00:00 2001 From: MartinBeranek Date: Thu, 20 Nov 2025 14:48:06 +0100 Subject: [PATCH 1/8] update php --- composer.json | 7 ++++--- src/Handlers/BaseHandler.php | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 9c52e1f..7e26865 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ } ], "require": { - "php": ">= 7.1.0", + "php": ">= 8.3", "ext-curl": "*", "ext-json": "*", "ext-session": "*", @@ -21,11 +21,12 @@ "tracy/tracy": "^2.6", "league/fractal": "~0.17", "tomaj/nette-bootstrap-form": "^2.0", - "justinrainbow/json-schema": "^5.2" + "justinrainbow/json-schema": "^5.2", + "latte/latte": "^3.0", + "nette/utils": "^4.0" }, "require-dev": { "nette/di": "^3.0", - "latte/latte": "^2.4 | ^3.0", "phpunit/phpunit": ">7.0 <10.0", "symfony/yaml": "^4.4|^5.0|^6.0", "squizlabs/php_codesniffer": "^3.2" diff --git a/src/Handlers/BaseHandler.php b/src/Handlers/BaseHandler.php index 727fc7e..e1a3116 100644 --- a/src/Handlers/BaseHandler.php +++ b/src/Handlers/BaseHandler.php @@ -29,7 +29,7 @@ abstract class BaseHandler implements ApiHandlerInterface */ protected $linkGenerator; - public function __construct(ScopeFactoryInterface $scopeFactory = null) + public function __construct(?ScopeFactoryInterface $scopeFactory = null) { $this->fractal = new Manager($scopeFactory); } From ef03f2a68eb5acc862ae6dfcfaa34b1cf149cb9c Mon Sep 17 00:00:00 2001 From: MartinBeranek Date: Thu, 20 Nov 2025 14:48:38 +0100 Subject: [PATCH 2/8] fix tests dynamic call to static methods --- .gitignore | 1 + phpstan.neon | 13 +++ src/Link/ApiLinkMacro.php | 58 ---------- src/Response/XmlApiResponse.php | 4 + tests/ApiDeciderTest.php | 30 ++--- .../BearerTokenAuthorizationTest.php | 34 +++--- .../CookieApiKeyAuthenticationTest.php | 12 +- .../HeaderApiKeyAuthenticationTest.php | 12 +- tests/Authorization/NoAuthorizationTest.php | 4 +- .../QueryApiKeyAuthenticationTest.php | 12 +- tests/EndpoinIdentifierTest.php | 32 +++--- tests/Handler/ApiListingHandlerTest.php | 10 +- tests/Handler/CorsPreflightHandlerTest.php | 10 +- tests/Handler/DefaultHandlerTest.php | 14 +-- tests/Handler/EchoHandlerTest.php | 12 +- tests/Handler/OpenApiHandlerTest.php | 8 +- tests/Handler/TestHandlerTest.php | 12 +- tests/Misc/ConsoleRequestTest.php | 4 +- tests/Misc/ConsoleResponseTest.php | 36 +++--- tests/Misc/IpDetectorTest.php | 8 +- tests/Misc/SchemaTransformerTest.php | 12 +- tests/Misc/StaticTokenRepositoryTest.php | 8 +- tests/Output/JsonOutputTest.php | 36 +++--- tests/Params/ConsoleParamsTest.php | 4 +- tests/Params/InpuParamTest.php | 108 +++++++++--------- tests/Params/ParamsProcessorTest.php | 16 +-- tests/Presenters/ApiPresenterTest.php | 24 ++-- tests/RateLimit/RateLimitResponseTest.php | 26 ++--- tests/Response/JsonApiResponseTest.php | 2 +- tests/Response/TextApiResponseTest.php | 2 +- tests/Response/XmlApiResponseTest.php | 2 +- 31 files changed, 263 insertions(+), 303 deletions(-) create mode 100644 phpstan.neon delete mode 100644 src/Link/ApiLinkMacro.php diff --git a/.gitignore b/.gitignore index ad3521a..829515f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ vendor build coverage.clover .idea +.phpunit.result.cache diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..43914e9 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,13 @@ +parameters: + level: 8 + paths: + - src + - tests + excludePaths: + - vendor + - tests + ignoreErrors: + # Ignore magic number warnings in Nette SmartObject trait (vendor code) + - + message: '#^Do not use magic number in bitwise operations\. Move to constant with a suitable name\.$#' + path: 'vendor/nette/utils/src/SmartObject.php' diff --git a/src/Link/ApiLinkMacro.php b/src/Link/ApiLinkMacro.php deleted file mode 100644 index 2e63f7b..0000000 --- a/src/Link/ApiLinkMacro.php +++ /dev/null @@ -1,58 +0,0 @@ - 'My title', 'data-foo' => 'bar']} - */ -class ApiLinkMacro extends MacroSet -{ - public static function install(Compiler $compiler) - { - $macroSet = new static($compiler); - $macroSet->addMacro('apiLink', [self::class, 'start']); - } - - public static function start(MacroNode $node, PhpWriter $writer) - { - $args = array_map('trim', explode(',', $node->args, 5)); - - if (count($args) < 3) { - $message = "Invalid link destination, too few arguments."; - if (!Debugger::$productionMode) { - throw new InvalidLinkException($message); - } - Debugger::log($message, Debugger::EXCEPTION); - return ''; - } - - $arguments = [ - 'method' => self::addQuotes($args[0]), - 'version' => $args[1], - 'package' => self::addQuotes($args[2]), - 'action' => isset($args[3]) ? self::addQuotes($args[3]) : 'null', - 'params' => $args[4] ?? '[]', - ]; - - return $writer->write('echo ($this->filters->apiLink)((new Tomaj\NetteApi\EndpointIdentifier(' . - $arguments['method'] . ', ' . - $arguments['version'] . ', ' . - $arguments['package'] . ', ' . - $arguments['action'] . ')), ' . $arguments['params'] . ')'); - } - - private static function addQuotes($string) - { - return '"' . trim($string, "'\"") . '"'; - } -} diff --git a/src/Response/XmlApiResponse.php b/src/Response/XmlApiResponse.php index d32baa0..fd95aa9 100644 --- a/src/Response/XmlApiResponse.php +++ b/src/Response/XmlApiResponse.php @@ -9,6 +9,10 @@ use Nette\Http\IResponse; use Nette\SmartObject; +/** + * @method mixed __call(string $name, array $args) + * @method static void __callStatic(string $name, array $args) + */ class XmlApiResponse implements ResponseInterface { use SmartObject; diff --git a/tests/ApiDeciderTest.php b/tests/ApiDeciderTest.php index ab87135..8a40de4 100644 --- a/tests/ApiDeciderTest.php +++ b/tests/ApiDeciderTest.php @@ -29,9 +29,9 @@ public function testDefaultHandlerWithNoRegisteredHandlers() $apiDecider = new ApiDecider($this->container); $result = $apiDecider->getApi('POST', '1', 'article', 'list'); - $this->assertInstanceOf(EndpointIdentifier::class, $result->getEndpoint()); - $this->assertInstanceOf(NoAuthorization::class, $result->getAuthorization()); - $this->assertInstanceOf(DefaultHandler::class, $result->getHandler()); + self::assertInstanceOf(EndpointIdentifier::class, $result->getEndpoint()); + self::assertInstanceOf(NoAuthorization::class, $result->getAuthorization()); + self::assertInstanceOf(DefaultHandler::class, $result->getHandler()); } public function testFindRightHandler() @@ -45,21 +45,21 @@ public function testFindRightHandler() $result = $apiDecider->getApi('POST', '2', 'comments', 'list'); - $this->assertInstanceOf(EndpointIdentifier::class, $result->getEndpoint()); - $this->assertInstanceOf(NoAuthorization::class, $result->getAuthorization()); - $this->assertInstanceOf(AlwaysOkHandler::class, $result->getHandler()); + self::assertInstanceOf(EndpointIdentifier::class, $result->getEndpoint()); + self::assertInstanceOf(NoAuthorization::class, $result->getAuthorization()); + self::assertInstanceOf(AlwaysOkHandler::class, $result->getHandler()); - $this->assertEquals('POST', $result->getEndpoint()->getMethod()); - $this->assertEquals('2', $result->getEndpoint()->getVersion()); - $this->assertEquals('comments', $result->getEndpoint()->getPackage()); - $this->assertEquals('list', $result->getEndpoint()->getApiAction()); + self::assertEquals('POST', $result->getEndpoint()->getMethod()); + self::assertEquals('2', $result->getEndpoint()->getVersion()); + self::assertEquals('comments', $result->getEndpoint()->getPackage()); + self::assertEquals('list', $result->getEndpoint()->getApiAction()); } public function testGetHandlers() { $apiDecider = new ApiDecider($this->container); - $this->assertEquals(0, count($apiDecider->getApis())); + self::assertEquals(0, count($apiDecider->getApis())); $apiDecider->addApi( new EndpointIdentifier('POST', '2', 'comments', 'list'), @@ -67,7 +67,7 @@ public function testGetHandlers() new NoAuthorization() ); - $this->assertEquals(1, count($apiDecider->getApis())); + self::assertEquals(1, count($apiDecider->getApis())); } public function testGlobalPreflight() @@ -75,7 +75,7 @@ public function testGlobalPreflight() $apiDecider = new ApiDecider($this->container); $apiDecider->enableGlobalPreflight(); - $this->assertEquals(0, count($apiDecider->getApis())); + self::assertEquals(0, count($apiDecider->getApis())); $apiDecider->addApi( new EndpointIdentifier('POST', '2', 'comments', 'list'), @@ -83,9 +83,9 @@ public function testGlobalPreflight() new NoAuthorization() ); - $this->assertEquals(1, count($apiDecider->getApis())); + self::assertEquals(1, count($apiDecider->getApis())); $handler = $apiDecider->getApi('OPTIONS', '2', 'comments', 'list'); - $this->assertInstanceOf(CorsPreflightHandler::class, $handler->getHandler()); + self::assertInstanceOf(CorsPreflightHandler::class, $handler->getHandler()); } } diff --git a/tests/Authorization/BearerTokenAuthorizationTest.php b/tests/Authorization/BearerTokenAuthorizationTest.php index 032dd2c..f71fa54 100644 --- a/tests/Authorization/BearerTokenAuthorizationTest.php +++ b/tests/Authorization/BearerTokenAuthorizationTest.php @@ -17,7 +17,7 @@ public function testAuthorizedToken() $bearerTokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertTrue($bearerTokenAuthorization->authorized()); + self::assertTrue($bearerTokenAuthorization->authorized()); } public function testUnarizedToken() @@ -26,8 +26,8 @@ public function testUnarizedToken() $bearerTokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertFalse($bearerTokenAuthorization->authorized()); - $this->assertEquals('Token doesn\'t exists or isn\'t active', $bearerTokenAuthorization->getErrorMessage()); + self::assertFalse($bearerTokenAuthorization->authorized()); + self::assertEquals('Token doesn\'t exists or isn\'t active', $bearerTokenAuthorization->getErrorMessage()); } public function testWrongAuthorizationFormat() @@ -36,8 +36,8 @@ public function testWrongAuthorizationFormat() $bearerTokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertFalse($bearerTokenAuthorization->authorized()); - $this->assertEquals('Authorization header contains invalid structure', $bearerTokenAuthorization->getErrorMessage()); + self::assertFalse($bearerTokenAuthorization->authorized()); + self::assertEquals('Authorization header contains invalid structure', $bearerTokenAuthorization->getErrorMessage()); } public function testWrongBearerAuthorizationFormat() @@ -46,8 +46,8 @@ public function testWrongBearerAuthorizationFormat() $bearerTokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertFalse($bearerTokenAuthorization->authorized()); - $this->assertEquals('Authorization header doesn\'t contain bearer token', $bearerTokenAuthorization->getErrorMessage()); + self::assertFalse($bearerTokenAuthorization->authorized()); + self::assertEquals('Authorization header doesn\'t contain bearer token', $bearerTokenAuthorization->getErrorMessage()); } public function testNoAuthorizationHeader() @@ -56,8 +56,8 @@ public function testNoAuthorizationHeader() $bearerTokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertFalse($bearerTokenAuthorization->authorized()); - $this->assertEquals('Authorization header HTTP_Authorization is not set', $bearerTokenAuthorization->getErrorMessage()); + self::assertFalse($bearerTokenAuthorization->authorized()); + self::assertEquals('Authorization header HTTP_Authorization is not set', $bearerTokenAuthorization->getErrorMessage()); } public function testIpRestrictionWithValidIp() @@ -66,7 +66,7 @@ public function testIpRestrictionWithValidIp() $bearerTokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '34.24.126.44']); $ipDetector = new StaticIpDetector('34.24.126.44'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertTrue($bearerTokenAuthorization->authorized()); + self::assertTrue($bearerTokenAuthorization->authorized()); } public function testIpRestrictionWithoutValidIp() @@ -75,8 +75,8 @@ public function testIpRestrictionWithoutValidIp() $bearerTokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '34.24.126.45']); $ipDetector = new StaticIpDetector('34.24.126.44'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertFalse($bearerTokenAuthorization->authorized()); - $this->assertEquals('Invalid IP', $bearerTokenAuthorization->getErrorMessage()); + self::assertFalse($bearerTokenAuthorization->authorized()); + self::assertEquals('Invalid IP', $bearerTokenAuthorization->getErrorMessage()); } public function testIpInRange() @@ -85,7 +85,7 @@ public function testIpInRange() $bearerTokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '192.168.0.0/24']); $ipDetector = new StaticIpDetector('192.168.0.33'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertTrue($bearerTokenAuthorization->authorized()); + self::assertTrue($bearerTokenAuthorization->authorized()); } public function testTokenWithMultipleIps() @@ -95,11 +95,11 @@ public function testTokenWithMultipleIps() $ipDetector = new StaticIpDetector('5.6.2.1'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertTrue($bearerTokenAuthorization->authorized()); + self::assertTrue($bearerTokenAuthorization->authorized()); $ipDetector = new StaticIpDetector('5.6.2.2'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertFalse($bearerTokenAuthorization->authorized()); + self::assertFalse($bearerTokenAuthorization->authorized()); } public function testTokenWithDisabledAccess() @@ -109,10 +109,10 @@ public function testTokenWithDisabledAccess() $ipDetector = new StaticIpDetector('5.6.2.1'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertFalse($bearerTokenAuthorization->authorized()); + self::assertFalse($bearerTokenAuthorization->authorized()); $ipDetector = new StaticIpDetector('5.6.2.2'); $bearerTokenAuthorization = new BearerTokenAuthorization($bearerTokenRepository, $ipDetector); - $this->assertFalse($bearerTokenAuthorization->authorized()); + self::assertFalse($bearerTokenAuthorization->authorized()); } } diff --git a/tests/Authorization/CookieApiKeyAuthenticationTest.php b/tests/Authorization/CookieApiKeyAuthenticationTest.php index 3e93c4c..30b41fa 100644 --- a/tests/Authorization/CookieApiKeyAuthenticationTest.php +++ b/tests/Authorization/CookieApiKeyAuthenticationTest.php @@ -17,7 +17,7 @@ public function testAuthorizedApiKey() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new CookieApiKeyAuthentication('api_key', $tokenRepository, $ipDetector); - $this->assertTrue($authorization->authorized()); + self::assertTrue($authorization->authorized()); } public function testUnarizedApiKey() @@ -26,8 +26,8 @@ public function testUnarizedApiKey() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new CookieApiKeyAuthentication('api_key', $tokenRepository, $ipDetector); - $this->assertFalse($authorization->authorized()); - $this->assertEquals('Token doesn\'t exists or isn\'t active', $authorization->getErrorMessage()); + self::assertFalse($authorization->authorized()); + self::assertEquals('Token doesn\'t exists or isn\'t active', $authorization->getErrorMessage()); } public function testNoApiKey() @@ -35,8 +35,8 @@ public function testNoApiKey() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new CookieApiKeyAuthentication('api_key', $tokenRepository, $ipDetector); - $this->assertFalse($authorization->authorized()); - $this->assertEquals('API key is not set', $authorization->getErrorMessage()); + self::assertFalse($authorization->authorized()); + self::assertEquals('API key is not set', $authorization->getErrorMessage()); } public function testGetCookieName() @@ -44,6 +44,6 @@ public function testGetCookieName() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new CookieApiKeyAuthentication('api_key', $tokenRepository, $ipDetector); - $this->assertEquals('api_key', $authorization->getCookieName()); + self::assertEquals('api_key', $authorization->getCookieName()); } } diff --git a/tests/Authorization/HeaderApiKeyAuthenticationTest.php b/tests/Authorization/HeaderApiKeyAuthenticationTest.php index 2873161..57acbb0 100644 --- a/tests/Authorization/HeaderApiKeyAuthenticationTest.php +++ b/tests/Authorization/HeaderApiKeyAuthenticationTest.php @@ -17,7 +17,7 @@ public function testAuthorizedApiKey() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new HeaderApiKeyAuthentication('X-API-KEY', $tokenRepository, $ipDetector); - $this->assertTrue($authorization->authorized()); + self::assertTrue($authorization->authorized()); } public function testUnarizedApiKey() @@ -26,8 +26,8 @@ public function testUnarizedApiKey() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new HeaderApiKeyAuthentication('X-API-KEY', $tokenRepository, $ipDetector); - $this->assertFalse($authorization->authorized()); - $this->assertEquals('Token doesn\'t exists or isn\'t active', $authorization->getErrorMessage()); + self::assertFalse($authorization->authorized()); + self::assertEquals('Token doesn\'t exists or isn\'t active', $authorization->getErrorMessage()); } public function testNoApiKey() @@ -35,8 +35,8 @@ public function testNoApiKey() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new HeaderApiKeyAuthentication('X-API-KEY', $tokenRepository, $ipDetector); - $this->assertFalse($authorization->authorized()); - $this->assertEquals('API key is not set', $authorization->getErrorMessage()); + self::assertFalse($authorization->authorized()); + self::assertEquals('API key is not set', $authorization->getErrorMessage()); } public function testGetQueryParamName() @@ -44,6 +44,6 @@ public function testGetQueryParamName() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new HeaderApiKeyAuthentication('X-API-KEY', $tokenRepository, $ipDetector); - $this->assertEquals('X-API-KEY', $authorization->getHeaderName()); + self::assertEquals('X-API-KEY', $authorization->getHeaderName()); } } diff --git a/tests/Authorization/NoAuthorizationTest.php b/tests/Authorization/NoAuthorizationTest.php index 51966be..27c1175 100644 --- a/tests/Authorization/NoAuthorizationTest.php +++ b/tests/Authorization/NoAuthorizationTest.php @@ -12,7 +12,7 @@ class NoAuthorizationTest extends TestCase public function testResponse() { $noAuthorization = new NoAuthorization(); - $this->assertTrue($noAuthorization->authorized()); - $this->assertNull($noAuthorization->getErrorMessage()); + self::assertTrue($noAuthorization->authorized()); + self::assertNull($noAuthorization->getErrorMessage()); } } diff --git a/tests/Authorization/QueryApiKeyAuthenticationTest.php b/tests/Authorization/QueryApiKeyAuthenticationTest.php index 0d1c2e9..7029679 100644 --- a/tests/Authorization/QueryApiKeyAuthenticationTest.php +++ b/tests/Authorization/QueryApiKeyAuthenticationTest.php @@ -17,7 +17,7 @@ public function testAuthorizedApiKey() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new QueryApiKeyAuthentication('api_key', $tokenRepository, $ipDetector); - $this->assertTrue($authorization->authorized()); + self::assertTrue($authorization->authorized()); } public function testUnarizedApiKey() @@ -26,8 +26,8 @@ public function testUnarizedApiKey() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new QueryApiKeyAuthentication('api_key', $tokenRepository, $ipDetector); - $this->assertFalse($authorization->authorized()); - $this->assertEquals('Token doesn\'t exists or isn\'t active', $authorization->getErrorMessage()); + self::assertFalse($authorization->authorized()); + self::assertEquals('Token doesn\'t exists or isn\'t active', $authorization->getErrorMessage()); } public function testNoApiKey() @@ -35,8 +35,8 @@ public function testNoApiKey() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new QueryApiKeyAuthentication('api_key', $tokenRepository, $ipDetector); - $this->assertFalse($authorization->authorized()); - $this->assertEquals('API key is not set', $authorization->getErrorMessage()); + self::assertFalse($authorization->authorized()); + self::assertEquals('API key is not set', $authorization->getErrorMessage()); } public function testGetQueryParamName() @@ -44,6 +44,6 @@ public function testGetQueryParamName() $tokenRepository = new StaticTokenRepository(['sad0f98uwegoihweg09i4hergy' => '*']); $ipDetector = new StaticIpDetector('34.24.126.44'); $authorization = new QueryApiKeyAuthentication('api_key', $tokenRepository, $ipDetector); - $this->assertEquals('api_key', $authorization->getQueryParamName()); + self::assertEquals('api_key', $authorization->getQueryParamName()); } } diff --git a/tests/EndpoinIdentifierTest.php b/tests/EndpoinIdentifierTest.php index 26d5c9f..ec5b685 100644 --- a/tests/EndpoinIdentifierTest.php +++ b/tests/EndpoinIdentifierTest.php @@ -14,42 +14,42 @@ public function testValidation() { $endpoint = new EndpointIdentifier('POST', '1', 'core', 'show'); - $this->assertSame('1', $endpoint->getVersion()); - $this->assertEquals('POST', $endpoint->getMethod()); - $this->assertEquals('core', $endpoint->getPackage()); - $this->assertEquals('show', $endpoint->getApiAction()); - $this->assertEquals('v1/core/show', $endpoint->getUrl()); + self::assertSame('1', $endpoint->getVersion()); + self::assertEquals('POST', $endpoint->getMethod()); + self::assertEquals('core', $endpoint->getPackage()); + self::assertEquals('show', $endpoint->getApiAction()); + self::assertEquals('v1/core/show', $endpoint->getUrl()); $endpoint = new EndpointIdentifier('POST', '1.1', 'core', 'show'); - $this->assertEquals('v1.1/core/show', $endpoint->getUrl()); + self::assertEquals('v1.1/core/show', $endpoint->getUrl()); $endpoint = new EndpointIdentifier('POST', '1.1.2', 'core', 'show'); - $this->assertEquals('v1.1.2/core/show', $endpoint->getUrl()); + self::assertEquals('v1.1.2/core/show', $endpoint->getUrl()); } public function testSimpleUrl() { $endpoint = new EndpointIdentifier('get', '2', 'main', ''); - $this->assertNull($endpoint->getApiAction()); - $this->assertEquals('GET', $endpoint->getMethod()); + self::assertNull($endpoint->getApiAction()); + self::assertEquals('GET', $endpoint->getMethod()); } public function testSupportedVersions() { $endpoint = new EndpointIdentifier('GET', '0', 'core', 'show'); - $this->assertEquals('v0/core/show', $endpoint->getUrl()); + self::assertEquals('v0/core/show', $endpoint->getUrl()); $endpoint = new EndpointIdentifier('GET', '1', 'core', 'show'); - $this->assertEquals('v1/core/show', $endpoint->getUrl()); + self::assertEquals('v1/core/show', $endpoint->getUrl()); $endpoint = new EndpointIdentifier('GET', '1.0', 'core', 'show'); - $this->assertEquals('v1.0/core/show', $endpoint->getUrl()); + self::assertEquals('v1.0/core/show', $endpoint->getUrl()); $endpoint = new EndpointIdentifier('GET', '1.1', 'core', 'show'); - $this->assertEquals('v1.1/core/show', $endpoint->getUrl()); + self::assertEquals('v1.1/core/show', $endpoint->getUrl()); $endpoint = new EndpointIdentifier('GET', '1.33', 'core', 'show'); - $this->assertEquals('v1.33/core/show', $endpoint->getUrl()); + self::assertEquals('v1.33/core/show', $endpoint->getUrl()); $endpoint = new EndpointIdentifier('GET', '1.33-dev', 'core', 'show'); - $this->assertEquals('v1.33-dev/core/show', $endpoint->getUrl()); + self::assertEquals('v1.33-dev/core/show', $endpoint->getUrl()); $endpoint = new EndpointIdentifier('GET', '0.33.43', 'core', 'show'); - $this->assertEquals('v0.33.43/core/show', $endpoint->getUrl()); + self::assertEquals('v0.33.43/core/show', $endpoint->getUrl()); } public function testFailVersion() diff --git a/tests/Handler/ApiListingHandlerTest.php b/tests/Handler/ApiListingHandlerTest.php index fc3183d..966f6e6 100644 --- a/tests/Handler/ApiListingHandlerTest.php +++ b/tests/Handler/ApiListingHandlerTest.php @@ -49,9 +49,9 @@ public function testDefaultHandle() $handler = $result->getHandler(); $response = $handler->handle([]); - $this->assertEquals(200, $response->getCode()); + self::assertEquals(200, $response->getCode()); $payload = $response->getPayload(); - $this->assertEquals(2, count($payload['endpoints'])); + self::assertEquals(2, count($payload['endpoints'])); } public function testHandlerWithParam() @@ -76,9 +76,9 @@ public function testHandlerWithParam() $handler = $result->getHandler(); $response = $handler->handle([]); - $this->assertEquals(200, $response->getCode()); + self::assertEquals(200, $response->getCode()); $payload = $response->getPayload(); - $this->assertEquals(2, count($payload['endpoints'])); - $this->assertEquals(2, count($payload['endpoints'][0]['params'])); + self::assertEquals(2, count($payload['endpoints'])); + self::assertEquals(2, count($payload['endpoints'][0]['params'])); } } diff --git a/tests/Handler/CorsPreflightHandlerTest.php b/tests/Handler/CorsPreflightHandlerTest.php index fea17da..e3eef6d 100644 --- a/tests/Handler/CorsPreflightHandlerTest.php +++ b/tests/Handler/CorsPreflightHandlerTest.php @@ -19,18 +19,18 @@ public function testResponse() { $preflighthandler = new CorsPreflightHandler(new Response()); $result = $preflighthandler->handle([]); - $this->assertEquals(200, $result->getCode()); - $this->assertEquals([], $result->getPayload()); + self::assertEquals(200, $result->getCode()); + self::assertEquals([], $result->getPayload()); } public function testEndpointSetter() { $defaultHandler = new CorsPreflightHandler(new Response()); - $this->assertNull($defaultHandler->getEndpoint()); + self::assertNull($defaultHandler->getEndpoint()); $endpointIdentifier = new EndpointIdentifier('OPTIONS', '1', 'article', 'detail'); $defaultHandler->setEndpointIdentifier($endpointIdentifier); - $this->assertEquals($endpointIdentifier, $defaultHandler->getEndpoint()); + self::assertEquals($endpointIdentifier, $defaultHandler->getEndpoint()); } public function testExceptionWhenCreatingLinkWithoutLinkGenerator() @@ -64,6 +64,6 @@ public function testCreateLink() $endpointIdentifier = new EndpointIdentifier('OPTIONS', '1', 'article', 'detail'); $defaultHandler->setEndpointIdentifier($endpointIdentifier); - $this->assertEquals('http://test/?version=1&package=article&apiAction=detail&page=2&action=default&presenter=Api%3AApi', $defaultHandler->createLink(['page' => 2])); + self::assertEquals('http://test/?version=1&package=article&apiAction=detail&page=2&action=default&presenter=Api%3AApi', $defaultHandler->createLink(['page' => 2])); } } diff --git a/tests/Handler/DefaultHandlerTest.php b/tests/Handler/DefaultHandlerTest.php index 00e0160..18d4010 100644 --- a/tests/Handler/DefaultHandlerTest.php +++ b/tests/Handler/DefaultHandlerTest.php @@ -18,20 +18,20 @@ public function testResponse() { $defaultHandler = new DefaultHandler(); $result = $defaultHandler->handle([]); - $this->assertEquals(404, $result->getCode()); - $this->assertEquals('application/json', $result->getContentType()); - $this->assertEquals('utf-8', $result->getCharset()); - $this->assertEquals(['status' => 'error', 'message' => 'Unknown api endpoint'], $result->getPayload()); + self::assertEquals(404, $result->getCode()); + self::assertEquals('application/json', $result->getContentType()); + self::assertEquals('utf-8', $result->getCharset()); + self::assertEquals(['status' => 'error', 'message' => 'Unknown api endpoint'], $result->getPayload()); } public function testEndpointSetter() { $defaultHandler = new DefaultHandler(); - $this->assertNull($defaultHandler->getEndpoint()); + self::assertNull($defaultHandler->getEndpoint()); $endpointIdentifier = new EndpointIdentifier('POST', '1', 'article', 'detail'); $defaultHandler->setEndpointIdentifier($endpointIdentifier); - $this->assertEquals($endpointIdentifier, $defaultHandler->getEndpoint()); + self::assertEquals($endpointIdentifier, $defaultHandler->getEndpoint()); } public function testExceptionWhenCreatingLinkWithoutLinkGenerator() @@ -65,6 +65,6 @@ public function testCreateLink() $endpointIdentifier = new EndpointIdentifier('POST', '1', 'article', 'detail'); $defaultHandler->setEndpointIdentifier($endpointIdentifier); - $this->assertEquals('http://test/?version=1&package=article&apiAction=detail&page=2&action=default&presenter=Api%3AApi', $defaultHandler->createLink(['page' => 2])); + self::assertEquals('http://test/?version=1&package=article&apiAction=detail&page=2&action=default&presenter=Api%3AApi', $defaultHandler->createLink(['page' => 2])); } } diff --git a/tests/Handler/EchoHandlerTest.php b/tests/Handler/EchoHandlerTest.php index e9e9870..f87ab36 100644 --- a/tests/Handler/EchoHandlerTest.php +++ b/tests/Handler/EchoHandlerTest.php @@ -12,14 +12,14 @@ class EchoHandlerTest extends TestCase public function testResponse() { $handler = new EchoHandler(); - $this->assertEquals('', $handler->summary()); - $this->assertEquals('', $handler->description()); - $this->assertFalse($handler->deprecated()); - $this->assertEquals([], $handler->tags()); + self::assertEquals('', $handler->summary()); + self::assertEquals('', $handler->description()); + self::assertFalse($handler->deprecated()); + self::assertEquals([], $handler->tags()); $result = $handler->handle(['status' => 'error', 'message' => 'Hello']); - $this->assertEquals(200, $result->getCode()); + self::assertEquals(200, $result->getCode()); - $this->assertEquals(['status' => 'error', 'params' => ['status' => 'error', 'message' => 'Hello']], $result->getPayload()); + self::assertEquals(['status' => 'error', 'params' => ['status' => 'error', 'message' => 'Hello']], $result->getPayload()); } } diff --git a/tests/Handler/OpenApiHandlerTest.php b/tests/Handler/OpenApiHandlerTest.php index 5667173..6acc9aa 100644 --- a/tests/Handler/OpenApiHandlerTest.php +++ b/tests/Handler/OpenApiHandlerTest.php @@ -49,15 +49,15 @@ public function testHandlerWithMultipleResponseSchemas() $handler = $result->getHandler(); $response = $handler->handle(['format' => 'json']); - $this->assertEquals(200, $response->getCode()); + self::assertEquals(200, $response->getCode()); $payload = $response->getPayload(); - $this->assertEquals(2, count($payload['paths'])); + self::assertEquals(2, count($payload['paths'])); $def = array_values($payload['paths'])[0]; // MultipleOutputTestHandler - $this->assertEquals(2, count($def['get']['responses'][200]['content']['application/json; charset=utf-8']['schema']['oneOf'])); + self::assertEquals(2, count($def['get']['responses'][200]['content']['application/json; charset=utf-8']['schema']['oneOf'])); $def = array_values($payload['paths'])[1]; // OpenApiHandler - $this->assertFalse(isset($def['get']['responses'][200]['content']['application/json; charset=utf-8']['schema']['oneOf'])); + self::assertFalse(isset($def['get']['responses'][200]['content']['application/json; charset=utf-8']['schema']['oneOf'])); } } diff --git a/tests/Handler/TestHandlerTest.php b/tests/Handler/TestHandlerTest.php index ccbc4f3..bc17173 100644 --- a/tests/Handler/TestHandlerTest.php +++ b/tests/Handler/TestHandlerTest.php @@ -13,15 +13,15 @@ class TestHandlerTest extends TestCase public function testParentConstructCall() { $handler = new TestHandler(); - $this->assertEquals('Test handler', $handler->summary()); - $this->assertEquals('This API handler is for test purpose and it is marked as deprecated', $handler->description()); - $this->assertTrue($handler->deprecated()); - $this->assertEquals(['test'], $handler->tags()); + self::assertEquals('Test handler', $handler->summary()); + self::assertEquals('This API handler is for test purpose and it is marked as deprecated', $handler->description()); + self::assertTrue($handler->deprecated()); + self::assertEquals(['test'], $handler->tags()); /** @var JsonApiResponse $result */ $result = $handler->handle([]); - $this->assertEquals(200, $result->getCode()); - $this->assertEquals(['hello' => 'world'], $result->getPayload()); + self::assertEquals(200, $result->getCode()); + self::assertEquals(['hello' => 'world'], $result->getPayload()); $this->expectException(InvalidStateException::class); $this->expectExceptionMessage("Fractal manager isn't initialized. Did you call parent::__construct() in your handler constructor?"); diff --git a/tests/Misc/ConsoleRequestTest.php b/tests/Misc/ConsoleRequestTest.php index 76e057b..34b8cca 100644 --- a/tests/Misc/ConsoleRequestTest.php +++ b/tests/Misc/ConsoleRequestTest.php @@ -17,7 +17,7 @@ public function testLogRequest() $request = new ConsoleRequest($handler); $response = $request->makeRequest("http://127.0.0.1:23523/", 'POST', ['status' => 'ok', 'message' => 'Hello']); - $this->assertTrue($response->isError()); - $this->assertEquals('http://127.0.0.1:23523/?status=ok&message=Hello', $response->getUrl()); + self::assertTrue($response->isError()); + self::assertEquals('http://127.0.0.1:23523/?status=ok&message=Hello', $response->getUrl()); } } diff --git a/tests/Misc/ConsoleResponseTest.php b/tests/Misc/ConsoleResponseTest.php index 507187c..037279e 100644 --- a/tests/Misc/ConsoleResponseTest.php +++ b/tests/Misc/ConsoleResponseTest.php @@ -20,22 +20,22 @@ public function testLogRequest() ['Content-Type' => 'text'] ); - $this->assertEquals('http://url.com/', $response->getUrl()); - $this->assertEquals('POST', $response->getMethod()); - $this->assertEquals(['mykey1' => 'asdsd'], $response->getPostFields()); - $this->assertEquals(['mykey2' => 'wegewg'], $response->getGetFields()); - $this->assertEquals(['mykey3' => 'gwegerg'], $response->getCookieFields()); - $this->assertEquals(['Content-Type' => 'text'], $response->getHeaders()); - $this->assertNull($response->getResponseCode()); - $this->assertFalse($response->isError()); + self::assertEquals('http://url.com/', $response->getUrl()); + self::assertEquals('POST', $response->getMethod()); + self::assertEquals(['mykey1' => 'asdsd'], $response->getPostFields()); + self::assertEquals(['mykey2' => 'wegewg'], $response->getGetFields()); + self::assertEquals(['mykey3' => 'gwegerg'], $response->getCookieFields()); + self::assertEquals(['Content-Type' => 'text'], $response->getHeaders()); + self::assertNull($response->getResponseCode()); + self::assertFalse($response->isError()); $response->logRequest(202, '{"aaa": "bbb"}', 'responseheadersd', 145); - $this->assertEquals('{"aaa": "bbb"}', $response->getResponseBody()); - $this->assertEquals('responseheadersd', $response->getResponseHeaders()); - $this->assertEquals("{\n \"aaa\": \"bbb\"\n}", $response->getFormattedJsonBody()); - $this->assertEquals(145, $response->getResponseTime()); - $this->assertFalse($response->isError()); - $this->assertEquals(202, $response->getResponseCode()); + self::assertEquals('{"aaa": "bbb"}', $response->getResponseBody()); + self::assertEquals('responseheadersd', $response->getResponseHeaders()); + self::assertEquals("{\n \"aaa\": \"bbb\"\n}", $response->getFormattedJsonBody()); + self::assertEquals(145, $response->getResponseTime()); + self::assertFalse($response->isError()); + self::assertEquals(202, $response->getResponseCode()); } public function testLogErrorRequest() @@ -49,9 +49,9 @@ public function testLogErrorRequest() ); $response->logError(503, 'err message', 21); - $this->assertEquals(503, $response->getErrorNumber()); - $this->assertEquals('err message', $response->getErrorMessage()); - $this->assertEquals(21, $response->getResponseTime()); - $this->assertTrue($response->isError()); + self::assertEquals(503, $response->getErrorNumber()); + self::assertEquals('err message', $response->getErrorMessage()); + self::assertEquals(21, $response->getResponseTime()); + self::assertTrue($response->isError()); } } diff --git a/tests/Misc/IpDetectorTest.php b/tests/Misc/IpDetectorTest.php index 394800b..e2c0d81 100644 --- a/tests/Misc/IpDetectorTest.php +++ b/tests/Misc/IpDetectorTest.php @@ -12,18 +12,18 @@ class IpDetectorTest extends TestCase public function testValidation() { $ipDetector = new IpDetector(); - $this->assertEquals('cli', $ipDetector->getRequestIp()); + self::assertEquals('cli', $ipDetector->getRequestIp()); $_SERVER['HTTP_CLIENT_IP'] = '1.2.3.4'; - $this->assertEquals('1.2.3.4', $ipDetector->getRequestIp()); + self::assertEquals('1.2.3.4', $ipDetector->getRequestIp()); unset($_SERVER['HTTP_CLIENT_IP']); $_SERVER['HTTP_X_FORWARDED_FOR'] = '1.2.3.5'; - $this->assertEquals('1.2.3.5', $ipDetector->getRequestIp()); + self::assertEquals('1.2.3.5', $ipDetector->getRequestIp()); unset($_SERVER['HTTP_X_FORWARDED_FOR']); $_SERVER['REMOTE_ADDR'] = '1.2.3.6'; - $this->assertEquals('1.2.3.6', $ipDetector->getRequestIp()); + self::assertEquals('1.2.3.6', $ipDetector->getRequestIp()); unset($_SERVER['REMOTE_ADDR']); } } diff --git a/tests/Misc/SchemaTransformerTest.php b/tests/Misc/SchemaTransformerTest.php index 7e79131..34e52dc 100644 --- a/tests/Misc/SchemaTransformerTest.php +++ b/tests/Misc/SchemaTransformerTest.php @@ -27,7 +27,7 @@ public function testSingeTypeRequest() ]; OpenApiTransform::transformTypes($schema); - $this->assertEquals($expected, $schema); + self::assertEquals($expected, $schema); } public function testTypePropertyRequest() @@ -48,7 +48,7 @@ public function testTypePropertyRequest() ]; OpenApiTransform::transformTypes($schema); - $this->assertEquals($expected, $schema); + self::assertEquals($expected, $schema); } public function testNullStringRequest() @@ -70,7 +70,7 @@ public function testNullStringRequest() ]; OpenApiTransform::transformTypes($schema); - $this->assertEquals($expected, $schema); + self::assertEquals($expected, $schema); } public function testIntegerStringRequest() @@ -94,7 +94,7 @@ public function testIntegerStringRequest() ]; OpenApiTransform::transformTypes($schema); - $this->assertEquals($expected, $schema); + self::assertEquals($expected, $schema); } public function testNullIntegerStringRequest() @@ -119,7 +119,7 @@ public function testNullIntegerStringRequest() ]; OpenApiTransform::transformTypes($schema); - $this->assertEquals($expected, $schema); + self::assertEquals($expected, $schema); } public function testTypePropertyNullIntegerStringRequest() @@ -144,6 +144,6 @@ public function testTypePropertyNullIntegerStringRequest() ]; OpenApiTransform::transformTypes($schema); - $this->assertEquals($expected, $schema); + self::assertEquals($expected, $schema); } } diff --git a/tests/Misc/StaticTokenRepositoryTest.php b/tests/Misc/StaticTokenRepositoryTest.php index 1236947..3cee405 100644 --- a/tests/Misc/StaticTokenRepositoryTest.php +++ b/tests/Misc/StaticTokenRepositoryTest.php @@ -15,9 +15,9 @@ public function testValidation() 'mytoken' => '*', ]); - $this->assertTrue($repository->validToken('mytoken')); - $this->assertFalse($repository->validToken('mytoken2')); - $this->assertEquals('*', $repository->ipRestrictions('mytoken')); + self::assertTrue($repository->validToken('mytoken')); + self::assertFalse($repository->validToken('mytoken2')); + self::assertEquals('*', $repository->ipRestrictions('mytoken')); } public function testIpRestrictionsForInvalidToken() @@ -25,6 +25,6 @@ public function testIpRestrictionsForInvalidToken() $repository = new StaticTokenRepository([ 'mytoken' => '*', ]); - $this->assertNull($repository->ipRestrictions('mytoken2')); + self::assertNull($repository->ipRestrictions('mytoken2')); } } diff --git a/tests/Output/JsonOutputTest.php b/tests/Output/JsonOutputTest.php index bd7cb89..af9a753 100644 --- a/tests/Output/JsonOutputTest.php +++ b/tests/Output/JsonOutputTest.php @@ -18,9 +18,9 @@ public function testSimpleValidation() $response = new JsonApiResponse(200, ['hello' => 'world']); $validationResult = $output->validate($response); - $this->assertInstanceOf(ValidationResultInterface::class, $validationResult); - $this->assertTrue($validationResult->isOk()); - $this->assertEquals([], $validationResult->getErrors()); + self::assertInstanceOf(ValidationResultInterface::class, $validationResult); + self::assertTrue($validationResult->isOk()); + self::assertEquals([], $validationResult->getErrors()); } public function testWrongOutputSchema() @@ -29,18 +29,18 @@ public function testWrongOutputSchema() $response = new JsonApiResponse(200, ['hello', 'world']); $validationResult = $output->validate($response); - $this->assertInstanceOf(ValidationResultInterface::class, $validationResult); - $this->assertFalse($validationResult->isOk()); - $this->assertEquals(['Array value found, but an object is required'], $validationResult->getErrors()); + self::assertInstanceOf(ValidationResultInterface::class, $validationResult); + self::assertFalse($validationResult->isOk()); + self::assertEquals(['Array value found, but an object is required'], $validationResult->getErrors()); $output = new JsonOutput(200, '{"type": "string"}'); $response = new JsonApiResponse(200, ['hello' => 'world']); $validationResult = $output->validate($response); - $this->assertInstanceOf(ValidationResultInterface::class, $validationResult); - $this->assertFalse($validationResult->isOk()); - $this->assertEquals(['Object value found, but a string is required'], $validationResult->getErrors()); + self::assertInstanceOf(ValidationResultInterface::class, $validationResult); + self::assertFalse($validationResult->isOk()); + self::assertEquals(['Object value found, but a string is required'], $validationResult->getErrors()); $schema = [ 'type' => 'object', @@ -56,9 +56,9 @@ public function testWrongOutputSchema() $response = new JsonApiResponse(200, ['hello' => 'space']); $validationResult = $output->validate($response); - $this->assertInstanceOf(ValidationResultInterface::class, $validationResult); - $this->assertFalse($validationResult->isOk()); - $this->assertEquals(['[Property hello] Does not have a value in the enumeration ["world","europe"]'], $validationResult->getErrors()); + self::assertInstanceOf(ValidationResultInterface::class, $validationResult); + self::assertFalse($validationResult->isOk()); + self::assertEquals(['[Property hello] Does not have a value in the enumeration ["world","europe"]'], $validationResult->getErrors()); } public function testWrongResponseCode() @@ -67,9 +67,9 @@ public function testWrongResponseCode() $response = new JsonApiResponse(404, ['error' => ' not found']); $validationResult = $output->validate($response); - $this->assertInstanceOf(ValidationResultInterface::class, $validationResult); - $this->assertFalse($validationResult->isOk()); - $this->assertEquals(['Response code doesn\'t match'], $validationResult->getErrors()); + self::assertInstanceOf(ValidationResultInterface::class, $validationResult); + self::assertFalse($validationResult->isOk()); + self::assertEquals(['Response code doesn\'t match'], $validationResult->getErrors()); } public function testValidateOtherResponseType() @@ -78,8 +78,8 @@ public function testValidateOtherResponseType() $response = new TextApiResponse(200, 'hello world'); $validationResult = $output->validate($response); - $this->assertInstanceOf(ValidationResultInterface::class, $validationResult); - $this->assertFalse($validationResult->isOk()); - $this->assertEquals([], $validationResult->getErrors()); + self::assertInstanceOf(ValidationResultInterface::class, $validationResult); + self::assertFalse($validationResult->isOk()); + self::assertEquals([], $validationResult->getErrors()); } } diff --git a/tests/Params/ConsoleParamsTest.php b/tests/Params/ConsoleParamsTest.php index 3d7e335..21ffbe3 100644 --- a/tests/Params/ConsoleParamsTest.php +++ b/tests/Params/ConsoleParamsTest.php @@ -67,10 +67,10 @@ private function addInputsToForm(array $inputParams) $inputParam->updateConsoleForm($form); } - $this->assertCount($totalCount, $form->getControls()); + self::assertCount($totalCount, $form->getControls()); foreach ($form->getControls() as $control) { - $this->assertInstanceOf(BaseControl::class, $control); + self::assertInstanceOf(BaseControl::class, $control); } } } diff --git a/tests/Params/InpuParamTest.php b/tests/Params/InpuParamTest.php index 9321040..546630d 100644 --- a/tests/Params/InpuParamTest.php +++ b/tests/Params/InpuParamTest.php @@ -20,97 +20,97 @@ public function testValidation() { $inputParam = (new PostInputParam('mykey1'))->setRequired(); $_POST['mykey1'] = 'hello'; - $this->assertTrue($inputParam->validate()->isOk()); - $this->assertEquals('hello', $inputParam->getValue()); + self::assertTrue($inputParam->validate()->isOk()); + self::assertEquals('hello', $inputParam->getValue()); unset($_POST['mykey1']); $inputParam = new PostInputParam('mykey2'); - $this->assertTrue($inputParam->validate()->isOk()); - $this->assertNull($inputParam->getValue()); + self::assertTrue($inputParam->validate()->isOk()); + self::assertNull($inputParam->getValue()); $inputParam = (new PostInputParam('mykey3'))->setRequired()->setAvailableValues(['a', 'b']); $_POST['mykey3'] = 'hello'; - $this->assertFalse($inputParam->validate()->isOk()); - $this->assertEquals('hello', $inputParam->getValue()); + self::assertFalse($inputParam->validate()->isOk()); + self::assertEquals('hello', $inputParam->getValue()); $_POST['mykey3'] = 'a'; - $this->assertTrue($inputParam->validate()->isOk()); - $this->assertEquals('a', $inputParam->getValue()); + self::assertTrue($inputParam->validate()->isOk()); + self::assertEquals('a', $inputParam->getValue()); unset($_POST['mykey3']); $inputParam = new GetInputParam('asdsd'); - $this->assertNull($inputParam->getValue()); + self::assertNull($inputParam->getValue()); $inputParam = new JsonInputParam('json', '{}'); - $this->assertTrue($inputParam->validate()->isOk()); - $this->assertNull($inputParam->getValue()); - $this->assertEquals([], $inputParam->validate()->getErrors()); + self::assertTrue($inputParam->validate()->isOk()); + self::assertNull($inputParam->getValue()); + self::assertEquals([], $inputParam->validate()->getErrors()); $inputParam = (new JsonInputParam('json', '{}'))->setRequired(); - $this->assertFalse($inputParam->validate()->isOk()); - $this->assertNull($inputParam->getValue()); - $this->assertEquals(['missing data'], $inputParam->validate()->getErrors()); + self::assertFalse($inputParam->validate()->isOk()); + self::assertNull($inputParam->getValue()); + self::assertEquals(['missing data'], $inputParam->validate()->getErrors()); $inputParam = (new JsonInputParam('json', '{"type": "object"}'))->setDefault('{}'); - $this->assertTrue($inputParam->validate()->isOk()); - $this->assertEquals([], $inputParam->getValue()); - $this->assertEquals([], $inputParam->validate()->getErrors()); + self::assertTrue($inputParam->validate()->isOk()); + self::assertEquals([], $inputParam->getValue()); + self::assertEquals([], $inputParam->validate()->getErrors()); $inputParam = (new JsonInputParam('json', '{"type": "string"}'))->setDefault('{"hello": "world"}'); - $this->assertFalse($inputParam->validate()->isOk()); - $this->assertEquals(['hello' => 'world'], $inputParam->getValue()); - $this->assertEquals(['Object value found, but a string is required'], $inputParam->validate()->getErrors()); + self::assertFalse($inputParam->validate()->isOk()); + self::assertEquals(['hello' => 'world'], $inputParam->getValue()); + self::assertEquals(['Object value found, but a string is required'], $inputParam->validate()->getErrors()); } public function testVariableAccess() { $inputParam = (new GetInputParam('mykey4'))->setRequired()->setAvailableValues(['c', 'asdsadsad']); - $this->assertEquals('GET', $inputParam->getType()); - $this->assertEquals('mykey4', $inputParam->getKey()); - $this->assertEquals(true, $inputParam->isRequired()); - $this->assertEquals(['c' => 'c', 'asdsadsad' => 'asdsadsad'], $inputParam->getAvailableValues()); + self::assertEquals('GET', $inputParam->getType()); + self::assertEquals('mykey4', $inputParam->getKey()); + self::assertEquals(true, $inputParam->isRequired()); + self::assertEquals(['c' => 'c', 'asdsadsad' => 'asdsadsad'], $inputParam->getAvailableValues()); } public function testNotFoundFileType() { $inputParam = (new FileInputParam('myfile'))->setRequired(); - $this->assertNull($inputParam->getValue()); - $this->assertFalse($inputParam->validate()->isOk()); + self::assertNull($inputParam->getValue()); + self::assertFalse($inputParam->validate()->isOk()); } public function testGetInputType() { $inputParam = (new GetInputParam('mykey'))->setRequired(); - $this->assertNull($inputParam->getValue()); - $this->assertEquals('', $inputParam->getDescription()); + self::assertNull($inputParam->getValue()); + self::assertEquals('', $inputParam->getDescription()); $inputParam = (new GetInputParam('mykey'))->setMulti()->setDescription('mykey description'); - $this->assertNull($inputParam->getValue()); - $this->assertEquals('mykey description', $inputParam->getDescription()); + self::assertNull($inputParam->getValue()); + self::assertEquals('mykey description', $inputParam->getDescription()); $_GET['mykey'] = 'asd'; $inputParam = (new GetInputParam('mykey'))->setRequired(); - $this->assertEquals('asd', $inputParam->getValue()); + self::assertEquals('asd', $inputParam->getValue()); } public function testPostInputType() { $inputParam = (new PostInputParam('mykey'))->setRequired(); - $this->assertNull($inputParam->getValue()); + self::assertNull($inputParam->getValue()); $inputParam = (new PostInputParam('mykey'))->setMulti(); - $this->assertNull($inputParam->getValue()); + self::assertNull($inputParam->getValue()); $_POST['mykey'] = 'asd'; $inputParam = (new PostInputParam('mykey'))->setRequired(); - $this->assertEquals('asd', $inputParam->getValue()); + self::assertEquals('asd', $inputParam->getValue()); } public function testFileInputType() { $_FILES['myfile'] = 'hello'; $inputParam = (new FileInputParam('myfile'))->setRequired(); - $this->assertEquals('hello', $inputParam->getValue()); + self::assertEquals('hello', $inputParam->getValue()); } public function testMultiFileInput() @@ -125,62 +125,62 @@ public function testMultiFileInput() $inputParam = (new FileInputParam('myfile'))->setRequired()->setMulti(); $value = $inputParam->getValue(); - $this->assertCount(2, $value); + self::assertCount(2, $value); - $this->assertEquals('file1', $value[0]['name']); - $this->assertEquals('text/plain', $value[0]['type']); - $this->assertEquals('/tmp/1', $value[0]['tmp_name']); - $this->assertEquals(101, $value[0]['size']); + self::assertEquals('file1', $value[0]['name']); + self::assertEquals('text/plain', $value[0]['type']); + self::assertEquals('/tmp/1', $value[0]['tmp_name']); + self::assertEquals(101, $value[0]['size']); - $this->assertEquals('file2', $value[1]['name']); - $this->assertEquals('image/jpeg', $value[1]['type']); - $this->assertEquals('/tmp/2', $value[1]['tmp_name']); - $this->assertEquals(102, $value[1]['size']); + self::assertEquals('file2', $value[1]['name']); + self::assertEquals('image/jpeg', $value[1]['type']); + self::assertEquals('/tmp/2', $value[1]['tmp_name']); + self::assertEquals(102, $value[1]['size']); } public function testCookiesValues() { $inputParam = (new CookieInputParam('mykey'))->setRequired(); - $this->assertNull($inputParam->getValue()); + self::assertNull($inputParam->getValue()); $_COOKIE['mykey'] = 'asd'; $inputParam = (new CookieInputParam('mykey'))->setRequired(); - $this->assertEquals('asd', $inputParam->getValue()); + self::assertEquals('asd', $inputParam->getValue()); } public function testStaticAvailableValues() { $_GET['dsgerg'] = 'asfsaf'; $inputParam = (new GetInputParam('dsgerg'))->setRequired()->setAvailableValues(['vgdgr']); - $this->assertFalse($inputParam->validate()->isOk()); + self::assertFalse($inputParam->validate()->isOk()); $_GET['dsgerg'] = 'vgdgr'; - $this->assertTrue($inputParam->validate()->isOk()); + self::assertTrue($inputParam->validate()->isOk()); } public function testStaticAvailableValuesWithSpecialKeys() { $_GET['dsgerg'] = 'asfsaf'; $inputParam = (new GetInputParam('dsgerg'))->setRequired()->setAvailableValues(['vgdgr' => 'VGDGR']); - $this->assertFalse($inputParam->validate()->isOk()); + self::assertFalse($inputParam->validate()->isOk()); $_GET['dsgerg'] = 'VGDGR'; - $this->assertFalse($inputParam->validate()->isOk()); + self::assertFalse($inputParam->validate()->isOk()); $_GET['dsgerg'] = 'vgdgr'; - $this->assertTrue($inputParam->validate()->isOk()); + self::assertTrue($inputParam->validate()->isOk()); } public function testRawPostData() { $inputParam = new RawInputParam('raw_post'); - $this->assertEquals('', $inputParam->getValue()); + self::assertEquals('', $inputParam->getValue()); } public function testPutData() { $inputParam = new PutInputParam('put'); - $this->assertEquals('', $inputParam->getValue()); + self::assertEquals('', $inputParam->getValue()); } public function testSetMultiOnJsonInputParam() diff --git a/tests/Params/ParamsProcessorTest.php b/tests/Params/ParamsProcessorTest.php index d84e3dc..9c0794e 100644 --- a/tests/Params/ParamsProcessorTest.php +++ b/tests/Params/ParamsProcessorTest.php @@ -18,16 +18,16 @@ public function testError() (new PostInputParam('mykey1'))->setRequired(), ]); - $this->assertTrue($processor->isError()); - $this->assertEquals(['mykey1' => ['Field is required']], $processor->getErrors()); + self::assertTrue($processor->isError()); + self::assertEquals(['mykey1' => ['Field is required']], $processor->getErrors()); $_GET['mykey2'] = 'x'; $processor = new ParamsProcessor([ (new GetInputParam('mykey2'))->setRequired()->setAvailableValues(['a', 'b', 'c']), ]); - $this->assertTrue($processor->isError()); - $this->assertEquals(['mykey2' => ['Field contains not available value(s)']], $processor->getErrors()); + self::assertTrue($processor->isError()); + self::assertEquals(['mykey2' => ['Field contains not available value(s)']], $processor->getErrors()); } public function testPass() @@ -42,10 +42,10 @@ public function testPass() new PostInputParam('mykey3'), ]); - $this->assertFalse($processor->isError()); - $this->assertEquals([], $processor->getErrors()); + self::assertFalse($processor->isError()); + self::assertEquals([], $processor->getErrors()); - $this->assertEquals($processor->getValues(), [ + self::assertEquals($processor->getValues(), [ 'mykey1' => 'hello', 'mykey2' => 'asdasd', 'mykey3' => 'asd', @@ -60,7 +60,7 @@ public function testOptionalDefaultValue() new PutInputParam('mykey30'), ]); - $this->assertEquals($processor->getValues(), [ + self::assertEquals($processor->getValues(), [ 'mykey10' => null, 'mykey20' => null, 'mykey30' => null, diff --git a/tests/Presenters/ApiPresenterTest.php b/tests/Presenters/ApiPresenterTest.php index 2d194d5..3394485 100644 --- a/tests/Presenters/ApiPresenterTest.php +++ b/tests/Presenters/ApiPresenterTest.php @@ -47,10 +47,10 @@ public function testSimpleResponse() $request = new Request('Api:Api:default', 'GET', ['version' => '1', 'package' => 'test', 'apiAction' => 'api']); $result = $presenter->run($request); - $this->assertEquals(200, $result->getCode()); - $this->assertEquals(['status' => 'ok'], $result->getPayload()); - $this->assertEquals('application/json', $result->getContentType()); - $this->assertEquals('utf-8', $result->getCharset()); + self::assertEquals(200, $result->getCode()); + self::assertEquals(['status' => 'ok'], $result->getPayload()); + self::assertEquals('application/json', $result->getContentType()); + self::assertEquals('utf-8', $result->getCharset()); } public function testWithAuthorization() @@ -72,8 +72,8 @@ public function testWithAuthorization() $request = new Request('Api:Api:default', 'GET', ['version' => '1', 'package' => 'test', 'apiAction' => 'api']); $result = $presenter->run($request); - $this->assertEquals(['status' => 'error', 'message' => 'Authorization header HTTP_Authorization is not set'], $result->getPayload()); - $this->assertEquals('application/json', $result->getContentType()); + self::assertEquals(['status' => 'error', 'message' => 'Authorization header HTTP_Authorization is not set'], $result->getPayload()); + self::assertEquals('application/json', $result->getContentType()); } public function testWithParams() @@ -97,14 +97,14 @@ public function testWithParams() $request = new Request('Api:Api:default', 'GET', ['version' => '1', 'package' => 'test', 'apiAction' => 'api']); $result = $presenter->run($request); - $this->assertEquals(['status' => 'error', 'message' => 'wrong input'], $result->getPayload()); - $this->assertEquals('application/json', $result->getContentType()); + self::assertEquals(['status' => 'error', 'message' => 'wrong input'], $result->getPayload()); + self::assertEquals('application/json', $result->getContentType()); Debugger::$productionMode = Debugger::DETECT; $result = $presenter->run($request); - $this->assertEquals(['status' => 'error', 'message' => 'wrong input', 'detail' => ['status' => ['Field is required']]], $result->getPayload()); - $this->assertEquals('application/json', $result->getContentType()); + self::assertEquals(['status' => 'error', 'message' => 'wrong input', 'detail' => ['status' => ['Field is required']]], $result->getPayload()); + self::assertEquals('application/json', $result->getContentType()); } public function testWithOutputs() @@ -126,7 +126,7 @@ public function testWithOutputs() $request = new Request('Api:Api:default', 'GET', ['version' => '1', 'package' => 'test', 'apiAction' => 'api']); $result = $presenter->run($request); - $this->assertEquals(['hello' => 'world'], $result->getPayload()); - $this->assertEquals('application/json', $result->getContentType()); + self::assertEquals(['hello' => 'world'], $result->getPayload()); + self::assertEquals('application/json', $result->getContentType()); } } diff --git a/tests/RateLimit/RateLimitResponseTest.php b/tests/RateLimit/RateLimitResponseTest.php index 9501579..402a4a1 100644 --- a/tests/RateLimit/RateLimitResponseTest.php +++ b/tests/RateLimit/RateLimitResponseTest.php @@ -13,23 +13,23 @@ class RateLimitResponseTest extends TestCase public function testGetters() { $rateLimitResponse = new RateLimitResponse(60, 50); - $this->assertEquals(60, $rateLimitResponse->getLimit()); - $this->assertEquals(50, $rateLimitResponse->getRemaining()); - $this->assertNull($rateLimitResponse->getRetryAfter()); - $this->assertNull($rateLimitResponse->getErrorResponse()); + self::assertEquals(60, $rateLimitResponse->getLimit()); + self::assertEquals(50, $rateLimitResponse->getRemaining()); + self::assertNull($rateLimitResponse->getRetryAfter()); + self::assertNull($rateLimitResponse->getErrorResponse()); $rateLimitResponse = new RateLimitResponse(60, 0, 3600); - $this->assertEquals(60, $rateLimitResponse->getLimit()); - $this->assertEquals(0, $rateLimitResponse->getRemaining()); - $this->assertEquals(3600, $rateLimitResponse->getRetryAfter()); - $this->assertNull($rateLimitResponse->getErrorResponse()); + self::assertEquals(60, $rateLimitResponse->getLimit()); + self::assertEquals(0, $rateLimitResponse->getRemaining()); + self::assertEquals(3600, $rateLimitResponse->getRetryAfter()); + self::assertNull($rateLimitResponse->getErrorResponse()); $rateLimitResponse = new RateLimitResponse(60, 0, 3600, new TextResponse('My error response')); - $this->assertEquals(60, $rateLimitResponse->getLimit()); - $this->assertEquals(0, $rateLimitResponse->getRemaining()); - $this->assertEquals(3600, $rateLimitResponse->getRetryAfter()); + self::assertEquals(60, $rateLimitResponse->getLimit()); + self::assertEquals(0, $rateLimitResponse->getRemaining()); + self::assertEquals(3600, $rateLimitResponse->getRetryAfter()); $errorResponse = $rateLimitResponse->getErrorResponse(); - $this->assertInstanceOf(TextResponse::class, $errorResponse); - $this->assertEquals('My error response', $errorResponse->getSource()); + self::assertInstanceOf(TextResponse::class, $errorResponse); + self::assertEquals('My error response', $errorResponse->getSource()); } } diff --git a/tests/Response/JsonApiResponseTest.php b/tests/Response/JsonApiResponseTest.php index 6e97722..acfe78a 100644 --- a/tests/Response/JsonApiResponseTest.php +++ b/tests/Response/JsonApiResponseTest.php @@ -15,7 +15,7 @@ class JsonApiResponseTest extends TestCase public function testCreatingResponse() { $jsonResponse = new JsonApiResponse(200, ['asdasd' => 'asdsd']); - $this->assertEquals(200, $jsonResponse->getCode()); + self::assertEquals(200, $jsonResponse->getCode()); $this->expectOutputString('{"asdasd":"asdsd"}'); $jsonResponse->send(new Request(new UrlScript()), new Response()); diff --git a/tests/Response/TextApiResponseTest.php b/tests/Response/TextApiResponseTest.php index da3fb01..91716ce 100644 --- a/tests/Response/TextApiResponseTest.php +++ b/tests/Response/TextApiResponseTest.php @@ -15,7 +15,7 @@ class TextApiResponseTest extends TestCase public function testCreatingResponse() { $apiResponse = new TextApiResponse(200, 'hello'); - $this->assertEquals(200, $apiResponse->getCode()); + self::assertEquals(200, $apiResponse->getCode()); $request = new Request(new UrlScript()); $response = new Response(); diff --git a/tests/Response/XmlApiResponseTest.php b/tests/Response/XmlApiResponseTest.php index a7ab2f9..af6980a 100644 --- a/tests/Response/XmlApiResponseTest.php +++ b/tests/Response/XmlApiResponseTest.php @@ -15,7 +15,7 @@ class XmlApiResponseTest extends TestCase public function testCreatingResponse() { $xmlResponse = new XmlApiResponse(200, 'hello'); - $this->assertEquals(200, $xmlResponse->getCode()); + self::assertEquals(200, $xmlResponse->getCode()); $this->expectOutputString('hello'); $xmlResponse->send(new Request(new UrlScript()), new Response()); From 39fe31dcb8fe8ae8f46a1a197f13dfa5e8c2c1d8 Mon Sep 17 00:00:00 2001 From: MartinBeranek Date: Fri, 21 Nov 2025 14:05:46 +0100 Subject: [PATCH 3/8] Pstan lvl 8 and php 8.3 fixes --- CHANGELOG.md | 2 + src/Api.php | 7 +- src/ApiDecider.php | 36 +++------- src/Authorization/BasicAuthentication.php | 4 +- .../BearerTokenAuthorization.php | 15 +++-- src/Authorization/TokenAuthorization.php | 1 + src/Component/ApiConsoleControl.php | 51 +++++++-------- src/Component/ApiListingControl.php | 19 +++--- .../DefaultApiConsoleFormFactory.php | 6 +- src/EndpointIdentifier.php | 2 +- src/Error/ErrorHandlerInterface.php | 7 +- src/Handlers/ApiHandlerInterface.php | 4 +- src/Handlers/ApiListingHandler.php | 15 +++-- src/Handlers/BaseHandler.php | 6 +- src/Handlers/CorsPreflightHandler.php | 11 +++- src/Handlers/DefaultHandler.php | 1 + src/Handlers/EchoHandler.php | 1 + src/Handlers/OpenApiHandler.php | 65 ++++++++++++++----- src/Link/ApiLink.php | 7 +- src/Misc/ConsoleRequest.php | 32 +++++++-- src/Misc/ConsoleResponse.php | 64 ++++++++++++------ src/Misc/OpenApiTransform.php | 3 +- src/Misc/StaticTokenRepository.php | 24 +------ src/Output/AbstractOutput.php | 12 ++-- src/Output/Configurator/QueryConfigurator.php | 2 +- src/Output/JsonOutput.php | 2 +- src/Params/CookieInputParam.php | 2 +- src/Params/FileInputParam.php | 8 ++- src/Params/GetInputParam.php | 2 +- src/Params/InputParam.php | 45 ++++++------- src/Params/JsonInputParam.php | 16 ++--- src/Params/ParamInterface.php | 17 ++--- src/Params/ParamsProcessor.php | 7 ++ src/Params/PostInputParam.php | 2 +- src/Params/PutInputParam.php | 5 +- src/Params/RawInputParam.php | 2 +- src/Presenters/ApiPresenter.php | 16 +++-- src/Response/JsonApiResponse.php | 10 +-- src/Response/XmlApiResponse.php | 2 +- src/ValidationResult/ValidationResult.php | 10 ++- .../ValidationResultInterface.php | 3 + 41 files changed, 311 insertions(+), 235 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 034e545..ac3c037 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip ## [Unreleased][unreleased] ### Changed * Set null value when process empty file params, instead of false +* [BC] Update to php >= 8.3, support for 8.4 +* [BC] addApi register method now requires ApiHandlerInterface as second parameter instead of string or service name diff --git a/src/Api.php b/src/Api.php index 5c53491..2d2c182 100644 --- a/src/Api.php +++ b/src/Api.php @@ -21,7 +21,7 @@ class Api /** * @param EndpointInterface $endpoint - * @param ApiHandlerInterface|string $handler + * @param ApiHandlerInterface $handler * @param ApiAuthorizationInterface $authorization * @param RateLimitInterface|null $rateLimit */ @@ -42,10 +42,7 @@ public function getEndpoint(): EndpointInterface return $this->endpoint; } - /** - * @return ApiHandlerInterface|string - */ - public function getHandler() + public function getHandler(): ApiHandlerInterface { return $this->handler; } diff --git a/src/ApiDecider.php b/src/ApiDecider.php index 541bd2e..243185a 100644 --- a/src/ApiDecider.php +++ b/src/ApiDecider.php @@ -4,30 +4,25 @@ namespace Tomaj\NetteApi; -use Nette\DI\Container; use Nette\Http\Response; use Tomaj\NetteApi\Authorization\ApiAuthorizationInterface; use Tomaj\NetteApi\Authorization\NoAuthorization; use Tomaj\NetteApi\Handlers\ApiHandlerInterface; use Tomaj\NetteApi\Handlers\CorsPreflightHandler; +use Tomaj\NetteApi\Handlers\CorsPreflightHandlerInterface; use Tomaj\NetteApi\Handlers\DefaultHandler; use Tomaj\NetteApi\RateLimit\RateLimitInterface; -use Tomaj\NetteApi\Handlers\CorsPreflightHandlerInterface; class ApiDecider { - /** @var Container */ - private $container; - /** @var Api[] */ private $apis = []; - /** @var ApiHandlerInterface|null */ - private $globalPreflightHandler = null; + private ?ApiHandlerInterface $globalPreflightHandler = null; + + public function __construct( + ) { - public function __construct(Container $container) - { - $this->container = $container; } /** @@ -61,7 +56,7 @@ public function getApi(string $method, string $version, string $package, ?string return new Api(new EndpointIdentifier($method, $version, $package, $apiAction), new DefaultHandler(), new NoAuthorization()); } - public function enableGlobalPreflight(CorsPreflightHandlerInterface $corsHandler = null) + public function enableGlobalPreflight(?CorsPreflightHandlerInterface $corsHandler = null): void { if (!$corsHandler) { $corsHandler = new CorsPreflightHandler(new Response()); @@ -71,14 +66,8 @@ public function enableGlobalPreflight(CorsPreflightHandlerInterface $corsHandler /** * Register new api handler - * - * @param EndpointInterface $endpointIdentifier - * @param ApiHandlerInterface|string $handler - * @param ApiAuthorizationInterface $apiAuthorization - * @param RateLimitInterface|null $rateLimit - * @return self */ - public function addApi(EndpointInterface $endpointIdentifier, $handler, ApiAuthorizationInterface $apiAuthorization, RateLimitInterface $rateLimit = null): self + public function addApi(EndpointInterface $endpointIdentifier, ApiHandlerInterface $handler, ApiAuthorizationInterface $apiAuthorization, ?RateLimitInterface $rateLimit = null): self { $this->apis[] = new Api($endpointIdentifier, $handler, $apiAuthorization, $rateLimit); return $this; @@ -101,15 +90,6 @@ public function getApis(): array private function getHandler(Api $api): ApiHandlerInterface { - $handler = $api->getHandler(); - if (!is_string($handler)) { - return $handler; - } - - if (str_starts_with($handler, '@')) { - return $this->container->getByName(substr($handler, 1)); - } - - return $this->container->getByType($handler); + return $api->getHandler(); } } diff --git a/src/Authorization/BasicAuthentication.php b/src/Authorization/BasicAuthentication.php index e34a225..ea557c3 100644 --- a/src/Authorization/BasicAuthentication.php +++ b/src/Authorization/BasicAuthentication.php @@ -8,8 +8,8 @@ class BasicAuthentication implements ApiAuthorizationInterface { - /** @var array */ - private $authentications; + /** @var array */ + private array $authentications; /** @var IRequest */ private $httpRequest; diff --git a/src/Authorization/BearerTokenAuthorization.php b/src/Authorization/BearerTokenAuthorization.php index a5cd14b..ebd0f7c 100644 --- a/src/Authorization/BearerTokenAuthorization.php +++ b/src/Authorization/BearerTokenAuthorization.php @@ -9,12 +9,13 @@ class BearerTokenAuthorization extends TokenAuthorization { - /** - * BearerTokenAuthorization constructor. - * - * @param TokenRepositoryInterface $tokenRepository - * @param IpDetectorInterface $ipDetector - */ + private const EXPECTED_HTTP_PARTS = 2; + /** + * BearerTokenAuthorization constructor. + * + * @param TokenRepositoryInterface $tokenRepository + * @param IpDetectorInterface $ipDetector + */ public function __construct(TokenRepositoryInterface $tokenRepository, IpDetectorInterface $ipDetector) { parent::__construct($tokenRepository, $ipDetector); @@ -33,7 +34,7 @@ protected function readAuthorizationToken(): ?string return null; } $parts = explode(' ', $_SERVER['HTTP_AUTHORIZATION']); - if (count($parts) !== 2) { + if (count($parts) !== self::EXPECTED_HTTP_PARTS) { $this->errorMessage = 'Authorization header contains invalid structure'; return null; } diff --git a/src/Authorization/TokenAuthorization.php b/src/Authorization/TokenAuthorization.php index 6378f7d..4890be5 100644 --- a/src/Authorization/TokenAuthorization.php +++ b/src/Authorization/TokenAuthorization.php @@ -113,6 +113,7 @@ private function ipInRange(string $ip, string $range): bool list($range, $netmask) = explode('/', $range, 2); $range_decimal = ip2long($range); $ipDecimal = ip2long($ip); + /** @phpstan-ignore-next-line */ $wildcard_decimal = pow(2, (32 - (int)$netmask)) - 1; $netmask_decimal = ~ $wildcard_decimal; return (($ipDecimal & $netmask_decimal) === ($range_decimal & $netmask_decimal)); diff --git a/src/Component/ApiConsoleControl.php b/src/Component/ApiConsoleControl.php index c35d67d..c343c84 100644 --- a/src/Component/ApiConsoleControl.php +++ b/src/Component/ApiConsoleControl.php @@ -6,8 +6,8 @@ use Nette\Application\UI\Control; use Nette\Application\UI\Form; -use Nette\Bridges\ApplicationLatte\Template; -use Nette\Forms\IFormRenderer; +use Nette\Bridges\ApplicationLatte\DefaultTemplate; +use Nette\Forms\FormRenderer; use Nette\Http\IRequest; use Nette\Utils\ArrayHash; use Tomaj\Form\Renderer\BootstrapVerticalRenderer; @@ -19,40 +19,29 @@ use Tomaj\NetteApi\Handlers\ApiHandlerInterface; use Tomaj\NetteApi\Link\ApiLink; use Tomaj\NetteApi\Misc\ConsoleRequest; -use Tomaj\NetteApi\Component\ApiConsoleFormFactoryInterface; -use Tomaj\NetteApi\Component\DefaultApiConsoleFormFactory; class ApiConsoleControl extends Control { - private $request; + private ApiConsoleFormFactoryInterface $formFactory; - private $endpoint; + private ?FormRenderer $formRenderer = null; - private $handler; + private ?string $templateFilePath = null; - private $authorization; - - private $apiLink; - - private $formFactory; - - private $formRenderer; - - private $templateFilePath; - - public function __construct(IRequest $request, EndpointInterface $endpoint, ApiHandlerInterface $handler, ApiAuthorizationInterface $authorization, ApiLink $apiLink = null, ApiConsoleFormFactoryInterface $formFactory = null) - { - $this->request = $request; - $this->endpoint = $endpoint; - $this->handler = $handler; - $this->authorization = $authorization; - $this->apiLink = $apiLink; + public function __construct( + private IRequest $request, + private EndpointInterface $endpoint, + private ApiHandlerInterface $handler, + private ApiAuthorizationInterface $authorization, + private ?ApiLink $apiLink = null, + ?ApiConsoleFormFactoryInterface $formFactory = null + ) { $this->formFactory = $formFactory ?: new DefaultApiConsoleFormFactory(); } public function render(): void { - /** @var Template $template */ + /** @var DefaultTemplate $template */ $template = $this->getTemplate(); $template->setFile($this->getTemplateFilePath()); $template->add('handler', $this->handler); @@ -97,7 +86,7 @@ public function formSucceeded(Form $form, ArrayHash $values): void $additionalValues['getFields'][$queryParamName] = $values[$queryParamName] ?? null; } elseif ($this->authorization instanceof HeaderApiKeyAuthentication) { $headerName = $this->authorization->getHeaderName(); - $additionalValues['headers'][] = $headerName . ':' . $values['header_api_key'] ?? null; + $additionalValues['headers'][] = $headerName . ':' . ($values['header_api_key'] ?? null); } elseif ($this->authorization instanceof CookieApiKeyAuthentication) { $cookieName = $this->authorization->getCookieName(); $additionalValues['cookieFields'][$cookieName] = $values['cookie_api_key'] ?? null; @@ -106,7 +95,7 @@ public function formSucceeded(Form $form, ArrayHash $values): void $consoleRequest = new ConsoleRequest($this->handler, $this->endpoint, $this->apiLink); $result = $consoleRequest->makeRequest($url, $method, $this->filterFormValues((array) $values), $additionalValues, $token); - /** @var Template $template */ + /** @var DefaultTemplate $template */ $template = $this->getTemplate(); $template->add('response', $result); @@ -115,12 +104,12 @@ public function formSucceeded(Form $form, ArrayHash $values): void } } - public function setFormRenderer(IFormRenderer $formRenderer): void + public function setFormRenderer(FormRenderer $formRenderer): void { $this->formRenderer = $formRenderer; } - private function getFormRenderer(): IFormRenderer + private function getFormRenderer(): FormRenderer { return $this->formRenderer ?: new BootstrapVerticalRenderer(); } @@ -135,6 +124,10 @@ private function getTemplateFilePath(): string return $this->templateFilePath ?: __DIR__ . '/console.latte'; } + /** + * @param mixed[] $values + * @return mixed[] + */ private function filterFormValues(array $values): array { foreach ($this->handler->params() as $param) { diff --git a/src/Component/ApiListingControl.php b/src/Component/ApiListingControl.php index 4965a98..9ac64b2 100644 --- a/src/Component/ApiListingControl.php +++ b/src/Component/ApiListingControl.php @@ -5,21 +5,24 @@ namespace Tomaj\NetteApi\Component; use Nette\Application\UI\Control; -use Nette\Bridges\ApplicationLatte\Template; -use Tomaj\NetteApi\ApiDecider; +use Nette\Bridges\ApplicationLatte\DefaultTemplate; use Tomaj\NetteApi\Api; +use Tomaj\NetteApi\ApiDecider; /** - * @method void onClick(string $method, int $version, string $package, ?string $apiAction) + * @method void onClick(string $method, string $version, string $package, ?string $apiAction) */ class ApiListingControl extends Control { /** @var ApiDecider */ private $apiDecider; - public $onClick = []; + /** + * @var array + */ + public array $onClick = []; - private $templateFilePath; + private ?string $templateFilePath = null; public function __construct(ApiDecider $apiDecider) { @@ -30,21 +33,21 @@ public function render(): void { $apis = $this->apiDecider->getApis(); - /** @var Template $template */ + /** @var DefaultTemplate $template */ $template = $this->getTemplate(); $template->add('apis', $this->groupApis($apis)); $template->setFile($this->getTemplateFilePath()); $template->render(); } - public function handleSelect(string $method, $version, string $package, ?string $apiAction = null): void + public function handleSelect(string $method, string $version, string $package, ?string $apiAction = null): void { $this->onClick($method, $version, $package, $apiAction); } /** * @param Api[] $handlers - * @return array + * @return array>. */ private function groupApis(array $handlers): array { diff --git a/src/Component/DefaultApiConsoleFormFactory.php b/src/Component/DefaultApiConsoleFormFactory.php index 7c48715..246da45 100644 --- a/src/Component/DefaultApiConsoleFormFactory.php +++ b/src/Component/DefaultApiConsoleFormFactory.php @@ -20,6 +20,7 @@ class DefaultApiConsoleFormFactory implements ApiConsoleFormFactoryInterface { + private const HTTP_PORT = 80; public function create( IRequest $request, EndpointInterface $endpoint, @@ -67,13 +68,16 @@ protected function getUrl(IRequest $request, EndpointInterface $endpoint, ?ApiLi $scheme = $_SERVER['HTTP_X_FORWARDED_PROTO']; } $port = ''; - if ($uri->scheme === 'http' && $uri->port !== 80) { + if ($uri->scheme === 'http' && $uri->port !== self::HTTP_PORT) { $port = ':' . $uri->port; } return $scheme . '://' . $uri->host . $port . '/api/' . $endpoint->getUrl(); } + /** + * @param array $defaults + */ protected function addAuthorization(Form $form, ApiAuthorizationInterface $authorization, array &$defaults): void { if ($authorization instanceof BearerTokenAuthorization) { diff --git a/src/EndpointIdentifier.php b/src/EndpointIdentifier.php index 43fae40..ca249d8 100644 --- a/src/EndpointIdentifier.php +++ b/src/EndpointIdentifier.php @@ -41,7 +41,7 @@ public function getMethod(): string public function getVersion(): string { - return $this->version; + return (string) $this->version; } public function getPackage(): string diff --git a/src/Error/ErrorHandlerInterface.php b/src/Error/ErrorHandlerInterface.php index 91974e4..10cfe99 100644 --- a/src/Error/ErrorHandlerInterface.php +++ b/src/Error/ErrorHandlerInterface.php @@ -4,9 +4,9 @@ namespace Tomaj\NetteApi\Error; +use Throwable; use Tomaj\NetteApi\Authorization\ApiAuthorizationInterface; use Tomaj\NetteApi\Response\JsonApiResponse; -use Throwable; interface ErrorHandlerInterface { @@ -16,13 +16,12 @@ interface ErrorHandlerInterface public function handle(Throwable $exception, array $params): JsonApiResponse; /** - * @param array $errors - * @param array $params + * @param array $errors */ public function handleInputParams(array $errors): JsonApiResponse; /** - * @param array $errors + * @param array $errors * @param array $params */ public function handleSchema(array $errors, array $params): JsonApiResponse; diff --git a/src/Handlers/ApiHandlerInterface.php b/src/Handlers/ApiHandlerInterface.php index b2ed174..b40271c 100644 --- a/src/Handlers/ApiHandlerInterface.php +++ b/src/Handlers/ApiHandlerInterface.php @@ -32,7 +32,7 @@ public function params(): array; /** * Returns list of tags for handler - * @return array + * @return string[] */ public function tags(): array; @@ -46,7 +46,7 @@ public function deprecated(): bool; * Main handle method that will be executed when api * endpoint contected with this handler will be triggered * - * @param array $params + * @param array $params * * @return ResponseInterface */ diff --git a/src/Handlers/ApiListingHandler.php b/src/Handlers/ApiListingHandler.php index 0d0be0e..74ca594 100644 --- a/src/Handlers/ApiListingHandler.php +++ b/src/Handlers/ApiListingHandler.php @@ -4,8 +4,8 @@ namespace Tomaj\NetteApi\Handlers; -use Tomaj\NetteApi\ApiDecider; use Tomaj\NetteApi\Api; +use Tomaj\NetteApi\ApiDecider; use Tomaj\NetteApi\Link\ApiLink; use Tomaj\NetteApi\Params\InputParam; use Tomaj\NetteApi\Response\JsonApiResponse; @@ -41,17 +41,17 @@ public function __construct(ApiDecider $apiDecider, ApiLink $apiLink) */ public function handle(array $params): ResponseInterface { - $version = $this->getEndpoint()->getVersion(); - $endpoints = $this->getApiList($version); + $version = $this->getEndpoint()?->getVersion(); + $endpoints = $this->getApiList($version ?? ''); return new JsonApiResponse(200, ['endpoints' => $endpoints]); } /** * Create handler list for specified version * - * @param integer $version + * @param string $version * - * @return array + * @return array */ private function getApiList(string $version): array { @@ -77,11 +77,12 @@ private function getApiList(string $version): array * * @param ApiHandlerInterface $handler * - * @return array + * @return array{type: string, key: string, is_required: bool, available_values?: non-empty-array} */ private function createParamsList(ApiHandlerInterface $handler): array { - return array_map(function (InputParam $param) { + /** @phpstan-ignore-next-line */ + return array_map(function (InputParam $param): array { $parameter = [ 'type' => $param->getType(), 'key' => $param->getKey(), diff --git a/src/Handlers/BaseHandler.php b/src/Handlers/BaseHandler.php index e1a3116..4ef8897 100644 --- a/src/Handlers/BaseHandler.php +++ b/src/Handlers/BaseHandler.php @@ -60,6 +60,7 @@ public function params(): array /** * {@inheritdoc} + * @return string[] */ public function tags(): array { @@ -119,7 +120,7 @@ final public function setupLinkGenerator(LinkGenerator $linkGenerator): self /** * Create link to actual handler endpoint * - * @param array $params + * @param array $params * * @return string * @throws InvalidLinkException if handler doesn't have linkgenerator or endpoint @@ -137,11 +138,12 @@ final public function createLink(array $params = []): string 'package' => $this->endpoint->getPackage(), 'apiAction' => $this->endpoint->getApiAction() ], $params); - return $this->linkGenerator->link('Api:Api:default', $params); + return $this->linkGenerator->link('Api:Api:default', $params) ?: ''; } /** * {@inheritdoc} + * @param array $params */ abstract public function handle(array $params): ResponseInterface; } diff --git a/src/Handlers/CorsPreflightHandler.php b/src/Handlers/CorsPreflightHandler.php index 1213798..cde5ef3 100644 --- a/src/Handlers/CorsPreflightHandler.php +++ b/src/Handlers/CorsPreflightHandler.php @@ -10,10 +10,14 @@ class CorsPreflightHandler extends BaseHandler implements CorsPreflightHandlerInterface { - private $response; + private Response $response; - private $headers = []; + /** @var array */ + private array $headers = []; + /** + * @param array $headers + */ public function __construct( Response $response, array $headers = [ @@ -28,6 +32,9 @@ public function __construct( $this->headers = $headers; } + /** + * @param array $params + */ public function handle(array $params): ResponseInterface { foreach ($this->headers as $name => $values) { diff --git a/src/Handlers/DefaultHandler.php b/src/Handlers/DefaultHandler.php index 598881e..6fba838 100644 --- a/src/Handlers/DefaultHandler.php +++ b/src/Handlers/DefaultHandler.php @@ -12,6 +12,7 @@ class DefaultHandler extends BaseHandler { /** * {@inheritdoc} + * @param array $params */ public function handle(array $params): ResponseInterface { diff --git a/src/Handlers/EchoHandler.php b/src/Handlers/EchoHandler.php index 0a50537..1636c42 100644 --- a/src/Handlers/EchoHandler.php +++ b/src/Handlers/EchoHandler.php @@ -23,6 +23,7 @@ public function params(): array /** * {@inheritdoc} + * @param array $params */ public function handle(array $params): ResponseInterface { diff --git a/src/Handlers/OpenApiHandler.php b/src/Handlers/OpenApiHandler.php index 7f372c4..38f7e07 100644 --- a/src/Handlers/OpenApiHandler.php +++ b/src/Handlers/OpenApiHandler.php @@ -40,16 +40,19 @@ class OpenApiHandler extends BaseHandler /** @var Request */ private $request; + /** @var array */ private $initData = []; + /** @var array */ private $definitions = []; + /** * OpenApiHandler constructor. * @param ApiDecider $apiDecider * @param ApiLink $apiLink * @param Request $request - * @param array $initData - structured data for initialization response + * @param array $initData - structured data for initialization response */ public function __construct( ApiDecider $apiDecider, @@ -64,6 +67,9 @@ public function __construct( $this->initData = $initData; } + /** + * @return InputParam[] + */ public function params(): array { $availableFormats = ['json']; @@ -85,6 +91,7 @@ public function description(): string /** * {@inheritdoc} + * @return string[] */ public function tags(): array { @@ -93,11 +100,12 @@ public function tags(): array /** * {@inheritdoc} + * @param array $params */ public function handle(array $params): ResponseInterface { - $version = $this->getEndpoint()->getVersion(); - $apis = $this->getApis($version); + $version = $this->getEndpoint()?->getVersion(); + $apis = $this->getApis($version ?: ''); $scheme = $this->request->getUrl()->getScheme(); $baseUrl = $this->request->getUrl()->getHostUrl(); $basePath = $this->getBasePath($apis, $baseUrl); @@ -152,7 +160,7 @@ public function handle(array $params): ResponseInterface $data = [ 'openapi' => '3.0.0', 'info' => [ - 'version' => (string)$version, + 'version' => $version, 'title' => 'Nette API', ], 'servers' => [ @@ -227,6 +235,9 @@ public function handle(array $params): ResponseInterface return new JsonApiResponse(IResponse::S200_OK, $data); } + /** + * @return Api[] + */ private function getApis(string $version): array { return array_filter($this->apiDecider->getApis(), function (Api $api) use ($version) { @@ -238,7 +249,7 @@ private function getApis(string $version): array * @param Api[] $versionApis * @param string $baseUrl * @param string $basePath - * @return array + * @return array * @throws InvalidLinkException */ private function getPaths(array $versionApis, string $baseUrl, string $basePath): array @@ -315,24 +326,29 @@ private function getPaths(array $versionApis, string $baseUrl, string $basePath) ]; if (!empty($examples = $output->getExamples())) { if (count($examples) === 1) { - $example = is_array($output->getExample())? $output->getExample() : json_decode($output->getExample(), true); + $example = is_array($output->getExample()) ? $output->getExample() : json_decode($output->getExample(), true); + /** @phpstan-ignore-next-line */ $responses[$output->getCode()]['content']['application/json; charset=utf-8']['example'] = $example; } else { foreach ($examples as $exampleKey => $example) { - $example = is_array($example)? $example : json_decode($example, true); + $example = is_array($example) ? $example : json_decode($example, true); + /** @phpstan-ignore-next-line */ $responses[$output->getCode()]['content']['application/json; charset=utf-8']['examples'][$exampleKey] = $example; } } } } else { if (!isset($responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']['oneOf'])) { + /** @phpstan-ignore-next-line */ $tmp = $responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']; unset($responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']); + /** @phpstan-ignore-next-line */ $responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema'] = [ 'oneOf' => [], ]; $responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']['oneOf'][] = $tmp; } + /** @phpstan-ignore-next-line */ $responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']['oneOf'][] = $schema; } } @@ -397,6 +413,9 @@ private function getPaths(array $versionApis, string $baseUrl, string $basePath) return $list; } + /** + * @param Api[] $apis + */ private function getBasePath(array $apis, string $baseUrl): string { $basePath = ''; @@ -406,7 +425,8 @@ private function getBasePath(array $apis, string $baseUrl): string return rtrim(str_replace($baseUrl, '', $basePath), '/'); } - private function getLongestCommonSubstring($path1, $path2) + + private function getLongestCommonSubstring(?string $path1, string $path2): string { if ($path1 === null) { return $path2; @@ -426,10 +446,9 @@ private function getLongestCommonSubstring($path1, $path2) * Create array with params for specified handler * * @param ApiHandlerInterface $handler - * - * @return array + * @return array> */ - private function createParamsList(ApiHandlerInterface $handler) + private function createParamsList(ApiHandlerInterface $handler): array { $parameters = []; foreach ($handler->params() as $param) { @@ -476,6 +495,10 @@ private function createParamsList(ApiHandlerInterface $handler) return $parameters; } + /** + * @param ApiHandlerInterface $handler + * @return array|null + */ private function createRequestBody(ApiHandlerInterface $handler) { $requestBody = [ @@ -489,10 +512,10 @@ private function createRequestBody(ApiHandlerInterface $handler) $schema = json_decode($param->getSchema(), true); if (!empty($examples = $param->getExamples())) { if (count($examples) === 1) { - $schema['example'] = is_array($param->getExample())? $param->getExample() : json_decode($param->getExample(), true); + $schema['example'] = is_array($param->getExample()) ? $param->getExample() : json_decode($param->getExample(), true); } else { foreach ($examples as $exampleKey => $example) { - $schema['examples'][$exampleKey] = is_array($example)? $example : json_decode($example, true); + $schema['examples'][$exampleKey] = is_array($example) ? $example : json_decode($example, true); } } } @@ -607,6 +630,10 @@ private function createRequestBody(ApiHandlerInterface $handler) return null; } + /** + * @param int|string $type + * @return string + */ private function createIn($type) { if ($type == InputParam::TYPE_GET) { @@ -618,6 +645,10 @@ private function createIn($type) return 'body'; } + /** + * @param array $schema + * @return array + */ private function transformSchema(array $schema) { OpenApiTransform::transformTypes($schema); @@ -628,10 +659,14 @@ private function transformSchema(array $schema) } unset($schema['definitions']); } - return json_decode(str_replace('#/definitions/', '#/components/schemas/', json_encode($schema, JSON_UNESCAPED_SLASHES)), true); + return json_decode(str_replace('#/definitions/', '#/components/schemas/', json_encode($schema, JSON_UNESCAPED_SLASHES) ?: ''), true); } - private function addDefinition($name, $definition) + /** + * @param string $name + * @param array $definition + */ + private function addDefinition($name, $definition): void { if (isset($this->definitions[$name]) && $this->definitions[$name] !== $definition) { throw new InvalidArgumentException('Definition with name ' . $name . ' already exists. Rename it.'); diff --git a/src/Link/ApiLink.php b/src/Link/ApiLink.php index c9a8e1b..2f68dec 100644 --- a/src/Link/ApiLink.php +++ b/src/Link/ApiLink.php @@ -27,18 +27,17 @@ public function __construct(LinkGenerator $linkGenerator) * Create link to specified api endpoint * * @param EndpointInterface $endpoint - * @param array $params + * @param array $params * - * @return string * @throws InvalidLinkException */ - public function link(EndpointInterface $endpoint, $params = []) + public function link(EndpointInterface $endpoint, $params = []): string { $params = array_merge([ 'version' => $endpoint->getVersion(), 'package' => $endpoint->getPackage(), 'apiAction' => $endpoint->getApiAction() ], $params); - return $this->linkGenerator->link('Api:Api:default', $params); + return $this->linkGenerator->link('Api:Api:default', $params) ?: ''; } } diff --git a/src/Misc/ConsoleRequest.php b/src/Misc/ConsoleRequest.php index f9ab891..43c7b58 100644 --- a/src/Misc/ConsoleRequest.php +++ b/src/Misc/ConsoleRequest.php @@ -13,6 +13,9 @@ class ConsoleRequest { + public const DEFAULT_TIMEOUT = 30; + public const ELAPSED_MILLISECONDS = 1000; + /** @var ApiHandlerInterface */ private $handler; @@ -29,6 +32,13 @@ public function __construct(ApiHandlerInterface $handler, ?EndpointInterface $en $this->apiLink = $apiLink; } + /** + * @param string $url + * @param string $method + * @param array $values + * @param array $additionalValues + * @param string|null $token + */ public function makeRequest(string $url, string $method, array $values, array $additionalValues = [], ?string $token = null): ConsoleResponse { list($postFields, $getFields, $cookieFields, $rawPost, $putFields) = $this->processValues($values); @@ -73,7 +83,7 @@ public function makeRequest(string $url, string $method, array $values, array $a curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_VERBOSE, false); - curl_setopt($curl, CURLOPT_TIMEOUT, $additionalValues['timeout'] ?? 30); + curl_setopt($curl, CURLOPT_TIMEOUT, $additionalValues['timeout'] ?? self::DEFAULT_TIMEOUT); curl_setopt($curl, CURLOPT_HEADER, true); if (count($postFields) || $rawPost || $putRawPost !== null) { @@ -113,13 +123,14 @@ public function makeRequest(string $url, string $method, array $values, array $a ); $response = curl_exec($curl); - $elapsed = intval((microtime(true) - $startTime) * 1000); + $elapsed = (int) ((microtime(true) - $startTime) * self::ELAPSED_MILLISECONDS); if ($response === false) { $response = ''; } $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + $response = (string) $response; $responseHeaders = substr($response, 0, $headerSize); $responseBody = substr($response, $headerSize); @@ -138,18 +149,21 @@ public function makeRequest(string $url, string $method, array $values, array $a /** * Process given values to POST and GET fields * - * @param array $values - * - * @return array + * @param array $values + * @return array{0:array,1:array,2:array,3:string|null,4:array} */ private function processValues(array $values): array { $params = $this->handler->params(); + /** @var array $postFields */ $postFields = []; $rawPost = isset($values['post_raw']) ? $values['post_raw'] : null; + /** @var array $getFields */ $getFields = []; + /** @var array $putFields */ $putFields = []; + /** @var array $cookieFields */ $cookieFields = []; foreach ($values as $key => $value) { @@ -165,7 +179,7 @@ private function processValues(array $values): array } if ($param->isMulti()) { - if (in_array($param->getType(), [InputParam::TYPE_POST, InputParam::TYPE_FILE])) { + if (in_array($param->getType(), [InputParam::TYPE_POST, InputParam::TYPE_FILE], true)) { $postFields[$key][] = $valueData; } elseif ($param->getType() === InputParam::TYPE_PUT) { $putFields[$key][] = $valueData; @@ -175,7 +189,7 @@ private function processValues(array $values): array $getFields[$key][] = urlencode((string)$valueData); } } else { - if (in_array($param->getType(), [InputParam::TYPE_POST, InputParam::TYPE_FILE])) { + if (in_array($param->getType(), [InputParam::TYPE_POST, InputParam::TYPE_FILE], true)) { $postFields[$key] = $valueData; } elseif ($param->getType() === InputParam::TYPE_PUT) { $putFields[$key] = $valueData; @@ -222,6 +236,10 @@ private function processParam(ParamInterface $param, string $key, $value) return null; } + /** + * @param array $values + * @return array + */ private function normalizeValues(array $values): array { $result = []; diff --git a/src/Misc/ConsoleResponse.php b/src/Misc/ConsoleResponse.php index e231ef9..1d0897a 100644 --- a/src/Misc/ConsoleResponse.php +++ b/src/Misc/ConsoleResponse.php @@ -6,34 +6,46 @@ class ConsoleResponse { - private $postFields; + /** @var array */ + private array $postFields; - private $rawPost; + private ?string $rawPost; - private $getFields; + /** @var array */ + private array $getFields; - private $cookieFields; + /** @var array */ + private array $cookieFields; - private $url; + private string $url; - private $method; + private string $method; - private $headers; + /** @var array */ + private array $headers; - private $responseCode; + private ?int $responseCode = null; - private $responseBody; + private ?string $responseBody = null; - private $responseHeaders; + private ?string $responseHeaders = null; + private ?int $responseTime = null; - private $responseTime; + private bool $isError = false; - private $isError = false; + private ?int $errorNumber = null; - private $errorNumber; - - private $errorMessage; + private ?string $errorMessage = null; + /** + * @param string $url + * @param string $method + * @param array $postFields + * @param array $getFields + * @param array $cookieFields + * @param array $headers + * @param string|null $rawPost + */ public function __construct(string $url, string $method, array $postFields = [], array $getFields = [], array $cookieFields = [], array $headers = [], ?string $rawPost = null) { $this->url = $url; @@ -71,6 +83,9 @@ public function getMethod(): string return $this->method; } + /** + * @return array + */ public function getPostFields(): array { return $this->postFields; @@ -81,16 +96,25 @@ public function getRawPost(): ?string return $this->rawPost; } + /** + * @return array + */ public function getGetFields(): array { return $this->getFields; } + /** + * @return array + */ public function getCookieFields(): array { return $this->cookieFields; } + /** + * @return array + */ public function getHeaders(): array { return $this->headers; @@ -106,7 +130,7 @@ public function getResponseCode(): ?int return $this->responseCode; } - public function getResponseBody(): string + public function getResponseBody(): ?string { return $this->responseBody; } @@ -121,7 +145,7 @@ public function getFormattedJsonBody(): string if ($decoded) { $body = json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } - return $body; + return $body ?: ''; } public function getResponseHeaders(): ?string @@ -129,17 +153,17 @@ public function getResponseHeaders(): ?string return $this->responseHeaders; } - public function getResponseTime(): int + public function getResponseTime(): ?int { return $this->responseTime; } - public function getErrorNumber(): int + public function getErrorNumber(): ?int { return $this->errorNumber; } - public function getErrorMessage(): string + public function getErrorMessage(): ?string { return $this->errorMessage; } diff --git a/src/Misc/OpenApiTransform.php b/src/Misc/OpenApiTransform.php index 6afbfdf..3b00241 100644 --- a/src/Misc/OpenApiTransform.php +++ b/src/Misc/OpenApiTransform.php @@ -7,6 +7,7 @@ class OpenApiTransform { /** + * @param array $schema * @param string|int|null $parent */ public static function transformTypes(array &$schema, $parent = null): void @@ -14,7 +15,7 @@ public static function transformTypes(array &$schema, $parent = null): void foreach ($schema as $key => &$value) { if ($key === 'type' && is_array($value) && $parent !== 'properties') { if (count($value) > 1 && in_array('null', $value, true)) { - unset($value[array_search('null', $value)]); + unset($value[array_search('null', $value, true)]); $schema['nullable'] = true; } if (count($value) === 1) { diff --git a/src/Misc/StaticTokenRepository.php b/src/Misc/StaticTokenRepository.php index a9aa642..0e061e3 100644 --- a/src/Misc/StaticTokenRepository.php +++ b/src/Misc/StaticTokenRepository.php @@ -10,28 +10,10 @@ class StaticTokenRepository implements BearerTokenRepositoryInterface { /** - * array + * @param array $validTokens Array of valid tokens as keys and optional IP restrictions as values */ - private $validTokens = []; - - /** - * Create static bearer token repository. - * You can pass multiple tokens that will be available for your api. - * Format is associtive array where key is token string and value is IP range - * - * Example: - * ['ef0p9iwehjgoihrgrsdgfoihw4t' => '*'] - * - * Or: - * ['asfoihegoihregoihrhgrehg' => '127.0.0.1', 'asfo9uyewtoiyewgt4ty4r' => '*'] - * - * @see BearerTokenAuthorization#isValidIp for all available Ip range formats - * - * @param array $validTokens - */ - public function __construct($validTokens = []) + public function __construct(private array $validTokens = []) { - $this->validTokens = $validTokens; } /** @@ -39,7 +21,7 @@ public function __construct($validTokens = []) */ public function validToken(string $token): bool { - return in_array($token, array_keys($this->validTokens)); + return in_array($token, array_keys($this->validTokens), true); } /** diff --git a/src/Output/AbstractOutput.php b/src/Output/AbstractOutput.php index ed2a0f2..cbdc1cb 100644 --- a/src/Output/AbstractOutput.php +++ b/src/Output/AbstractOutput.php @@ -6,12 +6,14 @@ abstract class AbstractOutput implements OutputInterface { - protected $code; + /** @var int */ + protected int $code; - protected $description; + /** @var string */ + protected string $description; - /** @var array */ - protected $examples = []; + /** @var array */ + protected array $examples = []; public function __construct(int $code, string $description = '') { @@ -66,7 +68,7 @@ public function getExample() /** * Returns all examples - * @return array + * @return array */ public function getExamples(): array { diff --git a/src/Output/Configurator/QueryConfigurator.php b/src/Output/Configurator/QueryConfigurator.php index 0a4fba1..6754790 100644 --- a/src/Output/Configurator/QueryConfigurator.php +++ b/src/Output/Configurator/QueryConfigurator.php @@ -10,7 +10,7 @@ class QueryConfigurator implements ConfiguratorInterface { private $schemaValidateParam = 'schema_validate'; private $errorDetailParam = 'error_detail'; - public $request = null; + public Request $request; /** * @param string $schemaValidateParam Name of get parameter to enable schema validation diff --git a/src/Output/JsonOutput.php b/src/Output/JsonOutput.php index 38bcf68..5fb49d9 100644 --- a/src/Output/JsonOutput.php +++ b/src/Output/JsonOutput.php @@ -29,7 +29,7 @@ public function validate(ResponseInterface $response): ValidationResultInterface return new ValidationResult(ValidationResult::STATUS_ERROR, ['Response code doesn\'t match']); } - $value = json_decode(json_encode($response->getPayload())); + $value = json_decode(json_encode($response->getPayload()) ?: ''); $schemaValidator = new JsonSchemaValidator(); return $schemaValidator->validate($value, $this->schema); diff --git a/src/Params/CookieInputParam.php b/src/Params/CookieInputParam.php index acdd90f..7ff4417 100644 --- a/src/Params/CookieInputParam.php +++ b/src/Params/CookieInputParam.php @@ -8,7 +8,7 @@ class CookieInputParam extends InputParam { protected $type = self::TYPE_COOKIE; - public function getValue() + public function getValue(): mixed { if (!filter_has_var(INPUT_COOKIE, $this->key) && isset($_COOKIE[$this->key])) { return $_COOKIE[$this->key]; diff --git a/src/Params/FileInputParam.php b/src/Params/FileInputParam.php index 11df2f8..1386f96 100644 --- a/src/Params/FileInputParam.php +++ b/src/Params/FileInputParam.php @@ -16,7 +16,7 @@ protected function addFormInput(Form $form, string $key): BaseControl return $form->addUpload($key, $this->getParamLabel()); } - public function getValue() + public function getValue(): mixed { if (isset($_FILES[$this->key])) { return $this->isMulti() ? $this->processMultiFileUploads($_FILES[$this->key]) : $_FILES[$this->key]; @@ -24,7 +24,11 @@ public function getValue() return $this->default; } - private function processMultiFileUploads($files) + /** + * @param array $files + * @return array + */ + private function processMultiFileUploads(array$files): array { $result = []; foreach ($files as $key => $values) { diff --git a/src/Params/GetInputParam.php b/src/Params/GetInputParam.php index b6b7a9c..f8d502c 100644 --- a/src/Params/GetInputParam.php +++ b/src/Params/GetInputParam.php @@ -8,7 +8,7 @@ class GetInputParam extends InputParam { protected $type = self::TYPE_GET; - public function getValue() + public function getValue(): mixed { if (!filter_has_var(INPUT_GET, $this->key) && isset($_GET[$this->key])) { return $_GET[$this->key]; diff --git a/src/Params/InputParam.php b/src/Params/InputParam.php index 468520f..9777975 100644 --- a/src/Params/InputParam.php +++ b/src/Params/InputParam.php @@ -12,16 +12,18 @@ abstract class InputParam implements ParamInterface { - const TYPE_POST = 'POST'; - const TYPE_GET = 'GET'; - const TYPE_PUT = 'PUT'; - const TYPE_FILE = 'FILE'; - const TYPE_COOKIE = 'COOKIE'; - const TYPE_POST_RAW = 'POST_RAW'; - const TYPE_POST_JSON = 'POST_JSON'; + public const TYPE_POST = 'POST'; + public const TYPE_GET = 'GET'; + public const TYPE_PUT = 'PUT'; + public const TYPE_FILE = 'FILE'; + public const TYPE_COOKIE = 'COOKIE'; + public const TYPE_POST_RAW = 'POST_RAW'; + public const TYPE_POST_JSON = 'POST_JSON'; - const OPTIONAL = false; - const REQUIRED = true; + public const OPTIONAL = false; + public const REQUIRED = true; + + public const DEFAULT_MULTI_INPUT_COUNT = 5; /** @var string */ protected $type; @@ -32,7 +34,7 @@ abstract class InputParam implements ParamInterface /** @var bool */ protected $required = self::OPTIONAL; - /** @var array|null */ + /** @var array|null */ protected $availableValues = null; /** @var bool */ @@ -44,7 +46,7 @@ abstract class InputParam implements ParamInterface /** @var mixed */ protected $default; - /** @var array */ + /** @var array */ protected $examples = []; public function __construct(string $key) @@ -58,6 +60,9 @@ public function setRequired(): self return $this; } + /** + * @param array $availableValues + */ public function setAvailableValues(array $availableValues): self { if ($availableValues === array_values($availableValues)) { @@ -88,6 +93,9 @@ public function isRequired(): bool return $this->required; } + /** + * @return array|null + */ public function getAvailableValues(): ?array { return $this->availableValues; @@ -119,10 +127,7 @@ public function setDefault($default): self return $this; } - /** - * @return mixed - */ - public function getDefault() + public function getDefault(): mixed { return $this->default; } @@ -151,11 +156,7 @@ public function setExample($example): self return $this; } - /** - * Returns first example - * @return mixed - */ - public function getExample() + public function getExample(): mixed { if (empty($this->examples)) { return null; @@ -165,7 +166,7 @@ public function getExample() /** * Returns all examples - * @return array + * @return array */ public function getExamples(): array { @@ -174,7 +175,7 @@ public function getExamples(): array public function updateConsoleForm(Form $form): void { - $count = $this->isMulti() ? 5 : 1; // TODO moznost nastavit kolko inputov sa ma vygenerovat v konzole, default moze byt 5 + $count = $this->isMulti() ? self::DEFAULT_MULTI_INPUT_COUNT : 1; // TODO moznost nastavit kolko inputov sa ma vygenerovat v konzole, default moze byt 5 for ($i = 0; $i < $count; $i++) { $key = $this->getKey(); if ($this->isMulti()) { diff --git a/src/Params/JsonInputParam.php b/src/Params/JsonInputParam.php index f7ab440..3a5a549 100644 --- a/src/Params/JsonInputParam.php +++ b/src/Params/JsonInputParam.php @@ -15,9 +15,9 @@ class JsonInputParam extends InputParam { protected $type = self::TYPE_POST_JSON; - private $schema; + private string $schema; - private $rawInput; + private mixed $rawInput = null; public function __construct(string $key, string $schema) { @@ -30,7 +30,7 @@ public function setMulti(): InputParam throw new Exception('Cannot use multi json input param'); } - public function getValue() + public function getValue(): mixed { $input = $this->rawInput = file_get_contents("php://input") ?: $this->default; if ($input === null) { @@ -54,7 +54,7 @@ public function validate(): ValidationResultInterface return new ValidationResult(ValidationResult::STATUS_OK); } - $value = json_decode(json_encode($value)); + $value = json_decode(json_encode($value) ?: ''); $schemaValidator = new JsonSchemaValidator(); return $schemaValidator->validate($value, $this->schema); } @@ -70,10 +70,10 @@ protected function addFormInput(Form $form, string $key): BaseControl if (!empty($examples = $this->getExamples())) { if (count($examples) === 1) { - $fullSchema['example'] = is_array($this->getExample())? $this->getExample() : json_decode($this->getExample(), true); + $fullSchema['example'] = is_array($this->getExample()) ? $this->getExample() : json_decode($this->getExample(), true); } else { foreach ($examples as $exampleKey => $example) { - $fullSchema['examples'][$exampleKey] = is_array($example)? $example : json_decode($example, true); + $fullSchema['examples'][$exampleKey] = is_array($example) ? $example : json_decode($example, true); // pretty formatting of json example if decoded } } @@ -86,7 +86,7 @@ protected function addFormInput(Form $form, string $key): BaseControl Select Example:  HTML; foreach ($fullSchema['examples'] as $exampleKey => $exampleValue) { - $example = htmlentities(json_encode($exampleValue, JSON_PRETTY_PRINT)); + $example = htmlentities(json_encode($exampleValue, JSON_PRETTY_PRINT) ?: ''); $this->description .= <<< HTML
{$exampleKey} @@ -107,7 +107,7 @@ function setExample(btn) { $this->description .= ' '; + . nl2br(str_replace(' ', ' ', json_encode($fullSchema, JSON_PRETTY_PRINT) ?: '')) . '
'; return $form->addTextArea('post_raw', $this->getParamLabel()) ->setHtmlAttribute('rows', 10); diff --git a/src/Params/ParamInterface.php b/src/Params/ParamInterface.php index 0f75e18..3053f40 100644 --- a/src/Params/ParamInterface.php +++ b/src/Params/ParamInterface.php @@ -17,25 +17,20 @@ public function getKey(): string; public function isRequired(): bool; + /** + * @return array|null + */ public function getAvailableValues(): ?array; public function isMulti(): bool; public function getDescription(): string; - /** - * default value - * @return mixed - */ - public function getDefault(); + public function getDefault(): mixed; - /** - * example value - * @return mixed - */ - public function getExample(); + public function getExample(): mixed; - public function getValue(); + public function getValue(): mixed; public function updateConsoleForm(Form $form): void; } diff --git a/src/Params/ParamsProcessor.php b/src/Params/ParamsProcessor.php index b055064..b000677 100644 --- a/src/Params/ParamsProcessor.php +++ b/src/Params/ParamsProcessor.php @@ -9,6 +9,7 @@ class ParamsProcessor /** @var ParamInterface[] */ private $params; + /** @var array */ private $errors = []; /** @@ -30,11 +31,17 @@ public function isError(): bool return !empty($this->errors); } + /** + * @return array + */ public function getErrors(): array { return $this->errors; } + /** + * @return array + */ public function getValues(): array { $result = []; diff --git a/src/Params/PostInputParam.php b/src/Params/PostInputParam.php index e30e5fd..9496e19 100644 --- a/src/Params/PostInputParam.php +++ b/src/Params/PostInputParam.php @@ -8,7 +8,7 @@ class PostInputParam extends InputParam { protected $type = self::TYPE_POST; - public function getValue() + public function getValue(): mixed { if (!filter_has_var(INPUT_POST, $this->key) && isset($_POST[$this->key])) { return $_POST[$this->key]; diff --git a/src/Params/PutInputParam.php b/src/Params/PutInputParam.php index e702168..cf06eba 100644 --- a/src/Params/PutInputParam.php +++ b/src/Params/PutInputParam.php @@ -8,9 +8,10 @@ class PutInputParam extends InputParam { protected $type = self::TYPE_PUT; - public function getValue() + public function getValue(): mixed { - parse_str(file_get_contents("php://input"), $params); + $values = file_get_contents("php://input"); + parse_str($values ? $values : '', $params); return $params[$this->key] ?? $this->default; } } diff --git a/src/Params/RawInputParam.php b/src/Params/RawInputParam.php index 56a1efc..cbb3d6f 100644 --- a/src/Params/RawInputParam.php +++ b/src/Params/RawInputParam.php @@ -17,7 +17,7 @@ public function setMulti(): InputParam throw new Exception('Cannot use multi raw input param'); } - public function getValue() + public function getValue(): mixed { return file_get_contents("php://input") ?: $this->default; } diff --git a/src/Presenters/ApiPresenter.php b/src/Presenters/ApiPresenter.php index ea32b33..290e11d 100644 --- a/src/Presenters/ApiPresenter.php +++ b/src/Presenters/ApiPresenter.php @@ -24,6 +24,9 @@ final class ApiPresenter implements IPresenter { + private const TO_SECONDS = 1000; + private const HTTP_PORT = 80; + /** @var ApiDecider @inject */ public $apiDecider; @@ -141,13 +144,16 @@ public function run(Request $request): IResponse private function getApi(Request $request): Api { return $this->apiDecider->getApi( - $request->getMethod(), + $request->getMethod() ?? '', $request->getParameter('version'), $request->getParameter('package'), $request->getParameter('apiAction') ); } + /** + * @param array $params + */ private function checkAuth(ApiAuthorizationInterface $authorization, array $params): ?IResponse { try { @@ -208,12 +214,12 @@ private function logRequest(Request $request, ApiLoggerInterface $logger, int $c $ipDetector = $this->context->getByType(IpDetectorInterface::class); $logger->log( $code, - $request->getMethod(), + $request->getMethod() ?? '', $requestHeaders, (string) filter_input(INPUT_SERVER, 'REQUEST_URI'), - $ipDetector ? $ipDetector->getRequestIp() : '', + $ipDetector->getRequestIp(), (string) filter_input(INPUT_SERVER, 'HTTP_USER_AGENT'), - (int) ($elapsed) * 1000 + (int) ($elapsed * self::TO_SECONDS) ); } @@ -250,7 +256,7 @@ private function getRequestDomain(): ?string return null; } $url = $refererParsedUrl['scheme'] . '://' . $refererParsedUrl['host']; - if (isset($refererParsedUrl['port']) && $refererParsedUrl['port'] !== 80) { + if (isset($refererParsedUrl['port']) && $refererParsedUrl['port'] !== self::HTTP_PORT) { $url .= ':' . $refererParsedUrl['port']; } return $url; diff --git a/src/Response/JsonApiResponse.php b/src/Response/JsonApiResponse.php index 9429748..597c8d1 100644 --- a/src/Response/JsonApiResponse.php +++ b/src/Response/JsonApiResponse.php @@ -18,7 +18,7 @@ class JsonApiResponse implements ResponseInterface /** @var integer */ private $code; - /** @var array|JsonSerializable */ + /** @var array|JsonSerializable */ private $payload; /** @var string */ @@ -31,7 +31,7 @@ class JsonApiResponse implements ResponseInterface private $expiration; /** - * @param array|JsonSerializable $payload + * @param array|JsonSerializable $payload * @param DateTimeInterface|null|false $expiration */ public function __construct(int $code, $payload, string $contentType = 'application/json', string $charset = 'utf-8', $expiration = null) @@ -52,9 +52,9 @@ public function getCode(): int } /** - * @return array|JsonSerializable + * @return array|JsonSerializable */ - public function getPayload() + public function getPayload(): array|JsonSerializable { return $this->payload; } @@ -69,7 +69,7 @@ public function getCharset(): string return $this->charset; } - public function getExpiration(): ?DateTimeInterface + public function getExpiration(): DateTimeInterface|false|null { return $this->expiration; } diff --git a/src/Response/XmlApiResponse.php b/src/Response/XmlApiResponse.php index fd95aa9..11a6386 100644 --- a/src/Response/XmlApiResponse.php +++ b/src/Response/XmlApiResponse.php @@ -44,7 +44,7 @@ public function getCode(): int return $this->code; } - public function getExpiration(): ?DateTimeInterface + public function getExpiration(): DateTimeInterface|false|null { return $this->expiration; } diff --git a/src/ValidationResult/ValidationResult.php b/src/ValidationResult/ValidationResult.php index 2d9fa33..034b3a2 100644 --- a/src/ValidationResult/ValidationResult.php +++ b/src/ValidationResult/ValidationResult.php @@ -8,14 +8,17 @@ class ValidationResult implements ValidationResultInterface { - const STATUS_OK = 'OK'; + public const STATUS_OK = 'OK'; - const STATUS_ERROR = 'error'; + public const STATUS_ERROR = 'error'; private $status; private $errors = []; + /** + * @param array $errors + */ public function __construct(string $status, array $errors = []) { if (!in_array($status, [self::STATUS_OK, self::STATUS_ERROR], true)) { @@ -31,6 +34,9 @@ public function isOk(): bool return $this->status === self::STATUS_OK; } + /** + * @return array + */ public function getErrors(): array { return $this->errors; diff --git a/src/ValidationResult/ValidationResultInterface.php b/src/ValidationResult/ValidationResultInterface.php index 37d72b9..0189cb6 100644 --- a/src/ValidationResult/ValidationResultInterface.php +++ b/src/ValidationResult/ValidationResultInterface.php @@ -8,5 +8,8 @@ interface ValidationResultInterface { public function isOk(): bool; + /** + * @return array + */ public function getErrors(): array; } From 59187ee64cf088415b307dab84f8bc3f55f5ae46 Mon Sep 17 00:00:00 2001 From: MartinBeranek Date: Fri, 21 Nov 2025 14:13:53 +0100 Subject: [PATCH 4/8] sniffer --- src/ApiDecider.php | 5 ++--- src/Authorization/BearerTokenAuthorization.php | 1 + src/Authorization/TokenAuthorization.php | 4 ---- src/Component/DefaultApiConsoleFormFactory.php | 1 + src/Handlers/BaseHandler.php | 6 +++--- src/Handlers/CorsPreflightHandlerInterface.php | 4 ---- src/Handlers/OpenApiHandler.php | 10 ++++------ src/Link/ApiLink.php | 2 +- src/Link/ApiLinkNode.php | 4 ++-- src/Misc/ConsoleRequest.php | 4 ++-- src/Misc/ConsoleResponse.php | 1 + src/Output/AbstractOutput.php | 2 +- src/Output/Configurator/EnvConfigurator.php | 1 + src/Output/Configurator/QueryConfigurator.php | 2 ++ src/Params/InputParam.php | 16 ++++++++-------- src/Params/JsonInputParam.php | 3 +-- src/Params/PutInputParam.php | 2 +- src/Params/RawInputParam.php | 2 +- src/Presenters/ApiPresenter.php | 2 +- src/Response/RedirectResponse.php | 2 +- 20 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/ApiDecider.php b/src/ApiDecider.php index 243185a..31524cd 100644 --- a/src/ApiDecider.php +++ b/src/ApiDecider.php @@ -20,9 +20,8 @@ class ApiDecider private ?ApiHandlerInterface $globalPreflightHandler = null; - public function __construct( - ) { - + public function __construct() + { } /** diff --git a/src/Authorization/BearerTokenAuthorization.php b/src/Authorization/BearerTokenAuthorization.php index ebd0f7c..04debd5 100644 --- a/src/Authorization/BearerTokenAuthorization.php +++ b/src/Authorization/BearerTokenAuthorization.php @@ -10,6 +10,7 @@ class BearerTokenAuthorization extends TokenAuthorization { private const EXPECTED_HTTP_PARTS = 2; + /** * BearerTokenAuthorization constructor. * diff --git a/src/Authorization/TokenAuthorization.php b/src/Authorization/TokenAuthorization.php index 4890be5..5b80ac5 100644 --- a/src/Authorization/TokenAuthorization.php +++ b/src/Authorization/TokenAuthorization.php @@ -24,10 +24,6 @@ abstract class TokenAuthorization implements ApiAuthorizationInterface */ protected $ipDetector; - /** - * @param TokenRepositoryInterface $tokenRepository - * @param IpDetectorInterface $ipDetector - */ public function __construct(TokenRepositoryInterface $tokenRepository, IpDetectorInterface $ipDetector) { $this->tokenRepository = $tokenRepository; diff --git a/src/Component/DefaultApiConsoleFormFactory.php b/src/Component/DefaultApiConsoleFormFactory.php index 246da45..296c2e6 100644 --- a/src/Component/DefaultApiConsoleFormFactory.php +++ b/src/Component/DefaultApiConsoleFormFactory.php @@ -21,6 +21,7 @@ class DefaultApiConsoleFormFactory implements ApiConsoleFormFactoryInterface { private const HTTP_PORT = 80; + public function create( IRequest $request, EndpointInterface $endpoint, diff --git a/src/Handlers/BaseHandler.php b/src/Handlers/BaseHandler.php index 4ef8897..26d2f4d 100644 --- a/src/Handlers/BaseHandler.php +++ b/src/Handlers/BaseHandler.php @@ -128,15 +128,15 @@ final public function setupLinkGenerator(LinkGenerator $linkGenerator): self final public function createLink(array $params = []): string { if (!$this->linkGenerator) { - throw new InvalidStateException("You have setupLinkGenerator for this handler if you want to generate link in this handler"); + throw new InvalidStateException('You have setupLinkGenerator for this handler if you want to generate link in this handler'); } if (!$this->endpoint) { - throw new InvalidStateException("You have setEndpoint() for this handler if you want to generate link in this handler"); + throw new InvalidStateException('You have setEndpoint() for this handler if you want to generate link in this handler'); } $params = array_merge([ 'version' => $this->endpoint->getVersion(), 'package' => $this->endpoint->getPackage(), - 'apiAction' => $this->endpoint->getApiAction() + 'apiAction' => $this->endpoint->getApiAction(), ], $params); return $this->linkGenerator->link('Api:Api:default', $params) ?: ''; } diff --git a/src/Handlers/CorsPreflightHandlerInterface.php b/src/Handlers/CorsPreflightHandlerInterface.php index e4e87e6..5019123 100644 --- a/src/Handlers/CorsPreflightHandlerInterface.php +++ b/src/Handlers/CorsPreflightHandlerInterface.php @@ -4,10 +4,6 @@ namespace Tomaj\NetteApi\Handlers; -use Nette\Http\Response; -use Tomaj\NetteApi\Response\JsonApiResponse; -use Tomaj\NetteApi\Response\ResponseInterface; - interface CorsPreflightHandlerInterface extends ApiHandlerInterface { diff --git a/src/Handlers/OpenApiHandler.php b/src/Handlers/OpenApiHandler.php index 38f7e07..94e1e5d 100644 --- a/src/Handlers/OpenApiHandler.php +++ b/src/Handlers/OpenApiHandler.php @@ -46,7 +46,6 @@ class OpenApiHandler extends BaseHandler /** @var array */ private $definitions = []; - /** * OpenApiHandler constructor. * @param ApiDecider $apiDecider @@ -281,7 +280,7 @@ private function getPaths(array $versionApis, string $baseUrl, string $basePath) 'schema' => [ '$ref' => '#/components/schemas/ErrorWrongInput', ], - ] + ], ], ]; } @@ -322,7 +321,7 @@ private function getPaths(array $versionApis, string $baseUrl, string $basePath) 'application/json; charset=utf-8' => [ 'schema' => $schema, ], - ] + ], ]; if (!empty($examples = $output->getExamples())) { if (count($examples) === 1) { @@ -361,9 +360,9 @@ private function getPaths(array $versionApis, string $baseUrl, string $basePath) 'description' => $output->getDescription(), 'schema' => [ 'type' => 'string', - ] + ], ], - ] + ], ]; } } @@ -425,7 +424,6 @@ private function getBasePath(array $apis, string $baseUrl): string return rtrim(str_replace($baseUrl, '', $basePath), '/'); } - private function getLongestCommonSubstring(?string $path1, string $path2): string { if ($path1 === null) { diff --git a/src/Link/ApiLink.php b/src/Link/ApiLink.php index 2f68dec..1406e67 100644 --- a/src/Link/ApiLink.php +++ b/src/Link/ApiLink.php @@ -36,7 +36,7 @@ public function link(EndpointInterface $endpoint, $params = []): string $params = array_merge([ 'version' => $endpoint->getVersion(), 'package' => $endpoint->getPackage(), - 'apiAction' => $endpoint->getApiAction() + 'apiAction' => $endpoint->getApiAction(), ], $params); return $this->linkGenerator->link('Api:Api:default', $params) ?: ''; } diff --git a/src/Link/ApiLinkNode.php b/src/Link/ApiLinkNode.php index 1699971..bfe9ac8 100644 --- a/src/Link/ApiLinkNode.php +++ b/src/Link/ApiLinkNode.php @@ -4,6 +4,7 @@ namespace Tomaj\NetteApi\Link; +use Generator; use Latte\Compiler\Nodes\Php\Expression\ArrayNode; use Latte\Compiler\Nodes\StatementNode; use Latte\Compiler\PrintContext; @@ -37,8 +38,7 @@ public function print(PrintContext $context): string return $context->format('echo ($this->filters->apiLink)(new Tomaj\NetteApi\EndpointIdentifier(%args), %args);', $this->endpointArgs, $this->endpointParams); } - - public function &getIterator(): \Generator + public function &getIterator(): Generator { yield $this->endpointArgs; yield $this->endpointParams; diff --git a/src/Misc/ConsoleRequest.php b/src/Misc/ConsoleRequest.php index 43c7b58..87688ac 100644 --- a/src/Misc/ConsoleRequest.php +++ b/src/Misc/ConsoleRequest.php @@ -97,7 +97,7 @@ public function makeRequest(string $url, string $method, array $values, array $a foreach ($cookieFields as $key => $value) { $parts[] = "$key=$value"; } - $headers[] = "Cookie: " . implode('&', $parts); + $headers[] = 'Cookie: ' . implode('&', $parts); } if ($token !== null && $token !== false) { $headers[] = 'Authorization: Bearer ' . $token; @@ -251,7 +251,7 @@ private function normalizeValues(array $values): array foreach ($value as $innerKey => $innerValue) { if ($innerValue !== '' && $innerValue !== null) { - $result[$key . "[" . $innerKey . "]"] = $innerValue; + $result[$key . '[' . $innerKey . ']'] = $innerValue; } } } diff --git a/src/Misc/ConsoleResponse.php b/src/Misc/ConsoleResponse.php index 1d0897a..d9c67e8 100644 --- a/src/Misc/ConsoleResponse.php +++ b/src/Misc/ConsoleResponse.php @@ -29,6 +29,7 @@ class ConsoleResponse private ?string $responseBody = null; private ?string $responseHeaders = null; + private ?int $responseTime = null; private bool $isError = false; diff --git a/src/Output/AbstractOutput.php b/src/Output/AbstractOutput.php index cbdc1cb..57323a6 100644 --- a/src/Output/AbstractOutput.php +++ b/src/Output/AbstractOutput.php @@ -50,7 +50,7 @@ public function addExample(string $name, $example): self */ public function setExample($example): self { - $this->examples["default"] = $example; + $this->examples['default'] = $example; return $this; } diff --git a/src/Output/Configurator/EnvConfigurator.php b/src/Output/Configurator/EnvConfigurator.php index 51d07f4..10e6c2c 100644 --- a/src/Output/Configurator/EnvConfigurator.php +++ b/src/Output/Configurator/EnvConfigurator.php @@ -7,6 +7,7 @@ class EnvConfigurator implements ConfiguratorInterface { private $envVariable = 'APP_ENV'; + private $productionValue = 'production'; /** diff --git a/src/Output/Configurator/QueryConfigurator.php b/src/Output/Configurator/QueryConfigurator.php index 6754790..9203e83 100644 --- a/src/Output/Configurator/QueryConfigurator.php +++ b/src/Output/Configurator/QueryConfigurator.php @@ -9,7 +9,9 @@ class QueryConfigurator implements ConfiguratorInterface { private $schemaValidateParam = 'schema_validate'; + private $errorDetailParam = 'error_detail'; + public Request $request; /** diff --git a/src/Params/InputParam.php b/src/Params/InputParam.php index 9777975..dcd40b8 100644 --- a/src/Params/InputParam.php +++ b/src/Params/InputParam.php @@ -12,12 +12,12 @@ abstract class InputParam implements ParamInterface { - public const TYPE_POST = 'POST'; - public const TYPE_GET = 'GET'; - public const TYPE_PUT = 'PUT'; - public const TYPE_FILE = 'FILE'; - public const TYPE_COOKIE = 'COOKIE'; - public const TYPE_POST_RAW = 'POST_RAW'; + public const TYPE_POST = 'POST'; + public const TYPE_GET = 'GET'; + public const TYPE_PUT = 'PUT'; + public const TYPE_FILE = 'FILE'; + public const TYPE_COOKIE = 'COOKIE'; + public const TYPE_POST_RAW = 'POST_RAW'; public const TYPE_POST_JSON = 'POST_JSON'; public const OPTIONAL = false; @@ -152,7 +152,7 @@ public function addExample(string $name, $example): self */ public function setExample($example): self { - $this->examples["default"] = $example; + $this->examples['default'] = $example; return $this; } @@ -175,7 +175,7 @@ public function getExamples(): array public function updateConsoleForm(Form $form): void { - $count = $this->isMulti() ? self::DEFAULT_MULTI_INPUT_COUNT : 1; // TODO moznost nastavit kolko inputov sa ma vygenerovat v konzole, default moze byt 5 + $count = $this->isMulti() ? self::DEFAULT_MULTI_INPUT_COUNT : 1; // TODO moznost nastavit kolko inputov sa ma vygenerovat v konzole, default moze byt 5 for ($i = 0; $i < $count; $i++) { $key = $this->getKey(); if ($this->isMulti()) { diff --git a/src/Params/JsonInputParam.php b/src/Params/JsonInputParam.php index 3a5a549..aacaaae 100644 --- a/src/Params/JsonInputParam.php +++ b/src/Params/JsonInputParam.php @@ -32,7 +32,7 @@ public function setMulti(): InputParam public function getValue(): mixed { - $input = $this->rawInput = file_get_contents("php://input") ?: $this->default; + $input = $this->rawInput = file_get_contents('php://input') ?: $this->default; if ($input === null) { $input = ''; } @@ -79,7 +79,6 @@ protected function addFormInput(Form $form, string $key): BaseControl } } - if (!empty($fullSchema['examples'])) { $this->description .= <<< HTML
diff --git a/src/Params/PutInputParam.php b/src/Params/PutInputParam.php index cf06eba..e6891fc 100644 --- a/src/Params/PutInputParam.php +++ b/src/Params/PutInputParam.php @@ -10,7 +10,7 @@ class PutInputParam extends InputParam public function getValue(): mixed { - $values = file_get_contents("php://input"); + $values = file_get_contents('php://input'); parse_str($values ? $values : '', $params); return $params[$this->key] ?? $this->default; } diff --git a/src/Params/RawInputParam.php b/src/Params/RawInputParam.php index cbb3d6f..5858bed 100644 --- a/src/Params/RawInputParam.php +++ b/src/Params/RawInputParam.php @@ -19,7 +19,7 @@ public function setMulti(): InputParam public function getValue(): mixed { - return file_get_contents("php://input") ?: $this->default; + return file_get_contents('php://input') ?: $this->default; } protected function addFormInput(Form $form, string $key): BaseControl diff --git a/src/Presenters/ApiPresenter.php b/src/Presenters/ApiPresenter.php index 290e11d..b7a1dad 100644 --- a/src/Presenters/ApiPresenter.php +++ b/src/Presenters/ApiPresenter.php @@ -108,7 +108,7 @@ public function run(Request $request): IResponse $outputValidatorErrors = []; foreach ($outputs as $output) { if (!$output instanceof OutputInterface) { - $outputValidatorErrors[] = ["Output does not implement OutputInterface"]; + $outputValidatorErrors[] = ['Output does not implement OutputInterface']; continue; } $validationResult = $output->validate($response); diff --git a/src/Response/RedirectResponse.php b/src/Response/RedirectResponse.php index 94efca2..ac04d0a 100644 --- a/src/Response/RedirectResponse.php +++ b/src/Response/RedirectResponse.php @@ -4,8 +4,8 @@ namespace Tomaj\NetteApi\Response; -use Nette\Http\IResponse; use Nette\Http\IRequest; +use Nette\Http\IResponse; use Nette\SmartObject; class RedirectResponse implements ResponseInterface From d162dd201deb06538c7d05df2d030c116b42792b Mon Sep 17 00:00:00 2001 From: MartinBeranek Date: Fri, 21 Nov 2025 14:16:30 +0100 Subject: [PATCH 5/8] remove nette utils --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 7e26865..d626d49 100644 --- a/composer.json +++ b/composer.json @@ -22,8 +22,7 @@ "league/fractal": "~0.17", "tomaj/nette-bootstrap-form": "^2.0", "justinrainbow/json-schema": "^5.2", - "latte/latte": "^3.0", - "nette/utils": "^4.0" + "latte/latte": "^3.0" }, "require-dev": { "nette/di": "^3.0", From cd019423eb1e743ce5d18f585e67f6b8defc6bed Mon Sep 17 00:00:00 2001 From: MartinBeranek Date: Fri, 21 Nov 2025 14:19:37 +0100 Subject: [PATCH 6/8] fix comment --- src/Misc/StaticTokenRepository.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Misc/StaticTokenRepository.php b/src/Misc/StaticTokenRepository.php index 0e061e3..9b836c1 100644 --- a/src/Misc/StaticTokenRepository.php +++ b/src/Misc/StaticTokenRepository.php @@ -10,6 +10,18 @@ class StaticTokenRepository implements BearerTokenRepositoryInterface { /** + * + * Create static bearer token repository. + * You can pass multiple tokens that will be available for your api. + * Format is associtive array where key is token string and value is IP range + * + * Example: + * ['ef0p9iwehjgoihrgrsdgfoihw4t' => '*'] + * + * Or: + * ['asfoihegoihregoihrhgrehg' => '127.0.0.1', 'asfo9uyewtoiyewgt4ty4r' => '*'] + * + * @see BearerTokenAuthorization#isValidIp for all available Ip range formats * @param array $validTokens Array of valid tokens as keys and optional IP restrictions as values */ public function __construct(private array $validTokens = []) From c009ff55b01db373e17b6b0c192c3439cccf9676 Mon Sep 17 00:00:00 2001 From: MartinBeranek Date: Thu, 11 Dec 2025 09:53:41 +0100 Subject: [PATCH 7/8] remove tests from pstan --- phpstan.neon | 1 - 1 file changed, 1 deletion(-) diff --git a/phpstan.neon b/phpstan.neon index 43914e9..42802a8 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,7 +2,6 @@ parameters: level: 8 paths: - src - - tests excludePaths: - vendor - tests From 3e08d5329118d65466aff16971cfd4e02d197c80 Mon Sep 17 00:00:00 2001 From: MartinBeranek Date: Thu, 11 Dec 2025 10:00:22 +0100 Subject: [PATCH 8/8] Refactor with rector --- src/Api.php | 3 -- src/ApiDecider.php | 11 +++--- .../ApiAuthorizationInterface.php | 4 --- src/Authorization/BasicAuthentication.php | 2 +- .../BearerTokenAuthorization.php | 12 +++---- .../CookieApiKeyAuthentication.php | 1 + .../HeaderApiKeyAuthentication.php | 1 + .../QueryApiKeyAuthentication.php | 1 + src/Authorization/TokenAuthorization.php | 10 +++--- src/Component/ApiConsoleControl.php | 4 ++- src/Component/ApiListingControl.php | 2 ++ .../DefaultApiConsoleFormFactory.php | 1 + src/EndpointIdentifier.php | 4 ++- src/Error/DefaultErrorHandler.php | 3 ++ src/Handlers/ApiHandlerInterface.php | 7 ---- src/Handlers/ApiListingHandler.php | 6 +--- src/Handlers/BaseHandler.php | 6 ++-- src/Handlers/CorsPreflightHandler.php | 1 + src/Handlers/OpenApiHandler.php | 35 +++++++++++++++---- src/Link/ApiLink.php | 4 --- src/Misc/ConsoleRequest.php | 28 ++++++++------- src/Misc/ConsoleResponse.php | 5 ++- src/Misc/IpDetector.php | 1 + src/Misc/IpDetectorInterface.php | 2 -- src/Misc/OpenApiTransform.php | 2 ++ src/Misc/StaticIpDetector.php | 2 -- src/Misc/StaticTokenRepository.php | 5 +-- src/Misc/TokenRepositoryInterface.php | 5 --- src/Output/AbstractOutput.php | 5 +-- src/Output/Configurator/EnvConfigurator.php | 2 ++ src/Output/JsonOutput.php | 1 + src/Output/RedirectOutput.php | 2 ++ src/Params/CookieInputParam.php | 3 +- src/Params/FileInputParam.php | 2 ++ src/Params/GetInputParam.php | 1 + src/Params/InputParam.php | 19 +++++++--- src/Params/JsonInputParam.php | 3 ++ src/Params/ParamsProcessor.php | 1 + src/Params/PostInputParam.php | 1 + src/Params/PutInputParam.php | 2 +- src/Presenters/ApiPresenter.php | 25 ++++++++----- src/Response/JsonApiResponse.php | 1 + src/Response/ResponseInterface.php | 2 -- src/Response/TextApiResponse.php | 1 - src/Response/XmlApiResponse.php | 1 + src/Validation/JsonSchemaValidator.php | 4 +-- tests/Handler/TestHandler.php | 1 + 47 files changed, 138 insertions(+), 107 deletions(-) diff --git a/src/Api.php b/src/Api.php index 2d2c182..a47da1d 100644 --- a/src/Api.php +++ b/src/Api.php @@ -20,10 +20,7 @@ class Api private $rateLimit; /** - * @param EndpointInterface $endpoint * @param ApiHandlerInterface $handler - * @param ApiAuthorizationInterface $authorization - * @param RateLimitInterface|null $rateLimit */ public function __construct( EndpointInterface $endpoint, diff --git a/src/ApiDecider.php b/src/ApiDecider.php index 31524cd..4220bc6 100644 --- a/src/ApiDecider.php +++ b/src/ApiDecider.php @@ -20,17 +20,10 @@ class ApiDecider private ?ApiHandlerInterface $globalPreflightHandler = null; - public function __construct() - { - } - /** * Get api handler that match input method, version, package and apiAction. * If decider cannot find handler for given handler, returns defaults. * - * @param string $method - * @param string $version - * @param string $package * @param string $apiAction * * @return Api @@ -48,10 +41,12 @@ public function getApi(string $method, string $version, string $package, ?string $handler->setEndpointIdentifier($endpointIdentifier); return new Api($api->getEndpoint(), $handler, $api->getAuthorization(), $api->getRateLimit()); } + if ($method === 'OPTIONS' && $this->globalPreflightHandler && $identifier->getVersion() === $version && $identifier->getPackage() === $package && $identifier->getApiAction() === $apiAction) { return new Api(new EndpointIdentifier('OPTIONS', $version, $package, $apiAction), $this->globalPreflightHandler, new NoAuthorization()); } } + return new Api(new EndpointIdentifier($method, $version, $package, $apiAction), new DefaultHandler(), new NoAuthorization()); } @@ -60,6 +55,7 @@ public function enableGlobalPreflight(?CorsPreflightHandlerInterface $corsHandle if (!$corsHandler) { $corsHandler = new CorsPreflightHandler(new Response()); } + $this->globalPreflightHandler = $corsHandler; } @@ -84,6 +80,7 @@ public function getApis(): array $handler = $this->getHandler($api); $apis[] = new Api($api->getEndpoint(), $handler, $api->getAuthorization(), $api->getRateLimit()); } + return $apis; } diff --git a/src/Authorization/ApiAuthorizationInterface.php b/src/Authorization/ApiAuthorizationInterface.php index db37947..8dc12cf 100644 --- a/src/Authorization/ApiAuthorizationInterface.php +++ b/src/Authorization/ApiAuthorizationInterface.php @@ -8,16 +8,12 @@ interface ApiAuthorizationInterface { /** * Main method to check if this authorization authorize actual request. - * - * @return boolean */ public function authorized(): bool; /** * If authorization deny acces, this method should provide additional information * abount cause of restriction. - * - * @return string|null */ public function getErrorMessage(): ?string; } diff --git a/src/Authorization/BasicAuthentication.php b/src/Authorization/BasicAuthentication.php index ea557c3..7638449 100644 --- a/src/Authorization/BasicAuthentication.php +++ b/src/Authorization/BasicAuthentication.php @@ -16,7 +16,6 @@ class BasicAuthentication implements ApiAuthorizationInterface /** * @param array $autentications - available username - password pairs - * @param IRequest $httpRequest */ public function __construct(array $autentications, IRequest $httpRequest) { @@ -34,6 +33,7 @@ public function authorized(): bool if (!$authentication) { return false; } + return $authentication === $urlScript->getPassword(); } diff --git a/src/Authorization/BearerTokenAuthorization.php b/src/Authorization/BearerTokenAuthorization.php index 04debd5..7604877 100644 --- a/src/Authorization/BearerTokenAuthorization.php +++ b/src/Authorization/BearerTokenAuthorization.php @@ -12,11 +12,8 @@ class BearerTokenAuthorization extends TokenAuthorization private const EXPECTED_HTTP_PARTS = 2; /** - * BearerTokenAuthorization constructor. - * - * @param TokenRepositoryInterface $tokenRepository - * @param IpDetectorInterface $ipDetector - */ + * BearerTokenAuthorization constructor. + */ public function __construct(TokenRepositoryInterface $tokenRepository, IpDetectorInterface $ipDetector) { parent::__construct($tokenRepository, $ipDetector); @@ -25,8 +22,6 @@ public function __construct(TokenRepositoryInterface $tokenRepository, IpDetecto /** * Read HTTP reader with authorization token * If everything is ok, it return token. In other situations returns false and set errorMessage. - * - * @return string|null */ protected function readAuthorizationToken(): ?string { @@ -34,15 +29,18 @@ protected function readAuthorizationToken(): ?string $this->errorMessage = 'Authorization header HTTP_Authorization is not set'; return null; } + $parts = explode(' ', $_SERVER['HTTP_AUTHORIZATION']); if (count($parts) !== self::EXPECTED_HTTP_PARTS) { $this->errorMessage = 'Authorization header contains invalid structure'; return null; } + if (strtolower($parts[0]) !== 'bearer') { $this->errorMessage = 'Authorization header doesn\'t contain bearer token'; return null; } + return $parts[1]; } } diff --git a/src/Authorization/CookieApiKeyAuthentication.php b/src/Authorization/CookieApiKeyAuthentication.php index 4b95051..69bd1bb 100644 --- a/src/Authorization/CookieApiKeyAuthentication.php +++ b/src/Authorization/CookieApiKeyAuthentication.php @@ -24,6 +24,7 @@ protected function readAuthorizationToken(): ?string $this->errorMessage = 'API key is not set'; return null; } + return $apiKey; } diff --git a/src/Authorization/HeaderApiKeyAuthentication.php b/src/Authorization/HeaderApiKeyAuthentication.php index 0843ddc..4693944 100644 --- a/src/Authorization/HeaderApiKeyAuthentication.php +++ b/src/Authorization/HeaderApiKeyAuthentication.php @@ -25,6 +25,7 @@ protected function readAuthorizationToken(): ?string $this->errorMessage = 'API key is not set'; return null; } + return $apiKey; } diff --git a/src/Authorization/QueryApiKeyAuthentication.php b/src/Authorization/QueryApiKeyAuthentication.php index 43a9ff4..22c6b52 100644 --- a/src/Authorization/QueryApiKeyAuthentication.php +++ b/src/Authorization/QueryApiKeyAuthentication.php @@ -24,6 +24,7 @@ protected function readAuthorizationToken(): ?string $this->errorMessage = 'API key is not set'; return null; } + return $apiKey; } diff --git a/src/Authorization/TokenAuthorization.php b/src/Authorization/TokenAuthorization.php index 5b80ac5..f5c6c37 100644 --- a/src/Authorization/TokenAuthorization.php +++ b/src/Authorization/TokenAuthorization.php @@ -70,17 +70,17 @@ public function getErrorMessage(): ?string * '127.0.0.1,127.0.02' - accessible from multiple IP, separator could be new line or space * '127.0.0.1/32' - accessible from ip range * null - disabled access - * - * @return boolean */ private function isValidIp(?string $ipRestrictions): bool { if ($ipRestrictions === null) { return false; } + if ($ipRestrictions === '*' || $ipRestrictions === '') { return true; } + $ip = $this->ipDetector->getRequestIp(); $ipWhiteList = str_replace([',', ' ', "\n"], '#', $ipRestrictions); @@ -89,6 +89,7 @@ private function isValidIp(?string $ipRestrictions): bool if ($whiteIp === $ip) { return true; } + if (strpos($whiteIp, '/') !== false) { return $this->ipInRange($ip, $whiteIp); } @@ -102,15 +103,14 @@ private function isValidIp(?string $ipRestrictions): bool * * @param string $ip this ip will be verified * @param string $range is in IP/CIDR format eg 127.0.0.1/24 - * @return boolean */ private function ipInRange(string $ip, string $range): bool { - list($range, $netmask) = explode('/', $range, 2); + [$range, $netmask] = explode('/', $range, 2); $range_decimal = ip2long($range); $ipDecimal = ip2long($ip); /** @phpstan-ignore-next-line */ - $wildcard_decimal = pow(2, (32 - (int)$netmask)) - 1; + $wildcard_decimal = 2 ** (32 - (int)$netmask) - 1; $netmask_decimal = ~ $wildcard_decimal; return (($ipDecimal & $netmask_decimal) === ($range_decimal & $netmask_decimal)); } diff --git a/src/Component/ApiConsoleControl.php b/src/Component/ApiConsoleControl.php index c343c84..7a5b7be 100644 --- a/src/Component/ApiConsoleControl.php +++ b/src/Component/ApiConsoleControl.php @@ -52,7 +52,7 @@ protected function createComponentConsoleForm(): Form { $form = $this->formFactory->create($this->request, $this->endpoint, $this->handler, $this->authorization, $this->apiLink); $form->setRenderer($this->getFormRenderer()); - $form->onSuccess[] = array($this, 'formSucceeded'); + $form->onSuccess[] = [$this, 'formSucceeded']; return $form; } @@ -135,8 +135,10 @@ private function filterFormValues(array $values): array if ($values['do_not_send_empty_value_for_' . $key] === true && $values[$key] === '') { unset($values[$key]); } + unset($values['do_not_send_empty_value_for_' . $key]); } + return $values; } } diff --git a/src/Component/ApiListingControl.php b/src/Component/ApiListingControl.php index 9ac64b2..1157bdb 100644 --- a/src/Component/ApiListingControl.php +++ b/src/Component/ApiListingControl.php @@ -57,8 +57,10 @@ private function groupApis(array $handlers): array if (!isset($versionHandlers[$endPoint->getVersion()])) { $versionHandlers[$endPoint->getVersion()] = []; } + $versionHandlers[$endPoint->getVersion()][] = $handler; } + return $versionHandlers; } diff --git a/src/Component/DefaultApiConsoleFormFactory.php b/src/Component/DefaultApiConsoleFormFactory.php index 296c2e6..fb5fb50 100644 --- a/src/Component/DefaultApiConsoleFormFactory.php +++ b/src/Component/DefaultApiConsoleFormFactory.php @@ -68,6 +68,7 @@ protected function getUrl(IRequest $request, EndpointInterface $endpoint, ?ApiLi if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { $scheme = $_SERVER['HTTP_X_FORWARDED_PROTO']; } + $port = ''; if ($uri->scheme === 'http' && $uri->port !== self::HTTP_PORT) { $port = ':' . $uri->port; diff --git a/src/EndpointIdentifier.php b/src/EndpointIdentifier.php index ca249d8..1f451c9 100644 --- a/src/EndpointIdentifier.php +++ b/src/EndpointIdentifier.php @@ -29,6 +29,7 @@ public function __construct(string $method, $version, string $package, ?string $ if (strpos($version, '/') !== false) { throw new InvalidArgumentException('Version must have semantic numbering. For example "1", "1.1", "0.13.2" etc.'); } + $this->version = $version; $this->package = $package; $this->apiAction = $apiAction; @@ -54,11 +55,12 @@ public function getApiAction(): ?string if ($this->apiAction === '') { return null; } + return $this->apiAction; } public function getUrl(): string { - return "v{$this->version}/{$this->package}/{$this->apiAction}"; + return sprintf('v%s/%s/%s', $this->version, $this->package, $this->apiAction); } } diff --git a/src/Error/DefaultErrorHandler.php b/src/Error/DefaultErrorHandler.php index 9dcb512..56eb2cc 100644 --- a/src/Error/DefaultErrorHandler.php +++ b/src/Error/DefaultErrorHandler.php @@ -29,6 +29,7 @@ public function handle(Throwable $exception, array $params): JsonApiResponse } else { $response = new JsonApiResponse(Response::S500_INTERNAL_SERVER_ERROR, ['status' => 'error', 'message' => 'Internal server error']); } + return $response; } @@ -39,6 +40,7 @@ public function handleInputParams(array $errors): JsonApiResponse } else { $response = new JsonApiResponse(Response::S400_BAD_REQUEST, ['status' => 'error', 'message' => 'wrong input']); } + return $response; } @@ -51,6 +53,7 @@ public function handleSchema(array $errors, array $params): JsonApiResponse } else { $response = new JsonApiResponse(Response::S500_INTERNAL_SERVER_ERROR, ['status' => 'error', 'message' => 'Internal server error']); } + return $response; } diff --git a/src/Handlers/ApiHandlerInterface.php b/src/Handlers/ApiHandlerInterface.php index b40271c..d4e9581 100644 --- a/src/Handlers/ApiHandlerInterface.php +++ b/src/Handlers/ApiHandlerInterface.php @@ -13,13 +13,11 @@ interface ApiHandlerInterface { /** * Summary of handler - short description of handler - * @return string */ public function summary(): string; /** * Description of handler - * @return string */ public function description(): string; @@ -38,7 +36,6 @@ public function tags(): array; /** * Marks handler as deprecated - * @return bool */ public function deprecated(): bool; @@ -47,8 +44,6 @@ public function deprecated(): bool; * endpoint contected with this handler will be triggered * * @param array $params - * - * @return ResponseInterface */ public function handle(array $params): ResponseInterface; @@ -56,9 +51,7 @@ public function handle(array $params): ResponseInterface; * Set actual endpoint identifier to hnadler. * It is neccesary for link creation. * - * @param EndpointInterface $endpoint * - * @return void */ public function setEndpointIdentifier(EndpointInterface $endpoint): void; diff --git a/src/Handlers/ApiListingHandler.php b/src/Handlers/ApiListingHandler.php index 74ca594..df43e19 100644 --- a/src/Handlers/ApiListingHandler.php +++ b/src/Handlers/ApiListingHandler.php @@ -25,9 +25,6 @@ class ApiListingHandler extends BaseHandler /** * ApiListingHandler constructor. - * - * @param ApiDecider $apiDecider - * @param ApiLink $apiLink */ public function __construct(ApiDecider $apiDecider, ApiLink $apiLink) { @@ -49,7 +46,6 @@ public function handle(array $params): ResponseInterface /** * Create handler list for specified version * - * @param string $version * * @return array */ @@ -75,7 +71,6 @@ private function getApiList(string $version): array /** * Create array with params for specified handler * - * @param ApiHandlerInterface $handler * * @return array{type: string, key: string, is_required: bool, available_values?: non-empty-array} */ @@ -91,6 +86,7 @@ private function createParamsList(ApiHandlerInterface $handler): array if ($param->getAvailableValues()) { $parameter['available_values'] = $param->getAvailableValues(); } + return $parameter; }, $handler->params()); } diff --git a/src/Handlers/BaseHandler.php b/src/Handlers/BaseHandler.php index 26d2f4d..6d83380 100644 --- a/src/Handlers/BaseHandler.php +++ b/src/Handlers/BaseHandler.php @@ -88,6 +88,7 @@ protected function getFractal(): Manager if (!$this->fractal) { throw new InvalidStateException("Fractal manager isn't initialized. Did you call parent::__construct() in your handler constructor?"); } + return $this->fractal; } @@ -107,9 +108,7 @@ final public function getEndpoint(): ?EndpointInterface /** * Set link generator to handler * - * @param LinkGenerator $linkGenerator * - * @return self */ final public function setupLinkGenerator(LinkGenerator $linkGenerator): self { @@ -122,7 +121,6 @@ final public function setupLinkGenerator(LinkGenerator $linkGenerator): self * * @param array $params * - * @return string * @throws InvalidLinkException if handler doesn't have linkgenerator or endpoint */ final public function createLink(array $params = []): string @@ -130,9 +128,11 @@ final public function createLink(array $params = []): string if (!$this->linkGenerator) { throw new InvalidStateException('You have setupLinkGenerator for this handler if you want to generate link in this handler'); } + if (!$this->endpoint) { throw new InvalidStateException('You have setEndpoint() for this handler if you want to generate link in this handler'); } + $params = array_merge([ 'version' => $this->endpoint->getVersion(), 'package' => $this->endpoint->getPackage(), diff --git a/src/Handlers/CorsPreflightHandler.php b/src/Handlers/CorsPreflightHandler.php index cde5ef3..178783c 100644 --- a/src/Handlers/CorsPreflightHandler.php +++ b/src/Handlers/CorsPreflightHandler.php @@ -43,6 +43,7 @@ public function handle(array $params): ResponseInterface $this->response->addHeader($name, $value); } } + return new JsonApiResponse(Response::S200_OK, []); } } diff --git a/src/Handlers/OpenApiHandler.php b/src/Handlers/OpenApiHandler.php index 94e1e5d..a2e7cca 100644 --- a/src/Handlers/OpenApiHandler.php +++ b/src/Handlers/OpenApiHandler.php @@ -48,9 +48,6 @@ class OpenApiHandler extends BaseHandler /** * OpenApiHandler constructor. - * @param ApiDecider $apiDecider - * @param ApiLink $apiLink - * @param Request $request * @param array $initData - structured data for initialization response */ public function __construct( @@ -75,6 +72,7 @@ public function params(): array if (class_exists(Yaml::class)) { $availableFormats[] = 'yaml'; } + return [ (new GetInputParam('format'))->setAvailableValues($availableFormats)->setDescription('Response format'), ]; @@ -120,6 +118,7 @@ public function handle(array $params): ResponseInterface ]; continue; } + if ($authorization instanceof BearerTokenAuthorization) { $securitySchemes['Bearer'] = [ 'type' => 'http', @@ -127,6 +126,7 @@ public function handle(array $params): ResponseInterface ]; continue; } + if ($authorization instanceof QueryApiKeyAuthentication) { $queryParamName = $authorization->getQueryParamName(); $securitySchemes[$this->normalizeSecuritySchemeName('query', $queryParamName)] = [ @@ -136,6 +136,7 @@ public function handle(array $params): ResponseInterface ]; continue; } + if ($authorization instanceof HeaderApiKeyAuthentication) { $headerName = $authorization->getHeaderName(); $securitySchemes[$this->normalizeSecuritySchemeName('header', $headerName)] = [ @@ -145,6 +146,7 @@ public function handle(array $params): ResponseInterface ]; continue; } + if ($authorization instanceof CookieApiKeyAuthentication) { $cookieName = $authorization->getCookieName(); $securitySchemes[$this->normalizeSecuritySchemeName('cookie', $cookieName)] = [ @@ -231,6 +233,7 @@ public function handle(array $params): ResponseInterface if ($params['format'] === 'yaml') { return new TextApiResponse(IResponse::S200_OK, Yaml::dump($data, PHP_INT_MAX, 2, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE)); } + return new JsonApiResponse(IResponse::S200_OK, $data); } @@ -246,8 +249,6 @@ private function getApis(string $version): array /** * @param Api[] $versionApis - * @param string $baseUrl - * @param string $basePath * @return array * @throws InvalidLinkException */ @@ -347,6 +348,7 @@ private function getPaths(array $versionApis, string $baseUrl, string $basePath) ]; $responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']['oneOf'][] = $tmp; } + /** @phpstan-ignore-next-line */ $responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']['oneOf'][] = $schema; } @@ -406,9 +408,11 @@ private function getPaths(array $versionApis, string $baseUrl, string $basePath) ], ]; } + $settings['responses'] = $responses; $list[$path][strtolower($api->getEndpoint()->getMethod())] = $settings; } + return $list; } @@ -421,6 +425,7 @@ private function getBasePath(array $apis, string $baseUrl): string foreach ($apis as $handler) { $basePath = $this->getLongestCommonSubstring($basePath, $this->apiLink->link($handler->getEndpoint())); } + return rtrim(str_replace($baseUrl, '', $basePath), '/'); } @@ -429,21 +434,23 @@ private function getLongestCommonSubstring(?string $path1, string $path2): strin if ($path1 === null) { return $path2; } + $commonSubstring = ''; $shortest = min(strlen($path1), strlen($path2)); for ($i = 0; $i <= $shortest; ++$i) { if (substr($path1, 0, $i) !== substr($path2, 0, $i)) { break; } + $commonSubstring = substr($path1, 0, $i); } + return $commonSubstring; } /** * Create array with params for specified handler * - * @param ApiHandlerInterface $handler * @return array> */ private function createParamsList(ApiHandlerInterface $handler): array @@ -466,10 +473,12 @@ private function createParamsList(ApiHandlerInterface $handler): array if ($param->isMulti()) { $schema['items'] = ['type' => 'string']; } + $descriptionParts = []; if ($param->getDescription()) { $descriptionParts[] = $param->getDescription(); } + $availableValues = $param->getAvailableValues(); if ($availableValues) { $schema['enum'] = array_keys($availableValues); @@ -479,6 +488,7 @@ private function createParamsList(ApiHandlerInterface $handler): array } } } + $parameter['schema'] = $schema; if ($descriptionParts !== []) { $parameter['description'] = implode("\n", $descriptionParts); @@ -490,11 +500,11 @@ private function createParamsList(ApiHandlerInterface $handler): array $parameters[] = $parameter; } + return $parameters; } /** - * @param ApiHandlerInterface $handler * @return array|null */ private function createRequestBody(ApiHandlerInterface $handler) @@ -517,6 +527,7 @@ private function createRequestBody(ApiHandlerInterface $handler) } } } + return [ 'description' => $param->getDescription(), 'required' => $param->isRequired(), @@ -527,6 +538,7 @@ private function createRequestBody(ApiHandlerInterface $handler) ], ]; } + if ($param instanceof RawInputParam) { $schema = [ 'type' => 'string', @@ -538,6 +550,7 @@ private function createRequestBody(ApiHandlerInterface $handler) $schema['examples'] = $examples; } } + return [ 'description' => $param->getDescription(), 'required' => $param->isRequired(), @@ -548,6 +561,7 @@ private function createRequestBody(ApiHandlerInterface $handler) ], ]; } + if ($param->getType() === InputParam::TYPE_POST || $param->getType() === InputParam::TYPE_PUT) { $property = [ 'type' => $param->isMulti() ? 'array' : 'string', @@ -555,10 +569,12 @@ private function createRequestBody(ApiHandlerInterface $handler) if ($param->isMulti()) { $property['items'] = ['type' => 'string']; } + $descriptionParts = []; if ($param->getDescription()) { $descriptionParts[] = $param->getDescription(); } + $availableValues = $param->getAvailableValues(); if ($availableValues) { $property['enum'] = array_keys($availableValues); @@ -637,9 +653,11 @@ private function createIn($type) if ($type == InputParam::TYPE_GET) { return 'query'; } + if ($type == InputParam::TYPE_COOKIE) { return 'cookie'; } + return 'body'; } @@ -655,8 +673,10 @@ private function transformSchema(array $schema) foreach ($schema['definitions'] as $name => $definition) { $this->addDefinition($name, $this->transformSchema($definition)); } + unset($schema['definitions']); } + return json_decode(str_replace('#/definitions/', '#/components/schemas/', json_encode($schema, JSON_UNESCAPED_SLASHES) ?: ''), true); } @@ -669,6 +689,7 @@ private function addDefinition($name, $definition): void if (isset($this->definitions[$name]) && $this->definitions[$name] !== $definition) { throw new InvalidArgumentException('Definition with name ' . $name . ' already exists. Rename it.'); } + $this->definitions[$name] = $definition; } diff --git a/src/Link/ApiLink.php b/src/Link/ApiLink.php index 1406e67..0cdea93 100644 --- a/src/Link/ApiLink.php +++ b/src/Link/ApiLink.php @@ -15,8 +15,6 @@ class ApiLink /** * Create ApiLink - * - * @param LinkGenerator $linkGenerator */ public function __construct(LinkGenerator $linkGenerator) { @@ -26,9 +24,7 @@ public function __construct(LinkGenerator $linkGenerator) /** * Create link to specified api endpoint * - * @param EndpointInterface $endpoint * @param array $params - * * @throws InvalidLinkException */ public function link(EndpointInterface $endpoint, $params = []): string diff --git a/src/Misc/ConsoleRequest.php b/src/Misc/ConsoleRequest.php index 87688ac..2447749 100644 --- a/src/Misc/ConsoleRequest.php +++ b/src/Misc/ConsoleRequest.php @@ -14,6 +14,7 @@ class ConsoleRequest { public const DEFAULT_TIMEOUT = 30; + public const ELAPSED_MILLISECONDS = 1000; /** @var ApiHandlerInterface */ @@ -33,15 +34,12 @@ public function __construct(ApiHandlerInterface $handler, ?EndpointInterface $en } /** - * @param string $url - * @param string $method * @param array $values * @param array $additionalValues - * @param string|null $token */ public function makeRequest(string $url, string $method, array $values, array $additionalValues = [], ?string $token = null): ConsoleResponse { - list($postFields, $getFields, $cookieFields, $rawPost, $putFields) = $this->processValues($values); + [$postFields, $getFields, $cookieFields, $rawPost, $putFields] = $this->processValues($values); $postFields = array_merge($postFields, $additionalValues['postFields'] ?? []); $getFields = array_merge($getFields, $additionalValues['getFields'] ?? []); @@ -54,10 +52,10 @@ public function makeRequest(string $url, string $method, array $values, array $a if ($this->endpoint && $this->apiLink) { $url = $this->apiLink->link($this->endpoint, $getFields); - } elseif (count($getFields)) { + } elseif ($getFields !== []) { $parts = []; foreach ($getFields as $key => $value) { - $parts[] = "$key=$value"; + $parts[] = sprintf('%s=%s', $key, $value); } $parsedUrl = parse_url($url); @@ -66,11 +64,12 @@ public function makeRequest(string $url, string $method, array $values, array $a } $putRawPost = null; - if (count($putFields)) { + if ($putFields !== []) { $parts = []; foreach ($putFields as $key => $value) { - $parts[] = "$key=$value"; + $parts[] = sprintf('%s=%s', $key, $value); } + $putRawPost = implode('&', $parts); } @@ -92,16 +91,19 @@ public function makeRequest(string $url, string $method, array $values, array $a } $headers = $additionalValues['headers'] ?? []; - if (count($cookieFields)) { + if ($cookieFields !== []) { $parts = []; foreach ($cookieFields as $key => $value) { - $parts[] = "$key=$value"; + $parts[] = sprintf('%s=%s', $key, $value); } + $headers[] = 'Cookie: ' . implode('&', $parts); } + if ($token !== null && $token !== false) { $headers[] = 'Authorization: Bearer ' . $token; } + if (count($headers)) { curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); } @@ -109,7 +111,7 @@ public function makeRequest(string $url, string $method, array $values, array $a $basicAuthUsername = $values['basic_authentication_username'] ?? null; $basicAuthPassword = $values['basic_authentication_password'] ?? null; if ($basicAuthUsername && $basicAuthPassword) { - curl_setopt($curl, CURLOPT_USERPWD, "$basicAuthUsername:$basicAuthPassword"); + curl_setopt($curl, CURLOPT_USERPWD, sprintf('%s:%s', $basicAuthUsername, $basicAuthPassword)); } $consoleResponse = new ConsoleResponse( @@ -158,7 +160,7 @@ private function processValues(array $values): array /** @var array $postFields */ $postFields = []; - $rawPost = isset($values['post_raw']) ? $values['post_raw'] : null; + $rawPost = $values['post_raw'] ?? null; /** @var array $getFields */ $getFields = []; /** @var array $putFields */ @@ -233,6 +235,7 @@ private function processParam(ParamInterface $param, string $key, $value) return $valueData; } + return null; } @@ -255,6 +258,7 @@ private function normalizeValues(array $values): array } } } + return $result; } } diff --git a/src/Misc/ConsoleResponse.php b/src/Misc/ConsoleResponse.php index d9c67e8..1b2144c 100644 --- a/src/Misc/ConsoleResponse.php +++ b/src/Misc/ConsoleResponse.php @@ -39,13 +39,10 @@ class ConsoleResponse private ?string $errorMessage = null; /** - * @param string $url - * @param string $method * @param array $postFields * @param array $getFields * @param array $cookieFields * @param array $headers - * @param string|null $rawPost */ public function __construct(string $url, string $method, array $postFields = [], array $getFields = [], array $cookieFields = [], array $headers = [], ?string $rawPost = null) { @@ -142,10 +139,12 @@ public function getFormattedJsonBody(): string if ($body === null) { return ''; } + $decoded = json_decode($body); if ($decoded) { $body = json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } + return $body ?: ''; } diff --git a/src/Misc/IpDetector.php b/src/Misc/IpDetector.php index 36bea48..e37b780 100644 --- a/src/Misc/IpDetector.php +++ b/src/Misc/IpDetector.php @@ -20,6 +20,7 @@ public function getRequestIp(): string } else { $ip = 'cli'; } + return $ip; } } diff --git a/src/Misc/IpDetectorInterface.php b/src/Misc/IpDetectorInterface.php index 806fd11..a5ea8c8 100644 --- a/src/Misc/IpDetectorInterface.php +++ b/src/Misc/IpDetectorInterface.php @@ -8,8 +8,6 @@ interface IpDetectorInterface { /** * Get actual request IP. - * - * @return string */ public function getRequestIp(): string; } diff --git a/src/Misc/OpenApiTransform.php b/src/Misc/OpenApiTransform.php index 3b00241..32ea9cc 100644 --- a/src/Misc/OpenApiTransform.php +++ b/src/Misc/OpenApiTransform.php @@ -18,12 +18,14 @@ public static function transformTypes(array &$schema, $parent = null): void unset($value[array_search('null', $value, true)]); $schema['nullable'] = true; } + if (count($value) === 1) { $value = implode(',', $value); } elseif (count($value) > 1) { foreach ($schema['type'] as $type) { $schema['oneOf'][] = ['type' => $type]; } + unset($schema['type']); } } elseif (is_array($value)) { diff --git a/src/Misc/StaticIpDetector.php b/src/Misc/StaticIpDetector.php index 2287b33..bf7150a 100644 --- a/src/Misc/StaticIpDetector.php +++ b/src/Misc/StaticIpDetector.php @@ -12,8 +12,6 @@ class StaticIpDetector implements IpDetectorInterface /** * Create Static Ip Detector * Ip that will be in constructor will return as actual request IP. - * - * @param string $ip */ public function __construct(string $ip) { diff --git a/src/Misc/StaticTokenRepository.php b/src/Misc/StaticTokenRepository.php index 9b836c1..e60a464 100644 --- a/src/Misc/StaticTokenRepository.php +++ b/src/Misc/StaticTokenRepository.php @@ -41,9 +41,6 @@ public function validToken(string $token): bool */ public function ipRestrictions(string $token): ?string { - if (isset($this->validTokens[$token])) { - return $this->validTokens[$token]; - } - return null; + return $this->validTokens[$token] ?? null; } } diff --git a/src/Misc/TokenRepositoryInterface.php b/src/Misc/TokenRepositoryInterface.php index 5615718..2ca735e 100644 --- a/src/Misc/TokenRepositoryInterface.php +++ b/src/Misc/TokenRepositoryInterface.php @@ -8,9 +8,6 @@ interface TokenRepositoryInterface { /** * Return true if token is valid, otherwise return false - * - * @param string $token - * @return bool */ public function validToken(string $token): bool; @@ -23,9 +20,7 @@ public function validToken(string $token): bool; * '156.26.252/32' - access from ip range * false - if token doesn't exists * - * @param string $token * - * @return string|null */ public function ipRestrictions(string $token): ?string; } diff --git a/src/Output/AbstractOutput.php b/src/Output/AbstractOutput.php index 57323a6..b0602a9 100644 --- a/src/Output/AbstractOutput.php +++ b/src/Output/AbstractOutput.php @@ -6,10 +6,8 @@ abstract class AbstractOutput implements OutputInterface { - /** @var int */ protected int $code; - /** @var string */ protected string $description; /** @var array */ @@ -34,7 +32,6 @@ public function getDescription(): string /** * @param string $name Example name * @param mixed $example Example - * @return Self */ public function addExample(string $name, $example): self { @@ -45,7 +42,6 @@ public function addExample(string $name, $example): self /** * Set default example * @param mixed $example - * @return self * @deprecated Use addExample instead */ public function setExample($example): self @@ -63,6 +59,7 @@ public function getExample() if (empty($this->examples)) { return null; } + return reset($this->examples); } diff --git a/src/Output/Configurator/EnvConfigurator.php b/src/Output/Configurator/EnvConfigurator.php index 10e6c2c..8dc5cf9 100644 --- a/src/Output/Configurator/EnvConfigurator.php +++ b/src/Output/Configurator/EnvConfigurator.php @@ -26,6 +26,7 @@ public function validateSchema(): bool if ($appEnv === $this->productionValue) { return false; } + return true; } @@ -35,6 +36,7 @@ public function showErrorDetail(): bool if ($appEnv === $this->productionValue) { return false; } + return true; } } diff --git a/src/Output/JsonOutput.php b/src/Output/JsonOutput.php index 5fb49d9..3dc7317 100644 --- a/src/Output/JsonOutput.php +++ b/src/Output/JsonOutput.php @@ -25,6 +25,7 @@ public function validate(ResponseInterface $response): ValidationResultInterface if (!$response instanceof JsonApiResponse) { return new ValidationResult(ValidationResult::STATUS_ERROR); } + if ($this->code !== $response->getCode()) { return new ValidationResult(ValidationResult::STATUS_ERROR, ['Response code doesn\'t match']); } diff --git a/src/Output/RedirectOutput.php b/src/Output/RedirectOutput.php index 0613c75..c38e4d2 100644 --- a/src/Output/RedirectOutput.php +++ b/src/Output/RedirectOutput.php @@ -16,9 +16,11 @@ public function validate(ResponseInterface $response): ValidationResultInterface if (!$response instanceof RedirectResponse) { return new ValidationResult(ValidationResult::STATUS_ERROR); } + if ($this->code !== $response->getCode()) { return new ValidationResult(ValidationResult::STATUS_ERROR, ['Response code doesn\'t match']); } + return new ValidationResult(ValidationResult::STATUS_OK); } } diff --git a/src/Params/CookieInputParam.php b/src/Params/CookieInputParam.php index 7ff4417..7fb4228 100644 --- a/src/Params/CookieInputParam.php +++ b/src/Params/CookieInputParam.php @@ -13,7 +13,8 @@ public function getValue(): mixed if (!filter_has_var(INPUT_COOKIE, $this->key) && isset($_COOKIE[$this->key])) { return $_COOKIE[$this->key]; } + $value = filter_input(INPUT_COOKIE, $this->key); - return $value !== null ? $value : $this->default; + return $value ?? $this->default; } } diff --git a/src/Params/FileInputParam.php b/src/Params/FileInputParam.php index 1386f96..53a3bdc 100644 --- a/src/Params/FileInputParam.php +++ b/src/Params/FileInputParam.php @@ -21,6 +21,7 @@ public function getValue(): mixed if (isset($_FILES[$this->key])) { return $this->isMulti() ? $this->processMultiFileUploads($_FILES[$this->key]) : $_FILES[$this->key]; } + return $this->default; } @@ -36,6 +37,7 @@ private function processMultiFileUploads(array$files): array $result[$index][$key] = $value; } } + return $result; } } diff --git a/src/Params/GetInputParam.php b/src/Params/GetInputParam.php index f8d502c..9fe75ac 100644 --- a/src/Params/GetInputParam.php +++ b/src/Params/GetInputParam.php @@ -13,6 +13,7 @@ public function getValue(): mixed if (!filter_has_var(INPUT_GET, $this->key) && isset($_GET[$this->key])) { return $_GET[$this->key]; } + $value = $this->isMulti() ? filter_input(INPUT_GET, $this->key, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY) : filter_input(INPUT_GET, $this->key); return $value !== null && $value !== false ? $value : $this->default; } diff --git a/src/Params/InputParam.php b/src/Params/InputParam.php index dcd40b8..1244b71 100644 --- a/src/Params/InputParam.php +++ b/src/Params/InputParam.php @@ -13,14 +13,21 @@ abstract class InputParam implements ParamInterface { public const TYPE_POST = 'POST'; + public const TYPE_GET = 'GET'; + public const TYPE_PUT = 'PUT'; + public const TYPE_FILE = 'FILE'; + public const TYPE_COOKIE = 'COOKIE'; + public const TYPE_POST_RAW = 'POST_RAW'; + public const TYPE_POST_JSON = 'POST_JSON'; public const OPTIONAL = false; + public const REQUIRED = true; public const DEFAULT_MULTI_INPUT_COUNT = 5; @@ -68,6 +75,7 @@ public function setAvailableValues(array $availableValues): self if ($availableValues === array_values($availableValues)) { $availableValues = array_combine($availableValues, $availableValues); } + $this->availableValues = $availableValues; return $this; } @@ -119,7 +127,6 @@ public function getDescription(): string /** * @param mixed $default - * @return self */ public function setDefault($default): self { @@ -136,7 +143,6 @@ public function getDefault(): mixed * Add example, can be used multiple times to add many examples * @param string $name Example name * @param mixed $example Example - * @return Self */ public function addExample(string $name, $example): self { @@ -147,7 +153,6 @@ public function addExample(string $name, $example): self /** * Set default example * @param mixed $example - * @return self * @deprecated Use addExample instead */ public function setExample($example): self @@ -161,6 +166,7 @@ public function getExample(): mixed if (empty($this->examples)) { return null; } + return reset($this->examples); } @@ -181,16 +187,19 @@ public function updateConsoleForm(Form $form): void if ($this->isMulti()) { $key = $key . '___' . $i; } + $input = $this->addFormInput($form, $key); if ($this->description) { $input->setOption('description', Html::el('div', ['class' => 'param-description'])->setHtml($this->description)); } + if ($this->getExample() || $this->getDefault()) { $default = $this->getExample() ?: $this->getDefault(); $default = is_array($default) ? ($default[$i] ?? null) : $default; $input->setDefaultValue($default); } } + $form->addCheckbox('do_not_send_empty_value_for_' . $this->getKey(), 'Do not send empty value for ' . $this->getLabel()); } @@ -200,6 +209,7 @@ protected function addFormInput(Form $form, string $key): BaseControl return $form->addSelect($key, $this->getParamLabel(), $this->getAvailableValues()) ->setPrompt('Select ' . $this->getLabel()); } + return $form->addText($key, $this->getParamLabel()); } @@ -214,8 +224,7 @@ protected function getParamLabel(): string if ($this->isRequired()) { $title .= ' *'; } - $title .= ' (' . $this->getType() . ')'; - return $title; + return $title . (' (' . $this->getType() . ')'); } /** diff --git a/src/Params/JsonInputParam.php b/src/Params/JsonInputParam.php index aacaaae..05a71c9 100644 --- a/src/Params/JsonInputParam.php +++ b/src/Params/JsonInputParam.php @@ -36,6 +36,7 @@ public function getValue(): mixed if ($input === null) { $input = ''; } + return json_decode($input, true); } @@ -92,6 +93,7 @@ protected function addFormInput(Form $form, string $key): BaseControl
HTML; } + $this->description .= <<< HTML