diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf3c662..c5654e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,13 +12,13 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['8.0', '8.1', '8.2', '8.3','8.4'] + php-versions: ['8.3','8.4'] coverage: ['xdebug'] code-style: ['no'] code-analysis: ['no'] rector-check: ['no'] include: - - php-versions: '7.4' + - php-versions: '8.2' coverage: 'xdebug' code-style: 'yes' code-analysis: 'yes' @@ -73,5 +73,5 @@ jobs: run: vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-clover clover.xml - name: Code Coverage - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 if: matrix.coverage != 'none' diff --git a/.gitignore b/.gitignore index a5356dd..6f6f25e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ composer.lock # Tests tests/cov/ -.phpunit.result.cache +tests/.phpunit.cache +tests/.phpunit.result.cache .php_cs.cache .php-cs-fixer.cache diff --git a/composer.json b/composer.json index 244b623..8d450c9 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "homepage" : "https://github.com/fruux/sabre-http", "license" : "BSD-3-Clause", "require" : { - "php" : "^7.4 || ^8.0", + "php" : "^8.2", "ext-mbstring" : "*", "ext-ctype" : "*", "ext-curl" : "*", @@ -18,7 +18,7 @@ "phpstan/phpstan-phpunit": "^2.0", "phpstan/phpstan-strict-rules": "^2.0", "phpstan/extension-installer": "^1.4", - "phpunit/phpunit" : "^9.6", + "phpunit/phpunit" : "^10.5", "rector/rector": "^2.4" }, "suggest" : { @@ -74,6 +74,9 @@ "config": { "allow-plugins": { "phpstan/extension-installer": true + }, + "platform": { + "php": "8.2" } } } diff --git a/lib/Auth/AWS.php b/lib/Auth/AWS.php index f0b5e68..68c26d2 100644 --- a/lib/Auth/AWS.php +++ b/lib/Auth/AWS.php @@ -179,7 +179,7 @@ protected function getAmzHeaders(): string $amzHeaders = []; $headers = $this->request->getHeaders(); foreach ($headers as $headerName => $headerValue) { - if (0 === strpos(strtolower($headerName), 'x-amz-')) { + if (str_starts_with(strtolower($headerName), 'x-amz-')) { $amzHeaders[strtolower($headerName)] = str_replace(["\r\n"], [' '], $headerValue[0])."\n"; } } diff --git a/lib/Auth/AbstractAuth.php b/lib/Auth/AbstractAuth.php index 2586a58..8dff9a5 100644 --- a/lib/Auth/AbstractAuth.php +++ b/lib/Auth/AbstractAuth.php @@ -18,29 +18,23 @@ */ abstract class AbstractAuth { - /** - * Authentication realm. - */ - protected string $realm; - - /** - * Request object. - */ - protected RequestInterface $request; - - /** - * Response object. - */ - protected ResponseInterface $response; - /** * Creates the object. */ - public function __construct(string $realm, RequestInterface $request, ResponseInterface $response) - { - $this->realm = $realm; - $this->request = $request; - $this->response = $response; + public function __construct( + /** + * Authentication realm. + */ + protected string $realm, + /** + * Request object. + */ + protected RequestInterface $request, + /** + * Response object. + */ + protected ResponseInterface $response, + ) { } /** diff --git a/lib/Client.php b/lib/Client.php index 8ea8ecc..40d2cc9 100644 --- a/lib/Client.php +++ b/lib/Client.php @@ -74,7 +74,7 @@ public function __construct() { // See https://github.com/sabre-io/http/pull/115#discussion_r241292068 // Preserve compatibility for sub-classes that implement their own method `parseCurlResult` - $separatedHeaders = self::class === get_class($this); + $separatedHeaders = self::class === static::class; $this->curlSettings = [ CURLOPT_RETURNTRANSFER => true, @@ -82,7 +82,7 @@ public function __construct() CURLOPT_USERAGENT => 'sabre-http/'.Version::VERSION.' (http://sabre.io/)', ]; if ($separatedHeaders) { - $this->curlSettings[CURLOPT_HEADERFUNCTION] = [$this, 'receiveCurlHeader']; + $this->curlSettings[CURLOPT_HEADERFUNCTION] = $this->receiveCurlHeader(...); } else { $this->curlSettings[CURLOPT_HEADER] = true; } diff --git a/lib/ClientHttpException.php b/lib/ClientHttpException.php index 4eebc20..0edf585 100644 --- a/lib/ClientHttpException.php +++ b/lib/ClientHttpException.php @@ -16,18 +16,15 @@ */ class ClientHttpException extends \Exception implements HttpException { - /** - * Response object. - */ - protected ResponseInterface $response; - /** * Constructor. */ - public function __construct(ResponseInterface $response) + public function __construct(/** + * Response object. + */ + protected ResponseInterface $response) { - $this->response = $response; - parent::__construct($response->getStatusText(), $response->getStatus()); + parent::__construct($this->response->getStatusText(), $this->response->getStatus()); } /** diff --git a/lib/Request.php b/lib/Request.php index 35a1c23..3378305 100644 --- a/lib/Request.php +++ b/lib/Request.php @@ -171,7 +171,7 @@ public function getPath(): string $uri = Uri\normalize($uri); $baseUri = Uri\normalize($this->getBaseUrl()); - if (0 === strpos($uri, $baseUri)) { + if (str_starts_with($uri, $baseUri)) { // We're not interested in the query part (everything after the ?). [$uri] = explode('?', $uri); @@ -260,7 +260,7 @@ public function __toString(): string foreach ($this->getHeaders() as $key => $value) { foreach ($value as $v) { if ('Authorization' === $key) { - [$v] = explode(' ', $v, 2); + [$v] = explode(' ', (string) $v, 2); $v .= ' REDACTED'; } $out .= $key.': '.$v."\r\n"; diff --git a/lib/RequestDecorator.php b/lib/RequestDecorator.php index 5c56920..3828a49 100644 --- a/lib/RequestDecorator.php +++ b/lib/RequestDecorator.php @@ -17,19 +17,18 @@ class RequestDecorator implements RequestInterface { use MessageDecoratorTrait; - /** - * The inner request object. - * - * All method calls will be forwarded here. - */ - protected RequestInterface $inner; /** * Constructor. */ - public function __construct(RequestInterface $inner) - { - $this->inner = $inner; + public function __construct( + /** + * The inner request object. + * + * All method calls will be forwarded here. + */ + protected RequestInterface $inner, + ) { } /** diff --git a/lib/ResponseDecorator.php b/lib/ResponseDecorator.php index afe6cb5..3985bce 100644 --- a/lib/ResponseDecorator.php +++ b/lib/ResponseDecorator.php @@ -17,19 +17,18 @@ class ResponseDecorator implements ResponseInterface { use MessageDecoratorTrait; - /** - * The inner request object. - * - * All method calls will be forwarded here. - */ - protected ResponseInterface $inner; /** * Constructor. */ - public function __construct(ResponseInterface $inner) - { - $this->inner = $inner; + public function __construct( + /** + * The inner request object. + * + * All method calls will be forwarded here. + */ + protected ResponseInterface $inner, + ) { } /** diff --git a/lib/Sapi.php b/lib/Sapi.php index e2c4b1a..64a29f5 100644 --- a/lib/Sapi.php +++ b/lib/Sapi.php @@ -207,7 +207,7 @@ public static function createFromServerArray(array $serverArray): Request break; default: - if ('HTTP_' === substr($key, 0, 5)) { + if (str_starts_with($key, 'HTTP_')) { // It's an HTTP header // Normalizing it to be prettier diff --git a/lib/functions.php b/lib/functions.php index 17da562..a4bb544 100644 --- a/lib/functions.php +++ b/lib/functions.php @@ -59,13 +59,13 @@ function parseDate(string $dateString) } // append implicit GMT timezone to ANSI C time format - if (false === strpos($dateString, ' GMT')) { + if (!str_contains($dateString, ' GMT')) { $dateString .= ' GMT'; } try { return new \DateTime($dateString, new \DateTimeZone('UTC')); - } catch (\Exception $e) { + } catch (\Exception) { return false; } } @@ -109,7 +109,7 @@ function negotiateContentType(?string $acceptHeaderValue, array $availableOption } $proposals = array_map( - 'Sabre\HTTP\parseMimeType', + \Sabre\HTTP\parseMimeType(...), explode(',', $acceptHeaderValue) ); @@ -117,7 +117,7 @@ function negotiateContentType(?string $acceptHeaderValue, array $availableOption $availableOptions = array_values($availableOptions); $options = array_map( - 'Sabre\HTTP\parseMimeType', + \Sabre\HTTP\parseMimeType(...), $availableOptions ); diff --git a/phpstan-ignore-by-php-version.neon.php b/phpstan-ignore-by-php-version.neon.php deleted file mode 100644 index 5f58a1c..0000000 --- a/phpstan-ignore-by-php-version.neon.php +++ /dev/null @@ -1,18 +0,0 @@ -= 80000) { - $includes[] = __DIR__.'/phpstan-ignore-php8.neon'; -} else { - $includes[] = __DIR__.'/phpstan-ignore-php74.neon'; -} - -$config = []; -$config['includes'] = $includes; - -// overrides config.platform.php in composer.json -$config['parameters']['phpVersion'] = PHP_VERSION_ID; - -return $config; diff --git a/phpstan-ignore-php74.neon b/phpstan-ignore-php74.neon deleted file mode 100644 index 041b324..0000000 --- a/phpstan-ignore-php74.neon +++ /dev/null @@ -1,6 +0,0 @@ -parameters: - ignoreErrors: - - - message: "#^Left side of || is always false.$#" - count: 10 - path: lib/Client.php diff --git a/phpstan-ignore-php8.neon b/phpstan-ignore-php8.neon deleted file mode 100644 index 43b26f0..0000000 --- a/phpstan-ignore-php8.neon +++ /dev/null @@ -1,6 +0,0 @@ -parameters: - ignoreErrors: - - - message: "#^Left side of || is always false.$#" - count: 23 - path: lib/Client.php diff --git a/phpstan.neon b/phpstan.neon index 64e8b78..97e6a2a 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,3 @@ -includes: - - phpstan-ignore-by-php-version.neon.php - parameters: level: 6 ignoreErrors: @@ -20,3 +17,7 @@ parameters: message: "#^.* will always evaluate to true\\.$#" count: 4 path: tests/* + - + message: "#^Left side of || is always false.$#" + count: 23 + path: lib/Client.php diff --git a/rector.php b/rector.php index 7cccb12..e89e2cc 100644 --- a/rector.php +++ b/rector.php @@ -10,7 +10,7 @@ __DIR__.'/lib', __DIR__.'/tests', ]) - ->withPhpSets(false, false, false, false, true) + ->withPhpSets(false, true) ->withTypeCoverageLevel(0) ->withDeadCodeLevel(0) ->withCodeQualityLevel(0); diff --git a/tests/HTTP/Auth/AWSTest.php b/tests/HTTP/Auth/AWSTest.php index 88b18c6..35d610e 100644 --- a/tests/HTTP/Auth/AWSTest.php +++ b/tests/HTTP/Auth/AWSTest.php @@ -199,7 +199,7 @@ public function testValidRequest(): void public function test401(): void { $this->auth->requireLogin(); - $test = preg_match('/^AWS$/', $this->response->getHeader('WWW-Authenticate'), $matches); + $test = preg_match('/^AWS$/', (string) $this->response->getHeader('WWW-Authenticate'), $matches); self::assertTrue(1 === $test, 'The WWW-Authenticate response didn\'t match our pattern'); } diff --git a/tests/HTTP/Auth/DigestTest.php b/tests/HTTP/Auth/DigestTest.php index 083d82c..5391695 100644 --- a/tests/HTTP/Auth/DigestTest.php +++ b/tests/HTTP/Auth/DigestTest.php @@ -154,17 +154,14 @@ private function getServerTokens(int $qop = Digest::QOP_AUTH): array { $this->auth->requireLogin(); - switch ($qop) { - case Digest::QOP_AUTH: $qopstr = 'auth'; - break; - case Digest::QOP_AUTHINT: $qopstr = 'auth-int'; - break; - default: $qopstr = 'auth,auth-int'; - break; - } + $qopstr = match ($qop) { + Digest::QOP_AUTH => 'auth', + Digest::QOP_AUTHINT => 'auth-int', + default => 'auth,auth-int', + }; $test = preg_match('/Digest realm="'.self::REALM.'",qop="'.$qopstr.'",nonce="([0-9a-f]*)",opaque="([0-9a-f]*)"/', - $this->response->getHeader('WWW-Authenticate'), $matches); + (string) $this->response->getHeader('WWW-Authenticate'), $matches); self::assertTrue(1 === $test, 'The WWW-Authenticate response didn\'t match our pattern. We received: '.$this->response->getHeader('WWW-Authenticate')); diff --git a/tests/HTTP/ClientTest.php b/tests/HTTP/ClientTest.php index 62da6a3..817cb4c 100644 --- a/tests/HTTP/ClientTest.php +++ b/tests/HTTP/ClientTest.php @@ -323,7 +323,7 @@ public function testSendClientError(): void try { $client->send($request); self::fail('send() should have thrown an exception'); - } catch (ClientException $e) { + } catch (ClientException) { } self::assertTrue($called); } diff --git a/tests/HTTP/FunctionsTest.php b/tests/HTTP/FunctionsTest.php index 506786a..d120911 100644 --- a/tests/HTTP/FunctionsTest.php +++ b/tests/HTTP/FunctionsTest.php @@ -21,7 +21,7 @@ public function testGetHeaderValuesOnValues2(array $result, array $values1, arra /** * @return array>> */ - public function getHeaderValuesDataOnValues2(): array + public static function getHeaderValuesDataOnValues2(): array { return [ [ @@ -54,7 +54,7 @@ public function testGetHeaderValues($input, array $output): void /** * @return array */ - public function getHeaderValuesData(): array + public static function getHeaderValuesData(): array { return [ [ @@ -97,7 +97,7 @@ public function testPrefer($input, array $output): void /** * @return array */ - public function preferData(): array + public static function preferData(): array { return [ [ diff --git a/tests/HTTP/NegotiateTest.php b/tests/HTTP/NegotiateTest.php index 4ee2002..639865a 100644 --- a/tests/HTTP/NegotiateTest.php +++ b/tests/HTTP/NegotiateTest.php @@ -22,7 +22,7 @@ public function testNegotiate(?string $acceptHeader, array $available, ?string $ /** * @return array> */ - public function negotiateData(): array + public static function negotiateData(): array { return [ [ // simple diff --git a/tests/HTTP/SapiTest.php b/tests/HTTP/SapiTest.php index fefa40e..7c77132 100644 --- a/tests/HTTP/SapiTest.php +++ b/tests/HTTP/SapiTest.php @@ -252,7 +252,7 @@ public function testSendContentRangeStream( /** * @return array> */ - public function sendContentRangeStreamData(): array + public static function sendContentRangeStreamData(): array { return [ ['Ignore this. ', 'Send this.', 10, ' Ignore this at end.'], diff --git a/tests/phpunit.xml b/tests/phpunit.xml index 64ed73c..f79e4a0 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -1,10 +1,5 @@ - - - - ../lib/ - - + HTTP/ @@ -13,4 +8,9 @@ + + + ../lib/ + +