From 48fd9439b9f6e1a7bd01dbcefb6e281e39ff2b67 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 11 Feb 2021 03:09:13 +0100 Subject: [PATCH 01/11] typo --- src/Http/Response.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index 1c71bacd..e2ca6a65 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -311,7 +311,7 @@ private function checkHeaders(): void ob_get_length() && !array_filter(ob_get_status(true), function (array $i): bool { return !$i['chunk_size']; }) ) { - trigger_error('Possible problem: you are sending a HTTP header while already having some data in output buffer. Try Tracy\OutputDebugger or start session earlier.'); + trigger_error('Possible problem: you are sending a HTTP header while already having some data in output buffer. Try Tracy\OutputDebugger or send cookies/start session earlier.'); } } } From a292c25da54df5886de25b4372a18b2e38068973 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 15:28:42 +0100 Subject: [PATCH 02/11] opened 4.0-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5f258113..c1f09301 100644 --- a/composer.json +++ b/composer.json @@ -42,7 +42,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "4.0-dev" } } } From 86f87f3c83215fd59237d193a7ee8405e2961ed1 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 17:18:24 +0100 Subject: [PATCH 03/11] requires PHP 8.0 --- .github/workflows/coding-style.yml | 4 ++-- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 6 +++--- appveyor.yml | 2 +- composer.json | 2 +- readme.md | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index 39afa89a..50d857de 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.1 + php-version: 8.0 coverage: none - run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index a051b78b..2289a804 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer install --no-progress --prefer-dist diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a74590f9..8131aa9b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - php: ['7.2', '7.3', '7.4', '8.0'] + php: ['8.0'] # sapi: ['php', 'php-cgi'] fail-fast: false @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.2 + php-version: 8.0 coverage: none extensions: fileinfo, intl @@ -53,7 +53,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none extensions: fileinfo, intl diff --git a/appveyor.yml b/appveyor.yml index a672440d..d1d28c8d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,7 +14,7 @@ install: # Install PHP - IF EXIST c:\php (SET PHP=0) ELSE (mkdir c:\php) - IF %PHP%==1 cd c:\php - - IF %PHP%==1 curl https://windows.php.net/downloads/releases/archives/php-7.2.28-Win32-VC15-x64.zip --output php.zip + - IF %PHP%==1 curl https://windows.php.net/downloads/releases/archives/php-8.0.1-Win32-vs16-x64.zip --output php.zip - IF %PHP%==1 7z x php.zip >nul - IF %PHP%==1 echo extension_dir=ext >> php.ini - IF %PHP%==1 echo extension=php_openssl.dll >> php.ini diff --git a/composer.json b/composer.json index c1f09301..e885af42 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": ">=7.2 <8.1", + "php": ">=8.0 <8.1", "nette/utils": "^3.1" }, "require-dev": { diff --git a/readme.md b/readme.md index b6db972c..8d97f475 100644 --- a/readme.md +++ b/readme.md @@ -35,7 +35,7 @@ Installation composer require nette/http ``` -It requires PHP version 7.2 and supports PHP up to 8.0. +It requires PHP version 8.0. HTTP Request From e760eeef81b7f29d7fe601d19ef948b3fb9b0e33 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 16:44:09 +0100 Subject: [PATCH 04/11] composer: updated dependencies --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index e885af42..f7a2a077 100644 --- a/composer.json +++ b/composer.json @@ -16,13 +16,13 @@ ], "require": { "php": ">=8.0 <8.1", - "nette/utils": "^3.1" + "nette/utils": "^3.2 || ^4.0" }, "require-dev": { - "nette/di": "^3.0", - "nette/tester": "^2.0", - "nette/security": "^3.0", - "tracy/tracy": "^2.4", + "nette/di": "^4.0", + "nette/tester": "^2.4", + "nette/security": "^4.0", + "tracy/tracy": "^2.8", "phpstan/phpstan": "^0.12" }, "conflict": { From 14d2b7c871f55ac24fd0f04499517eb38bd8104a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 18:05:34 +0100 Subject: [PATCH 05/11] coding style --- src/Bridges/HttpDI/HttpExtension.php | 4 +- src/Http/FileUpload.php | 2 +- src/Http/Helpers.php | 2 +- src/Http/IResponse.php | 2 +- src/Http/Request.php | 2 +- src/Http/RequestFactory.php | 20 +++++----- src/Http/Response.php | 8 ++-- src/Http/Session.php | 8 ++-- src/Http/Url.php | 8 ++-- tests/Http.DI/HttpExtension.csp.phpt | 38 +++++++++---------- .../Http.DI/HttpExtension.featurePolicy.phpt | 17 ++++----- tests/Http.DI/HttpExtension.headers.phpt | 12 +++--- .../HttpExtension.sameSiteProtection.phpt | 2 +- tests/Http.DI/SessionExtension.config.phpt | 2 +- tests/Http/Helpers.phpt | 2 +- tests/Http/Request.getRawBody.phpt | 4 +- tests/Http/Response.setCookie.phpt | 2 +- tests/Http/Session.sameSite.phpt | 2 +- 18 files changed, 66 insertions(+), 71 deletions(-) diff --git a/src/Bridges/HttpDI/HttpExtension.php b/src/Bridges/HttpDI/HttpExtension.php index 5a1796c2..f77baae1 100644 --- a/src/Bridges/HttpDI/HttpExtension.php +++ b/src/Bridges/HttpDI/HttpExtension.php @@ -116,7 +116,7 @@ private function sendHeaders() $this->initialization->addBody('$cspNonce = base64_encode(random_bytes(16));'); $value = Nette\DI\ContainerBuilder::literal( 'str_replace(?, ? . $cspNonce, ?)', - ["'nonce", "'nonce-", $value] + ["'nonce", "'nonce-", $value], ); } $headers['Content-Security-Policy' . ($key === 'csp' ? '' : '-Report-Only')] = $value; @@ -135,7 +135,7 @@ private function sendHeaders() $this->initialization->addBody( 'Nette\Http\Helpers::initCookie($this->getService(?), $response);', - [$this->prefix('request')] + [$this->prefix('request')], ); } diff --git a/src/Http/FileUpload.php b/src/Http/FileUpload.php index 3c9ff21e..df6fc32c 100644 --- a/src/Http/FileUpload.php +++ b/src/Http/FileUpload.php @@ -181,7 +181,7 @@ public function move(string $dest) [$this->tmpName, $dest], function (string $message) use ($dest): void { throw new Nette\InvalidStateException("Unable to move uploaded file '$this->tmpName' to '$dest'. $message"); - } + }, ); @chmod($dest, 0666); // @ - possible low permission to chmod $this->tmpName = $dest; diff --git a/src/Http/Helpers.php b/src/Http/Helpers.php index efde3de6..ccac99d7 100644 --- a/src/Http/Helpers.php +++ b/src/Http/Helpers.php @@ -41,7 +41,7 @@ public static function formatDate($time): string public static function ipMatch(string $ip, string $mask): bool { [$mask, $size] = explode('/', $mask . '/'); - $tmp = function (int $n): string { return sprintf('%032b', $n); }; + $tmp = fn(int $n): string => sprintf('%032b', $n); $ip = implode('', array_map($tmp, unpack('N*', inet_pton($ip)))); $mask = implode('', array_map($tmp, unpack('N*', inet_pton($mask)))); $max = strlen($ip); diff --git a/src/Http/IResponse.php b/src/Http/IResponse.php index d968f8e2..c544cf6a 100644 --- a/src/Http/IResponse.php +++ b/src/Http/IResponse.php @@ -220,7 +220,7 @@ function setCookie( string $path = null, string $domain = null, bool $secure = null, - bool $httpOnly = null + bool $httpOnly = null, ); /** diff --git a/src/Http/Request.php b/src/Http/Request.php index 2aaff910..e828f51f 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -70,7 +70,7 @@ public function __construct( string $method = null, string $remoteAddress = null, string $remoteHost = null, - callable $rawBodyCallback = null + callable $rawBodyCallback = null, ) { $this->url = $url; $this->post = (array) $post; diff --git a/src/Http/RequestFactory.php b/src/Http/RequestFactory.php index 71d8d161..3fc62140 100644 --- a/src/Http/RequestFactory.php +++ b/src/Http/RequestFactory.php @@ -76,9 +76,7 @@ public function fromGlobals(): Request $this->getMethod(), $remoteAddr, $remoteHost, - function (): string { - return file_get_contents('php://input'); - } + fn(): string => file_get_contents('php://input'), ); } @@ -271,9 +269,7 @@ private function getClient(Url $url): array : null; // use real client address and host if trusted proxy is used - $usingTrustedProxy = $remoteAddr && array_filter($this->proxies, function (string $proxy) use ($remoteAddr): bool { - return Helpers::ipMatch($remoteAddr, $proxy); - }); + $usingTrustedProxy = $remoteAddr && array_filter($this->proxies, fn(string $proxy): bool => Helpers::ipMatch($remoteAddr, $proxy)); if ($usingTrustedProxy) { empty($_SERVER['HTTP_FORWARDED']) ? $this->useNonstandardProxy($url, $remoteAddr, $remoteHost) @@ -339,11 +335,13 @@ private function useNonstandardProxy(Url $url, &$remoteAddr, &$remoteHost): void } if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { - $xForwardedForWithoutProxies = array_filter(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']), function (string $ip): bool { - return !array_filter($this->proxies, function (string $proxy) use ($ip): bool { - return filter_var(trim($ip), FILTER_VALIDATE_IP) !== false && Helpers::ipMatch(trim($ip), $proxy); - }); - }); + $xForwardedForWithoutProxies = array_filter( + explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']), + fn(string $ip): bool => !array_filter( + $this->proxies, + fn(string $proxy): bool => filter_var(trim($ip), FILTER_VALIDATE_IP) !== false && Helpers::ipMatch(trim($ip), $proxy), + ), + ); if ($xForwardedForWithoutProxies) { $remoteAddr = trim(end($xForwardedForWithoutProxies)); $xForwardedForRealIpKey = key($xForwardedForWithoutProxies); diff --git a/src/Http/Response.php b/src/Http/Response.php index e2ca6a65..59b17034 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -148,7 +148,7 @@ public function sendAsFile(string $fileName) $this->setHeader( 'Content-Disposition', 'attachment; filename="' . str_replace('"', '', $fileName) . '"; ' - . "filename*=utf-8''" . rawurlencode($fileName) + . "filename*=utf-8''" . rawurlencode($fileName), ); return $this; } @@ -262,7 +262,7 @@ public function setCookie( string $domain = null, bool $secure = null, bool $httpOnly = null, - string $sameSite = null + string $sameSite = null, ) { self::checkHeaders(); $options = [ @@ -283,7 +283,7 @@ public function setCookie( $options['path'] . ($sameSite ? "; SameSite=$sameSite" : ''), $options['domain'], $options['secure'], - $options['httponly'] + $options['httponly'], ); } return $this; @@ -309,7 +309,7 @@ private function checkHeaders(): void } elseif ( $this->warnOnBuffer && ob_get_length() && - !array_filter(ob_get_status(true), function (array $i): bool { return !$i['chunk_size']; }) + !array_filter(ob_get_status(true), fn(array $i): bool => !$i['chunk_size']) ) { trigger_error('Possible problem: you are sending a HTTP header while already having some data in output buffer. Try Tracy\OutputDebugger or send cookies/start session earlier.'); } diff --git a/src/Http/Session.php b/src/Http/Session.php index 05adba59..006e3638 100644 --- a/src/Http/Session.php +++ b/src/Http/Session.php @@ -336,7 +336,7 @@ public function setOptions(array $options) if (!isset($allowed["session.$normKey"])) { $hint = substr((string) Nette\Utils\Helpers::getSuggestion(array_keys($allowed), "session.$normKey"), 8); if ($key !== $normKey) { - $hint = preg_replace_callback('#_(.)#', function ($m) { return strtoupper($m[1]); }, $hint); // snake_case -> camelCase + $hint = preg_replace_callback('#_(.)#', fn($m) => strtoupper($m[1]), $hint); // snake_case -> camelCase } throw new Nette\InvalidStateException("Invalid session configuration option '$key'" . ($hint ? ", did you mean '$hint'?" : '.')); } @@ -411,7 +411,7 @@ private function configure(array $config): void $cookie['path'] . (isset($cookie['samesite']) ? '; SameSite=' . $cookie['samesite'] : ''), $cookie['domain'], $cookie['secure'], - $cookie['httponly'] + $cookie['httponly'], ); } if (session_status() === PHP_SESSION_ACTIVE) { @@ -456,7 +456,7 @@ public function setCookieParameters( string $path, string $domain = null, bool $secure = null, - string $sameSite = null + string $sameSite = null, ) { return $this->setOptions([ 'cookie_path' => $path, @@ -515,7 +515,7 @@ private function sendCookie(): void $cookie['domain'], $cookie['secure'], $cookie['httponly'], - $cookie['samesite'] ?? null + $cookie['samesite'] ?? null, ); } } diff --git a/src/Http/Url.php b/src/Http/Url.php index fff7616c..c9e5e2b8 100644 --- a/src/Http/Url.php +++ b/src/Http/Url.php @@ -370,8 +370,8 @@ public function canonicalize() { $this->path = preg_replace_callback( '#[^!$&\'()*+,/:;=@%]+#', - function (array $m): string { return rawurlencode($m[0]); }, - self::unescape($this->path, '%/') + fn(array $m): string => rawurlencode($m[0]), + self::unescape($this->path, '%/'), ); $this->host = self::idnHostToUnicode(strtolower($this->host)); return $this; @@ -423,8 +423,8 @@ public static function unescape(string $s, string $reserved = '%;/?:@&=+$,'): st if ($reserved !== '') { $s = preg_replace_callback( '#%(' . substr(chunk_split(bin2hex($reserved), 2, '|'), 0, -1) . ')#i', - function (array $m): string { return '%25' . strtoupper($m[1]); }, - $s + fn(array $m): string => '%25' . strtoupper($m[1]), + $s, ); } return rawurldecode($s); diff --git a/tests/Http.DI/HttpExtension.csp.phpt b/tests/Http.DI/HttpExtension.csp.phpt index 00f2665d..338a9f48 100644 --- a/tests/Http.DI/HttpExtension.csp.phpt +++ b/tests/Http.DI/HttpExtension.csp.phpt @@ -22,25 +22,25 @@ $compiler = new DI\Compiler; $compiler->addExtension('http', new HttpExtension); $loader = new DI\Config\Loader; $config = $loader->load(Tester\FileMock::create(<<<'EOD' -http: - csp: - default-src: "'self' https://example.com" - upgrade-insecure-requests: - script-src: 'nonce' - style-src: - - self - - https://example.com - - http: - require-sri-for: style - sandbox: allow-forms - plugin-types: application/x-java-applet - - cspReportOnly: - default-src: "'nonce'" - report-uri: https://example.com/report - upgrade-insecure-requests: true - block-all-mixed-content: false -EOD + http: + csp: + default-src: "'self' https://example.com" + upgrade-insecure-requests: + script-src: 'nonce' + style-src: + - self + - https://example.com + - http: + require-sri-for: style + sandbox: allow-forms + plugin-types: application/x-java-applet + + cspReportOnly: + default-src: "'nonce'" + report-uri: https://example.com/report + upgrade-insecure-requests: true + block-all-mixed-content: false + EOD , 'neon')); eval($compiler->addConfig($config)->compile()); diff --git a/tests/Http.DI/HttpExtension.featurePolicy.phpt b/tests/Http.DI/HttpExtension.featurePolicy.phpt index 9a792053..9d3db400 100644 --- a/tests/Http.DI/HttpExtension.featurePolicy.phpt +++ b/tests/Http.DI/HttpExtension.featurePolicy.phpt @@ -22,14 +22,14 @@ $compiler = new DI\Compiler; $compiler->addExtension('http', new HttpExtension); $loader = new DI\Config\Loader; $config = $loader->load(Tester\FileMock::create(<<<'EOD' -http: - featurePolicy: - unsized-media: none - geolocation: - - self - - https://example.com - camera: * -EOD + http: + featurePolicy: + unsized-media: none + geolocation: + - self + - https://example.com + camera: * + EOD , 'neon')); eval($compiler->addConfig($config)->compile()); @@ -38,7 +38,6 @@ $container = new Container; $container->initialize(); $headers = headers_list(); -var_dump($headers); Assert::contains("Feature-Policy: unsized-media 'none'; geolocation 'self' https://example.com; camera *;", $headers); diff --git a/tests/Http.DI/HttpExtension.headers.phpt b/tests/Http.DI/HttpExtension.headers.phpt index cac2a1ce..7d8b2c5c 100644 --- a/tests/Http.DI/HttpExtension.headers.phpt +++ b/tests/Http.DI/HttpExtension.headers.phpt @@ -22,12 +22,12 @@ $compiler = new DI\Compiler; $compiler->addExtension('http', new HttpExtension); $loader = new DI\Config\Loader; $config = $loader->load(Tester\FileMock::create(<<<'EOD' -http: - headers: - A: b - C: - D: 0 -EOD + http: + headers: + A: b + C: + D: 0 + EOD , 'neon')); eval($compiler->addConfig($config)->compile()); diff --git a/tests/Http.DI/HttpExtension.sameSiteProtection.phpt b/tests/Http.DI/HttpExtension.sameSiteProtection.phpt index 842d941d..88b10575 100644 --- a/tests/Http.DI/HttpExtension.sameSiteProtection.phpt +++ b/tests/Http.DI/HttpExtension.sameSiteProtection.phpt @@ -28,5 +28,5 @@ Assert::contains( PHP_VERSION_ID >= 70300 ? 'Set-Cookie: _nss=1; path=/; HttpOnly; SameSite=Strict' : 'Set-Cookie: _nss=1; path=/; SameSite=Strict; HttpOnly', - $headers + $headers, ); diff --git a/tests/Http.DI/SessionExtension.config.phpt b/tests/Http.DI/SessionExtension.config.phpt index 3c59656f..94c54460 100644 --- a/tests/Http.DI/SessionExtension.config.phpt +++ b/tests/Http.DI/SessionExtension.config.phpt @@ -42,5 +42,5 @@ Assert::same( PHP_VERSION_ID >= 70300 ? ['lifetime' => 0, 'path' => '/x', 'domain' => 'nette.org', 'secure' => true, 'httponly' => true, 'samesite' => 'Lax'] : ['lifetime' => 0, 'path' => '/x; SameSite=Lax', 'domain' => 'nette.org', 'secure' => true, 'httponly' => true], - session_get_cookie_params() + session_get_cookie_params(), ); diff --git a/tests/Http/Helpers.phpt b/tests/Http/Helpers.phpt index 8c94b5fa..3ccd3523 100644 --- a/tests/Http/Helpers.phpt +++ b/tests/Http/Helpers.phpt @@ -45,5 +45,5 @@ test('', function () { Assert::same('Tue, 15 Nov 1994 08:12:31 GMT', Helpers::formatDate('1994-11-15T08:12:31+0000')); Assert::same('Tue, 15 Nov 1994 08:12:31 GMT', Helpers::formatDate('1994-11-15T10:12:31+0200')); Assert::same('Tue, 15 Nov 1994 08:12:31 GMT', Helpers::formatDate(new DateTime('1994-11-15T06:12:31-0200'))); - Assert::same('Tue, 15 Nov 1994 08:12:31 GMT', Helpers::formatDate(784887151)); + Assert::same('Tue, 15 Nov 1994 08:12:31 GMT', Helpers::formatDate(784_887_151)); }); diff --git a/tests/Http/Request.getRawBody.phpt b/tests/Http/Request.getRawBody.phpt index d0155969..a6ef5b40 100644 --- a/tests/Http/Request.getRawBody.phpt +++ b/tests/Http/Request.getRawBody.phpt @@ -14,9 +14,7 @@ require __DIR__ . '/../bootstrap.php'; test('', function () { - $request = new Http\Request(new Http\UrlScript, null, null, null, null, null, null, null, function () { - return 'raw body'; - }); + $request = new Http\Request(new Http\UrlScript, null, null, null, null, null, null, null, fn() => 'raw body'); Assert::same('raw body', $request->getRawBody()); }); diff --git a/tests/Http/Response.setCookie.phpt b/tests/Http/Response.setCookie.phpt index e4f342b0..be98ee97 100644 --- a/tests/Http/Response.setCookie.phpt +++ b/tests/Http/Response.setCookie.phpt @@ -36,7 +36,7 @@ Assert::same( PHP_VERSION_ID >= 70300 ? ['Set-Cookie: test=value; path=/; HttpOnly; SameSite=Lax', 'Set-Cookie: test=newvalue; path=/; HttpOnly; SameSite=Lax'] : ['Set-Cookie: test=value; path=/; SameSite=Lax; HttpOnly', 'Set-Cookie: test=newvalue; path=/; SameSite=Lax; HttpOnly'], - $headers + $headers, ); diff --git a/tests/Http/Session.sameSite.phpt b/tests/Http/Session.sameSite.phpt index 6afc49e5..4bc89dd7 100644 --- a/tests/Http/Session.sameSite.phpt +++ b/tests/Http/Session.sameSite.phpt @@ -26,5 +26,5 @@ Assert::contains( PHP_VERSION_ID >= 70300 ? 'Set-Cookie: PHPSESSID=' . $session->getId() . '; path=/; HttpOnly; SameSite=Lax' : 'Set-Cookie: PHPSESSID=' . $session->getId() . '; path=/; SameSite=Lax; HttpOnly', - headers_list() + headers_list(), ); From ff3d0dfeb45467dd4ecb8e8fda39114592c2e931 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 18:33:58 +0100 Subject: [PATCH 06/11] removed support for PHP 7 --- src/Http/Response.php | 14 +------------- src/Http/Session.php | 12 +----------- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index 59b17034..03401b49 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -273,19 +273,7 @@ public function setCookie( 'httponly' => $httpOnly ?? true, 'samesite' => $sameSite = ($sameSite ?? self::SAME_SITE_LAX), ]; - if (PHP_VERSION_ID >= 70300) { - setcookie($name, $value, $options); - } else { - setcookie( - $name, - $value, - $options['expires'], - $options['path'] . ($sameSite ? "; SameSite=$sameSite" : ''), - $options['domain'], - $options['secure'], - $options['httponly'], - ); - } + setcookie($name, $value, $options); return $this; } diff --git a/src/Http/Session.php b/src/Http/Session.php index 006e3638..0bcb6023 100644 --- a/src/Http/Session.php +++ b/src/Http/Session.php @@ -403,17 +403,7 @@ private function configure(array $config): void } if ($cookie !== $origCookie) { - if (PHP_VERSION_ID >= 70300) { - @session_set_cookie_params($cookie); // @ may trigger warning when session is active since PHP 7.2 - } else { - @session_set_cookie_params( // @ may trigger warning when session is active since PHP 7.2 - $cookie['lifetime'], - $cookie['path'] . (isset($cookie['samesite']) ? '; SameSite=' . $cookie['samesite'] : ''), - $cookie['domain'], - $cookie['secure'], - $cookie['httponly'], - ); - } + @session_set_cookie_params($cookie); // @ may trigger warning when session is active since PHP 7.2 if (session_status() === PHP_SESSION_ACTIVE) { $this->sendCookie(); } From 1f597a49c367cc465dc45d04f0bfca24508ba0a8 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 19:14:39 +0100 Subject: [PATCH 07/11] added property typehints --- src/Bridges/HttpDI/HttpExtension.php | 3 +-- src/Bridges/HttpDI/SessionExtension.php | 6 ++---- src/Http/Context.php | 6 ++---- src/Http/FileUpload.php | 15 +++++--------- src/Http/Request.php | 26 +++++++++--------------- src/Http/RequestFactory.php | 8 +++----- src/Http/Response.php | 24 +++++++++++----------- src/Http/Session.php | 24 +++++++++------------- src/Http/SessionSection.php | 9 +++------ src/Http/Url.php | 27 +++++++++---------------- src/Http/UrlImmutable.php | 27 +++++++++---------------- src/Http/UrlScript.php | 8 +++----- src/Http/UserStorage.php | 9 +++------ 13 files changed, 71 insertions(+), 121 deletions(-) diff --git a/src/Bridges/HttpDI/HttpExtension.php b/src/Bridges/HttpDI/HttpExtension.php index f77baae1..10034fe2 100644 --- a/src/Bridges/HttpDI/HttpExtension.php +++ b/src/Bridges/HttpDI/HttpExtension.php @@ -18,8 +18,7 @@ */ class HttpExtension extends Nette\DI\CompilerExtension { - /** @var bool */ - private $cliMode; + private bool $cliMode; public function __construct(bool $cliMode = false) diff --git a/src/Bridges/HttpDI/SessionExtension.php b/src/Bridges/HttpDI/SessionExtension.php index 0cba114e..84730260 100644 --- a/src/Bridges/HttpDI/SessionExtension.php +++ b/src/Bridges/HttpDI/SessionExtension.php @@ -19,11 +19,9 @@ */ class SessionExtension extends Nette\DI\CompilerExtension { - /** @var bool */ - private $debugMode; + private bool $debugMode; - /** @var bool */ - private $cliMode; + private bool $cliMode; public function __construct(bool $debugMode = false, bool $cliMode = false) diff --git a/src/Http/Context.php b/src/Http/Context.php index 7962ab30..1b5e91fd 100644 --- a/src/Http/Context.php +++ b/src/Http/Context.php @@ -19,11 +19,9 @@ class Context { use Nette\SmartObject; - /** @var IRequest */ - private $request; + private IRequest $request; - /** @var IResponse */ - private $response; + private IResponse $response; public function __construct(IRequest $request, IResponse $response) diff --git a/src/Http/FileUpload.php b/src/Http/FileUpload.php index df6fc32c..df1f1c1b 100644 --- a/src/Http/FileUpload.php +++ b/src/Http/FileUpload.php @@ -30,20 +30,15 @@ final class FileUpload public const IMAGE_MIME_TYPES = ['image/gif', 'image/png', 'image/jpeg', 'image/webp']; - /** @var string */ - private $name; + private string $name; - /** @var string|false|null */ - private $type; + private string|false|null $type = null; - /** @var int */ - private $size; + private int $size; - /** @var string */ - private $tmpName; + private string $tmpName; - /** @var int */ - private $error; + private int $error; public function __construct(?array $value) diff --git a/src/Http/Request.php b/src/Http/Request.php index e828f51f..416f25d8 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -33,31 +33,23 @@ class Request implements IRequest { use Nette\SmartObject; - /** @var string */ - private $method; + private string $method; - /** @var UrlScript */ - private $url; + private UrlScript $url; - /** @var array */ - private $post; + private array $post; - /** @var array */ - private $files; + private array $files; - /** @var array */ - private $cookies; + private array $cookies; - /** @var array */ - private $headers; + private array $headers; - /** @var string|null */ - private $remoteAddress; + private ?string $remoteAddress; - /** @var string|null */ - private $remoteHost; + private ?string $remoteHost; - /** @var callable|null */ + /** @var ?callable */ private $rawBodyCallback; diff --git a/src/Http/RequestFactory.php b/src/Http/RequestFactory.php index 3fc62140..437624aa 100644 --- a/src/Http/RequestFactory.php +++ b/src/Http/RequestFactory.php @@ -23,17 +23,15 @@ class RequestFactory /** @internal */ private const CHARS = '\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}'; - /** @var array */ - public $urlFilters = [ + public array $urlFilters = [ 'path' => ['#/{2,}#' => '/'], // '%20' => '' 'url' => [], // '#[.,)]$#D' => '' ]; - /** @var bool */ - private $binary = false; + private bool $binary = false; /** @var string[] */ - private $proxies = []; + private array $proxies = []; /** @return static */ diff --git a/src/Http/Response.php b/src/Http/Response.php index 03401b49..333d1838 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -22,26 +22,26 @@ final class Response implements IResponse { use Nette\SmartObject; - /** @var string The domain in which the cookie will be available */ - public $cookieDomain = ''; + /** The domain in which the cookie will be available */ + public string $cookieDomain = ''; - /** @var string The path in which the cookie will be available */ - public $cookiePath = '/'; + /** The path in which the cookie will be available */ + public string $cookiePath = '/'; - /** @var bool Whether the cookie is available only through HTTPS */ - public $cookieSecure = false; + /** Whether the cookie is available only through HTTPS */ + public bool $cookieSecure = false; /** @deprecated */ public $cookieHttpOnly; - /** @var bool Whether warn on possible problem with data in output buffer */ - public $warnOnBuffer = true; + /** Whether warn on possible problem with data in output buffer */ + public bool $warnOnBuffer = true; - /** @var bool Send invisible garbage for IE 6? */ - private static $fixIE = true; + /** Send invisible garbage for IE 6? */ + private static bool $fixIE = true; - /** @var int HTTP response code */ - private $code = self::S200_OK; + /** HTTP response code */ + private int $code = self::S200_OK; public function __construct() diff --git a/src/Http/Session.php b/src/Http/Session.php index 0bcb6023..dbc40bd3 100644 --- a/src/Http/Session.php +++ b/src/Http/Session.php @@ -31,30 +31,26 @@ class Session 'cookie_httponly' => true, // must be enabled to prevent Session Hijacking ]; - /** @var bool has been session ID regenerated? */ - private $regenerated = false; + /** has been session ID regenerated? */ + private bool $regenerated = false; - /** @var bool has been session started by Nette? */ - private $started = false; + /** has been session started by Nette? */ + private bool $started = false; - /** @var array default configuration */ - private $options = [ + /** default configuration */ + private array $options = [ 'cookie_samesite' => IResponse::SAME_SITE_LAX, 'cookie_lifetime' => 0, // for a maximum of 3 hours or until the browser is closed 'gc_maxlifetime' => self::DEFAULT_FILE_LIFETIME, // 3 hours ]; - /** @var IRequest */ - private $request; + private IRequest $request; - /** @var IResponse */ - private $response; + private IResponse $response; - /** @var \SessionHandlerInterface */ - private $handler; + private ?\SessionHandlerInterface $handler = null; - /** @var bool */ - private $readAndClose = false; + private bool $readAndClose = false; public function __construct(IRequest $request, IResponse $response) diff --git a/src/Http/SessionSection.php b/src/Http/SessionSection.php index 15a42d34..7b34e63e 100644 --- a/src/Http/SessionSection.php +++ b/src/Http/SessionSection.php @@ -19,14 +19,11 @@ class SessionSection implements \IteratorAggregate, \ArrayAccess { use Nette\SmartObject; - /** @var bool */ - public $warnOnUndefined = false; + public bool $warnOnUndefined = false; - /** @var Session */ - private $session; + private Session $session; - /** @var string */ - private $name; + private string $name; /** diff --git a/src/Http/Url.php b/src/Http/Url.php index c9e5e2b8..8d59fea5 100644 --- a/src/Http/Url.php +++ b/src/Http/Url.php @@ -45,36 +45,27 @@ class Url implements \JsonSerializable { use Nette\SmartObject; - /** @var array */ - public static $defaultPorts = [ + public static array $defaultPorts = [ 'http' => 80, 'https' => 443, 'ftp' => 21, ]; - /** @var string */ - private $scheme = ''; + private string $scheme = ''; - /** @var string */ - private $user = ''; + private string $user = ''; - /** @var string */ - private $password = ''; + private string $password = ''; - /** @var string */ - private $host = ''; + private string $host = ''; - /** @var int|null */ - private $port; + private ?int $port = null; - /** @var string */ - private $path = ''; + private string $path = ''; - /** @var array */ - private $query = []; + private array $query = []; - /** @var string */ - private $fragment = ''; + private string $fragment = ''; /** diff --git a/src/Http/UrlImmutable.php b/src/Http/UrlImmutable.php index 2301c662..b579895c 100644 --- a/src/Http/UrlImmutable.php +++ b/src/Http/UrlImmutable.php @@ -42,32 +42,23 @@ class UrlImmutable implements \JsonSerializable { use Nette\SmartObject; - /** @var string */ - private $scheme = ''; + private string $scheme = ''; - /** @var string */ - private $user = ''; + private string $user = ''; - /** @var string */ - private $password = ''; + private string $password = ''; - /** @var string */ - private $host = ''; + private string $host = ''; - /** @var int|null */ - private $port; + private ?int $port = null; - /** @var string */ - private $path = ''; + private string $path = ''; - /** @var array */ - private $query = []; + private array $query = []; - /** @var string */ - private $fragment = ''; + private string $fragment = ''; - /** @var string */ - private $authority = ''; + private string $authority = ''; /** diff --git a/src/Http/UrlScript.php b/src/Http/UrlScript.php index fdc26fae..1ccb597e 100644 --- a/src/Http/UrlScript.php +++ b/src/Http/UrlScript.php @@ -34,17 +34,15 @@ */ class UrlScript extends UrlImmutable { - /** @var string */ - private $scriptPath; + private string $scriptPath; - /** @var string */ - private $basePath; + private string $basePath; public function __construct($url = '/', string $scriptPath = '') { - parent::__construct($url); $this->scriptPath = $scriptPath; + parent::__construct($url); $this->build(); } diff --git a/src/Http/UserStorage.php b/src/Http/UserStorage.php index 0f283a53..3f4792a9 100644 --- a/src/Http/UserStorage.php +++ b/src/Http/UserStorage.php @@ -20,14 +20,11 @@ class UserStorage implements Nette\Security\IUserStorage { use Nette\SmartObject; - /** @var string */ - private $namespace = ''; + private string $namespace = ''; - /** @var Session */ - private $sessionHandler; + private Session $sessionHandler; - /** @var SessionSection */ - private $sessionSection; + private SessionSection $sessionSection; public function __construct(Session $sessionHandler) From d64cbd4cdd51cc6b1231d831babd476cb4c616de Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 19:53:41 +0100 Subject: [PATCH 08/11] added PHP 8 typehints --- src/Http/Context.php | 3 +- src/Http/FileUpload.php | 3 +- src/Http/Helpers.php | 3 +- src/Http/IRequest.php | 12 ++--- src/Http/IResponse.php | 18 +++---- src/Http/Request.php | 15 ++---- src/Http/RequestFactory.php | 6 +-- src/Http/Response.php | 24 +++------ src/Http/Session.php | 19 +++---- src/Http/SessionSection.php | 12 ++--- src/Http/Url.php | 54 +++++-------------- src/Http/UrlImmutable.php | 51 +++++------------- src/Http/UrlScript.php | 5 +- src/Http/UserStorage.php | 12 ++--- .../Http/SessionSection.setExpiration().phpt | 4 +- ...SessionSection.setExpirationUnlimited.phpt | 2 +- tests/Http/Url.query.phpt | 4 -- 17 files changed, 74 insertions(+), 173 deletions(-) diff --git a/src/Http/Context.php b/src/Http/Context.php index 1b5e91fd..d0f1ec68 100644 --- a/src/Http/Context.php +++ b/src/Http/Context.php @@ -33,9 +33,8 @@ public function __construct(IRequest $request, IResponse $response) /** * Attempts to cache the sent entity by its last modification date. - * @param string|int|\DateTimeInterface $lastModified */ - public function isModified($lastModified = null, string $etag = null): bool + public function isModified(string|int|\DateTimeInterface $lastModified = null, string $etag = null): bool { if ($lastModified) { $this->response->setHeader('Last-Modified', Helpers::formatDate($lastModified)); diff --git a/src/Http/FileUpload.php b/src/Http/FileUpload.php index df1f1c1b..37f074bd 100644 --- a/src/Http/FileUpload.php +++ b/src/Http/FileUpload.php @@ -164,9 +164,8 @@ public function hasFile(): bool /** * Moves an uploaded file to a new location. If the destination file already exists, it will be overwritten. - * @return static */ - public function move(string $dest) + public function move(string $dest): static { $dir = dirname($dest); Nette\Utils\FileSystem::createDir($dir); diff --git a/src/Http/Helpers.php b/src/Http/Helpers.php index ccac99d7..b8e237ef 100644 --- a/src/Http/Helpers.php +++ b/src/Http/Helpers.php @@ -26,9 +26,8 @@ final class Helpers /** * Returns HTTP valid date format. - * @param string|int|\DateTimeInterface $time */ - public static function formatDate($time): string + public static function formatDate(string|int|\DateTimeInterface $time): string { $time = DateTime::from($time)->setTimezone(new \DateTimeZone('GMT')); return $time->format('D, d M Y H:i:s \G\M\T'); diff --git a/src/Http/IRequest.php b/src/Http/IRequest.php index f263503d..2865b954 100644 --- a/src/Http/IRequest.php +++ b/src/Http/IRequest.php @@ -37,22 +37,19 @@ function getUrl(): UrlScript; /** * Returns variable provided to the script via URL query ($_GET). * If no key is passed, returns the entire array. - * @return mixed */ - function getQuery(string $key = null); + function getQuery(string $key = null): mixed; /** * Returns variable provided to the script via POST method ($_POST). * If no key is passed, returns the entire array. - * @return mixed */ - function getPost(string $key = null); + function getPost(string $key = null): mixed; /** * Returns uploaded file. - * @return FileUpload|array|null */ - function getFile(string $key); + function getFile(string $key): ?FileUpload; /** * Returns uploaded files. @@ -61,9 +58,8 @@ function getFiles(): array; /** * Returns variable provided to the script via HTTP cookies. - * @return mixed */ - function getCookie(string $key); + function getCookie(string $key): mixed; /** * Returns variables provided to the script via HTTP cookies. diff --git a/src/Http/IResponse.php b/src/Http/IResponse.php index c544cf6a..1034f7ec 100644 --- a/src/Http/IResponse.php +++ b/src/Http/IResponse.php @@ -155,9 +155,8 @@ interface IResponse /** * Sets HTTP response code. - * @return static */ - function setCode(int $code, string $reason = null); + function setCode(int $code, string $reason = null): static; /** * Returns HTTP response code. @@ -166,21 +165,18 @@ function getCode(): int; /** * Sends a HTTP header and replaces a previous one. - * @return static */ - function setHeader(string $name, string $value); + function setHeader(string $name, string $value): static; /** * Adds HTTP header. - * @return static */ - function addHeader(string $name, string $value); + function addHeader(string $name, string $value): static; /** * Sends a Content-type HTTP header. - * @return static */ - function setContentType(string $type, string $charset = null); + function setContentType(string $type, string $charset = null): static; /** * Redirects to a new URL. @@ -189,9 +185,8 @@ function redirect(string $url, int $code = self::S302_FOUND): void; /** * Sets the time (like '20 minutes') before a page cached on a browser expires, null means "must-revalidate". - * @return static */ - function setExpiration(?string $expire); + function setExpiration(?string $expire): static; /** * Checks if headers have been sent. @@ -211,7 +206,6 @@ function getHeaders(): array; /** * Sends a cookie. * @param string|int|\DateTimeInterface $expire time, value null means "until the browser session ends" - * @return static */ function setCookie( string $name, @@ -221,7 +215,7 @@ function setCookie( string $domain = null, bool $secure = null, bool $httpOnly = null, - ); + ): static; /** * Deletes a cookie. diff --git a/src/Http/Request.php b/src/Http/Request.php index 416f25d8..c65108d4 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -78,9 +78,8 @@ public function __construct( /** * Returns a clone with a different URL. - * @return static */ - public function withUrl(UrlScript $url) + public function withUrl(UrlScript $url): static { $dolly = clone $this; $dolly->url = $url; @@ -103,9 +102,8 @@ public function getUrl(): UrlScript /** * Returns variable provided to the script via URL query ($_GET). * If no key is passed, returns the entire array. - * @return mixed */ - public function getQuery(string $key = null) + public function getQuery(string $key = null): mixed { if (func_num_args() === 0) { return $this->url->getQueryParameters(); @@ -119,9 +117,8 @@ public function getQuery(string $key = null) /** * Returns variable provided to the script via POST method ($_POST). * If no key is passed, returns the entire array. - * @return mixed */ - public function getPost(string $key = null) + public function getPost(string $key = null): mixed { if (func_num_args() === 0) { return $this->post; @@ -135,9 +132,8 @@ public function getPost(string $key = null) /** * Returns uploaded file. * @param string|string[] $key - * @return ?FileUpload */ - public function getFile($key) + public function getFile($key): ?FileUpload { $res = Nette\Utils\Arrays::get($this->files, $key, null); return $res instanceof FileUpload ? $res : null; @@ -155,9 +151,8 @@ public function getFiles(): array /** * Returns a cookie or `null` if it does not exist. - * @return mixed */ - public function getCookie(string $key) + public function getCookie(string $key): mixed { if (func_num_args() > 1) { trigger_error(__METHOD__ . '() parameter $default is deprecated, use operator ??', E_USER_DEPRECATED); diff --git a/src/Http/RequestFactory.php b/src/Http/RequestFactory.php index 437624aa..e88bf6ad 100644 --- a/src/Http/RequestFactory.php +++ b/src/Http/RequestFactory.php @@ -34,8 +34,7 @@ class RequestFactory private array $proxies = []; - /** @return static */ - public function setBinary(bool $binary = true) + public function setBinary(bool $binary = true): static { $this->binary = $binary; return $this; @@ -44,9 +43,8 @@ public function setBinary(bool $binary = true) /** * @param string|string[] $proxy - * @return static */ - public function setProxy($proxy) + public function setProxy($proxy): static { $this->proxies = (array) $proxy; return $this; diff --git a/src/Http/Response.php b/src/Http/Response.php index 333d1838..201e676a 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -54,11 +54,10 @@ public function __construct() /** * Sets HTTP response code. - * @return static * @throws Nette\InvalidArgumentException if code is invalid * @throws Nette\InvalidStateException if HTTP headers have been sent */ - public function setCode(int $code, string $reason = null) + public function setCode(int $code, string $reason = null): static { if ($code < 100 || $code > 599) { throw new Nette\InvalidArgumentException("Bad HTTP response '$code'."); @@ -83,10 +82,9 @@ public function getCode(): int /** * Sends an HTTP header and overwrites previously sent header of the same name. - * @return static * @throws Nette\InvalidStateException if HTTP headers have been sent */ - public function setHeader(string $name, ?string $value) + public function setHeader(string $name, ?string $value): static { self::checkHeaders(); if ($value === null) { @@ -102,10 +100,9 @@ public function setHeader(string $name, ?string $value) /** * Sends an HTTP header and doesn't overwrite previously sent header of the same name. - * @return static * @throws Nette\InvalidStateException if HTTP headers have been sent */ - public function addHeader(string $name, string $value) + public function addHeader(string $name, string $value): static { self::checkHeaders(); header($name . ': ' . $value, false); @@ -115,10 +112,9 @@ public function addHeader(string $name, string $value) /** * Deletes a previously sent HTTP header. - * @return static * @throws Nette\InvalidStateException if HTTP headers have been sent */ - public function deleteHeader(string $name) + public function deleteHeader(string $name): static { self::checkHeaders(); header_remove($name); @@ -128,10 +124,9 @@ public function deleteHeader(string $name) /** * Sends a Content-type HTTP header. - * @return static * @throws Nette\InvalidStateException if HTTP headers have been sent */ - public function setContentType(string $type, string $charset = null) + public function setContentType(string $type, string $charset = null): static { $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : '')); return $this; @@ -140,10 +135,9 @@ public function setContentType(string $type, string $charset = null) /** * Response should be downloaded with 'Save as' dialog. - * @return static * @throws Nette\InvalidStateException if HTTP headers have been sent */ - public function sendAsFile(string $fileName) + public function sendAsFile(string $fileName): static { $this->setHeader( 'Content-Disposition', @@ -172,10 +166,9 @@ public function redirect(string $url, int $code = self::S302_FOUND): void /** * Sets the expiration of the HTTP document using the `Cache-Control` and `Expires` headers. * The parameter is either a time interval (as text) or `null`, which disables caching. - * @return static * @throws Nette\InvalidStateException if HTTP headers have been sent */ - public function setExpiration(?string $time) + public function setExpiration(?string $time): static { $this->setHeader('Pragma', null); if (!$time) { // no cache @@ -251,7 +244,6 @@ public function __destruct() /** * Sends a cookie. * @param string|int|\DateTimeInterface $time expiration time, value null means "until the browser session ends" - * @return static * @throws Nette\InvalidStateException if HTTP headers have been sent */ public function setCookie( @@ -263,7 +255,7 @@ public function setCookie( bool $secure = null, bool $httpOnly = null, string $sameSite = null, - ) { + ): static { self::checkHeaders(); $options = [ 'expires' => $time ? (int) DateTime::from($time)->format('U') : 0, diff --git a/src/Http/Session.php b/src/Http/Session.php index dbc40bd3..efb3e73f 100644 --- a/src/Http/Session.php +++ b/src/Http/Session.php @@ -227,9 +227,8 @@ public function getId(): string /** * Sets the session name to a specified one. - * @return static */ - public function setName(string $name) + public function setName(string $name): static { if (!preg_match('#[^0-9.][^.]*$#DA', $name)) { throw new Nette\InvalidArgumentException('Session name cannot contain dot.'); @@ -256,7 +255,6 @@ public function getName(): string /** * Returns specified session section. - * @throws Nette\InvalidArgumentException */ public function getSection(string $section, string $class = SessionSection::class): SessionSection { @@ -314,11 +312,10 @@ public function clean(): void /** * Sets session options. - * @return static * @throws Nette\NotSupportedException * @throws Nette\InvalidStateException */ - public function setOptions(array $options) + public function setOptions(array $options): static { $normalized = []; $allowed = ini_get_all('session', false) + ['read_and_close' => 1, 'session.cookie_samesite' => 1]; // for PHP < 7.3 @@ -414,9 +411,8 @@ private function configure(array $config): void /** * Sets the amount of time (like '20 minutes') allowed between requests before the session will be terminated, * null means "for a maximum of 3 hours or until the browser is closed". - * @return static */ - public function setExpiration(?string $time) + public function setExpiration(?string $time): static { if ($time === null) { return $this->setOptions([ @@ -436,14 +432,13 @@ public function setExpiration(?string $time) /** * Sets the session cookie parameters. - * @return static */ public function setCookieParameters( string $path, string $domain = null, bool $secure = null, string $sameSite = null, - ) { + ): static { return $this->setOptions([ 'cookie_path' => $path, 'cookie_domain' => $domain, @@ -463,9 +458,8 @@ public function getCookieParameters(): array /** * Sets path of the directory used to save session data. - * @return static */ - public function setSavePath(string $path) + public function setSavePath(string $path): static { return $this->setOptions([ 'save_path' => $path, @@ -475,9 +469,8 @@ public function setSavePath(string $path) /** * Sets user session handler. - * @return static */ - public function setHandler(\SessionHandlerInterface $handler) + public function setHandler(\SessionHandlerInterface $handler): static { if ($this->started) { throw new Nette\InvalidStateException('Unable to set handler when session has been started.'); diff --git a/src/Http/SessionSection.php b/src/Http/SessionSection.php index 7b34e63e..9a180cb6 100644 --- a/src/Http/SessionSection.php +++ b/src/Http/SessionSection.php @@ -57,9 +57,8 @@ public function __set(string $name, $value): void /** * Gets a variable from this session section. - * @return mixed */ - public function &__get(string $name) + public function &__get(string $name): mixed { $data = &$this->getData(true); if ($this->warnOnUndefined && !array_key_exists($name, $data ?? [])) { @@ -105,9 +104,8 @@ public function offsetSet($name, $value): void /** * Gets a variable from this session section. - * @return mixed */ - public function offsetGet($name) + public function offsetGet($name): mixed { return $this->__get($name); } @@ -133,11 +131,9 @@ public function offsetUnset($name): void /** * Sets the expiration of the section or specific variables. - * @param ?string $time * @param string|string[] $variables list of variables / single variable to expire - * @return static */ - public function setExpiration($time, $variables = null) + public function setExpiration(?string $time, string|array $variables = null): static { $meta = &$this->getMeta(); if ($time) { @@ -162,7 +158,7 @@ public function setExpiration($time, $variables = null) * Removes the expiration from the section or specific variables. * @param string|string[] $variables list of variables / single variable to expire */ - public function removeExpiration($variables = null): void + public function removeExpiration(string|array $variables = null): void { $meta = &$this->getMeta(); foreach (is_array($variables) ? $variables : [$variables] as $variable) { diff --git a/src/Http/Url.php b/src/Http/Url.php index 8d59fea5..126bce83 100644 --- a/src/Http/Url.php +++ b/src/Http/Url.php @@ -69,10 +69,9 @@ class Url implements \JsonSerializable /** - * @param string|self|UrlImmutable $url * @throws Nette\InvalidArgumentException if URL is malformed */ - public function __construct($url = null) + public function __construct(string|self|UrlImmutable $url = null) { if (is_string($url)) { $p = @parse_url($url); // @ - is escalated to exception @@ -91,15 +90,11 @@ public function __construct($url = null) } elseif ($url instanceof UrlImmutable || $url instanceof self) { [$this->scheme, $this->user, $this->password, $this->host, $this->port, $this->path, $this->query, $this->fragment] = $url->export(); - - } elseif ($url !== null) { - throw new Nette\InvalidArgumentException; } } - /** @return static */ - public function setScheme(string $scheme) + public function setScheme(string $scheme): static { $this->scheme = $scheme; return $this; @@ -112,8 +107,7 @@ public function getScheme(): string } - /** @return static */ - public function setUser(string $user) + public function setUser(string $user): static { $this->user = $user; return $this; @@ -126,8 +120,7 @@ public function getUser(): string } - /** @return static */ - public function setPassword(string $password) + public function setPassword(string $password): static { $this->password = $password; return $this; @@ -140,8 +133,7 @@ public function getPassword(): string } - /** @return static */ - public function setHost(string $host) + public function setHost(string $host): static { $this->host = $host; $this->setPath($this->path); @@ -170,8 +162,7 @@ public function getDomain(int $level = 2): string } - /** @return static */ - public function setPort(int $port) + public function setPort(int $port): static { $this->port = $port; return $this; @@ -184,8 +175,7 @@ public function getPort(): ?int } - /** @return static */ - public function setPath(string $path) + public function setPath(string $path): static { $this->path = $path; if ($this->host && substr($this->path, 0, 1) !== '/') { @@ -201,22 +191,14 @@ public function getPath(): string } - /** - * @param string|array $value - * @return static - */ - public function setQuery($query) + public function setQuery(string|array $query): static { $this->query = is_array($query) ? $query : self::parseQuery($query); return $this; } - /** - * @param string|array $value - * @return static - */ - public function appendQuery($query) + public function appendQuery(string|array $query): static { $this->query = is_array($query) ? $query + $this->query @@ -237,8 +219,7 @@ public function getQueryParameters(): array } - /** @return mixed */ - public function getQueryParameter(string $name) + public function getQueryParameter(string $name): mixed { if (func_num_args() > 1) { trigger_error(__METHOD__ . '() parameter $default is deprecated, use operator ??', E_USER_DEPRECATED); @@ -247,19 +228,14 @@ public function getQueryParameter(string $name) } - /** - * @param mixed $value null unsets the parameter - * @return static - */ - public function setQueryParameter(string $name, $value) + public function setQueryParameter(string $name, mixed $value): static { $this->query[$name] = $value; return $this; } - /** @return static */ - public function setFragment(string $fragment) + public function setFragment(string $fragment): static { $this->fragment = $fragment; return $this; @@ -331,9 +307,8 @@ public function getRelativeUrl(): string /** * URL comparison. - * @param string|self $url */ - public function isEqual($url): bool + public function isEqual(string|self $url): bool { $url = new self($url); $query = $url->query; @@ -354,10 +329,9 @@ public function isEqual($url): bool /** * Transforms URL to canonical form. - * @return static * @deprecated */ - public function canonicalize() + public function canonicalize(): static { $this->path = preg_replace_callback( '#[^!$&\'()*+,/:;=@%]+#', diff --git a/src/Http/UrlImmutable.php b/src/Http/UrlImmutable.php index b579895c..9efce873 100644 --- a/src/Http/UrlImmutable.php +++ b/src/Http/UrlImmutable.php @@ -62,23 +62,17 @@ class UrlImmutable implements \JsonSerializable /** - * @param string|self|Url $url * @throws Nette\InvalidArgumentException if URL is malformed */ - public function __construct($url) + public function __construct(string|self|Url $url) { - if (!$url instanceof Url && !$url instanceof self && !is_string($url)) { - throw new Nette\InvalidArgumentException; - } - $url = is_string($url) ? new Url($url) : $url; [$this->scheme, $this->user, $this->password, $this->host, $this->port, $this->path, $this->query, $this->fragment] = $url->export(); $this->build(); } - /** @return static */ - public function withScheme(string $scheme) + public function withScheme(string $scheme): static { $dolly = clone $this; $dolly->scheme = $scheme; @@ -93,8 +87,7 @@ public function getScheme(): string } - /** @return static */ - public function withUser(string $user) + public function withUser(string $user): static { $dolly = clone $this; $dolly->user = $user; @@ -109,8 +102,7 @@ public function getUser(): string } - /** @return static */ - public function withPassword(string $password) + public function withPassword(string $password): static { $dolly = clone $this; $dolly->password = $password; @@ -125,8 +117,7 @@ public function getPassword(): string } - /** @return static */ - public function withoutUserInfo() + public function withoutUserInfo(): static { $dolly = clone $this; $dolly->user = $dolly->password = ''; @@ -135,8 +126,7 @@ public function withoutUserInfo() } - /** @return static */ - public function withHost(string $host) + public function withHost(string $host): static { $dolly = clone $this; $dolly->host = $host; @@ -163,8 +153,7 @@ public function getDomain(int $level = 2): string } - /** @return static */ - public function withPort(int $port) + public function withPort(int $port): static { $dolly = clone $this; $dolly->port = $port; @@ -179,8 +168,7 @@ public function getPort(): ?int } - /** @return static */ - public function withPath(string $path) + public function withPath(string $path): static { $dolly = clone $this; $dolly->path = $path; @@ -195,11 +183,7 @@ public function getPath(): string } - /** - * @param string|array $query - * @return static - */ - public function withQuery($query) + public function withQuery(string|array $query): static { $dolly = clone $this; $dolly->query = is_array($query) ? $query : Url::parseQuery($query); @@ -214,11 +198,7 @@ public function getQuery(): string } - /** - * @param mixed $value null unsets the parameter - * @return static - */ - public function withQueryParameter(string $name, $value) + public function withQueryParameter(string $name, mixed $value): static { $dolly = clone $this; $dolly->query[$name] = $value; @@ -232,15 +212,13 @@ public function getQueryParameters(): array } - /** @return array|string|null */ - public function getQueryParameter(string $name) + public function getQueryParameter(string $name): array|string|null { return $this->query[$name] ?? null; } - /** @return static */ - public function withFragment(string $fragment) + public function withFragment(string $fragment): static { $dolly = clone $this; $dolly->fragment = $fragment; @@ -291,10 +269,7 @@ public function __toString(): string } - /** - * @param string|Url|self $url - */ - public function isEqual($url): bool + public function isEqual(string|Url|self $url): bool { return (new Url($this))->isEqual($url); } diff --git a/src/Http/UrlScript.php b/src/Http/UrlScript.php index 1ccb597e..5fe5b298 100644 --- a/src/Http/UrlScript.php +++ b/src/Http/UrlScript.php @@ -39,7 +39,7 @@ class UrlScript extends UrlImmutable private string $basePath; - public function __construct($url = '/', string $scriptPath = '') + public function __construct(string|Url $url = '/', string $scriptPath = '') { $this->scriptPath = $scriptPath; parent::__construct($url); @@ -47,8 +47,7 @@ public function __construct($url = '/', string $scriptPath = '') } - /** @return static */ - public function withPath(string $path, string $scriptPath = '') + public function withPath(string $path, string $scriptPath = ''): static { $dolly = clone $this; $dolly->scriptPath = $scriptPath; diff --git a/src/Http/UserStorage.php b/src/Http/UserStorage.php index 3f4792a9..0af04060 100644 --- a/src/Http/UserStorage.php +++ b/src/Http/UserStorage.php @@ -35,9 +35,8 @@ public function __construct(Session $sessionHandler) /** * Sets the authenticated status of this user. - * @return static */ - public function setAuthenticated(bool $state) + public function setAuthenticated(bool $state): self { $section = $this->getSessionSection(true); $section->authenticated = $state; @@ -69,9 +68,8 @@ public function isAuthenticated(): bool /** * Sets the user identity. - * @return static */ - public function setIdentity(?IIdentity $identity) + public function setIdentity(?IIdentity $identity): self { $this->getSessionSection(true)->identity = $identity; return $this; @@ -90,9 +88,8 @@ public function getIdentity(): ?Nette\Security\IIdentity /** * Changes namespace; allows more users to share a session. - * @return static */ - public function setNamespace(string $namespace) + public function setNamespace(string $namespace): self { if ($this->namespace !== $namespace) { $this->namespace = $namespace; @@ -113,9 +110,8 @@ public function getNamespace(): string /** * Enables log out after inactivity. Accepts flag IUserStorage::CLEAR_IDENTITY. - * @return static */ - public function setExpiration(?string $time, int $flags = 0) + public function setExpiration(?string $time, int $flags = 0): self { $section = $this->getSessionSection(true); if ($time) { diff --git a/tests/Http/SessionSection.setExpiration().phpt b/tests/Http/SessionSection.setExpiration().phpt index ba02ed97..6ae1f68b 100644 --- a/tests/Http/SessionSection.setExpiration().phpt +++ b/tests/Http/SessionSection.setExpiration().phpt @@ -35,7 +35,7 @@ test('try to expire whole namespace', function () use ($session) { test('try to expire only 1 of the keys', function () use ($session) { $namespace = $session->getSection('expireSingle'); - $namespace->setExpiration(1, 'g'); + $namespace->setExpiration('1 second', 'g'); $namespace->g = 'guava'; $namespace->p = 'plum'; @@ -51,5 +51,5 @@ test('try to expire only 1 of the keys', function () use ($session) { // small expiration Assert::error(function () use ($session) { $namespace = $session->getSection('tmp'); - $namespace->setExpiration(100); + $namespace->setExpiration('100 second'); }, E_USER_NOTICE, 'The expiration time is greater than the session expiration %d% seconds'); diff --git a/tests/Http/SessionSection.setExpirationUnlimited.phpt b/tests/Http/SessionSection.setExpirationUnlimited.phpt index 2fcf7871..57566c08 100644 --- a/tests/Http/SessionSection.setExpirationUnlimited.phpt +++ b/tests/Http/SessionSection.setExpirationUnlimited.phpt @@ -18,6 +18,6 @@ $session->setOptions(['gc_maxlifetime' => '0']); //memcache handler supports unl //try to set section to shorter expiration $namespace = $session->getSection('maxlifetime'); -$namespace->setExpiration(100); +$namespace->setExpiration('100 second'); Assert::same(true, true); // fix Error: This test forgets to execute an assertion. diff --git a/tests/Http/Url.query.phpt b/tests/Http/Url.query.phpt index 15f89043..078abc08 100644 --- a/tests/Http/Url.query.phpt +++ b/tests/Http/Url.query.phpt @@ -17,10 +17,6 @@ $url = new Url('http://hostname/path?arg=value'); Assert::same('arg=value', $url->query); Assert::same(['arg' => 'value'], $url->getQueryParameters()); -$url->appendQuery(null); -Assert::same('arg=value', $url->query); -Assert::same(['arg' => 'value'], $url->getQueryParameters()); - $url->appendQuery([null]); Assert::same('arg=value', $url->query); Assert::same([null, 'arg' => 'value'], $url->getQueryParameters()); From 3affe3a7b3dca69e9c606cf4f9504046e9a5d8b3 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 2 Mar 2021 14:59:23 +0100 Subject: [PATCH 09/11] removed deprecated stuff & UserStorage --- src/Bridges/HttpDI/SessionExtension.php | 10 +- src/Http/IResponse.php | 6 - src/Http/Request.php | 10 -- src/Http/Response.php | 6 - src/Http/Session.php | 8 -- src/Http/Url.php | 4 - src/Http/UserStorage.php | 178 ------------------------ 7 files changed, 1 insertion(+), 221 deletions(-) delete mode 100644 src/Http/UserStorage.php diff --git a/src/Bridges/HttpDI/SessionExtension.php b/src/Bridges/HttpDI/SessionExtension.php index 84730260..0e962ce7 100644 --- a/src/Bridges/HttpDI/SessionExtension.php +++ b/src/Bridges/HttpDI/SessionExtension.php @@ -39,7 +39,7 @@ public function getConfigSchema(): Nette\Schema\Schema 'expiration' => Expect::string()->dynamic(), 'handler' => Expect::string()->dynamic(), 'readAndClose' => Expect::bool(), - 'cookieSamesite' => Expect::anyOf(IResponse::SAME_SITE_LAX, IResponse::SAME_SITE_STRICT, IResponse::SAME_SITE_NONE, true) + 'cookieSamesite' => Expect::anyOf(IResponse::SAME_SITE_LAX, IResponse::SAME_SITE_STRICT, IResponse::SAME_SITE_NONE) ->firstIsDefault(), ])->otherItems('mixed'); } @@ -62,14 +62,6 @@ public function loadConfiguration() if (($config->cookieDomain ?? null) === 'domain') { $config->cookieDomain = $builder::literal('$this->getByType(Nette\Http\IRequest::class)->getUrl()->getDomain(2)'); } - if (isset($config->cookieSecure)) { - trigger_error("The item 'session › cookieSecure' is deprecated, use 'http › cookieSecure' (it has default value 'auto').", E_USER_DEPRECATED); - unset($config->cookieSecure); - } - if ($config->cookieSamesite === true) { - trigger_error("In 'session › cookieSamesite' replace true with 'Lax'.", E_USER_DEPRECATED); - $config->cookieSamesite = IResponse::SAME_SITE_LAX; - } $this->compiler->addExportedType(Nette\Http\IRequest::class); if ($this->debugMode && $config->debugger) { diff --git a/src/Http/IResponse.php b/src/Http/IResponse.php index 1034f7ec..3269d110 100644 --- a/src/Http/IResponse.php +++ b/src/Http/IResponse.php @@ -16,12 +16,6 @@ */ interface IResponse { - /** @deprecated */ - public const PERMANENT = 2116333333; - - /** @deprecated */ - public const BROWSER = 0; - /** HTTP 1.1 response code */ public const S100_CONTINUE = 100, diff --git a/src/Http/Request.php b/src/Http/Request.php index c65108d4..6c92dbd1 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -107,8 +107,6 @@ public function getQuery(string $key = null): mixed { if (func_num_args() === 0) { return $this->url->getQueryParameters(); - } elseif (func_num_args() > 1) { - trigger_error(__METHOD__ . '() parameter $default is deprecated, use operator ??', E_USER_DEPRECATED); } return $this->url->getQueryParameter($key); } @@ -122,8 +120,6 @@ public function getPost(string $key = null): mixed { if (func_num_args() === 0) { return $this->post; - } elseif (func_num_args() > 1) { - trigger_error(__METHOD__ . '() parameter $default is deprecated, use operator ??', E_USER_DEPRECATED); } return $this->post[$key] ?? null; } @@ -154,9 +150,6 @@ public function getFiles(): array */ public function getCookie(string $key): mixed { - if (func_num_args() > 1) { - trigger_error(__METHOD__ . '() parameter $default is deprecated, use operator ??', E_USER_DEPRECATED); - } return $this->cookies[$key] ?? null; } @@ -196,9 +189,6 @@ public function isMethod(string $method): bool */ public function getHeader(string $header): ?string { - if (func_num_args() > 1) { - trigger_error(__METHOD__ . '() parameter $default is deprecated, use operator ??', E_USER_DEPRECATED); - } $header = strtolower($header); return $this->headers[$header] ?? null; } diff --git a/src/Http/Response.php b/src/Http/Response.php index 201e676a..41877c51 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -31,9 +31,6 @@ final class Response implements IResponse /** Whether the cookie is available only through HTTPS */ public bool $cookieSecure = false; - /** @deprecated */ - public $cookieHttpOnly; - /** Whether warn on possible problem with data in output buffer */ public bool $warnOnBuffer = true; @@ -199,9 +196,6 @@ public function isSent(): bool */ public function getHeader(string $header): ?string { - if (func_num_args() > 1) { - trigger_error(__METHOD__ . '() parameter $default is deprecated, use operator ??', E_USER_DEPRECATED); - } $header .= ':'; $len = strlen($header); foreach (headers_list() as $item) { diff --git a/src/Http/Session.php b/src/Http/Session.php index efb3e73f..0f6e739f 100644 --- a/src/Http/Session.php +++ b/src/Http/Session.php @@ -448,14 +448,6 @@ public function setCookieParameters( } - /** @deprecated */ - public function getCookieParameters(): array - { - trigger_error(__METHOD__ . '() is deprecated.', E_USER_DEPRECATED); - return session_get_cookie_params(); - } - - /** * Sets path of the directory used to save session data. */ diff --git a/src/Http/Url.php b/src/Http/Url.php index 126bce83..0c8d0809 100644 --- a/src/Http/Url.php +++ b/src/Http/Url.php @@ -221,9 +221,6 @@ public function getQueryParameters(): array public function getQueryParameter(string $name): mixed { - if (func_num_args() > 1) { - trigger_error(__METHOD__ . '() parameter $default is deprecated, use operator ??', E_USER_DEPRECATED); - } return $this->query[$name] ?? null; } @@ -329,7 +326,6 @@ public function isEqual(string|self $url): bool /** * Transforms URL to canonical form. - * @deprecated */ public function canonicalize(): static { diff --git a/src/Http/UserStorage.php b/src/Http/UserStorage.php deleted file mode 100644 index 0af04060..00000000 --- a/src/Http/UserStorage.php +++ /dev/null @@ -1,178 +0,0 @@ -sessionHandler = $sessionHandler; - } - - - /** - * Sets the authenticated status of this user. - */ - public function setAuthenticated(bool $state): self - { - $section = $this->getSessionSection(true); - $section->authenticated = $state; - - // Session Fixation defence - $this->sessionHandler->regenerateId(); - - if ($state) { - $section->reason = null; - $section->authTime = time(); // informative value - - } else { - $section->reason = self::MANUAL; - $section->authTime = null; - } - return $this; - } - - - /** - * Is this user authenticated? - */ - public function isAuthenticated(): bool - { - $session = $this->getSessionSection(false); - return $session && $session->authenticated; - } - - - /** - * Sets the user identity. - */ - public function setIdentity(?IIdentity $identity): self - { - $this->getSessionSection(true)->identity = $identity; - return $this; - } - - - /** - * Returns current user identity, if any. - */ - public function getIdentity(): ?Nette\Security\IIdentity - { - $session = $this->getSessionSection(false); - return $session ? $session->identity : null; - } - - - /** - * Changes namespace; allows more users to share a session. - */ - public function setNamespace(string $namespace): self - { - if ($this->namespace !== $namespace) { - $this->namespace = $namespace; - $this->sessionSection = null; - } - return $this; - } - - - /** - * Returns current namespace. - */ - public function getNamespace(): string - { - return $this->namespace; - } - - - /** - * Enables log out after inactivity. Accepts flag IUserStorage::CLEAR_IDENTITY. - */ - public function setExpiration(?string $time, int $flags = 0): self - { - $section = $this->getSessionSection(true); - if ($time) { - $time = Nette\Utils\DateTime::from($time)->format('U'); - $section->expireTime = $time; - $section->expireDelta = $time - time(); - - } else { - unset($section->expireTime, $section->expireDelta); - } - - $section->expireIdentity = (bool) ($flags & self::CLEAR_IDENTITY); - $section->setExpiration($time, 'foo'); // time check - return $this; - } - - - /** - * Why was user logged out? - */ - public function getLogoutReason(): ?int - { - $session = $this->getSessionSection(false); - return $session ? $session->reason : null; - } - - - /** - * Returns and initializes $this->sessionSection. - */ - protected function getSessionSection(bool $need): ?SessionSection - { - if ($this->sessionSection !== null) { - return $this->sessionSection; - } - - if (!$need && !$this->sessionHandler->exists()) { - return null; - } - - $this->sessionSection = $section = $this->sessionHandler->getSection('Nette.Http.UserStorage/' . $this->namespace); - - if (!$section->identity instanceof IIdentity || !is_bool($section->authenticated)) { - $section->remove(); - } - - if ($section->authenticated && $section->expireDelta > 0) { // check time expiration - if ($section->expireTime < time()) { - $section->reason = self::INACTIVITY; - $section->authenticated = false; - if ($section->expireIdentity) { - unset($section->identity); - } - } - $section->expireTime = time() + $section->expireDelta; // sliding expiration - } - - if (!$section->authenticated) { - unset($section->expireTime, $section->expireDelta, $section->expireIdentity, $section->authTime); - } - - return $this->sessionSection; - } -} From e35a7019deede9138bfc5540672fca6e52df87c3 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 11 Mar 2021 21:53:22 +0100 Subject: [PATCH 10/11] removed community health files --- .github/ISSUE_TEMPLATE/Bug_report.md | 19 ------------- .github/ISSUE_TEMPLATE/Feature_request.md | 9 ------ .github/ISSUE_TEMPLATE/Support_question.md | 12 -------- .github/ISSUE_TEMPLATE/Support_us.md | 21 -------------- .github/funding.yml | 2 -- .github/pull_request_template.md | 11 -------- contributing.md | 33 ---------------------- 7 files changed, 107 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/Bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/Feature_request.md delete mode 100644 .github/ISSUE_TEMPLATE/Support_question.md delete mode 100644 .github/ISSUE_TEMPLATE/Support_us.md delete mode 100644 .github/funding.yml delete mode 100644 .github/pull_request_template.md delete mode 100644 contributing.md diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md deleted file mode 100644 index a4cd1263..00000000 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: "🐛 Bug Report" -about: "If something isn't working as expected 🤔" - ---- - -Version: ?.?.? - -### Bug Description -... A clear and concise description of what the bug is. A good bug report shouldn't leave others needing to chase you up for more information. - -### Steps To Reproduce -... If possible a minimal demo of the problem ... - -### Expected Behavior -... A clear and concise description of what you expected to happen. - -### Possible Solution -... Only if you have suggestions on a fix for the bug diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md deleted file mode 100644 index d2e21948..00000000 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: "🚀 Feature Request" -about: "I have a suggestion (and may want to implement it) 🙂" - ---- - -- Is your feature request related to a problem? Please describe. -- Explain your intentions. -- It's up to you to make a strong case to convince the project's developers of the merits of this feature. diff --git a/.github/ISSUE_TEMPLATE/Support_question.md b/.github/ISSUE_TEMPLATE/Support_question.md deleted file mode 100644 index 75c48b6e..00000000 --- a/.github/ISSUE_TEMPLATE/Support_question.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: "🤗 Support Question" -about: "If you have a question 💬, please check out our forum!" - ---- - ---------------^ Click "Preview" for a nicer view! -We primarily use GitHub as an issue tracker; for usage and support questions, please check out these resources below. Thanks! 😁. - -* Nette Forum: https://forum.nette.org -* Nette Gitter: https://gitter.im/nette/nette -* Slack (czech): https://pehapkari.slack.com/messages/C2R30BLKA diff --git a/.github/ISSUE_TEMPLATE/Support_us.md b/.github/ISSUE_TEMPLATE/Support_us.md deleted file mode 100644 index 92d8a4c3..00000000 --- a/.github/ISSUE_TEMPLATE/Support_us.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: "❤️ Support us" -about: "If you would like to support our efforts in maintaining this project 🙌" - ---- - ---------------^ Click "Preview" for a nicer view! - -> https://nette.org/donate - -Help support Nette! - -We develop Nette Framework for more than 14 years. In order to make your life more comfortable. Nette cares about the safety of your sites. Nette saves you time. And gives job opportunities. - -Nette earns you money. And is absolutely free. - -To ensure future development and improving the documentation, we need your donation. - -Whether you are chief of IT company which benefits from Nette, or developer who goes for advice on our forum, if you like Nette, [please make a donation now](https://nette.org/donate). - -Thank you! diff --git a/.github/funding.yml b/.github/funding.yml deleted file mode 100644 index 25adc952..00000000 --- a/.github/funding.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: dg -custom: "https://nette.org/donate" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index f8aa3f40..00000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,11 +0,0 @@ -- bug fix / new feature? -- BC break? yes/no -- doc PR: nette/docs#??? - - diff --git a/contributing.md b/contributing.md deleted file mode 100644 index 184152c0..00000000 --- a/contributing.md +++ /dev/null @@ -1,33 +0,0 @@ -How to contribute & use the issue tracker -========================================= - -Nette welcomes your contributions. There are several ways to help out: - -* Create an issue on GitHub, if you have found a bug -* Write test cases for open bug issues -* Write fixes for open bug/feature issues, preferably with test cases included -* Contribute to the [documentation](https://nette.org/en/writing) - -Issues ------- - -Please **do not use the issue tracker to ask questions**. We will be happy to help you -on [Nette forum](https://forum.nette.org) or chat with us on [Gitter](https://gitter.im/nette/nette). - -A good bug report shouldn't leave others needing to chase you up for more -information. Please try to be as detailed as possible in your report. - -**Feature requests** are welcome. But take a moment to find out whether your idea -fits with the scope and aims of the project. It's up to *you* to make a strong -case to convince the project's developers of the merits of this feature. - -Contributing ------------- - -If you'd like to contribute, please take a moment to read [the contributing guide](https://nette.org/en/contributing). - -The best way to propose a feature is to discuss your ideas on [Nette forum](https://forum.nette.org) before implementing them. - -Please do not fix whitespace, format code, or make a purely cosmetic patch. - -Thanks! :heart: From 6c738640f2b4ecab8a0fa819ff6a75abe1a2ee1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bar=C3=A1=C5=A1ek?= Date: Sun, 4 Apr 2021 11:31:56 +0200 Subject: [PATCH 11/11] Url: Add method removeQueryParameter(). --- src/Http/Url.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Http/Url.php b/src/Http/Url.php index 0c8d0809..d1814cb1 100644 --- a/src/Http/Url.php +++ b/src/Http/Url.php @@ -232,6 +232,12 @@ public function setQueryParameter(string $name, mixed $value): static } + public function removeQueryParameter(string $name): void + { + $this->query[$name] = null; + } + + public function setFragment(string $fragment): static { $this->fragment = $fragment;