From a795df54ee9f22e04ba2d74767e02f217fb9923f Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 13 Oct 2022 00:46:26 +0200 Subject: [PATCH 01/30] updated github workflow --- .github/workflows/coding-style.yml | 4 ++-- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index 21ab198e6..3c6c1bef0 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -7,7 +7,7 @@ jobs: name: Nette Code Checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: 7.4 @@ -21,7 +21,7 @@ jobs: name: Nette Coding Standard runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: 8.0 diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 362037155..5424fc71f 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -7,7 +7,7 @@ jobs: name: PHPStan runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: 7.4 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 85a429af5..0cf0e238c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,7 @@ jobs: name: PHP ${{ matrix.php }} tests on ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} @@ -24,7 +24,7 @@ jobs: - run: composer install --no-progress --prefer-dist - run: vendor/bin/tester tests -s -C - if: failure() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: output path: tests/**/output @@ -34,7 +34,7 @@ jobs: name: Code Coverage runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: 7.4 From 6b4eac6ee497bfcbf0bb739bbf42119909ea83ca Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 13 Oct 2022 00:48:31 +0200 Subject: [PATCH 02/30] cs --- ncs.php | 2 ++ ncs.xml | 7 +------ src/Utils/Image.php | 3 ++- src/Utils/Validators.php | 7 ++++--- tests/Utils/Arrays.every().phpt | 35 ++++++++++++++++++++++++++------- tests/Utils/Arrays.map().phpt | 20 +++++++++++++++---- tests/Utils/Arrays.some().phpt | 35 ++++++++++++++++++++++++++------- 7 files changed, 81 insertions(+), 28 deletions(-) diff --git a/ncs.php b/ncs.php index 8f86bacb9..2bc1491f2 100644 --- a/ncs.php +++ b/ncs.php @@ -11,4 +11,6 @@ // use function in Arrays.php, Callback.php, Html.php, Strings.php 'single_import_per_statement' => false, 'ordered_imports' => false, + // Reflection.php + 'Nette/statement_indentation' => false, ]; diff --git a/ncs.xml b/ncs.xml index 6f360cb07..b6b7482ac 100644 --- a/ncs.xml +++ b/ncs.xml @@ -2,17 +2,12 @@ - - - 0 - - ./tests/Utils/Reflection.getDeclaringMethod.alias.phpt ./tests/Utils/Reflection.getDeclaringMethod.insteadof.phpt - 0 + ./src/*/*.php diff --git a/src/Utils/Image.php b/src/Utils/Image.php index b993ceecd..858629883 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -393,7 +393,8 @@ public static function calculateSize( $newWidth, $newHeight, int $flags = self::FIT - ): array { + ): array + { if ($newWidth === null) { } elseif (self::isPercent($newWidth)) { $newWidth = (int) round($srcWidth / 100 * abs($newWidth)); diff --git a/src/Utils/Validators.php b/src/Utils/Validators.php index 143480a84..11ee350ee 100644 --- a/src/Utils/Validators.php +++ b/src/Utils/Validators.php @@ -118,7 +118,8 @@ public static function assertField( $key, ?string $expected = null, string $label = "item '%' in array" - ): void { + ): void + { if (!array_key_exists($key, $array)) { throw new AssertionException('Missing ' . str_replace('%', $key, $label) . '.'); @@ -327,7 +328,7 @@ public static function isEmail(string $value): bool [$alpha]([-0-9$alpha]{0,17}[$alpha])? # top domain $)Dix XX -, $value); + , $value); } @@ -351,7 +352,7 @@ public static function isUrl(string $value): bool (\\#\\S*)? # fragment $)Dix XX -, $value); + , $value); } diff --git a/tests/Utils/Arrays.every().phpt b/tests/Utils/Arrays.every().phpt index eed82ec59..1aef6f6a3 100644 --- a/tests/Utils/Arrays.every().phpt +++ b/tests/Utils/Arrays.every().phpt @@ -18,7 +18,10 @@ test('', function () { $log = []; $res = Arrays::every( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return false; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return false; + } ); Assert::true($res); Assert::same([], $log); @@ -29,7 +32,10 @@ test('', function () { $log = []; $res = Arrays::every( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return true; + } ); Assert::true($res); Assert::same([], $log); @@ -40,7 +46,10 @@ test('', function () { $log = []; $res = Arrays::every( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return false; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return false; + } ); Assert::false($res); Assert::same([['a', 0, $arr]], $log); @@ -51,7 +60,10 @@ test('', function () { $log = []; $res = Arrays::every( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return true; + } ); Assert::true($res); Assert::same([['a', 0, $arr], ['b', 1, $arr]], $log); @@ -62,7 +74,10 @@ test('', function () { $log = []; $res = Arrays::every( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v === 'a'; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return $v === 'a'; + } ); Assert::false($res); Assert::same([['a', 0, $arr], ['b', 1, $arr]], $log); @@ -73,7 +88,10 @@ test('', function () { $log = []; $res = Arrays::every( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return true; + } ); Assert::true($res); Assert::same([['a', 'x', $arr], ['b', 'y', $arr]], $log); @@ -84,7 +102,10 @@ test('', function () { $log = []; $res = Arrays::every( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return true; + } ); Assert::true($res); Assert::same([['a', 'x', $arr], ['b', 'y', $arr]], $log); diff --git a/tests/Utils/Arrays.map().phpt b/tests/Utils/Arrays.map().phpt index 5cdabdedf..1df271682 100644 --- a/tests/Utils/Arrays.map().phpt +++ b/tests/Utils/Arrays.map().phpt @@ -18,7 +18,10 @@ test('', function () { $log = []; $res = Arrays::map( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return true; + } ); Assert::same([], $res); Assert::same([], $log); @@ -29,7 +32,10 @@ test('', function () { $log = []; $res = Arrays::map( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v . $v; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return $v . $v; + } ); Assert::same(['aa', 'bb'], $res); Assert::same([['a', 0, $arr], ['b', 1, $arr]], $log); @@ -40,7 +46,10 @@ test('', function () { $log = []; $res = Arrays::map( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v . $v; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return $v . $v; + } ); Assert::same(['x' => 'aa', 'y' => 'bb'], $res); Assert::same([['a', 'x', $arr], ['b', 'y', $arr]], $log); @@ -51,7 +60,10 @@ test('', function () { $log = []; $res = Arrays::map( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v . $v; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return $v . $v; + } ); Assert::same(['x' => 'aa', 'y' => 'bb'], $res); Assert::same([['a', 'x', $arr], ['b', 'y', $arr]], $log); diff --git a/tests/Utils/Arrays.some().phpt b/tests/Utils/Arrays.some().phpt index 3cbfadb3a..96623a85d 100644 --- a/tests/Utils/Arrays.some().phpt +++ b/tests/Utils/Arrays.some().phpt @@ -18,7 +18,10 @@ test('', function () { $log = []; $res = Arrays::some( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return false; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return false; + } ); Assert::false($res); Assert::same([], $log); @@ -29,7 +32,10 @@ test('', function () { $log = []; $res = Arrays::some( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return true; + } ); Assert::false($res); Assert::same([], $log); @@ -40,7 +46,10 @@ test('', function () { $log = []; $res = Arrays::some( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return false; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return false; + } ); Assert::false($res); Assert::same([['a', 0, $arr], ['b', 1, $arr]], $log); @@ -51,7 +60,10 @@ test('', function () { $log = []; $res = Arrays::some( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return true; + } ); Assert::true($res); Assert::same([['a', 0, $arr]], $log); @@ -62,7 +74,10 @@ test('', function () { $log = []; $res = Arrays::some( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v === 'a'; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return $v === 'a'; + } ); Assert::true($res); Assert::same([['a', 0, $arr]], $log); @@ -73,7 +88,10 @@ test('', function () { $log = []; $res = Arrays::some( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v === 'a'; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return $v === 'a'; + } ); Assert::true($res); Assert::same([['a', 'x', $arr]], $log); @@ -84,7 +102,10 @@ test('', function () { $log = []; $res = Arrays::some( $arr, - function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v === 'a'; } + function ($v, $k, $arr) use (&$log) { + $log[] = func_get_args(); + return $v === 'a'; + } ); Assert::true($res); Assert::same([['a', 'x', $arr]], $log); From d9a5ce7d828d255cde61f75de1f4ba71af076c18 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 1 Mar 2022 22:40:29 +0100 Subject: [PATCH 03/30] refactoring --- src/Utils/Callback.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils/Callback.php b/src/Utils/Callback.php index 83b6e268d..04e886a6f 100644 --- a/src/Utils/Callback.php +++ b/src/Utils/Callback.php @@ -157,7 +157,7 @@ public static function toReflection($callable): \ReflectionFunctionAbstract */ public static function isStatic(callable $callable): bool { - return is_array($callable) ? is_string($callable[0]) : is_string($callable); + return is_string(is_array($callable) ? $callable[0] : $callable); } From a2c2295460303c5edb2439c4cb5ece7517297668 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 15:30:47 +0100 Subject: [PATCH 04/30] opened 4.0-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 198407938..d80737b2a 100644 --- a/composer.json +++ b/composer.json @@ -44,7 +44,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "4.0-dev" } } } From 7ca6cf6f4e30e20ee8c05d057812a5a22a65320b Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 6 Sep 2022 02:56:07 +0200 Subject: [PATCH 05/30] requires PHP 8.0 --- .github/workflows/coding-style.yml | 2 +- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 4 ++-- composer.json | 2 +- ncs.xml | 2 +- readme.md | 1 + 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index 3c6c1bef0..a8099a358 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 5424fc71f..25e44dd05 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v3 - 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 0cf0e238c..cb1b4d11d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest] - php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + php: ['8.0', '8.1', '8.2'] fail-fast: false @@ -37,7 +37,7 @@ jobs: - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 extensions: iconv, json, mbstring, xml, gd, intl, tokenizer coverage: none diff --git a/composer.json b/composer.json index d80737b2a..b087b180e 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": ">=7.2 <8.3" + "php": ">=8.0 <8.3" }, "require-dev": { "nette/tester": "~2.0", diff --git a/ncs.xml b/ncs.xml index b6b7482ac..a1f287f25 100644 --- a/ncs.xml +++ b/ncs.xml @@ -1,6 +1,6 @@ - + ./tests/Utils/Reflection.getDeclaringMethod.alias.phpt diff --git a/readme.md b/readme.md index 2064aa8a1..b20c3127f 100644 --- a/readme.md +++ b/readme.md @@ -39,6 +39,7 @@ The recommended way to install is via Composer: composer require nette/utils ``` +- Nette Utils 4.0 is compatible with PHP 8.0 to 8.2 - Nette Utils 3.2 is compatible with PHP 7.2 to 8.2 - Nette Utils 3.1 is compatible with PHP 7.1 to 8.0 - Nette Utils 3.0 is compatible with PHP 7.1 to 8.0 From 7d10dff6f64e73663fffcd0787aa6c967e770124 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 16:43:25 +0100 Subject: [PATCH 06/30] composer: updated dependencies --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index b087b180e..f0d7f8258 100644 --- a/composer.json +++ b/composer.json @@ -18,8 +18,8 @@ "php": ">=8.0 <8.3" }, "require-dev": { - "nette/tester": "~2.0", - "tracy/tracy": "^2.3", + "nette/tester": "^2.4", + "tracy/tracy": "^2.8", "phpstan/phpstan": "^1.0" }, "conflict": { From cc145b44e488b96c4b7f2a740af1a140b63a1699 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 12:47:36 +0200 Subject: [PATCH 07/30] removed support for PHP 7 --- src/Utils/Callback.php | 2 - src/Utils/Html.php | 11 +- src/Utils/Image.php | 11 +- src/Utils/Reflection.php | 6 +- src/Utils/Type.php | 4 +- .../Utils/Reflection.getParameterType.80.phpt | 70 --------- tests/Utils/Reflection.getParameterType.phpt | 19 ++- .../Utils/Reflection.getPropertyType.74.phpt | 46 ------ .../Utils/Reflection.getPropertyType.80.phpt | 62 -------- tests/Utils/Reflection.getPropertyType.phpt | 40 ++++- tests/Utils/Reflection.getReturnType.80.phpt | 137 ------------------ tests/Utils/Reflection.getReturnType.phpt | 40 +++++ tests/Utils/SmartObject.events.74.phpt | 26 ---- tests/Utils/SmartObject.events.phpt | 7 + tests/Utils/SmartObject.undeclaredMethod.phpt | 18 +-- 15 files changed, 114 insertions(+), 385 deletions(-) delete mode 100644 tests/Utils/Reflection.getParameterType.80.phpt delete mode 100644 tests/Utils/Reflection.getPropertyType.74.phpt delete mode 100644 tests/Utils/Reflection.getPropertyType.80.phpt delete mode 100644 tests/Utils/Reflection.getReturnType.80.phpt delete mode 100644 tests/Utils/SmartObject.events.74.phpt diff --git a/src/Utils/Callback.php b/src/Utils/Callback.php index 04e886a6f..cc6420dc6 100644 --- a/src/Utils/Callback.php +++ b/src/Utils/Callback.php @@ -119,8 +119,6 @@ public static function toString($callable): string if ($callable instanceof \Closure) { $inner = self::unwrap($callable); return '{closure' . ($inner instanceof \Closure ? '}' : ' ' . self::toString($inner) . '}'); - } elseif (is_string($callable) && $callable[0] === "\0") { - return '{lambda}'; } else { is_callable(is_object($callable) ? [$callable, '__invoke'] : $callable, true, $textual); return $textual; diff --git a/src/Utils/Html.php b/src/Utils/Html.php index 0e1f6436e..cf2cddc29 100644 --- a/src/Utils/Html.php +++ b/src/Utils/Html.php @@ -771,16 +771,7 @@ final public function render(?int $indent = null): string final public function __toString(): string { - try { - return $this->render(); - } catch (\Throwable $e) { - if (PHP_VERSION_ID >= 70400) { - throw $e; - } - - trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR); - return ''; - } + return $this->render(); } diff --git a/src/Utils/Image.php b/src/Utils/Image.php index 858629883..7f1988715 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -624,16 +624,7 @@ public function toString(int $type = self::JPEG, ?int $quality = null): string */ public function __toString(): string { - try { - return $this->toString(); - } catch (\Throwable $e) { - if (func_num_args() || PHP_VERSION_ID >= 70400) { - throw $e; - } - - trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR); - return ''; - } + return $this->toString(); } diff --git a/src/Utils/Reflection.php b/src/Utils/Reflection.php index a69ed1266..d3a041bd3 100644 --- a/src/Utils/Reflection.php +++ b/src/Utils/Reflection.php @@ -98,7 +98,7 @@ public static function getParameterTypes(\ReflectionParameter $param): array */ public static function getPropertyType(\ReflectionProperty $prop): ?string { - return self::getType($prop, PHP_VERSION_ID >= 70400 ? $prop->getType() : null); + return self::getType($prop, $prop->getType()); } @@ -327,9 +327,7 @@ private static function parseUseStatements(string $code, ?string $forClass = nul $namespace = $class = $classLevel = $level = null; $res = $uses = []; - $nameTokens = PHP_VERSION_ID < 80000 - ? [T_STRING, T_NS_SEPARATOR] - : [T_STRING, T_NS_SEPARATOR, T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED]; + $nameTokens = [T_STRING, T_NS_SEPARATOR, T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED]; while ($token = current($tokens)) { next($tokens); diff --git a/src/Utils/Type.php b/src/Utils/Type.php index 2d61e5a00..e00f8f535 100644 --- a/src/Utils/Type.php +++ b/src/Utils/Type.php @@ -34,9 +34,7 @@ final class Type */ public static function fromReflection($reflection): ?self { - if ($reflection instanceof \ReflectionProperty && PHP_VERSION_ID < 70400) { - return null; - } elseif ($reflection instanceof \ReflectionMethod) { + if ($reflection instanceof \ReflectionMethod) { $type = $reflection->getReturnType() ?? (PHP_VERSION_ID >= 80100 ? $reflection->getTentativeReturnType() : null); } else { $type = $reflection instanceof \ReflectionFunctionAbstract diff --git a/tests/Utils/Reflection.getParameterType.80.phpt b/tests/Utils/Reflection.getParameterType.80.phpt deleted file mode 100644 index 57261ac51..000000000 --- a/tests/Utils/Reflection.getParameterType.80.phpt +++ /dev/null @@ -1,70 +0,0 @@ -getParameters(); - -Assert::same('Undeclared', Reflection::getParameterType($params[0])); -Assert::same('Test\B', Reflection::getParameterType($params[1])); -Assert::same('array', Reflection::getParameterType($params[2])); -Assert::same('callable', Reflection::getParameterType($params[3])); -Assert::same('A', Reflection::getParameterType($params[4])); -Assert::null(Reflection::getParameterType($params[5])); -Assert::same('Test\B', Reflection::getParameterType($params[6])); -Assert::same(['Test\B', 'null'], Reflection::getParameterTypes($params[6])); -Assert::same('mixed', Reflection::getParameterType($params[7])); -Assert::same(['mixed'], Reflection::getParameterTypes($params[7])); -Assert::same(['A', 'array'], Reflection::getParameterTypes($params[8])); -Assert::same(['A', 'array', 'null'], Reflection::getParameterTypes($params[9])); - -Assert::exception(function () use ($params) { - Reflection::getParameterType($params[8]); -}, Nette\InvalidStateException::class, 'The $union in A::method() is not expected to have a union or intersection type.'); - -Assert::exception(function () use ($params) { - Reflection::getParameterType($params[9]); -}, Nette\InvalidStateException::class, 'The $nullableUnion in A::method() is not expected to have a union or intersection type.'); - - -$method = new ReflectionMethod('AExt', 'methodExt'); -$params = $method->getParameters(); - -Assert::same('A', Reflection::getParameterType($params[0])); diff --git a/tests/Utils/Reflection.getParameterType.phpt b/tests/Utils/Reflection.getParameterType.phpt index f80468ae8..9ffa52501 100644 --- a/tests/Utils/Reflection.getParameterType.phpt +++ b/tests/Utils/Reflection.getParameterType.phpt @@ -23,7 +23,10 @@ class A callable $callable, self $self, $none, - ?B $nullable + ?B $nullable, + mixed $mixed, + array|self $union, + array|self|null $nullableUnion, ) { } } @@ -45,6 +48,20 @@ Assert::same('callable', Reflection::getParameterType($params[3])); Assert::same('A', Reflection::getParameterType($params[4])); Assert::null(Reflection::getParameterType($params[5])); Assert::same('Test\B', Reflection::getParameterType($params[6])); +Assert::same(['Test\B', 'null'], Reflection::getParameterTypes($params[6])); +Assert::same('mixed', Reflection::getParameterType($params[7])); +Assert::same(['mixed'], Reflection::getParameterTypes($params[7])); +Assert::same(['A', 'array'], Reflection::getParameterTypes($params[8])); +Assert::same(['A', 'array', 'null'], Reflection::getParameterTypes($params[9])); + +Assert::exception(function () use ($params) { + Reflection::getParameterType($params[8]); +}, Nette\InvalidStateException::class, 'The $union in A::method() is not expected to have a union or intersection type.'); + +Assert::exception(function () use ($params) { + Reflection::getParameterType($params[9]); +}, Nette\InvalidStateException::class, 'The $nullableUnion in A::method() is not expected to have a union or intersection type.'); + $method = new ReflectionMethod('AExt', 'methodExt'); $params = $method->getParameters(); diff --git a/tests/Utils/Reflection.getPropertyType.74.phpt b/tests/Utils/Reflection.getPropertyType.74.phpt deleted file mode 100644 index b822be995..000000000 --- a/tests/Utils/Reflection.getPropertyType.74.phpt +++ /dev/null @@ -1,46 +0,0 @@ -getProperties(); - -Assert::same('Undeclared', Reflection::getPropertyType($props[0])); -Assert::same('Test\B', Reflection::getPropertyType($props[1])); -Assert::same('array', Reflection::getPropertyType($props[2])); -Assert::same('A', Reflection::getPropertyType($props[3])); -Assert::null(Reflection::getPropertyType($props[4])); -Assert::same('Test\B', Reflection::getPropertyType($props[5])); - -$class = new ReflectionClass('AExt'); -$props = $class->getProperties(); - -Assert::same('A', Reflection::getPropertyType($props[0])); diff --git a/tests/Utils/Reflection.getPropertyType.80.phpt b/tests/Utils/Reflection.getPropertyType.80.phpt deleted file mode 100644 index 00378ce66..000000000 --- a/tests/Utils/Reflection.getPropertyType.80.phpt +++ /dev/null @@ -1,62 +0,0 @@ -getProperties(); - -Assert::same('Undeclared', Reflection::getPropertyType($props[0])); -Assert::same('Test\B', Reflection::getPropertyType($props[1])); -Assert::same('array', Reflection::getPropertyType($props[2])); -Assert::same('A', Reflection::getPropertyType($props[3])); -Assert::null(Reflection::getPropertyType($props[4])); -Assert::same('Test\B', Reflection::getPropertyType($props[5])); -Assert::same(['Test\B', 'null'], Reflection::getPropertyTypes($props[5])); -Assert::same('mixed', Reflection::getPropertyType($props[6])); -Assert::same(['mixed'], Reflection::getPropertyTypes($props[6])); -Assert::same(['A', 'array'], Reflection::getPropertyTypes($props[7])); -Assert::same(['A', 'array', 'null'], Reflection::getPropertyTypes($props[8])); - -Assert::exception(function () use ($props) { - Reflection::getPropertyType($props[7]); -}, Nette\InvalidStateException::class, 'The A::$union is not expected to have a union or intersection type.'); - -Assert::exception(function () use ($props) { - Reflection::getPropertyType($props[8]); -}, Nette\InvalidStateException::class, 'The A::$nullableUnion is not expected to have a union or intersection type.'); - -$class = new ReflectionClass('AExt'); -$props = $class->getProperties(); - -Assert::same('A', Reflection::getPropertyType($props[0])); diff --git a/tests/Utils/Reflection.getPropertyType.phpt b/tests/Utils/Reflection.getPropertyType.phpt index 8b15eb85e..e79e0d107 100644 --- a/tests/Utils/Reflection.getPropertyType.phpt +++ b/tests/Utils/Reflection.getPropertyType.phpt @@ -7,6 +7,7 @@ declare(strict_types=1); use Nette\Utils\Reflection; +use Test\B; // for testing purposes use Tester\Assert; @@ -15,11 +16,46 @@ require __DIR__ . '/../bootstrap.php'; class A { + public Undeclared $undeclared; + public B $b; + public array $array; + public self $self; public $none; + public ?B $nullable; + public mixed $mixed; + public array|self $union; + public array|self|null $nullableUnion; +} + +class AExt extends A +{ + public parent $parent; } $class = new ReflectionClass('A'); $props = $class->getProperties(); -Assert::null(Reflection::getPropertyType($props[0])); -Assert::same([], Reflection::getPropertyTypes($props[0])); +Assert::same('Undeclared', Reflection::getPropertyType($props[0])); +Assert::same('Test\B', Reflection::getPropertyType($props[1])); +Assert::same('array', Reflection::getPropertyType($props[2])); +Assert::same('A', Reflection::getPropertyType($props[3])); +Assert::null(Reflection::getPropertyType($props[4])); +Assert::same('Test\B', Reflection::getPropertyType($props[5])); +Assert::same(['Test\B', 'null'], Reflection::getPropertyTypes($props[5])); +Assert::same('mixed', Reflection::getPropertyType($props[6])); +Assert::same(['mixed'], Reflection::getPropertyTypes($props[6])); +Assert::same(['A', 'array'], Reflection::getPropertyTypes($props[7])); +Assert::same(['A', 'array', 'null'], Reflection::getPropertyTypes($props[8])); + +Assert::exception(function () use ($props) { + Reflection::getPropertyType($props[7]); +}, Nette\InvalidStateException::class, 'The A::$union is not expected to have a union or intersection type.'); + +Assert::exception(function () use ($props) { + Reflection::getPropertyType($props[8]); +}, Nette\InvalidStateException::class, 'The A::$nullableUnion is not expected to have a union or intersection type.'); + +$class = new ReflectionClass('AExt'); +$props = $class->getProperties(); + +Assert::same('A', Reflection::getPropertyType($props[0])); diff --git a/tests/Utils/Reflection.getReturnType.80.phpt b/tests/Utils/Reflection.getReturnType.80.phpt deleted file mode 100644 index e08b50a10..000000000 --- a/tests/Utils/Reflection.getReturnType.80.phpt +++ /dev/null @@ -1,137 +0,0 @@ -onEvent(); -}); diff --git a/tests/Utils/SmartObject.events.phpt b/tests/Utils/SmartObject.events.phpt index 4d3899627..d7952fadf 100644 --- a/tests/Utils/SmartObject.events.phpt +++ b/tests/Utils/SmartObject.events.phpt @@ -19,6 +19,8 @@ class TestClass public static $onPublicStatic; + public array $onEvent; + protected $onProtected; private $onPrivate; @@ -81,3 +83,8 @@ Assert::exception(function () use ($obj) { $obj->onPublic = 'string'; $obj->onPublic(); }, Nette\UnexpectedValueException::class, 'Property TestClass::$onPublic must be iterable or null, string given.'); + +Assert::noError(function () { + $obj = new TestClass; + $obj->onEvent(); +}); diff --git a/tests/Utils/SmartObject.undeclaredMethod.phpt b/tests/Utils/SmartObject.undeclaredMethod.phpt index 60d255cb8..c11e52cd1 100644 --- a/tests/Utils/SmartObject.undeclaredMethod.phpt +++ b/tests/Utils/SmartObject.undeclaredMethod.phpt @@ -120,18 +120,12 @@ Assert::exception(function () { $obj::callMissingParentStatic(); }, Nette\MemberAccessException::class, 'Call to undefined static method InterClass::callMissingParentStatic().'); -Assert::exception( - function () { - $obj = new ChildClass; - $obj->callPrivateParent(); - }, - Nette\MemberAccessException::class, - PHP_VERSION_ID < 70400 - ? 'Call to private method InterClass::callPrivateParent() from scope ChildClass.' - : (PHP_VERSION_ID < 80100 - ? 'Call to undefined static method InterClass::callPrivateParent().' // differs from native error message - : 'Call to undefined method InterClass::callPrivateParent().') -); +Assert::exception(function () { + $obj = new ChildClass; + $obj->callPrivateParent(); +}, Nette\MemberAccessException::class, PHP_VERSION_ID < 80100 + ? 'Call to undefined static method InterClass::callPrivateParent().' // differs from native error message + : 'Call to undefined method InterClass::callPrivateParent().'); Assert::exception(function () { $obj = new ChildClass; From 7f0392f2952abdd70bd34330222c3511939a3367 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 2 Mar 2021 15:50:58 +0100 Subject: [PATCH 08/30] removed deprecated stuff --- src/Utils/Callback.php | 41 ---------------- src/Utils/ObjectMixin.php | 41 ---------------- src/Utils/Reflection.php | 30 ------------ tests/Utils/Callback.invoke.phpt | 49 ------------------- .../Utils/Reflection.getParameterType.81.phpt | 4 -- tests/Utils/Reflection.getParameterType.phpt | 4 -- .../Utils/Reflection.getPropertyType.81.phpt | 4 -- tests/Utils/Reflection.getPropertyType.phpt | 4 -- tests/Utils/Reflection.getReturnType.81.phpt | 7 --- tests/Utils/Reflection.getReturnType.phpt | 6 --- 10 files changed, 190 deletions(-) delete mode 100644 src/Utils/ObjectMixin.php delete mode 100644 tests/Utils/Callback.invoke.phpt diff --git a/src/Utils/Callback.php b/src/Utils/Callback.php index cc6420dc6..dae82e6ae 100644 --- a/src/Utils/Callback.php +++ b/src/Utils/Callback.php @@ -20,47 +20,6 @@ final class Callback { use Nette\StaticClass; - /** - * @param string|object|callable $callable class, object, callable - * @deprecated use Closure::fromCallable() - */ - public static function closure($callable, ?string $method = null): \Closure - { - trigger_error(__METHOD__ . '() is deprecated, use Closure::fromCallable().', E_USER_DEPRECATED); - try { - return \Closure::fromCallable($method === null ? $callable : [$callable, $method]); - } catch (\TypeError $e) { - throw new Nette\InvalidArgumentException($e->getMessage()); - } - } - - - /** - * Invokes callback. - * @return mixed - * @deprecated - */ - public static function invoke($callable, ...$args) - { - trigger_error(__METHOD__ . '() is deprecated, use native invoking.', E_USER_DEPRECATED); - self::check($callable); - return $callable(...$args); - } - - - /** - * Invokes callback with an array of parameters. - * @return mixed - * @deprecated - */ - public static function invokeArgs($callable, array $args = []) - { - trigger_error(__METHOD__ . '() is deprecated, use native invoking.', E_USER_DEPRECATED); - self::check($callable); - return $callable(...$args); - } - - /** * Invokes internal PHP function with own error handler. * @return mixed diff --git a/src/Utils/ObjectMixin.php b/src/Utils/ObjectMixin.php deleted file mode 100644 index 33249509b..000000000 --- a/src/Utils/ObjectMixin.php +++ /dev/null @@ -1,41 +0,0 @@ -getNames() : []; - } - - /** * Returns the type of given parameter and normalizes `self` and `parent` to the actual class names. * If the parameter does not have a type, it returns null. @@ -81,16 +71,6 @@ public static function getParameterType(\ReflectionParameter $param): ?string } - /** - * @deprecated - */ - public static function getParameterTypes(\ReflectionParameter $param): array - { - $type = Type::fromReflection($param); - return $type ? $type->getNames() : []; - } - - /** * Returns the type of given property and normalizes `self` and `parent` to the actual class names. * If the property does not have a type, it returns null. @@ -102,16 +82,6 @@ public static function getPropertyType(\ReflectionProperty $prop): ?string } - /** - * @deprecated - */ - public static function getPropertyTypes(\ReflectionProperty $prop): array - { - $type = Type::fromReflection($prop); - return $type ? $type->getNames() : []; - } - - /** * @param \ReflectionFunction|\ReflectionMethod|\ReflectionParameter|\ReflectionProperty $reflection */ diff --git a/tests/Utils/Callback.invoke.phpt b/tests/Utils/Callback.invoke.phpt deleted file mode 100644 index 9d072f29f..000000000 --- a/tests/Utils/Callback.invoke.phpt +++ /dev/null @@ -1,49 +0,0 @@ - Date: Sun, 19 Sep 2021 19:03:08 +0200 Subject: [PATCH 09/30] coding style --- src/Iterators/CachingIterator.php | 2 +- src/Utils/Callback.php | 2 +- src/Utils/DateTime.php | 6 +-- src/Utils/FileSystem.php | 20 ++++---- src/Utils/Html.php | 2 +- src/Utils/Image.php | 14 +++--- src/Utils/ObjectHelpers.php | 18 ++++---- src/Utils/Random.php | 9 ++-- src/Utils/Strings.php | 2 +- src/Utils/Type.php | 31 +++++-------- src/Utils/Validators.php | 46 +++++++++---------- tests/Iterators/Mapper.phpt | 4 +- tests/Utils/Arrays.associate().phpt | 38 +++++++-------- tests/Utils/Arrays.every().phpt | 14 +++--- tests/Utils/Arrays.invoke.phpt | 4 +- tests/Utils/Arrays.invokeMethod.phpt | 4 +- tests/Utils/Arrays.map().phpt | 8 ++-- tests/Utils/Arrays.normalize.phpt | 4 +- tests/Utils/Arrays.some().phpt | 14 +++--- tests/Utils/Callback.invokeSafe.phpt | 4 +- tests/Utils/DateTime.JSON.phpt | 2 +- tests/Utils/DateTime.from.phpt | 12 ++--- tests/Utils/DateTime.modifyClone.phpt | 2 +- tests/Utils/Json.decode().phpt | 2 +- tests/Utils/Reflection.expandClassName.phpt | 8 ++-- .../Utils/Reflection.groupUseStatements.phpt | 2 +- .../Reflection.nonClassUseStatements.phpt | 2 +- tests/Utils/Strings.replace().phpt | 2 +- tests/Utils/Type.fromReflection.method.phpt | 4 +- .../fixtures.reflection/defaultValue.php | 2 +- 30 files changed, 137 insertions(+), 147 deletions(-) diff --git a/src/Iterators/CachingIterator.php b/src/Iterators/CachingIterator.php index b07bbbfa4..cf8f6785f 100644 --- a/src/Iterators/CachingIterator.php +++ b/src/Iterators/CachingIterator.php @@ -48,7 +48,7 @@ public function __construct($iterator) } elseif ($iterator instanceof \Traversable) { $iterator = new \IteratorIterator($iterator); } else { - throw new Nette\InvalidArgumentException(sprintf('Invalid argument passed to %s; array or Traversable expected, %s given.', self::class, is_object($iterator) ? get_class($iterator) : gettype($iterator))); + throw new Nette\InvalidArgumentException(sprintf('Invalid argument passed to %s; array or Traversable expected, %s given.', self::class, is_object($iterator) ? $iterator::class : gettype($iterator))); } parent::__construct($iterator, 0); diff --git a/src/Utils/Callback.php b/src/Utils/Callback.php index dae82e6ae..f7a0f39ad 100644 --- a/src/Utils/Callback.php +++ b/src/Utils/Callback.php @@ -61,7 +61,7 @@ public static function check($callable, bool $syntax = false) throw new Nette\InvalidArgumentException( $syntax ? 'Given value is not a callable type.' - : sprintf("Callback '%s' is not callable.", self::toString($callable)) + : sprintf("Callback '%s' is not callable.", self::toString($callable)), ); } diff --git a/src/Utils/DateTime.php b/src/Utils/DateTime.php index aa61a4b4f..e53f41de0 100644 --- a/src/Utils/DateTime.php +++ b/src/Utils/DateTime.php @@ -32,10 +32,10 @@ class DateTime extends \DateTime implements \JsonSerializable public const WEEK = 7 * self::DAY; /** average month in seconds */ - public const MONTH = 2629800; + public const MONTH = 2_629_800; /** average year in seconds */ - public const YEAR = 31557600; + public const YEAR = 31_557_600; /** @@ -73,7 +73,7 @@ public static function fromParts( int $day, int $hour = 0, int $minute = 0, - float $second = 0.0 + float $second = 0.0, ) { $s = sprintf('%04d-%02d-%02d %02d:%02d:%02.5F', $year, $month, $day, $hour, $minute, $second); if ( diff --git a/src/Utils/FileSystem.php b/src/Utils/FileSystem.php index c61603380..826d07b2d 100644 --- a/src/Utils/FileSystem.php +++ b/src/Utils/FileSystem.php @@ -30,7 +30,7 @@ public static function createDir(string $dir, int $mode = 0777): void "Unable to create directory '%s' with mode %s. %s", self::normalizePath($dir), decoct($mode), - Helpers::getLastError() + Helpers::getLastError(), )); } } @@ -73,7 +73,7 @@ public static function copy(string $origin, string $target, bool $overwrite = tr "Unable to copy file '%s' to '%s'. %s", self::normalizePath($origin), self::normalizePath($target), - Helpers::getLastError() + Helpers::getLastError(), )); } } @@ -92,7 +92,7 @@ public static function delete(string $path): void throw new Nette\IOException(sprintf( "Unable to delete '%s'. %s", self::normalizePath($path), - Helpers::getLastError() + Helpers::getLastError(), )); } } elseif (is_dir($path)) { @@ -104,7 +104,7 @@ public static function delete(string $path): void throw new Nette\IOException(sprintf( "Unable to delete directory '%s'. %s", self::normalizePath($path), - Helpers::getLastError() + Helpers::getLastError(), )); } } @@ -135,7 +135,7 @@ public static function rename(string $origin, string $target, bool $overwrite = "Unable to rename file or directory '%s' to '%s'. %s", self::normalizePath($origin), self::normalizePath($target), - Helpers::getLastError() + Helpers::getLastError(), )); } } @@ -153,7 +153,7 @@ public static function read(string $file): string throw new Nette\IOException(sprintf( "Unable to read file '%s'. %s", self::normalizePath($file), - Helpers::getLastError() + Helpers::getLastError(), )); } @@ -172,7 +172,7 @@ public static function write(string $file, string $content, ?int $mode = 0666): throw new Nette\IOException(sprintf( "Unable to write file '%s'. %s", self::normalizePath($file), - Helpers::getLastError() + Helpers::getLastError(), )); } @@ -181,7 +181,7 @@ public static function write(string $file, string $content, ?int $mode = 0666): "Unable to chmod file '%s' to mode %s. %s", self::normalizePath($file), decoct($mode), - Helpers::getLastError() + Helpers::getLastError(), )); } } @@ -199,7 +199,7 @@ public static function makeWritable(string $path, int $dirMode = 0777, int $file "Unable to chmod file '%s' to mode %s. %s", self::normalizePath($path), decoct($fileMode), - Helpers::getLastError() + Helpers::getLastError(), )); } } elseif (is_dir($path)) { @@ -212,7 +212,7 @@ public static function makeWritable(string $path, int $dirMode = 0777, int $file "Unable to chmod directory '%s' to mode %s. %s", self::normalizePath($path), decoct($dirMode), - Helpers::getLastError() + Helpers::getLastError(), )); } } else { diff --git a/src/Utils/Html.php b/src/Utils/Html.php index cf2cddc29..b052b1735 100644 --- a/src/Utils/Html.php +++ b/src/Utils/Html.php @@ -853,7 +853,7 @@ final public function attributes(): string . str_replace( ['&', $q, '<'], ['&', $q === '"' ? '"' : ''', self::$xhtml ? '<' : '<'], - $value + $value, ) . (strpos($value, '`') !== false && strpbrk($value, ' <>"\'') === false ? ' ' : '') . $q; diff --git a/src/Utils/Image.php b/src/Utils/Image.php index 7f1988715..2db8490ca 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -369,7 +369,7 @@ public function resize($width, $height, int $flags = self::FIT) $newWidth, $newHeight, $this->getWidth(), - $this->getHeight() + $this->getHeight(), ); $this->image = $newImage; } @@ -392,7 +392,7 @@ public static function calculateSize( int $srcHeight, $newWidth, $newHeight, - int $flags = self::FIT + int $flags = self::FIT, ): array { if ($newWidth === null) { @@ -591,7 +591,7 @@ public function place(self $image, $left = 0, $top = 0, int $opacity = 100) 0, 0, $width, - $height + $height, ); return $this; } @@ -603,7 +603,7 @@ public function place(self $image, $left = 0, $top = 0, int $opacity = 100) */ public function save(string $file, ?int $quality = null, ?int $type = null): void { - $type = $type ?? self::extensionToType(pathinfo($file, PATHINFO_EXTENSION)); + $type ??= self::extensionToType(pathinfo($file, PATHINFO_EXTENSION)); $this->output($type, $quality, $file); } @@ -613,7 +613,7 @@ public function save(string $file, ?int $quality = null, ?int $type = null): voi */ public function toString(int $type = self::JPEG, ?int $quality = null): string { - return Helpers::capture(function () use ($type, $quality) { + return Helpers::capture(function () use ($type, $quality): void { $this->output($type, $quality); }); } @@ -706,13 +706,13 @@ public function __call(string $name, array $args) $value['red'], $value['green'], $value['blue'], - $value['alpha'] + $value['alpha'], ) ?: imagecolorresolvealpha( $this->image, $value['red'], $value['green'], $value['blue'], - $value['alpha'] + $value['alpha'], ); } } diff --git a/src/Utils/ObjectHelpers.php b/src/Utils/ObjectHelpers.php index 6cdfc5850..a85184b1f 100644 --- a/src/Utils/ObjectHelpers.php +++ b/src/Utils/ObjectHelpers.php @@ -28,8 +28,8 @@ public static function strictGet(string $class, string $name): void { $rc = new \ReflectionClass($class); $hint = self::getSuggestion(array_merge( - array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), function ($p) { return !$p->isStatic(); }), - self::parseFullDoc($rc, '~^[ \t*]*@property(?:-read)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m') + array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), fn($p) => !$p->isStatic()), + self::parseFullDoc($rc, '~^[ \t*]*@property(?:-read)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m'), ), $name); throw new MemberAccessException("Cannot read an undeclared property $class::\$$name" . ($hint ? ", did you mean \$$hint?" : '.')); } @@ -43,8 +43,8 @@ public static function strictSet(string $class, string $name): void { $rc = new \ReflectionClass($class); $hint = self::getSuggestion(array_merge( - array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), function ($p) { return !$p->isStatic(); }), - self::parseFullDoc($rc, '~^[ \t*]*@property(?:-write)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m') + array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), fn($p) => !$p->isStatic()), + self::parseFullDoc($rc, '~^[ \t*]*@property(?:-write)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m'), ), $name); throw new MemberAccessException("Cannot write to an undeclared property $class::\$$name" . ($hint ? ", did you mean \$$hint?" : '.')); } @@ -76,7 +76,7 @@ public static function strictCall(string $class, string $method, array $addition $hint = self::getSuggestion(array_merge( get_class_methods($class), self::parseFullDoc(new \ReflectionClass($class), '~^[ \t*]*@method[ \t]+(?:static[ \t]+)?(?:\S+[ \t]+)??(\w+)\(~m'), - $additionalMethods + $additionalMethods, ), $method); throw new MemberAccessException("Call to undefined method $class::$method()" . ($hint ? ", did you mean $hint()?" : '.')); } @@ -107,8 +107,8 @@ public static function strictStaticCall(string $class, string $method): void } else { $hint = self::getSuggestion( - array_filter((new \ReflectionClass($class))->getMethods(\ReflectionMethod::IS_PUBLIC), function ($m) { return $m->isStatic(); }), - $method + array_filter((new \ReflectionClass($class))->getMethods(\ReflectionMethod::IS_PUBLIC), fn($m) => $m->isStatic()), + $method, ); throw new MemberAccessException("Call to undefined static method $class::$method()" . ($hint ? ", did you mean $hint()?" : '.')); } @@ -133,7 +133,7 @@ public static function getMagicProperties(string $class): array '~^ [ \t*]* @property(|-read|-write|-deprecated) [ \t]+ [^\s$]+ [ \t]+ \$ (\w+) ()~mx', (string) $rc->getDocComment(), $matches, - PREG_SET_ORDER + PREG_SET_ORDER, ); $props = []; @@ -199,7 +199,7 @@ private static function parseFullDoc(\ReflectionClass $rc, string $pattern): arr } } while ($rc = $rc->getParentClass()); - return preg_match_all($pattern, implode($doc), $m) ? $m[1] : []; + return preg_match_all($pattern, implode('', $doc), $m) ? $m[1] : []; } diff --git a/src/Utils/Random.php b/src/Utils/Random.php index f900628a8..d8ebcdc7c 100644 --- a/src/Utils/Random.php +++ b/src/Utils/Random.php @@ -25,9 +25,12 @@ final class Random */ public static function generate(int $length = 10, string $charlist = '0-9a-z'): string { - $charlist = count_chars(preg_replace_callback('#.-.#', function (array $m): string { - return implode('', range($m[0][0], $m[0][2])); - }, $charlist), 3); + $charlist = preg_replace_callback( + '#.-.#', + fn(array $m): string => implode('', range($m[0][0], $m[0][2])), + $charlist, + ); + $charlist = count_chars($charlist, mode: 3); $chLen = strlen($charlist); if ($length < 1) { diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index 1314c62fc..ee7c493cf 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -186,7 +186,7 @@ public static function toAscii(string $s): string $s = strtr( $s, "\xa5\xa3\xbc\x8c\xa7\x8a\xaa\x8d\x8f\x8e\xaf\xb9\xb3\xbe\x9c\x9a\xba\x9d\x9f\x9e\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe\x96\xa0\x8b\x97\x9b\xa6\xad\xb7", - 'ALLSSSSTZZZallssstzzzRAAAALCCCEEEEIIDDNNOOOOxRUUUUYTsraaaalccceeeeiiddnnooooruuuuyt- <->|-.' + 'ALLSSSSTZZZallssstzzzRAAAALCCCEEEEIIDDNNOOOOxRUUUUYTsraaaalccceeeeiiddnnooooruuuuyt- <->|-.', ); $s = self::pcre('preg_replace', ['#[^\x00-\x7F]++#', '', $s]); } else { diff --git a/src/Utils/Type.php b/src/Utils/Type.php index e00f8f535..9e7822f8e 100644 --- a/src/Utils/Type.php +++ b/src/Utils/Type.php @@ -52,10 +52,10 @@ public static function fromReflection($reflection): ?self } elseif ($type instanceof \ReflectionUnionType || $type instanceof \ReflectionIntersectionType) { return new self( array_map( - function ($t) use ($reflection) { return self::resolve($t->getName(), $reflection); }, - $type->getTypes() + fn($t) => self::resolve($t->getName(), $reflection), + $type->getTypes(), ), - $type instanceof \ReflectionUnionType ? '|' : '&' + $type instanceof \ReflectionUnionType ? '|' : '&', ); } else { @@ -142,7 +142,7 @@ public function getNames(): array */ public function getTypes(): array { - return array_map(function ($name) { return self::fromString($name); }, $this->types); + return array_map(fn($name) => self::fromString($name), $this->types); } @@ -223,28 +223,21 @@ public function allows(string $type): bool $type = self::fromString($type); if ($this->isIntersection()) { - if (!$type->isIntersection()) { - return false; - } - - return Arrays::every($this->types, function ($currentType) use ($type) { - $builtin = Reflection::isBuiltinType($currentType); - return Arrays::some($type->types, function ($testedType) use ($currentType, $builtin) { - return $builtin + return $type->isIntersection() + && Arrays::every($this->types, function ($currentType) use ($type) { + $builtin = Reflection::isBuiltinType($currentType); + return Arrays::some($type->types, fn($testedType) => $builtin ? strcasecmp($currentType, $testedType) === 0 - : is_a($testedType, $currentType, true); + : is_a($testedType, $currentType, true)); }); - }); } $method = $type->isIntersection() ? 'some' : 'every'; return Arrays::$method($type->types, function ($testedType) { $builtin = Reflection::isBuiltinType($testedType); - return Arrays::some($this->types, function ($currentType) use ($testedType, $builtin) { - return $builtin - ? strcasecmp($currentType, $testedType) === 0 - : is_a($testedType, $currentType, true); - }); + return Arrays::some($this->types, fn($currentType) => $builtin + ? strcasecmp($currentType, $testedType) === 0 + : is_a($testedType, $currentType, true)); }); } } diff --git a/src/Utils/Validators.php b/src/Utils/Validators.php index 11ee350ee..22468ebe0 100644 --- a/src/Utils/Validators.php +++ b/src/Utils/Validators.php @@ -99,7 +99,7 @@ public static function assert($value, string $expected, string $label = 'variabl if (is_int($value) || is_float($value) || (is_string($value) && strlen($value) < 40)) { $type .= ' ' . var_export($value, true); } elseif (is_object($value)) { - $type .= ' ' . get_class($value); + $type .= ' ' . $value::class; } throw new AssertionException("The $label expects to be $expected, $type given."); @@ -117,7 +117,7 @@ public static function assertField( array $array, $key, ?string $expected = null, - string $label = "item '%' in array" + string $label = "item '%' in array", ): void { if (!array_key_exists($key, $array)) { @@ -321,14 +321,13 @@ public static function isEmail(string $value): bool $atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]"; // RFC 5322 unquoted characters in local-part $alpha = "a-z\x80-\xFF"; // superset of IDN return (bool) preg_match(<< 'Grudl', ]; -$callback = function ($item, $key) { - return $key . ': ' . $item; -}; +$callback = fn($item, $key) => $key . ': ' . $item; $iterator = new Iterators\Mapper(new ArrayIterator($arr), $callback); diff --git a/tests/Utils/Arrays.associate().phpt b/tests/Utils/Arrays.associate().phpt index 80e439e8f..d7cde4a53 100644 --- a/tests/Utils/Arrays.associate().phpt +++ b/tests/Utils/Arrays.associate().phpt @@ -28,12 +28,12 @@ Assert::same( 'Mary' => ['name' => 'Mary', 'age' => null], 'Paul' => ['name' => 'Paul', 'age' => 44], ], - Arrays::associate($arr, 'name') + Arrays::associate($arr, 'name'), ); Assert::same( [], - Arrays::associate([], 'name') + Arrays::associate([], 'name'), ); Assert::same( @@ -42,17 +42,17 @@ Assert::same( 'Mary' => ['name' => 'Mary', 'age' => null], 'Paul' => ['name' => 'Paul', 'age' => 44], ], - Arrays::associate($arr, 'name=') + Arrays::associate($arr, 'name='), ); Assert::same( ['John' => 22, 'Mary' => null, 'Paul' => 44], - Arrays::associate($arr, 'name=age') + Arrays::associate($arr, 'name=age'), ); Assert::same(// path as array ['John' => 22, 'Mary' => null, 'Paul' => 44], - Arrays::associate($arr, ['name', '=', 'age']) + Arrays::associate($arr, ['name', '=', 'age']), ); Assert::equal( @@ -70,7 +70,7 @@ Assert::equal( 'age' => 44, ], ], - Arrays::associate($arr, 'name->') + Arrays::associate($arr, 'name->'), ); Assert::equal( @@ -88,7 +88,7 @@ Assert::equal( 'Paul' => ['name' => 'Paul', 'age' => 44], ], ], - Arrays::associate($arr, 'age->name') + Arrays::associate($arr, 'age->name'), ); Assert::equal( @@ -97,12 +97,12 @@ Assert::equal( 'Mary' => ['name' => 'Mary', 'age' => null], 'Paul' => ['name' => 'Paul', 'age' => 44], ], - Arrays::associate($arr, '->name') + Arrays::associate($arr, '->name'), ); Assert::equal( (object) [], - Arrays::associate([], '->name') + Arrays::associate([], '->name'), ); Assert::same( @@ -118,7 +118,7 @@ Assert::same( 44 => ['name' => 'Paul', 'age' => 44], ], ], - Arrays::associate($arr, 'name|age') + Arrays::associate($arr, 'name|age'), ); Assert::same( @@ -127,7 +127,7 @@ Assert::same( 'Mary' => ['name' => 'Mary', 'age' => null], 'Paul' => ['name' => 'Paul', 'age' => 44], ], - Arrays::associate($arr, 'name|') + Arrays::associate($arr, 'name|'), ); Assert::same( @@ -143,7 +143,7 @@ Assert::same( ['name' => 'Paul', 'age' => 44], ], ], - Arrays::associate($arr, 'name[]') + Arrays::associate($arr, 'name[]'), ); Assert::same( @@ -153,12 +153,12 @@ Assert::same( ['Mary' => ['name' => 'Mary', 'age' => null]], ['Paul' => ['name' => 'Paul', 'age' => 44]], ], - Arrays::associate($arr, '[]name') + Arrays::associate($arr, '[]name'), ); Assert::same( ['John', 'John', 'Mary', 'Paul'], - Arrays::associate($arr, '[]=name') + Arrays::associate($arr, '[]=name'), ); Assert::same( @@ -174,12 +174,12 @@ Assert::same( [44 => ['name' => 'Paul', 'age' => 44]], ], ], - Arrays::associate($arr, 'name[]age') + Arrays::associate($arr, 'name[]age'), ); Assert::same( $arr, - Arrays::associate($arr, '[]') + Arrays::associate($arr, '[]'), ); // converts object to array @@ -190,7 +190,7 @@ Assert::same( (object) ['name' => 'John', 'age' => 22], (object) ['name' => 'Mary', 'age' => null], (object) ['name' => 'Paul', 'age' => 44], - ], '[]') + ], '[]'), ); // allowes objects in keys @@ -198,11 +198,11 @@ Assert::equal( ['2014-02-05 00:00:00' => new DateTime('2014-02-05')], Arrays::associate($arr = [ ['date' => new DateTime('2014-02-05')], - ], 'date=date') + ], 'date=date'), ); Assert::equal( (object) ['2014-02-05 00:00:00' => new DateTime('2014-02-05')], Arrays::associate($arr = [ ['date' => new DateTime('2014-02-05')], - ], '->date=date') + ], '->date=date'), ); diff --git a/tests/Utils/Arrays.every().phpt b/tests/Utils/Arrays.every().phpt index 1aef6f6a3..559542f7a 100644 --- a/tests/Utils/Arrays.every().phpt +++ b/tests/Utils/Arrays.every().phpt @@ -21,7 +21,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return false; - } + }, ); Assert::true($res); Assert::same([], $log); @@ -35,7 +35,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; - } + }, ); Assert::true($res); Assert::same([], $log); @@ -49,7 +49,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return false; - } + }, ); Assert::false($res); Assert::same([['a', 0, $arr]], $log); @@ -63,7 +63,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; - } + }, ); Assert::true($res); Assert::same([['a', 0, $arr], ['b', 1, $arr]], $log); @@ -77,7 +77,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v === 'a'; - } + }, ); Assert::false($res); Assert::same([['a', 0, $arr], ['b', 1, $arr]], $log); @@ -91,7 +91,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; - } + }, ); Assert::true($res); Assert::same([['a', 'x', $arr], ['b', 'y', $arr]], $log); @@ -105,7 +105,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; - } + }, ); Assert::true($res); Assert::same([['a', 'x', $arr], ['b', 'y', $arr]], $log); diff --git a/tests/Utils/Arrays.invoke.phpt b/tests/Utils/Arrays.invoke.phpt index 173106ce4..19d1094f0 100644 --- a/tests/Utils/Arrays.invoke.phpt +++ b/tests/Utils/Arrays.invoke.phpt @@ -30,10 +30,10 @@ $list['key'] = [new Test, 'fn2']; Assert::same( ['Test::fn1 a,b', 'key' => 'Test::fn2 a,b'], - Arrays::invoke($list, 'a', 'b') + Arrays::invoke($list, 'a', 'b'), ); Assert::same( ['Test::fn1 a,b', 'key' => 'Test::fn2 a,b'], - Arrays::invoke(new ArrayIterator($list), 'a', 'b') + Arrays::invoke(new ArrayIterator($list), 'a', 'b'), ); diff --git a/tests/Utils/Arrays.invokeMethod.phpt b/tests/Utils/Arrays.invokeMethod.phpt index 8e1eec51d..8c42d3186 100644 --- a/tests/Utils/Arrays.invokeMethod.phpt +++ b/tests/Utils/Arrays.invokeMethod.phpt @@ -26,10 +26,10 @@ $list = [new Test1, 'key' => new Test2]; Assert::same( ['Test1 a,b', 'key' => 'Test2 a,b'], - Arrays::invokeMethod($list, 'fn', 'a', 'b') + Arrays::invokeMethod($list, 'fn', 'a', 'b'), ); Assert::same( ['Test1 a,b', 'key' => 'Test2 a,b'], - Arrays::invokeMethod(new ArrayIterator($list), 'fn', 'a', 'b') + Arrays::invokeMethod(new ArrayIterator($list), 'fn', 'a', 'b'), ); diff --git a/tests/Utils/Arrays.map().phpt b/tests/Utils/Arrays.map().phpt index 1df271682..5b958515f 100644 --- a/tests/Utils/Arrays.map().phpt +++ b/tests/Utils/Arrays.map().phpt @@ -21,7 +21,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; - } + }, ); Assert::same([], $res); Assert::same([], $log); @@ -35,7 +35,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v . $v; - } + }, ); Assert::same(['aa', 'bb'], $res); Assert::same([['a', 0, $arr], ['b', 1, $arr]], $log); @@ -49,7 +49,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v . $v; - } + }, ); Assert::same(['x' => 'aa', 'y' => 'bb'], $res); Assert::same([['a', 'x', $arr], ['b', 'y', $arr]], $log); @@ -63,7 +63,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v . $v; - } + }, ); Assert::same(['x' => 'aa', 'y' => 'bb'], $res); Assert::same([['a', 'x', $arr], ['b', 'y', $arr]], $log); diff --git a/tests/Utils/Arrays.normalize.phpt b/tests/Utils/Arrays.normalize.phpt index 0ff385a96..44eab09f7 100644 --- a/tests/Utils/Arrays.normalize.phpt +++ b/tests/Utils/Arrays.normalize.phpt @@ -25,7 +25,7 @@ Assert::same( 'a' => 'second', 'd' => ['third'], 7 => 'fourth', - ]) + ]), ); @@ -37,5 +37,5 @@ Assert::same( Arrays::normalize([ 1 => 'first', '' => 'second', - ], true) + ], true), ); diff --git a/tests/Utils/Arrays.some().phpt b/tests/Utils/Arrays.some().phpt index 96623a85d..b39baf881 100644 --- a/tests/Utils/Arrays.some().phpt +++ b/tests/Utils/Arrays.some().phpt @@ -21,7 +21,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return false; - } + }, ); Assert::false($res); Assert::same([], $log); @@ -35,7 +35,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; - } + }, ); Assert::false($res); Assert::same([], $log); @@ -49,7 +49,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return false; - } + }, ); Assert::false($res); Assert::same([['a', 0, $arr], ['b', 1, $arr]], $log); @@ -63,7 +63,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return true; - } + }, ); Assert::true($res); Assert::same([['a', 0, $arr]], $log); @@ -77,7 +77,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v === 'a'; - } + }, ); Assert::true($res); Assert::same([['a', 0, $arr]], $log); @@ -91,7 +91,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v === 'a'; - } + }, ); Assert::true($res); Assert::same([['a', 'x', $arr]], $log); @@ -105,7 +105,7 @@ test('', function () { function ($v, $k, $arr) use (&$log) { $log[] = func_get_args(); return $v === 'a'; - } + }, ); Assert::true($res); Assert::same([['a', 'x', $arr]], $log); diff --git a/tests/Utils/Callback.invokeSafe.phpt b/tests/Utils/Callback.invokeSafe.phpt index 847f2c8f4..b9d34c8a9 100644 --- a/tests/Utils/Callback.invokeSafe.phpt +++ b/tests/Utils/Callback.invokeSafe.phpt @@ -31,9 +31,7 @@ Assert::same('OK1', $res); // ignored error -Callback::invokeSafe('preg_match', ['ab', 'foo'], function () { - return false; -}); +Callback::invokeSafe('preg_match', ['ab', 'foo'], fn() => false); Assert::match('preg_match(): Delimiter must not be alphanumeric%a%', $res); diff --git a/tests/Utils/DateTime.JSON.phpt b/tests/Utils/DateTime.JSON.phpt index 90761833a..5683bd981 100644 --- a/tests/Utils/DateTime.JSON.phpt +++ b/tests/Utils/DateTime.JSON.phpt @@ -14,4 +14,4 @@ require __DIR__ . '/../bootstrap.php'; date_default_timezone_set('Europe/Prague'); -Assert::same('"1978-01-23T11:40:00+01:00"', json_encode(DateTime::from(254400000))); +Assert::same('"1978-01-23T11:40:00+01:00"', json_encode(DateTime::from(254_400_000))); diff --git a/tests/Utils/DateTime.from.phpt b/tests/Utils/DateTime.from.phpt index 9cf9adc25..7a296ee01 100644 --- a/tests/Utils/DateTime.from.phpt +++ b/tests/Utils/DateTime.from.phpt @@ -14,14 +14,14 @@ require __DIR__ . '/../bootstrap.php'; date_default_timezone_set('Europe/Prague'); -Assert::same('1978-01-23 11:40:00', (string) DateTime::from(254400000)); -Assert::same('1978-01-23 11:40:00', (string) (new DateTime)->setTimestamp(254400000)); -Assert::same(254400000, DateTime::from(254400000)->getTimestamp()); +Assert::same('1978-01-23 11:40:00', (string) DateTime::from(254_400_000)); +Assert::same('1978-01-23 11:40:00', (string) (new DateTime)->setTimestamp(254_400_000)); +Assert::same(254_400_000, DateTime::from(254_400_000)->getTimestamp()); Assert::same(time() + 60, (int) DateTime::from(60)->format('U')); -Assert::same(PHP_VERSION_ID < 80100 ? '2050-08-13 11:40:00' : '2050-08-13 12:40:00', (string) DateTime::from(2544000000)); -Assert::same(PHP_VERSION_ID < 80100 ? '2050-08-13 11:40:00' : '2050-08-13 12:40:00', (string) (new DateTime)->setTimestamp(2544000000)); -Assert::same(is_int(2544000000) ? 2544000000 : '2544000000', DateTime::from(2544000000)->getTimestamp()); // 64 bit +Assert::same(PHP_VERSION_ID < 80100 ? '2050-08-13 11:40:00' : '2050-08-13 12:40:00', (string) DateTime::from(2_544_000_000)); +Assert::same(PHP_VERSION_ID < 80100 ? '2050-08-13 11:40:00' : '2050-08-13 12:40:00', (string) (new DateTime)->setTimestamp(2_544_000_000)); +Assert::same(is_int(2_544_000_000) ? 2_544_000_000 : '2544000000', DateTime::from(2_544_000_000)->getTimestamp()); // 64 bit Assert::same('1978-05-05 00:00:00', (string) DateTime::from('1978-05-05')); diff --git a/tests/Utils/DateTime.modifyClone.phpt b/tests/Utils/DateTime.modifyClone.phpt index 7e7fbb34b..b3ed3fbc2 100644 --- a/tests/Utils/DateTime.modifyClone.phpt +++ b/tests/Utils/DateTime.modifyClone.phpt @@ -14,7 +14,7 @@ require __DIR__ . '/../bootstrap.php'; date_default_timezone_set('Europe/Prague'); -$date = DateTime::from(254400000); +$date = DateTime::from(254_400_000); $dolly = $date->modifyClone(); Assert::type(DateTime::class, $dolly); Assert::notSame($date, $dolly); diff --git a/tests/Utils/Json.decode().phpt b/tests/Utils/Json.decode().phpt index ec0368237..e3ac443c9 100644 --- a/tests/Utils/Json.decode().phpt +++ b/tests/Utils/Json.decode().phpt @@ -66,7 +66,7 @@ Assert::exception(function () { if (defined('JSON_C_VERSION')) { if (PHP_INT_SIZE > 4) { // 64-bit - Assert::same([9223372036854775807], Json::decode('[12345678901234567890]')); // trimmed to max 64-bit integer + Assert::same([9_223_372_036_854_775_807], Json::decode('[12345678901234567890]')); // trimmed to max 64-bit integer } else { // 32-bit Assert::same(['9223372036854775807'], Json::decode('[12345678901234567890]')); // trimmed to max 64-bit integer diff --git a/tests/Utils/Reflection.expandClassName.phpt b/tests/Utils/Reflection.expandClassName.phpt index 904c1b125..389ff39d3 100644 --- a/tests/Utils/Reflection.expandClassName.phpt +++ b/tests/Utils/Reflection.expandClassName.phpt @@ -140,21 +140,21 @@ foreach ($cases as $alias => $fqn) { Assert::same( ['C' => 'A\B'], - Reflection::getUseStatements(new ReflectionClass('Test')) + Reflection::getUseStatements(new ReflectionClass('Test')), ); Assert::same( [], - Reflection::getUseStatements(new ReflectionClass('Test\Space\Foo')) + Reflection::getUseStatements(new ReflectionClass('Test\Space\Foo')), ); Assert::same( ['AAA' => 'AAA', 'B' => 'BBB', 'DDD' => 'CCC\DDD', 'F' => 'EEE\FFF', 'G' => 'GGG'], - Reflection::getUseStatements(new ReflectionClass('Test\Space\Bar')) + Reflection::getUseStatements(new ReflectionClass('Test\Space\Bar')), ); Assert::same( [], - Reflection::getUseStatements(new ReflectionClass('stdClass')) + Reflection::getUseStatements(new ReflectionClass('stdClass')), ); Assert::exception(function () use ($rcTest) { diff --git a/tests/Utils/Reflection.groupUseStatements.phpt b/tests/Utils/Reflection.groupUseStatements.phpt index 7332b69bd..560985937 100644 --- a/tests/Utils/Reflection.groupUseStatements.phpt +++ b/tests/Utils/Reflection.groupUseStatements.phpt @@ -16,5 +16,5 @@ require __DIR__ . '/fixtures.reflection/expandClass.groupUse.php'; Assert::same( ['A' => 'A\B\A', 'C' => 'A\B\B\C', 'D' => 'A\B\C', 'E' => 'D\E'], - Reflection::getUseStatements(new ReflectionClass('GroupUseTest')) + Reflection::getUseStatements(new ReflectionClass('GroupUseTest')), ); diff --git a/tests/Utils/Reflection.nonClassUseStatements.phpt b/tests/Utils/Reflection.nonClassUseStatements.phpt index c6ce04430..bad5b7ace 100644 --- a/tests/Utils/Reflection.nonClassUseStatements.phpt +++ b/tests/Utils/Reflection.nonClassUseStatements.phpt @@ -16,5 +16,5 @@ require __DIR__ . '/fixtures.reflection/expandClass.nonClassUse.php'; Assert::same( [], - Reflection::getUseStatements(new ReflectionClass('NonClassUseTest')) + Reflection::getUseStatements(new ReflectionClass('NonClassUseTest')), ); diff --git a/tests/Utils/Strings.replace().phpt b/tests/Utils/Strings.replace().phpt index c1b94b504..5dda17322 100644 --- a/tests/Utils/Strings.replace().phpt +++ b/tests/Utils/Strings.replace().phpt @@ -24,7 +24,7 @@ class Test Assert::same('hello world!', Strings::replace('hello world!', '#([E-L])+#', '#')); Assert::same('#o wor#d!', Strings::replace('hello world!', ['#([e-l])+#'], '#')); Assert::same('#o wor#d!', Strings::replace('hello world!', '#([e-l])+#', '#')); -Assert::same('@o wor@d!', Strings::replace('hello world!', '#[e-l]+#', function () { return '@'; })); +Assert::same('@o wor@d!', Strings::replace('hello world!', '#[e-l]+#', fn() => '@')); Assert::same('@o wor@d!', Strings::replace('hello world!', '#[e-l]+#', Closure::fromCallable('Test::cb'))); Assert::same('@o wor@d!', Strings::replace('hello world!', ['#[e-l]+#'], Closure::fromCallable('Test::cb'))); Assert::same('@o wor@d!', Strings::replace('hello world!', '#[e-l]+#', ['Test', 'cb'])); diff --git a/tests/Utils/Type.fromReflection.method.phpt b/tests/Utils/Type.fromReflection.method.phpt index 4d665a2f6..43e0cedad 100644 --- a/tests/Utils/Type.fromReflection.method.phpt +++ b/tests/Utils/Type.fromReflection.method.phpt @@ -35,5 +35,5 @@ $class = new class { }; $type = Type::fromReflection((new ReflectionObject($class))->getMethod('foo')); -Assert::same([get_class($class)], $type->getNames()); -Assert::same(get_class($class), (string) $type); +Assert::same([$class::class], $type->getNames()); +Assert::same($class::class, (string) $type); diff --git a/tests/Utils/fixtures.reflection/defaultValue.php b/tests/Utils/fixtures.reflection/defaultValue.php index 196ab13de..f2e646ad4 100644 --- a/tests/Utils/fixtures.reflection/defaultValue.php +++ b/tests/Utils/fixtures.reflection/defaultValue.php @@ -41,7 +41,7 @@ public function method( $m = DEFINED, $n = UNDEFINED, $o = NS_DEFINED, - $p = parent::PUBLIC_DEFINED + $p = parent::PUBLIC_DEFINED, ) { } } From 0500166d58b30d1801f2903c6a98f95dfe176135 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 12 Mar 2022 05:24:20 +0100 Subject: [PATCH 10/30] coding style: reformatted Assert::exception --- tests/Utils/ArrayHash.phpt | 18 ++- tests/Utils/ArrayList.phpt | 64 +++++--- tests/Utils/Arrays.associate().error.phpt | 8 +- tests/Utils/Arrays.get().phpt | 8 +- tests/Utils/Arrays.getRef().phpt | 10 +- tests/Utils/Arrays.grep().errors.phpt | 20 ++- tests/Utils/Arrays.pick().phpt | 8 +- tests/Utils/Arrays.wrap().phpt | 8 +- tests/Utils/Callback.check.phpt | 34 +++-- tests/Utils/Callback.closure.phpt | 34 +++-- tests/Utils/Callback.invokeSafe.phpt | 21 ++- tests/Utils/DateTime.createFromFormat.phpt | 8 +- tests/Utils/DateTime.fromParts.phpt | 107 +++++++------ tests/Utils/FileSystem.phpt | 88 +++++++---- tests/Utils/Floats.areEqual().phpt | 7 +- tests/Utils/Floats.compare().phpt | 25 +-- tests/Utils/Floats.isGreaterThan().phpt | 7 +- .../Floats.isGreaterThanOrEqualTo().phpt | 7 +- tests/Utils/Floats.isLessThan().phpt | 7 +- tests/Utils/Floats.isLessThanOrEqualTo().phpt | 7 +- tests/Utils/Helpers.capture().phpt | 10 +- tests/Utils/Helpers.clamp().phpt | 8 +- tests/Utils/Image.factories.phpt | 31 ++-- tests/Utils/Image.save.phpt | 20 ++- tests/Utils/Image.send.phpt | 8 +- tests/Utils/Json.decode().phpt | 56 ++++--- tests/Utils/Json.encode().phpt | 16 +- tests/Utils/ObjectHelpers.strictness.phpt | 144 +++++++++++------- tests/Utils/Random.generate().phpt | 18 ++- tests/Utils/Reflection.expandClassName.phpt | 29 ++-- .../Reflection.getParameterDefaultValue.phpt | 39 +++-- .../Utils/Reflection.getParameterType.81.phpt | 24 +-- tests/Utils/Reflection.getParameterType.phpt | 16 +- .../Utils/Reflection.getPropertyType.81.phpt | 26 ++-- tests/Utils/Reflection.getPropertyType.phpt | 18 ++- tests/Utils/Reflection.getReturnType.81.phpt | 46 +++--- tests/Utils/Reflection.getReturnType.phpt | 26 ++-- tests/Utils/SmartObject.events.phpt | 38 +++-- .../SmartObject.property.inheritance.phpt | 48 +++--- tests/Utils/SmartObject.property.phpt | 32 ++-- ...artObject.undeclaredMethod.annotation.phpt | 78 ++++++---- .../SmartObject.undeclaredMethod.hints.phpt | 49 +++--- tests/Utils/SmartObject.undeclaredMethod.phpt | 134 ++++++++-------- tests/Utils/StaticClass.phpt | 18 ++- .../Strings.Regexp.errors.backtrack.phpt | 46 +++--- .../Strings.Regexp.errors.compilation.phpt | 64 +++++--- tests/Utils/Strings.Regexp.errors.utf8.phpt | 46 +++--- tests/Utils/Strings.chr().phpt | 8 +- tests/Utils/Strings.contains().phpt | 8 +- tests/Utils/Strings.endsWith().phpt | 7 +- .../Strings.replace().errors.callback.phpt | 18 +-- tests/Utils/Strings.startsWith().phpt | 7 +- tests/Utils/Strings.toAscii().phpt | 9 +- tests/Utils/Strings.trim().phpt | 8 +- tests/Utils/Strings.webalize().phpt | 9 +- .../Type.fromReflection.function.81.phpt | 2 +- tests/Utils/Validators.assert().phpt | 108 +++++++------ tests/Utils/Validators.assertField().phpt | 23 +-- 58 files changed, 1074 insertions(+), 717 deletions(-) diff --git a/tests/Utils/ArrayHash.phpt b/tests/Utils/ArrayHash.phpt index 4c771efc6..47a9fd7ff 100644 --- a/tests/Utils/ArrayHash.phpt +++ b/tests/Utils/ArrayHash.phpt @@ -182,13 +182,17 @@ test('null fields', function () { test('undeclared fields', function () { $row = new ArrayHash; - Assert::error(function () use ($row) { - $row->undef; - }, PHP_VERSION_ID < 80000 ? E_NOTICE : E_WARNING, 'Undefined property: Nette\Utils\ArrayHash::$undef'); - - Assert::error(function () use ($row) { - $row['undef']; - }, PHP_VERSION_ID < 80000 ? E_NOTICE : E_WARNING, 'Undefined property: Nette\Utils\ArrayHash::$undef'); + Assert::error( + fn() => $row->undef, + PHP_VERSION_ID < 80000 ? E_NOTICE : E_WARNING, + 'Undefined property: Nette\Utils\ArrayHash::$undef', + ); + + Assert::error( + fn() => $row['undef'], + PHP_VERSION_ID < 80000 ? E_NOTICE : E_WARNING, + 'Undefined property: Nette\Utils\ArrayHash::$undef', + ); }); diff --git a/tests/Utils/ArrayList.phpt b/tests/Utils/ArrayList.phpt index 7264424c8..2a60da4d5 100644 --- a/tests/Utils/ArrayList.phpt +++ b/tests/Utils/ArrayList.phpt @@ -32,9 +32,11 @@ class Person test('ArrayList::from', function () { - Assert::exception(function () { - ArrayList::from(['a' => 1, 'b' => 2]); - }, Nette\InvalidArgumentException::class, 'Array is not valid list.'); + Assert::exception( + fn() => ArrayList::from(['a' => 1, 'b' => 2]), + Nette\InvalidArgumentException::class, + 'Array is not valid list.', + ); $mary = new Person('Mary'); $list = ArrayList::from([$mary, 'Jack']); @@ -93,17 +95,23 @@ test('', function () { $list[] = 'a'; $list[] = 'b'; - Assert::exception(function () use ($list) { - $list[-1] = true; - }, OutOfRangeException::class, 'Offset invalid or out of range'); - - Assert::exception(function () use ($list) { - $list[2] = true; - }, OutOfRangeException::class, 'Offset invalid or out of range'); - - Assert::exception(function () use ($list) { - $list['key'] = true; - }, OutOfRangeException::class, 'Offset invalid or out of range'); + Assert::exception( + fn() => $list[-1] = true, + OutOfRangeException::class, + 'Offset invalid or out of range', + ); + + Assert::exception( + fn() => $list[2] = true, + OutOfRangeException::class, + 'Offset invalid or out of range', + ); + + Assert::exception( + fn() => $list['key'] = true, + OutOfRangeException::class, + 'Offset invalid or out of range', + ); }); @@ -112,17 +120,23 @@ test('', function () { $list[] = 'a'; $list[] = 'b'; - Assert::exception(function () use ($list) { - $tmp = $list[-1]; - }, OutOfRangeException::class, 'Offset invalid or out of range'); - - Assert::exception(function () use ($list) { - $tmp = $list[2]; - }, OutOfRangeException::class, 'Offset invalid or out of range'); - - Assert::exception(function () use ($list) { - $tmp = $list['key']; - }, OutOfRangeException::class, 'Offset invalid or out of range'); + Assert::exception( + fn() => $list[-1], + OutOfRangeException::class, + 'Offset invalid or out of range', + ); + + Assert::exception( + fn() => $list[2], + OutOfRangeException::class, + 'Offset invalid or out of range', + ); + + Assert::exception( + fn() => $list['key'], + OutOfRangeException::class, + 'Offset invalid or out of range', + ); }); diff --git a/tests/Utils/Arrays.associate().error.phpt b/tests/Utils/Arrays.associate().error.phpt index b1b441772..ab03b6471 100644 --- a/tests/Utils/Arrays.associate().error.phpt +++ b/tests/Utils/Arrays.associate().error.phpt @@ -14,7 +14,9 @@ require __DIR__ . '/../bootstrap.php'; foreach (['', '=', '=age', '=>', '|', '|name'] as $path) { - Assert::exception(function () use ($path) { - Arrays::associate([], $path); - }, Nette\InvalidArgumentException::class, "Invalid path '$path'."); + Assert::exception( + fn() => Arrays::associate([], $path), + Nette\InvalidArgumentException::class, + "Invalid path '$path'.", + ); } diff --git a/tests/Utils/Arrays.get().phpt b/tests/Utils/Arrays.get().phpt index 277af3bf3..9b4e7d7c9 100644 --- a/tests/Utils/Arrays.get().phpt +++ b/tests/Utils/Arrays.get().phpt @@ -26,9 +26,11 @@ test('Single item', function () use ($arr) { Assert::same('second', Arrays::get($arr, 1)); Assert::same('second', Arrays::get($arr, 1, 'x')); Assert::same('x', Arrays::get($arr, 'undefined', 'x')); - Assert::exception(function () use ($arr) { - Arrays::get($arr, 'undefined'); - }, Nette\InvalidArgumentException::class, "Missing item 'undefined'."); + Assert::exception( + fn() => Arrays::get($arr, 'undefined'), + Nette\InvalidArgumentException::class, + "Missing item 'undefined'.", + ); }); diff --git a/tests/Utils/Arrays.getRef().phpt b/tests/Utils/Arrays.getRef().phpt index ad242bb90..4d4e80fad 100644 --- a/tests/Utils/Arrays.getRef().phpt +++ b/tests/Utils/Arrays.getRef().phpt @@ -69,8 +69,10 @@ test('Traversing', function () use ($arr) { test('Error', function () use ($arr) { - Assert::exception(function () use ($arr) { - $dolly = $arr; - $item = &Arrays::getRef($dolly, [7, 'item', 3]); - }, InvalidArgumentException::class, 'Traversed item is not an array.'); + $dolly = $arr; + Assert::exception( + fn() => $item = &Arrays::getRef($dolly, [7, 'item', 3]), + InvalidArgumentException::class, + 'Traversed item is not an array.', + ); }); diff --git a/tests/Utils/Arrays.grep().errors.phpt b/tests/Utils/Arrays.grep().errors.phpt index 791bffa39..89ea411ff 100644 --- a/tests/Utils/Arrays.grep().errors.phpt +++ b/tests/Utils/Arrays.grep().errors.phpt @@ -13,11 +13,15 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -Assert::exception(function () { - Arrays::grep(['a', '1', 'c'], '#*#'); -}, Nette\Utils\RegexpException::class, 'Compilation failed: %a% in pattern: #*#'); - - -Assert::exception(function () { - Arrays::grep(['a', "1\xFF", 'c'], '#\d#u'); -}, Nette\Utils\RegexpException::class, 'Malformed UTF-8 data (pattern: #\d#u)'); +Assert::exception( + fn() => Arrays::grep(['a', '1', 'c'], '#*#'), + Nette\Utils\RegexpException::class, + 'Compilation failed: %a% in pattern: #*#', +); + + +Assert::exception( + fn() => Arrays::grep(['a', "1\xFF", 'c'], '#\d#u'), + Nette\Utils\RegexpException::class, + 'Malformed UTF-8 data (pattern: #\d#u)', +); diff --git a/tests/Utils/Arrays.pick().phpt b/tests/Utils/Arrays.pick().phpt index b81ea0d89..458d8a025 100644 --- a/tests/Utils/Arrays.pick().phpt +++ b/tests/Utils/Arrays.pick().phpt @@ -23,8 +23,10 @@ test('Single item', function () use ($arr) { Assert::same('null', Arrays::pick($arr, null)); Assert::same('first', Arrays::pick($arr, 1)); Assert::same('x', Arrays::pick($arr, 1, 'x')); - Assert::exception(function () use ($arr) { - Arrays::pick($arr, 'undefined'); - }, Nette\InvalidArgumentException::class, "Missing item 'undefined'."); + Assert::exception( + fn() => Arrays::pick($arr, 'undefined'), + Nette\InvalidArgumentException::class, + "Missing item 'undefined'.", + ); Assert::same([2 => 'second'], $arr); }); diff --git a/tests/Utils/Arrays.wrap().phpt b/tests/Utils/Arrays.wrap().phpt index e16ce3c0f..83c530316 100644 --- a/tests/Utils/Arrays.wrap().phpt +++ b/tests/Utils/Arrays.wrap().phpt @@ -40,7 +40,9 @@ test('Type conversion', function () { ]; Assert::same(array_column($cases, 1), Arrays::wrap(array_column($cases, 0))); - Assert::error(function () { - Arrays::wrap([[]]); - }, PHP_VERSION_ID < 80000 ? E_NOTICE : E_WARNING, 'Array to string conversion'); + Assert::error( + fn() => Arrays::wrap([[]]), + PHP_VERSION_ID < 80000 ? E_NOTICE : E_WARNING, + 'Array to string conversion', + ); }); diff --git a/tests/Utils/Callback.check.phpt b/tests/Utils/Callback.check.phpt index d5af066a9..8205baa5c 100644 --- a/tests/Utils/Callback.check.phpt +++ b/tests/Utils/Callback.check.phpt @@ -18,21 +18,29 @@ Assert::same('trim', Callback::check('trim')); Assert::same('undefined', Callback::check('undefined', true)); -Assert::exception(function () { - Callback::check(123, true); -}, Nette\InvalidArgumentException::class, 'Given value is not a callable type.'); +Assert::exception( + fn() => Callback::check(123, true), + Nette\InvalidArgumentException::class, + 'Given value is not a callable type.', +); -Assert::exception(function () { - Callback::check('undefined'); -}, Nette\InvalidArgumentException::class, "Callback 'undefined' is not callable."); +Assert::exception( + fn() => Callback::check('undefined'), + Nette\InvalidArgumentException::class, + "Callback 'undefined' is not callable.", +); // PHP bugs - is_callable($object, true) fails -Assert::exception(function () { - Callback::check(new stdClass); -}, Nette\InvalidArgumentException::class, "Callback 'stdClass::__invoke' is not callable."); - -Assert::exception(function () { - Callback::check(new stdClass, true); -}, Nette\InvalidArgumentException::class, 'Given value is not a callable type.'); +Assert::exception( + fn() => Callback::check(new stdClass), + Nette\InvalidArgumentException::class, + "Callback 'stdClass::__invoke' is not callable.", +); + +Assert::exception( + fn() => Callback::check(new stdClass, true), + Nette\InvalidArgumentException::class, + 'Given value is not a callable type.', +); diff --git a/tests/Utils/Callback.closure.phpt b/tests/Utils/Callback.closure.phpt index 1495b970c..9655dd3e1 100644 --- a/tests/Utils/Callback.closure.phpt +++ b/tests/Utils/Callback.closure.phpt @@ -105,9 +105,11 @@ test('global function', function () { Assert::same('undefined', Callback::toString('undefined')); - Assert::exception(function () { - Callback::toReflection('undefined'); - }, ReflectionException::class, 'Function undefined() does not exist'); + Assert::exception( + fn() => Callback::toReflection('undefined'), + ReflectionException::class, + 'Function undefined() does not exist', + ); }); @@ -207,20 +209,26 @@ test('magic methods', function () { Assert::same('{closure TestDynamic::magic}', Callback::toString(Closure::fromCallable('TestDynamic::magic'))); Assert::same('TestDynamic::__callStatic magic *', Closure::fromCallable('TestDynamic::magic')->__invoke('*')); - Assert::exception(function () { - Callback::toReflection([new TestDynamic, 'magic']); - }, ReflectionException::class, 'Method TestDynamic::magic() does not exist'); - - Assert::exception(function () { - Callback::toReflection(Closure::fromCallable([new TestDynamic, 'magic'])); - }, ReflectionException::class, 'Method TestDynamic::magic() does not exist'); + Assert::exception( + fn() => Callback::toReflection([new TestDynamic, 'magic']), + ReflectionException::class, + 'Method TestDynamic::magic() does not exist', + ); + + Assert::exception( + fn() => Callback::toReflection(Closure::fromCallable([new TestDynamic, 'magic'])), + ReflectionException::class, + 'Method TestDynamic::magic() does not exist', + ); }); test('PHP bugs - is_callable($object, true) fails', function () { Assert::same('stdClass::__invoke', Callback::toString(new stdClass)); - Assert::exception(function () { - Callback::toReflection(new stdClass); - }, ReflectionException::class, 'Method stdClass::__invoke() does not exist'); + Assert::exception( + fn() => Callback::toReflection(new stdClass), + ReflectionException::class, + 'Method stdClass::__invoke() does not exist', + ); }); diff --git a/tests/Utils/Callback.invokeSafe.phpt b/tests/Utils/Callback.invokeSafe.phpt index b9d34c8a9..41b395254 100644 --- a/tests/Utils/Callback.invokeSafe.phpt +++ b/tests/Utils/Callback.invokeSafe.phpt @@ -36,11 +36,14 @@ Assert::match('preg_match(): Delimiter must not be alphanumeric%a%', $res); // error -> exception -Assert::exception(function () { - Callback::invokeSafe('preg_match', ['ab', 'foo'], function ($message, $severity) { +Assert::exception( + fn() => Callback::invokeSafe('preg_match', ['ab', 'foo'], function ($message, $severity) { throw new Exception($message, $severity); - }); -}, 'Exception', 'Delimiter must not be alphanumeric%a%', E_WARNING); + }), + 'Exception', + 'Delimiter must not be alphanumeric%a%', + E_WARNING, +); trigger_error('OK2', E_USER_WARNING); Assert::same('OK2', $res); @@ -57,11 +60,13 @@ Assert::same(PHP_VERSION_ID < 80000 ? 'Undefined variable: a' : 'Undefined varia // exception inside -Assert::exception(function () { - Callback::invokeSafe('preg_replace_callback', ['#.#', function () { +Assert::exception( + fn() => Callback::invokeSafe('preg_replace_callback', ['#.#', function () { throw new Exception('in callback'); - }, 'x'], function () {}); -}, 'Exception', 'in callback'); + }, 'x'], function () {}), + 'Exception', + 'in callback', +); trigger_error('OK3', E_USER_WARNING); Assert::same('OK3', $res); diff --git a/tests/Utils/DateTime.createFromFormat.phpt b/tests/Utils/DateTime.createFromFormat.phpt index 08ffdd709..04bfc3aa7 100644 --- a/tests/Utils/DateTime.createFromFormat.phpt +++ b/tests/Utils/DateTime.createFromFormat.phpt @@ -22,8 +22,10 @@ Assert::same('2050-08-13 11:40:00.123450', DateTime::createFromFormat('Y-m-d H:i Assert::same('Europe/Prague', DateTime::createFromFormat('Y', '2050')->getTimezone()->getName()); Assert::same('Europe/Bratislava', DateTime::createFromFormat('Y', '2050', 'Europe/Bratislava')->getTimezone()->getName()); -Assert::error(function () { - DateTime::createFromFormat('Y-m-d H:i:s', '2050-08-13 11:40:00', 5); -}, Nette\InvalidArgumentException::class, 'Invalid timezone given'); +Assert::exception( + fn() => DateTime::createFromFormat('Y-m-d H:i:s', '2050-08-13 11:40:00', 5), + Nette\InvalidArgumentException::class, + 'Invalid timezone given', +); Assert::false(DateTime::createFromFormat('Y-m-d', '2014-10')); diff --git a/tests/Utils/DateTime.fromParts.phpt b/tests/Utils/DateTime.fromParts.phpt index 8c4512a4d..c69831bc3 100644 --- a/tests/Utils/DateTime.fromParts.phpt +++ b/tests/Utils/DateTime.fromParts.phpt @@ -23,50 +23,63 @@ Assert::same('1985-12-09 01:02:03.000000', DateTime::fromParts(1985, 12, 9, 1, 2 Assert::same('1985-12-09 11:22:33.000000', DateTime::fromParts(1985, 12, 9, 11, 22, 33)->format('Y-m-d H:i:s.u')); Assert::same('1985-12-09 11:22:59.123000', DateTime::fromParts(1985, 12, 9, 11, 22, 59.123)->format('Y-m-d H:i:s.u')); -Assert::exception(function () { - DateTime::fromParts(1985, 2, 29); -}, Nette\InvalidArgumentException::class, "Invalid date '1985-02-29 00:00:0.00000'"); - -Assert::exception(function () { // year must be at least 1 due to limitation of checkdate() - DateTime::fromParts(0, 12, 9); -}, Nette\InvalidArgumentException::class); - -Assert::exception(function () { - DateTime::fromParts(1985, 0, 9); -}, Nette\InvalidArgumentException::class); - -Assert::exception(function () { - DateTime::fromParts(1985, 13, 9); -}, Nette\InvalidArgumentException::class); - -Assert::exception(function () { - DateTime::fromParts(1985, 12, 0); -}, Nette\InvalidArgumentException::class); - -Assert::exception(function () { - DateTime::fromParts(1985, 12, 32); -}, Nette\InvalidArgumentException::class); - -Assert::exception(function () { - DateTime::fromParts(1985, 12, 9, -1); -}, Nette\InvalidArgumentException::class); - -Assert::exception(function () { - DateTime::fromParts(1985, 12, 9, 60); -}, Nette\InvalidArgumentException::class); - -Assert::exception(function () { - DateTime::fromParts(1985, 12, 9, 0, -1); -}, Nette\InvalidArgumentException::class); - -Assert::exception(function () { - DateTime::fromParts(1985, 12, 9, 0, 60); -}, Nette\InvalidArgumentException::class); - -Assert::exception(function () { - DateTime::fromParts(1985, 12, 9, 0, 0, -1); -}, Nette\InvalidArgumentException::class); - -Assert::exception(function () { - DateTime::fromParts(1985, 12, 9, 0, 0, 60); -}, Nette\InvalidArgumentException::class); +Assert::exception( + fn() => DateTime::fromParts(1985, 2, 29), + Nette\InvalidArgumentException::class, + "Invalid date '1985-02-29 00:00:0.00000'", +); + +Assert::exception( + fn() => DateTime::fromParts(0, 12, 9), + Nette\InvalidArgumentException::class, +); + +Assert::exception( + fn() => DateTime::fromParts(1985, 0, 9), + Nette\InvalidArgumentException::class, +); + +Assert::exception( + fn() => DateTime::fromParts(1985, 13, 9), + Nette\InvalidArgumentException::class, +); + +Assert::exception( + fn() => DateTime::fromParts(1985, 12, 0), + Nette\InvalidArgumentException::class, +); + +Assert::exception( + fn() => DateTime::fromParts(1985, 12, 32), + Nette\InvalidArgumentException::class, +); + +Assert::exception( + fn() => DateTime::fromParts(1985, 12, 9, -1), + Nette\InvalidArgumentException::class, +); + +Assert::exception( + fn() => DateTime::fromParts(1985, 12, 9, 60), + Nette\InvalidArgumentException::class, +); + +Assert::exception( + fn() => DateTime::fromParts(1985, 12, 9, 0, -1), + Nette\InvalidArgumentException::class, +); + +Assert::exception( + fn() => DateTime::fromParts(1985, 12, 9, 0, 60), + Nette\InvalidArgumentException::class, +); + +Assert::exception( + fn() => DateTime::fromParts(1985, 12, 9, 0, 0, -1), + Nette\InvalidArgumentException::class, +); + +Assert::exception( + fn() => DateTime::fromParts(1985, 12, 9, 0, 0, 60), + Nette\InvalidArgumentException::class, +); diff --git a/tests/Utils/FileSystem.phpt b/tests/Utils/FileSystem.phpt index 4093898c4..cc78af86b 100644 --- a/tests/Utils/FileSystem.phpt +++ b/tests/Utils/FileSystem.phpt @@ -46,9 +46,11 @@ test('createDir', function () { FileSystem::createDir(getTempDir() . '/1/'); }); -Assert::exception(function () { - FileSystem::createDir(''); -}, Nette\IOException::class, "Unable to create directory '' with mode 777.%A%"); +Assert::exception( + fn() => FileSystem::createDir(''), + Nette\IOException::class, + "Unable to create directory '' with mode 777.%A%", +); test('write + read', function () { @@ -57,13 +59,17 @@ test('write + read', function () { Assert::same('Hello', FileSystem::read(getTempDir() . '/2/file')); }); -Assert::exception(function () { - FileSystem::write('', 'Hello'); -}, Nette\IOException::class, "Unable to create directory '' with mode 777.%A%"); +Assert::exception( + fn() => FileSystem::write('', 'Hello'), + Nette\IOException::class, + "Unable to create directory '' with mode 777.%A%", +); -Assert::exception(function () { - FileSystem::read('missing'); -}, Nette\IOException::class, "Unable to read file 'missing'. %a%"); +Assert::exception( + fn() => FileSystem::read('missing'), + Nette\IOException::class, + "Unable to read file 'missing'. %a%", +); test('copy', function () { @@ -79,22 +85,28 @@ test('copy', function () { FileSystem::write(getTempDir() . '/5/newfile', 'World'); - Assert::exception(function () { - FileSystem::copy(getTempDir() . '/5/newfile', getTempDir() . '/3/x/file', false); - }, Nette\InvalidStateException::class, "File or directory '%a%' already exists."); + Assert::exception( + fn() => FileSystem::copy(getTempDir() . '/5/newfile', getTempDir() . '/3/x/file', false), + Nette\InvalidStateException::class, + "File or directory '%a%' already exists.", + ); Assert::same('Hello', FileSystem::read(getTempDir() . '/3/x/file')); - Assert::exception(function () { - FileSystem::copy('remote://example.com', getTempDir() . '/3/x/file', false); - }, Nette\InvalidStateException::class, "File or directory '%a%' already exists."); + Assert::exception( + fn() => FileSystem::copy('remote://example.com', getTempDir() . '/3/x/file', false), + Nette\InvalidStateException::class, + "File or directory '%a%' already exists.", + ); Assert::same('Hello', FileSystem::read(getTempDir() . '/3/x/file')); FileSystem::copy(getTempDir() . '/5/newfile', getTempDir() . '/3/x/file'); Assert::same('World', FileSystem::read(getTempDir() . '/3/x/file')); - Assert::exception(function () { - FileSystem::copy(getTempDir() . '/5', getTempDir() . '/3', false); - }, Nette\InvalidStateException::class, "File or directory '%a%' already exists."); + Assert::exception( + fn() => FileSystem::copy(getTempDir() . '/5', getTempDir() . '/3', false), + Nette\InvalidStateException::class, + "File or directory '%a%' already exists.", + ); Assert::true(is_dir(getTempDir() . '/3/x/y')); Assert::false(file_exists(getTempDir() . '/3/newfile')); @@ -103,9 +115,11 @@ test('copy', function () { Assert::true(is_file(getTempDir() . '/3/newfile')); }); -Assert::exception(function () { - FileSystem::copy(getTempDir() . '/6', getTempDir() . '/3'); -}, Nette\IOException::class, "File or directory '%S%' not found."); +Assert::exception( + fn() => FileSystem::copy(getTempDir() . '/6', getTempDir() . '/3'), + Nette\IOException::class, + "File or directory '%S%' not found.", +); test('delete', function () { @@ -126,17 +140,21 @@ test('rename', function () { Assert::same('Hello', FileSystem::read(getTempDir() . '/9/x/file')); FileSystem::write(getTempDir() . '/8/newfile', 'World'); - Assert::exception(function () { - FileSystem::rename(getTempDir() . '/8/newfile', getTempDir() . '/9/x/file', false); - }, Nette\InvalidStateException::class, "File or directory '%a%' already exists."); + Assert::exception( + fn() => FileSystem::rename(getTempDir() . '/8/newfile', getTempDir() . '/9/x/file', false), + Nette\InvalidStateException::class, + "File or directory '%a%' already exists.", + ); Assert::same('Hello', FileSystem::read(getTempDir() . '/9/x/file')); FileSystem::rename(getTempDir() . '/8/newfile', getTempDir() . '/9/x/file'); Assert::same('World', FileSystem::read(getTempDir() . '/9/x/file')); FileSystem::createDir(getTempDir() . '/10/'); - Assert::exception(function () { - FileSystem::rename(getTempDir() . '/10', getTempDir() . '/9', false); - }, Nette\InvalidStateException::class, "File or directory '%a%' already exists."); + Assert::exception( + fn() => FileSystem::rename(getTempDir() . '/10', getTempDir() . '/9', false), + Nette\InvalidStateException::class, + "File or directory '%a%' already exists.", + ); Assert::same('World', FileSystem::read(getTempDir() . '/9/x/file')); FileSystem::rename(getTempDir() . '/10', getTempDir() . '/9'); @@ -150,9 +168,11 @@ test('rename', function () { Assert::true(file_exists(getTempDir() . '/11')); }); -Assert::exception(function () { - FileSystem::rename(getTempDir() . '/10', getTempDir() . '/9'); -}, Nette\IOException::class, "File or directory '%S%' not found."); +Assert::exception( + fn() => FileSystem::rename(getTempDir() . '/10', getTempDir() . '/9'), + Nette\IOException::class, + "File or directory '%S%' not found.", +); test('isAbsolute', function () { @@ -186,6 +206,8 @@ if (!defined('PHP_WINDOWS_VERSION_BUILD')) { }); } -Assert::exception(function () { - FileSystem::makeWritable(getTempDir() . '/13'); -}, Nette\IOException::class, "File or directory '%S%' not found."); +Assert::exception( + fn() => FileSystem::makeWritable(getTempDir() . '/13'), + Nette\IOException::class, + "File or directory '%S%' not found.", +); diff --git a/tests/Utils/Floats.areEqual().phpt b/tests/Utils/Floats.areEqual().phpt index 56b63027f..283ba6ced 100644 --- a/tests/Utils/Floats.areEqual().phpt +++ b/tests/Utils/Floats.areEqual().phpt @@ -36,6 +36,7 @@ Assert::true(Floats::areEqual(INF, INF)); Assert::false(Floats::areEqual(INF, -INF)); Assert::false(Floats::areEqual(-INF, INF)); -Assert::exception(function () { - Floats::areEqual(NAN, NAN); -}, LogicException::class); +Assert::exception( + fn() => Floats::areEqual(NAN, NAN), + LogicException::class, +); diff --git a/tests/Utils/Floats.compare().phpt b/tests/Utils/Floats.compare().phpt index 1694ebdc1..7ce566368 100644 --- a/tests/Utils/Floats.compare().phpt +++ b/tests/Utils/Floats.compare().phpt @@ -24,14 +24,17 @@ Assert::same(-1, Floats::compare(20, 30)); Assert::same(1, Floats::compare(-20, -30)); Assert::same(-1, Floats::compare(-50, -30)); -Assert::exception(function () { - Floats::compare(NAN, -30); -}, LogicException::class); - -Assert::exception(function () { - Floats::compare(6, NAN); -}, LogicException::class); - -Assert::exception(function () { - Floats::compare(NAN, NAN); -}, LogicException::class); +Assert::exception( + fn() => Floats::compare(NAN, -30), + LogicException::class, +); + +Assert::exception( + fn() => Floats::compare(6, NAN), + LogicException::class, +); + +Assert::exception( + fn() => Floats::compare(NAN, NAN), + LogicException::class, +); diff --git a/tests/Utils/Floats.isGreaterThan().phpt b/tests/Utils/Floats.isGreaterThan().phpt index 7f6a99f2f..7d524cd28 100644 --- a/tests/Utils/Floats.isGreaterThan().phpt +++ b/tests/Utils/Floats.isGreaterThan().phpt @@ -27,6 +27,7 @@ Assert::true(Floats::isGreaterThan(INF, -INF)); Assert::false(Floats::isGreaterThan(INF, INF)); Assert::false(Floats::isGreaterThan(-INF, INF)); -Assert::exception(function () { - Floats::isGreaterThan(NAN, NAN); -}, LogicException::class); +Assert::exception( + fn() => Floats::isGreaterThan(NAN, NAN), + LogicException::class, +); diff --git a/tests/Utils/Floats.isGreaterThanOrEqualTo().phpt b/tests/Utils/Floats.isGreaterThanOrEqualTo().phpt index 3e6802a00..089441ead 100644 --- a/tests/Utils/Floats.isGreaterThanOrEqualTo().phpt +++ b/tests/Utils/Floats.isGreaterThanOrEqualTo().phpt @@ -27,6 +27,7 @@ Assert::true(Floats::isGreaterThanOrEqualTo(INF, INF)); Assert::true(Floats::isGreaterThanOrEqualTo(INF, -INF)); Assert::false(Floats::isGreaterThanOrEqualTo(-INF, INF)); -Assert::exception(function () { - Floats::isGreaterThanOrEqualTo(NAN, NAN); -}, LogicException::class); +Assert::exception( + fn() => Floats::isGreaterThanOrEqualTo(NAN, NAN), + LogicException::class, +); diff --git a/tests/Utils/Floats.isLessThan().phpt b/tests/Utils/Floats.isLessThan().phpt index 40dfb0bc4..fd36b829c 100644 --- a/tests/Utils/Floats.isLessThan().phpt +++ b/tests/Utils/Floats.isLessThan().phpt @@ -27,6 +27,7 @@ Assert::true(Floats::isLessThan(-INF, INF)); Assert::false(Floats::isLessThan(INF, INF)); Assert::false(Floats::isLessThan(INF, -INF)); -Assert::exception(function () { - Floats::isLessThan(NAN, NAN); -}, LogicException::class); +Assert::exception( + fn() => Floats::isLessThan(NAN, NAN), + LogicException::class, +); diff --git a/tests/Utils/Floats.isLessThanOrEqualTo().phpt b/tests/Utils/Floats.isLessThanOrEqualTo().phpt index 6877e0b41..bc9f1e11b 100644 --- a/tests/Utils/Floats.isLessThanOrEqualTo().phpt +++ b/tests/Utils/Floats.isLessThanOrEqualTo().phpt @@ -27,6 +27,7 @@ Assert::true(Floats::isLessThanOrEqualTo(-INF, INF)); Assert::true(Floats::isLessThanOrEqualTo(INF, INF)); Assert::false(Floats::isLessThanOrEqualTo(INF, -INF)); -Assert::exception(function () { - Floats::isLessThanOrEqualTo(NAN, NAN); -}, LogicException::class); +Assert::exception( + fn() => Floats::isLessThanOrEqualTo(NAN, NAN), + LogicException::class, +); diff --git a/tests/Utils/Helpers.capture().phpt b/tests/Utils/Helpers.capture().phpt index 1e18f21cc..048e0567b 100644 --- a/tests/Utils/Helpers.capture().phpt +++ b/tests/Utils/Helpers.capture().phpt @@ -16,10 +16,10 @@ Assert::same('hello', Helpers::capture(function () { echo 'hello'; })); $level = ob_get_level(); -Assert::exception(function () { - Helpers::capture(function () { - undefined(); - }); -}, Error::class, 'Call to undefined function undefined()'); +Assert::exception( + fn() => Helpers::capture(fn() => undefined()), + Error::class, + 'Call to undefined function undefined()', +); Assert::same($level, ob_get_level()); diff --git a/tests/Utils/Helpers.clamp().phpt b/tests/Utils/Helpers.clamp().phpt index 4128e52eb..490f3531f 100644 --- a/tests/Utils/Helpers.clamp().phpt +++ b/tests/Utils/Helpers.clamp().phpt @@ -14,6 +14,8 @@ Assert::same(21, Helpers::clamp(20, 21, 30)); Assert::same(19, Helpers::clamp(20, 10, 19)); Assert::same(19.0, Helpers::clamp(20.0, 10.0, 19.0)); -Assert::exception(function () { - Helpers::clamp(20, 30, 10); -}, InvalidArgumentException::class, 'Minimum (30) is not less than maximum (10).'); +Assert::exception( + fn() => Helpers::clamp(20, 30, 10), + InvalidArgumentException::class, + 'Minimum (30) is not less than maximum (10).', +); diff --git a/tests/Utils/Image.factories.phpt b/tests/Utils/Image.factories.phpt index 1ec081b29..66e96374e 100644 --- a/tests/Utils/Image.factories.phpt +++ b/tests/Utils/Image.factories.phpt @@ -50,22 +50,28 @@ test('', function () { }); -Assert::exception(function () { - Image::fromFile('fixtures.images/missing.png'); -}, Nette\Utils\UnknownImageFileException::class, "File 'fixtures.images/missing.png' not found."); +Assert::exception( + fn() => Image::fromFile('fixtures.images/missing.png'), + Nette\Utils\UnknownImageFileException::class, + "File 'fixtures.images/missing.png' not found.", +); Assert::null(Image::detectTypeFromFile('fixtures.images/missing.png')); -Assert::exception(function () { - Image::fromFile(__DIR__ . '/fixtures.images/logo.tiff'); -}, Nette\Utils\UnknownImageFileException::class, "Unknown type of file '%a%fixtures.images/logo.tiff'."); +Assert::exception( + fn() => Image::fromFile(__DIR__ . '/fixtures.images/logo.tiff'), + Nette\Utils\UnknownImageFileException::class, + "Unknown type of file '%a%fixtures.images/logo.tiff'.", +); -Assert::exception(function () { - Image::fromFile(__DIR__ . '/fixtures.images/bad.gif'); -}, Nette\Utils\ImageException::class, '%a% not a valid GIF file'); +Assert::exception( + fn() => Image::fromFile(__DIR__ . '/fixtures.images/bad.gif'), + Nette\Utils\ImageException::class, + '%a% not a valid GIF file', +); test('', function () { @@ -87,9 +93,10 @@ test('', function () { }); -Assert::exception(function () { - Image::fromString('abcdefg'); -}, Nette\Utils\UnknownImageFileException::class); +Assert::exception( + fn() => Image::fromString('abcdefg'), + Nette\Utils\UnknownImageFileException::class, +); Assert::null(Image::detectTypeFromString('x')); diff --git a/tests/Utils/Image.save.phpt b/tests/Utils/Image.save.phpt index acb88ef8f..7c0546355 100644 --- a/tests/Utils/Image.save.phpt +++ b/tests/Utils/Image.save.phpt @@ -76,11 +76,15 @@ test('', function () use ($main) { }); -Assert::exception(function () use ($main) { // invalid image type - $main->save('foo', null, IMG_WBMP); -}, Nette\InvalidArgumentException::class, sprintf('Unsupported image type \'%d\'.', IMG_WBMP)); - - -Assert::exception(function () use ($main) { // invalid file extension - $main->save('foo.psd'); -}, Nette\InvalidArgumentException::class, 'Unsupported file extension \'psd\'.'); +Assert::exception( + fn() => $main->save('foo', null, IMG_WBMP), + Nette\InvalidArgumentException::class, + sprintf('Unsupported image type \'%d\'.', IMG_WBMP), +); + + +Assert::exception( + fn() => $main->save('foo.psd'), + Nette\InvalidArgumentException::class, + 'Unsupported file extension \'psd\'.', +); diff --git a/tests/Utils/Image.send.phpt b/tests/Utils/Image.send.phpt index 7f4df714f..e20634c1e 100644 --- a/tests/Utils/Image.send.phpt +++ b/tests/Utils/Image.send.phpt @@ -57,6 +57,8 @@ test('', function () use ($main) { }); -Assert::exception(function () use ($main) { // invalid image type - $main->send(IMG_WBMP); -}, Nette\InvalidArgumentException::class, sprintf('Unsupported image type \'%d\'.', IMG_WBMP)); +Assert::exception( + fn() => $main->send(IMG_WBMP), + Nette\InvalidArgumentException::class, + sprintf('Unsupported image type \'%d\'.', IMG_WBMP), +); diff --git a/tests/Utils/Json.decode().phpt b/tests/Utils/Json.decode().phpt index e3ac443c9..1f71fad08 100644 --- a/tests/Utils/Json.decode().phpt +++ b/tests/Utils/Json.decode().phpt @@ -22,34 +22,46 @@ Assert::equal((object) ['a' => 1], Json::decode('{"a":1}')); Assert::same(['a' => 1], Json::decode('{"a":1}', Json::FORCE_ARRAY)); -Assert::exception(function () { - Json::decode(''); -}, Nette\Utils\JsonException::class, 'Syntax error'); +Assert::exception( + fn() => Json::decode(''), + Nette\Utils\JsonException::class, + 'Syntax error', +); -Assert::exception(function () { - Json::decode('NULL'); -}, Nette\Utils\JsonException::class, 'Syntax error'); +Assert::exception( + fn() => Json::decode('NULL'), + Nette\Utils\JsonException::class, + 'Syntax error', +); -Assert::exception(function () { - Json::decode('{'); -}, Nette\Utils\JsonException::class, 'Syntax error'); +Assert::exception( + fn() => Json::decode('{'), + Nette\Utils\JsonException::class, + 'Syntax error', +); -Assert::exception(function () { - Json::decode('{}}'); -}, Nette\Utils\JsonException::class, 'Syntax error'); +Assert::exception( + fn() => Json::decode('{}}'), + Nette\Utils\JsonException::class, + 'Syntax error', +); -Assert::exception(function () { - Json::decode("\x00"); -}, Nette\Utils\JsonException::class, defined('JSON_C_VERSION') ? 'Syntax error' : 'Control character error, possibly incorrectly encoded'); +Assert::exception( + fn() => Json::decode("\x00"), + Nette\Utils\JsonException::class, + defined('JSON_C_VERSION') ? 'Syntax error' : 'Control character error, possibly incorrectly encoded', +); -Assert::exception(function () { - Json::decode('{"\u0000": 1}'); -}, Nette\Utils\JsonException::class, 'The decoded property name is invalid'); +Assert::exception( + fn() => Json::decode('{"\u0000": 1}'), + Nette\Utils\JsonException::class, + 'The decoded property name is invalid', +); Assert::same(["\x00" => 1], Json::decode('{"\u0000": 1}', Json::FORCE_ARRAY)); @@ -57,9 +69,11 @@ Assert::equal((object) ['a' => "\x00"], Json::decode('{"a": "\u0000"}')); Assert::equal((object) ["\"\x00" => 1], Json::decode('{"\"\u0000": 1}')); -Assert::exception(function () { - Json::decode("\"\xC1\xBF\""); -}, Nette\Utils\JsonException::class, 'Malformed UTF-8 characters, possibly incorrectly encoded'); +Assert::exception( + fn() => Json::decode("\"\xC1\xBF\""), + Nette\Utils\JsonException::class, + 'Malformed UTF-8 characters, possibly incorrectly encoded', +); // default JSON_BIGINT_AS_STRING diff --git a/tests/Utils/Json.encode().phpt b/tests/Utils/Json.encode().phpt index 888accbf4..bf2c02d97 100644 --- a/tests/Utils/Json.encode().phpt +++ b/tests/Utils/Json.encode().phpt @@ -16,9 +16,11 @@ require __DIR__ . '/../bootstrap.php'; Assert::same('"ok"', Json::encode('ok')); -Assert::exception(function () { - Json::encode(["bad utf\xFF"]); -}, Nette\Utils\JsonException::class, 'Malformed UTF-8 characters, possibly incorrectly encoded'); +Assert::exception( + fn() => Json::encode(["bad utf\xFF"]), + Nette\Utils\JsonException::class, + 'Malformed UTF-8 characters, possibly incorrectly encoded', +); Assert::exception(function () { @@ -42,9 +44,11 @@ Assert::same('"\u2028\u2029"', Json::encode("\u{2028}\u{2029}", Json::ESCAPE_UNI Assert::same("[\n 1,\n 2,\n 3\n]", Json::encode([1, 2, 3], Json::PRETTY)); -Assert::exception(function () { - Json::encode(NAN); -}, Nette\Utils\JsonException::class, 'Inf and NaN cannot be JSON encoded'); +Assert::exception( + fn() => Json::encode(NAN), + Nette\Utils\JsonException::class, + 'Inf and NaN cannot be JSON encoded', +); // JSON_PRESERVE_ZERO_FRACTION diff --git a/tests/Utils/ObjectHelpers.strictness.phpt b/tests/Utils/ObjectHelpers.strictness.phpt index 417ecd745..ac0dba9c7 100644 --- a/tests/Utils/ObjectHelpers.strictness.phpt +++ b/tests/Utils/ObjectHelpers.strictness.phpt @@ -52,66 +52,96 @@ class TestChild extends TestClass // calling -Assert::exception(function () { - ObjectHelpers::strictCall('TestClass', 'undeclared'); -}, MemberAccessException::class, 'Call to undefined method TestClass::undeclared().'); - -Assert::exception(function () { - ObjectHelpers::strictStaticCall('TestClass', 'undeclared'); -}, MemberAccessException::class, 'Call to undefined static method TestClass::undeclared().'); - -Assert::exception(function () { - ObjectHelpers::strictCall('TestChild', 'callParent'); -}, MemberAccessException::class, 'Call to method TestChild::callParent() from global scope.'); - -Assert::exception(function () { - ObjectHelpers::strictCall('TestClass', 'publicMethodX'); -}, MemberAccessException::class, 'Call to undefined method TestClass::publicMethodX(), did you mean publicMethod()?'); - -Assert::exception(function () { // suggest static method - ObjectHelpers::strictCall('TestClass', 'publicMethodStaticX'); -}, MemberAccessException::class, 'Call to undefined method TestClass::publicMethodStaticX(), did you mean publicMethodStatic()?'); - -Assert::exception(function () { // suggest static method - ObjectHelpers::strictStaticCall('TestClass', 'publicMethodStaticX'); -}, MemberAccessException::class, 'Call to undefined static method TestClass::publicMethodStaticX(), did you mean publicMethodStatic()?'); - -Assert::exception(function () { // suggest only public method - ObjectHelpers::strictCall('TestClass', 'protectedMethodX'); -}, MemberAccessException::class, 'Call to undefined method TestClass::protectedMethodX().'); +Assert::exception( + fn() => ObjectHelpers::strictCall('TestClass', 'undeclared'), + MemberAccessException::class, + 'Call to undefined method TestClass::undeclared().', +); + +Assert::exception( + fn() => ObjectHelpers::strictStaticCall('TestClass', 'undeclared'), + MemberAccessException::class, + 'Call to undefined static method TestClass::undeclared().', +); + +Assert::exception( + fn() => ObjectHelpers::strictCall('TestChild', 'callParent'), + MemberAccessException::class, + 'Call to method TestChild::callParent() from global scope.', +); + +Assert::exception( + fn() => ObjectHelpers::strictCall('TestClass', 'publicMethodX'), + MemberAccessException::class, + 'Call to undefined method TestClass::publicMethodX(), did you mean publicMethod()?', +); + +Assert::exception( + fn() => ObjectHelpers::strictCall('TestClass', 'publicMethodStaticX'), + MemberAccessException::class, + 'Call to undefined method TestClass::publicMethodStaticX(), did you mean publicMethodStatic()?', +); + +Assert::exception( + fn() => ObjectHelpers::strictStaticCall('TestClass', 'publicMethodStaticX'), + MemberAccessException::class, + 'Call to undefined static method TestClass::publicMethodStaticX(), did you mean publicMethodStatic()?', +); + +Assert::exception( + fn() => ObjectHelpers::strictCall('TestClass', 'protectedMethodX'), + MemberAccessException::class, + 'Call to undefined method TestClass::protectedMethodX().', +); // writing -Assert::exception(function () { - ObjectHelpers::strictSet('TestClass', 'undeclared'); -}, MemberAccessException::class, 'Cannot write to an undeclared property TestClass::$undeclared.'); - -Assert::exception(function () { - ObjectHelpers::strictSet('TestClass', 'publicX'); -}, MemberAccessException::class, 'Cannot write to an undeclared property TestClass::$publicX, did you mean $public?'); - -Assert::exception(function () { // suggest only non-static property - ObjectHelpers::strictSet('TestClass', 'publicStaticX'); -}, MemberAccessException::class, 'Cannot write to an undeclared property TestClass::$publicStaticX.'); - -Assert::exception(function () { // suggest only public property - ObjectHelpers::strictSet('TestClass', 'protectedX'); -}, MemberAccessException::class, 'Cannot write to an undeclared property TestClass::$protectedX.'); +Assert::exception( + fn() => ObjectHelpers::strictSet('TestClass', 'undeclared'), + MemberAccessException::class, + 'Cannot write to an undeclared property TestClass::$undeclared.', +); + +Assert::exception( + fn() => ObjectHelpers::strictSet('TestClass', 'publicX'), + MemberAccessException::class, + 'Cannot write to an undeclared property TestClass::$publicX, did you mean $public?', +); + +Assert::exception( + fn() => ObjectHelpers::strictSet('TestClass', 'publicStaticX'), + MemberAccessException::class, + 'Cannot write to an undeclared property TestClass::$publicStaticX.', +); + +Assert::exception( + fn() => ObjectHelpers::strictSet('TestClass', 'protectedX'), + MemberAccessException::class, + 'Cannot write to an undeclared property TestClass::$protectedX.', +); // reading -Assert::exception(function () { - ObjectHelpers::strictGet('TestClass', 'undeclared'); -}, MemberAccessException::class, 'Cannot read an undeclared property TestClass::$undeclared.'); - -Assert::exception(function () { - ObjectHelpers::strictGet('TestClass', 'publicX'); -}, MemberAccessException::class, 'Cannot read an undeclared property TestClass::$publicX, did you mean $public?'); - -Assert::exception(function () { // suggest only non-static property - ObjectHelpers::strictGet('TestClass', 'publicStaticX'); -}, MemberAccessException::class, 'Cannot read an undeclared property TestClass::$publicStaticX.'); - -Assert::exception(function () { // suggest only public property - ObjectHelpers::strictGet('TestClass', 'protectedX'); -}, MemberAccessException::class, 'Cannot read an undeclared property TestClass::$protectedX.'); +Assert::exception( + fn() => ObjectHelpers::strictGet('TestClass', 'undeclared'), + MemberAccessException::class, + 'Cannot read an undeclared property TestClass::$undeclared.', +); + +Assert::exception( + fn() => ObjectHelpers::strictGet('TestClass', 'publicX'), + MemberAccessException::class, + 'Cannot read an undeclared property TestClass::$publicX, did you mean $public?', +); + +Assert::exception( + fn() => ObjectHelpers::strictGet('TestClass', 'publicStaticX'), + MemberAccessException::class, + 'Cannot read an undeclared property TestClass::$publicStaticX.', +); + +Assert::exception( + fn() => ObjectHelpers::strictGet('TestClass', 'protectedX'), + MemberAccessException::class, + 'Cannot read an undeclared property TestClass::$protectedX.', +); diff --git a/tests/Utils/Random.generate().phpt b/tests/Utils/Random.generate().phpt index ec874e0c4..6831960f6 100644 --- a/tests/Utils/Random.generate().phpt +++ b/tests/Utils/Random.generate().phpt @@ -22,13 +22,17 @@ Assert::truthy(preg_match('#^[0-9]+$#', Random::generate(1000, '0-9'))); Assert::truthy(preg_match('#^[0a-z12]+$#', Random::generate(1000, '0a-z12'))); Assert::truthy(preg_match('#^[-a]+$#', Random::generate(1000, '-a'))); -Assert::exception(function () { - Random::generate(0); -}, Nette\InvalidArgumentException::class, 'Length must be greater than zero.'); - -Assert::exception(function () { - Random::generate(1, '000'); -}, Nette\InvalidArgumentException::class, 'Character list must contain at least two chars.'); +Assert::exception( + fn() => Random::generate(0), + Nette\InvalidArgumentException::class, + 'Length must be greater than zero.', +); + +Assert::exception( + fn() => Random::generate(1, '000'), + Nette\InvalidArgumentException::class, + 'Character list must contain at least two chars.', +); // frequency check diff --git a/tests/Utils/Reflection.expandClassName.phpt b/tests/Utils/Reflection.expandClassName.phpt index 389ff39d3..320323f07 100644 --- a/tests/Utils/Reflection.expandClassName.phpt +++ b/tests/Utils/Reflection.expandClassName.phpt @@ -29,15 +29,19 @@ $rcFoo = new ReflectionClass(Test\Space\Foo::class); $rcBar = new ReflectionClass(Test\Space\Bar::class); -Assert::exception(function () use ($rcTest) { - Reflection::expandClassName('', $rcTest); -}, Nette\InvalidArgumentException::class, 'Class name must not be empty.'); +Assert::exception( + fn() => Reflection::expandClassName('', $rcTest), + Nette\InvalidArgumentException::class, + 'Class name must not be empty.', +); -Assert::exception(function () use ($rcTest) { - Reflection::expandClassName('A', new ReflectionClass(new class { - })); -}, Nette\NotImplementedException::class, 'Anonymous classes are not supported.'); +Assert::exception( + fn() => Reflection::expandClassName('A', new ReflectionClass(new class { + })), + Nette\NotImplementedException::class, + 'Anonymous classes are not supported.', +); Assert::same('A', Reflection::expandClassName('A', $rcTest)); @@ -137,7 +141,6 @@ foreach ($cases as $alias => $fqn) { Assert::same($fqn[1], Reflection::expandClassName($alias, $rcBar)); } - Assert::same( ['C' => 'A\B'], Reflection::getUseStatements(new ReflectionClass('Test')), @@ -157,7 +160,9 @@ Assert::same( Reflection::getUseStatements(new ReflectionClass('stdClass')), ); -Assert::exception(function () use ($rcTest) { - Reflection::getUseStatements(new ReflectionClass(new class { - })); -}, Nette\NotImplementedException::class, 'Anonymous classes are not supported.'); +Assert::exception( + fn() => Reflection::getUseStatements(new ReflectionClass(new class { + })), + Nette\NotImplementedException::class, + 'Anonymous classes are not supported.', +); diff --git a/tests/Utils/Reflection.getParameterDefaultValue.phpt b/tests/Utils/Reflection.getParameterDefaultValue.phpt index 8cd5ce437..d7003fbc0 100644 --- a/tests/Utils/Reflection.getParameterDefaultValue.phpt +++ b/tests/Utils/Reflection.getParameterDefaultValue.phpt @@ -13,9 +13,10 @@ require __DIR__ . '/../bootstrap.php'; require __DIR__ . '/fixtures.reflection/defaultValue.php'; -Assert::exception(function () { - Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'a')); -}, ReflectionException::class); +Assert::exception( + fn() => Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'a')), + ReflectionException::class, +); Assert::same('abc', Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'b'))); @@ -33,24 +34,32 @@ Assert::same('abc', Reflection::getParameterDefaultValue(new ReflectionParameter Assert::same('xyz', Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'p'))); -Assert::exception(function () { - Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'i')); -}, ReflectionException::class, 'Unable to resolve constant self::UNDEFINED used as default value of $i in NS\Foo::method().'); +Assert::exception( + fn() => Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'i')), + ReflectionException::class, + 'Unable to resolve constant self::UNDEFINED used as default value of $i in NS\Foo::method().', +); -Assert::exception(function () { - Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'j')); -}, ReflectionException::class, 'Unable to resolve constant NS\\Foo::UNDEFINED used as default value of $j in NS\Foo::method().'); +Assert::exception( + fn() => Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'j')), + ReflectionException::class, + 'Unable to resolve constant NS\\Foo::UNDEFINED used as default value of $j in NS\Foo::method().', +); Assert::same(NS\Bar::DEFINED, Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'k'))); -Assert::exception(function () { - Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'l')); -}, ReflectionException::class, 'Unable to resolve constant NS\Undefined::ANY used as default value of $l in NS\Foo::method().'); +Assert::exception( + fn() => Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'l')), + ReflectionException::class, + 'Unable to resolve constant NS\Undefined::ANY used as default value of $l in NS\Foo::method().', +); Assert::same(DEFINED, Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'm'))); -Assert::exception(function () { - Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'n')); -}, ReflectionException::class, 'Unable to resolve constant NS\UNDEFINED used as default value of $n in NS\Foo::method().'); +Assert::exception( + fn() => Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'n')), + ReflectionException::class, + 'Unable to resolve constant NS\UNDEFINED used as default value of $n in NS\Foo::method().', +); Assert::same(NS\NS_DEFINED, Reflection::getParameterDefaultValue(new ReflectionParameter(['NS\Foo', 'method'], 'o'))); diff --git a/tests/Utils/Reflection.getParameterType.81.phpt b/tests/Utils/Reflection.getParameterType.81.phpt index 15d75986f..893f721d9 100644 --- a/tests/Utils/Reflection.getParameterType.81.phpt +++ b/tests/Utils/Reflection.getParameterType.81.phpt @@ -52,17 +52,23 @@ Assert::null(Reflection::getParameterType($params[5])); Assert::same('Test\B', Reflection::getParameterType($params[6])); Assert::same('mixed', Reflection::getParameterType($params[7])); -Assert::exception(function () use ($params) { - Reflection::getParameterType($params[8]); -}, Nette\InvalidStateException::class, 'The $union in A::method() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getParameterType($params[8]), + Nette\InvalidStateException::class, + 'The $union in A::method() is not expected to have a union or intersection type.', +); -Assert::exception(function () use ($params) { - Reflection::getParameterType($params[9]); -}, Nette\InvalidStateException::class, 'The $nullableUnion in A::method() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getParameterType($params[9]), + Nette\InvalidStateException::class, + 'The $nullableUnion in A::method() is not expected to have a union or intersection type.', +); -Assert::exception(function () use ($params) { - Reflection::getParameterType($params[10]); -}, Nette\InvalidStateException::class, 'The $intersection in A::method() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getParameterType($params[10]), + Nette\InvalidStateException::class, + 'The $intersection in A::method() is not expected to have a union or intersection type.', +); $method = new ReflectionMethod('AExt', 'methodExt'); $params = $method->getParameters(); diff --git a/tests/Utils/Reflection.getParameterType.phpt b/tests/Utils/Reflection.getParameterType.phpt index 9e00ed6d9..182b9539a 100644 --- a/tests/Utils/Reflection.getParameterType.phpt +++ b/tests/Utils/Reflection.getParameterType.phpt @@ -50,13 +50,17 @@ Assert::null(Reflection::getParameterType($params[5])); Assert::same('Test\B', Reflection::getParameterType($params[6])); Assert::same('mixed', Reflection::getParameterType($params[7])); -Assert::exception(function () use ($params) { - Reflection::getParameterType($params[8]); -}, Nette\InvalidStateException::class, 'The $union in A::method() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getParameterType($params[8]), + Nette\InvalidStateException::class, + 'The $union in A::method() is not expected to have a union or intersection type.', +); -Assert::exception(function () use ($params) { - Reflection::getParameterType($params[9]); -}, Nette\InvalidStateException::class, 'The $nullableUnion in A::method() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getParameterType($params[9]), + Nette\InvalidStateException::class, + 'The $nullableUnion in A::method() is not expected to have a union or intersection type.', +); $method = new ReflectionMethod('AExt', 'methodExt'); diff --git a/tests/Utils/Reflection.getPropertyType.81.phpt b/tests/Utils/Reflection.getPropertyType.81.phpt index d7905d6d6..39a35dfd8 100644 --- a/tests/Utils/Reflection.getPropertyType.81.phpt +++ b/tests/Utils/Reflection.getPropertyType.81.phpt @@ -26,7 +26,7 @@ class A public mixed $mixed; public array|self $union; public array|self|null $nullableUnion; - public AExt&A $intersection; + public AExt & A $intersection; } class AExt extends A @@ -45,17 +45,23 @@ Assert::null(Reflection::getPropertyType($props[4])); Assert::same('Test\B', Reflection::getPropertyType($props[5])); Assert::same('mixed', Reflection::getPropertyType($props[6])); -Assert::exception(function () use ($props) { - Reflection::getPropertyType($props[7]); -}, Nette\InvalidStateException::class, 'The A::$union is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getPropertyType($props[7]), + Nette\InvalidStateException::class, + 'The A::$union is not expected to have a union or intersection type.', +); -Assert::exception(function () use ($props) { - Reflection::getPropertyType($props[8]); -}, Nette\InvalidStateException::class, 'The A::$nullableUnion is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getPropertyType($props[8]), + Nette\InvalidStateException::class, + 'The A::$nullableUnion is not expected to have a union or intersection type.', +); -Assert::exception(function () use ($props) { - Reflection::getPropertyType($props[9]); -}, Nette\InvalidStateException::class, 'The A::$intersection is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getPropertyType($props[9]), + Nette\InvalidStateException::class, + 'The A::$intersection is not expected to have a union or intersection type.', +); $class = new ReflectionClass('AExt'); $props = $class->getProperties(); diff --git a/tests/Utils/Reflection.getPropertyType.phpt b/tests/Utils/Reflection.getPropertyType.phpt index 161e4ac7e..fa4fbe477 100644 --- a/tests/Utils/Reflection.getPropertyType.phpt +++ b/tests/Utils/Reflection.getPropertyType.phpt @@ -43,13 +43,17 @@ Assert::null(Reflection::getPropertyType($props[4])); Assert::same('Test\B', Reflection::getPropertyType($props[5])); Assert::same('mixed', Reflection::getPropertyType($props[6])); -Assert::exception(function () use ($props) { - Reflection::getPropertyType($props[7]); -}, Nette\InvalidStateException::class, 'The A::$union is not expected to have a union or intersection type.'); - -Assert::exception(function () use ($props) { - Reflection::getPropertyType($props[8]); -}, Nette\InvalidStateException::class, 'The A::$nullableUnion is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getPropertyType($props[7]), + Nette\InvalidStateException::class, + 'The A::$union is not expected to have a union or intersection type.', +); + +Assert::exception( + fn() => Reflection::getPropertyType($props[8]), + Nette\InvalidStateException::class, + 'The A::$nullableUnion is not expected to have a union or intersection type.', +); $class = new ReflectionClass('AExt'); $props = $class->getProperties(); diff --git a/tests/Utils/Reflection.getReturnType.81.phpt b/tests/Utils/Reflection.getReturnType.81.phpt index c6770121e..871276ad5 100644 --- a/tests/Utils/Reflection.getReturnType.81.phpt +++ b/tests/Utils/Reflection.getReturnType.81.phpt @@ -66,7 +66,7 @@ class A } - public function intersectionType(): AExt&A + public function intersectionType(): AExt & A { } } @@ -99,7 +99,7 @@ function unionType(): array|A } -function intersectionType(): AExt&A +function intersectionType(): AExt & A { } @@ -120,17 +120,23 @@ Assert::same('string', Reflection::getReturnType(new ReflectionMethod(A::class, Assert::same('A', Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableSelfType'))); -Assert::exception(function () { - Reflection::getReturnType(new ReflectionMethod(A::class, 'unionType')); -}, Nette\InvalidStateException::class, 'The A::unionType() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getReturnType(new ReflectionMethod(A::class, 'unionType')), + Nette\InvalidStateException::class, + 'The A::unionType() is not expected to have a union or intersection type.', +); -Assert::exception(function () { - Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableUnionType')); -}, Nette\InvalidStateException::class, 'The A::nullableUnionType() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableUnionType')), + Nette\InvalidStateException::class, + 'The A::nullableUnionType() is not expected to have a union or intersection type.', +); -Assert::exception(function () { - Reflection::getReturnType(new ReflectionMethod(A::class, 'intersectionType')); -}, Nette\InvalidStateException::class, 'The A::intersectionType() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getReturnType(new ReflectionMethod(A::class, 'intersectionType')), + Nette\InvalidStateException::class, + 'The A::intersectionType() is not expected to have a union or intersection type.', +); Assert::same('A', Reflection::getReturnType(new ReflectionMethod(AExt::class, 'parentTypeExt'))); @@ -140,13 +146,17 @@ Assert::same('Test\B', Reflection::getReturnType(new ReflectionFunction('classTy Assert::same('string', Reflection::getReturnType(new ReflectionFunction('nativeType'))); -Assert::exception(function () { - Reflection::getReturnType(new ReflectionFunction('unionType')); -}, Nette\InvalidStateException::class, 'The unionType() is not expected to have a union or intersection type.'); - -Assert::exception(function () { - Reflection::getReturnType(new ReflectionFunction('intersectionType')); -}, Nette\InvalidStateException::class, 'The intersectionType() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getReturnType(new ReflectionFunction('unionType')), + Nette\InvalidStateException::class, + 'The unionType() is not expected to have a union or intersection type.', +); + +Assert::exception( + fn() => Reflection::getReturnType(new ReflectionFunction('intersectionType')), + Nette\InvalidStateException::class, + 'The intersectionType() is not expected to have a union or intersection type.', +); // tentative type diff --git a/tests/Utils/Reflection.getReturnType.phpt b/tests/Utils/Reflection.getReturnType.phpt index 43021b705..16f57a5a8 100644 --- a/tests/Utils/Reflection.getReturnType.phpt +++ b/tests/Utils/Reflection.getReturnType.phpt @@ -109,13 +109,17 @@ Assert::same('string', Reflection::getReturnType(new ReflectionMethod(A::class, Assert::same('A', Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableSelfType'))); -Assert::exception(function () { - Reflection::getReturnType(new ReflectionMethod(A::class, 'unionType')); -}, Nette\InvalidStateException::class, 'The A::unionType() is not expected to have a union or intersection type.'); - -Assert::exception(function () { - Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableUnionType')); -}, Nette\InvalidStateException::class, 'The A::nullableUnionType() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getReturnType(new ReflectionMethod(A::class, 'unionType')), + Nette\InvalidStateException::class, + 'The A::unionType() is not expected to have a union or intersection type.', +); + +Assert::exception( + fn() => Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableUnionType')), + Nette\InvalidStateException::class, + 'The A::nullableUnionType() is not expected to have a union or intersection type.', +); Assert::same('A', Reflection::getReturnType(new ReflectionMethod(AExt::class, 'parentTypeExt'))); @@ -125,6 +129,8 @@ Assert::same('Test\B', Reflection::getReturnType(new ReflectionFunction('classTy Assert::same('string', Reflection::getReturnType(new ReflectionFunction('nativeType'))); -Assert::exception(function () { - Reflection::getReturnType(new ReflectionFunction('unionType')); -}, Nette\InvalidStateException::class, 'The unionType() is not expected to have a union or intersection type.'); +Assert::exception( + fn() => Reflection::getReturnType(new ReflectionFunction('unionType')), + Nette\InvalidStateException::class, + 'The unionType() is not expected to have a union or intersection type.', +); diff --git a/tests/Utils/SmartObject.events.phpt b/tests/Utils/SmartObject.events.phpt index d7952fadf..0f8ce94aa 100644 --- a/tests/Utils/SmartObject.events.phpt +++ b/tests/Utils/SmartObject.events.phpt @@ -60,31 +60,37 @@ $obj->onPublic($var); Assert::same(3, $var->counter); -Assert::exception(function () use ($obj) { - $obj->onPublicStatic(123); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::onPublicStatic().'); +Assert::exception( + fn() => $obj->onPublicStatic(123), + Nette\MemberAccessException::class, + 'Call to undefined method TestClass::onPublicStatic().', +); -Assert::exception(function () use ($obj) { - $obj->onProtected(123); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::onProtected().'); +Assert::exception( + fn() => $obj->onProtected(123), + Nette\MemberAccessException::class, + 'Call to undefined method TestClass::onProtected().', +); -Assert::exception(function () use ($obj) { - $obj->onPrivate(123); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::onPrivate().'); +Assert::exception( + fn() => $obj->onPrivate(123), + Nette\MemberAccessException::class, + 'Call to undefined method TestClass::onPrivate().', +); -Assert::exception(function () use ($obj) { - $obj->onUndefined(123); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::onUndefined().'); +Assert::exception( + fn() => $obj->onUndefined(123), + Nette\MemberAccessException::class, + 'Call to undefined method TestClass::onUndefined().', +); Assert::exception(function () use ($obj) { $obj->onPublic = 'string'; $obj->onPublic(); }, Nette\UnexpectedValueException::class, 'Property TestClass::$onPublic must be iterable or null, string given.'); -Assert::noError(function () { - $obj = new TestClass; - $obj->onEvent(); -}); +$obj = new TestClass; +Assert::noError(fn() => $obj->onEvent()); diff --git a/tests/Utils/SmartObject.property.inheritance.phpt b/tests/Utils/SmartObject.property.inheritance.phpt index 80dd51bb5..d4893768a 100644 --- a/tests/Utils/SmartObject.property.inheritance.phpt +++ b/tests/Utils/SmartObject.property.inheritance.phpt @@ -82,22 +82,32 @@ Assert::same('getTraitC', $obj->traitC); Assert::same('getClassA', $obj->classA); Assert::same('getClassB', $obj->classB); -Assert::exception(function () use ($obj) { - $obj->classBX; -}, Nette\MemberAccessException::class, 'Cannot read an undeclared property ChildClass::$classBX, did you mean $classB?'); - -Assert::exception(function () use ($obj) { - $obj->classAX; -}, Nette\MemberAccessException::class, 'Cannot read an undeclared property ChildClass::$classAX, did you mean $classA?'); - -Assert::exception(function () use ($obj) { - $obj->traitCX; -}, Nette\MemberAccessException::class, 'Cannot read an undeclared property ChildClass::$traitCX, did you mean $traitC?'); - -Assert::exception(function () use ($obj) { - $obj->traitBX; -}, Nette\MemberAccessException::class, 'Cannot read an undeclared property ChildClass::$traitBX, did you mean $traitB?'); - -Assert::exception(function () use ($obj) { - $obj->traitAX; -}, Nette\MemberAccessException::class, 'Cannot read an undeclared property ChildClass::$traitAX, did you mean $traitA?'); +Assert::exception( + fn() => $obj->classBX, + Nette\MemberAccessException::class, + 'Cannot read an undeclared property ChildClass::$classBX, did you mean $classB?', +); + +Assert::exception( + fn() => $obj->classAX, + Nette\MemberAccessException::class, + 'Cannot read an undeclared property ChildClass::$classAX, did you mean $classA?', +); + +Assert::exception( + fn() => $obj->traitCX, + Nette\MemberAccessException::class, + 'Cannot read an undeclared property ChildClass::$traitCX, did you mean $traitC?', +); + +Assert::exception( + fn() => $obj->traitBX, + Nette\MemberAccessException::class, + 'Cannot read an undeclared property ChildClass::$traitBX, did you mean $traitB?', +); + +Assert::exception( + fn() => $obj->traitAX, + Nette\MemberAccessException::class, + 'Cannot read an undeclared property ChildClass::$traitAX, did you mean $traitA?', +); diff --git a/tests/Utils/SmartObject.property.phpt b/tests/Utils/SmartObject.property.phpt index 6d258e835..b2a841681 100644 --- a/tests/Utils/SmartObject.property.phpt +++ b/tests/Utils/SmartObject.property.phpt @@ -92,9 +92,11 @@ Assert::same('hello world', $obj->foo); // Undeclared property writing -Assert::exception(function () use ($obj) { - $obj->undeclared = 'value'; -}, Nette\MemberAccessException::class, 'Cannot write to an undeclared property TestClass::$undeclared, did you mean $declared?'); +Assert::exception( + fn() => $obj->undeclared = 'value', + Nette\MemberAccessException::class, + 'Cannot write to an undeclared property TestClass::$undeclared, did you mean $declared?', +); // Undeclared property reading @@ -102,9 +104,11 @@ Assert::false(isset($obj->S)); Assert::false(isset($obj->s)); Assert::false(isset($obj->undeclared)); -Assert::exception(function () use ($obj) { - $val = $obj->undeclared; -}, Nette\MemberAccessException::class, 'Cannot read an undeclared property TestClass::$undeclared, did you mean $declared?'); +Assert::exception( + fn() => $obj->undeclared, + Nette\MemberAccessException::class, + 'Cannot read an undeclared property TestClass::$undeclared, did you mean $declared?', +); // Read-only property @@ -112,9 +116,11 @@ $obj = new TestClass('Hello', 'World'); Assert::true(isset($obj->bar)); Assert::same('World', $obj->bar); -Assert::exception(function () use ($obj) { - $obj->bar = 'value'; -}, Nette\MemberAccessException::class, 'Cannot write to a read-only property TestClass::$bar.'); +Assert::exception( + fn() => $obj->bar = 'value', + Nette\MemberAccessException::class, + 'Cannot write to a read-only property TestClass::$bar.', +); // write-only property @@ -123,9 +129,11 @@ Assert::true(isset($obj->bazz)); $obj->bazz = 'World'; Assert::same('World', $obj->bar); -Assert::exception(function () use ($obj) { - $val = $obj->bazz; -}, Nette\MemberAccessException::class, 'Cannot read a write-only property TestClass::$bazz.'); +Assert::exception( + fn() => $obj->bazz, + Nette\MemberAccessException::class, + 'Cannot read a write-only property TestClass::$bazz.', +); // deprecated property diff --git a/tests/Utils/SmartObject.undeclaredMethod.annotation.phpt b/tests/Utils/SmartObject.undeclaredMethod.annotation.phpt index 3a27cd45d..a6ce44562 100644 --- a/tests/Utils/SmartObject.undeclaredMethod.annotation.phpt +++ b/tests/Utils/SmartObject.undeclaredMethod.annotation.phpt @@ -56,34 +56,50 @@ class ChildClass extends ParentClass $obj = new ChildClass; -Assert::exception(function () use ($obj) { - $obj->classBX(); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::classBX(), did you mean classB()?'); - -Assert::exception(function () use ($obj) { - $obj->classCX(); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::classCX(), did you mean classC()?'); - -Assert::exception(function () use ($obj) { - $obj->classS1X(); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::classS1X(), did you mean classS1()?'); - -Assert::exception(function () use ($obj) { - $obj->classS2X(); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::classS2X(), did you mean classS2()?'); - -Assert::exception(function () use ($obj) { - $obj->classAX(); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::classAX(), did you mean classA()?'); - -Assert::exception(function () use ($obj) { - $obj->traitCX(); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::traitCX(), did you mean traitC()?'); - -Assert::exception(function () use ($obj) { - $obj->traitBX(); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::traitBX(), did you mean traitB()?'); - -Assert::exception(function () use ($obj) { - $obj->traitAX(); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::traitAX(), did you mean traitA()?'); +Assert::exception( + fn() => $obj->classBX(), + Nette\MemberAccessException::class, + 'Call to undefined method ChildClass::classBX(), did you mean classB()?', +); + +Assert::exception( + fn() => $obj->classCX(), + Nette\MemberAccessException::class, + 'Call to undefined method ChildClass::classCX(), did you mean classC()?', +); + +Assert::exception( + fn() => $obj->classS1X(), + Nette\MemberAccessException::class, + 'Call to undefined method ChildClass::classS1X(), did you mean classS1()?', +); + +Assert::exception( + fn() => $obj->classS2X(), + Nette\MemberAccessException::class, + 'Call to undefined method ChildClass::classS2X(), did you mean classS2()?', +); + +Assert::exception( + fn() => $obj->classAX(), + Nette\MemberAccessException::class, + 'Call to undefined method ChildClass::classAX(), did you mean classA()?', +); + +Assert::exception( + fn() => $obj->traitCX(), + Nette\MemberAccessException::class, + 'Call to undefined method ChildClass::traitCX(), did you mean traitC()?', +); + +Assert::exception( + fn() => $obj->traitBX(), + Nette\MemberAccessException::class, + 'Call to undefined method ChildClass::traitBX(), did you mean traitB()?', +); + +Assert::exception( + fn() => $obj->traitAX(), + Nette\MemberAccessException::class, + 'Call to undefined method ChildClass::traitAX(), did you mean traitA()?', +); diff --git a/tests/Utils/SmartObject.undeclaredMethod.hints.phpt b/tests/Utils/SmartObject.undeclaredMethod.hints.phpt index 21d493e34..c5790f798 100644 --- a/tests/Utils/SmartObject.undeclaredMethod.hints.phpt +++ b/tests/Utils/SmartObject.undeclaredMethod.hints.phpt @@ -36,26 +36,35 @@ class TestClass } -Assert::exception(function () { - $obj = new TestClass; - $obj->abc(); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::abc().'); - -Assert::exception(function () { - $obj = new TestClass; - $obj->method(); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::method(), did you mean methodO2()?'); - -Assert::exception(function () { - TestClass::abc(); -}, Nette\MemberAccessException::class, 'Call to undefined static method TestClass::abc().'); - -Assert::exception(function () { - TestClass::method(); -}, Nette\MemberAccessException::class, 'Call to undefined static method TestClass::method(), did you mean methodS2()?'); +$obj = new TestClass; +Assert::exception( + fn() => $obj->abc(), + Nette\MemberAccessException::class, + 'Call to undefined method TestClass::abc().', +); + +Assert::exception( + fn() => $obj->method(), + Nette\MemberAccessException::class, + 'Call to undefined method TestClass::method(), did you mean methodO2()?', +); + +Assert::exception( + fn() => TestClass::abc(), + Nette\MemberAccessException::class, + 'Call to undefined static method TestClass::abc().', +); + +Assert::exception( + fn() => TestClass::method(), + Nette\MemberAccessException::class, + 'Call to undefined static method TestClass::method(), did you mean methodS2()?', +); if (extension_loaded('gd')) { - Assert::exception(function () { - Nette\Utils\Image::fromBlank(1, 1)->filledElippse(); - }, Nette\MemberAccessException::class, 'Call to undefined method Nette\Utils\Image::filledElippse(), did you mean filledEllipse()?'); + Assert::exception( + fn() => Nette\Utils\Image::fromBlank(1, 1)->filledElippse(), + Nette\MemberAccessException::class, + 'Call to undefined method Nette\Utils\Image::filledElippse(), did you mean filledEllipse()?', + ); } diff --git a/tests/Utils/SmartObject.undeclaredMethod.phpt b/tests/Utils/SmartObject.undeclaredMethod.phpt index c11e52cd1..5e4778166 100644 --- a/tests/Utils/SmartObject.undeclaredMethod.phpt +++ b/tests/Utils/SmartObject.undeclaredMethod.phpt @@ -90,64 +90,78 @@ class ChildClass extends InterClass -Assert::exception(function () { - $obj = new ParentClass; - $obj->undef(); -}, Nette\MemberAccessException::class, 'Call to undefined method ParentClass::undef().'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj->undef(); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::undef().'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj->callParents(); -}, Nette\MemberAccessException::class, 'Call to undefined method ParentClass::callParents().'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj->callMissingParent(); -}, Nette\MemberAccessException::class, 'Call to undefined method InterClass::callMissingParent().'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj->callMissingParentStatic(); -}, Nette\MemberAccessException::class, 'Call to undefined static method InterClass::callMissingParentStatic().'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj::callMissingParentStatic(); -}, Nette\MemberAccessException::class, 'Call to undefined static method InterClass::callMissingParentStatic().'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj->callPrivateParent(); -}, Nette\MemberAccessException::class, PHP_VERSION_ID < 80100 +$obj = new ParentClass; +Assert::exception( + fn() => $obj->undef(), + Nette\MemberAccessException::class, + 'Call to undefined method ParentClass::undef().', +); + +$obj = new ChildClass; +Assert::exception( + fn() => $obj->undef(), + Nette\MemberAccessException::class, + 'Call to undefined method ChildClass::undef().', +); + +Assert::exception( + fn() => $obj->callParents(), + Nette\MemberAccessException::class, + 'Call to undefined method ParentClass::callParents().', +); + +Assert::exception( + fn() => $obj->callMissingParent(), + Nette\MemberAccessException::class, + 'Call to undefined method InterClass::callMissingParent().', +); + +Assert::exception( + fn() => $obj->callMissingParentStatic(), + Nette\MemberAccessException::class, + 'Call to undefined static method InterClass::callMissingParentStatic().', +); + +Assert::exception( + fn() => $obj::callMissingParentStatic(), + Nette\MemberAccessException::class, + 'Call to undefined static method InterClass::callMissingParentStatic().', +); + +Assert::exception( + fn() => $obj->callPrivateParent(), + Nette\MemberAccessException::class, + PHP_VERSION_ID < 80100 ? 'Call to undefined static method InterClass::callPrivateParent().' // differs from native error message - : 'Call to undefined method InterClass::callPrivateParent().'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj->protectedMethod(); -}, Nette\MemberAccessException::class, 'Call to protected method ChildClass::protectedMethod() from global scope.'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj->protectedStaticMethod(); -}, Nette\MemberAccessException::class, 'Call to protected method ChildClass::protectedStaticMethod() from global scope.'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj::protectedStaticMethod(); -}, Nette\MemberAccessException::class, 'Call to protected method ChildClass::protectedStaticMethod() from global scope.'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj->callPrivate(); -}, Nette\MemberAccessException::class, 'Call to private method ChildClass::privateMethod() from scope ParentClass.'); - -Assert::exception(function () { - $obj = new ChildClass; - $obj->callPrivateStatic(); -}, Nette\MemberAccessException::class, 'Call to private method ChildClass::privateStaticMethod() from scope ParentClass.'); + : 'Call to undefined method InterClass::callPrivateParent().', +); + +Assert::exception( + fn() => $obj->protectedMethod(), + Nette\MemberAccessException::class, + 'Call to protected method ChildClass::protectedMethod() from global scope.', +); + +Assert::exception( + fn() => $obj->protectedStaticMethod(), + Nette\MemberAccessException::class, + 'Call to protected method ChildClass::protectedStaticMethod() from global scope.', +); + +Assert::exception( + fn() => $obj::protectedStaticMethod(), + Nette\MemberAccessException::class, + 'Call to protected method ChildClass::protectedStaticMethod() from global scope.', +); + +Assert::exception( + fn() => $obj->callPrivate(), + Nette\MemberAccessException::class, + 'Call to private method ChildClass::privateMethod() from scope ParentClass.', +); + +Assert::exception( + fn() => $obj->callPrivateStatic(), + Nette\MemberAccessException::class, + 'Call to private method ChildClass::privateStaticMethod() from scope ParentClass.', +); diff --git a/tests/Utils/StaticClass.phpt b/tests/Utils/StaticClass.phpt index ef119ee29..01d87d38e 100644 --- a/tests/Utils/StaticClass.phpt +++ b/tests/Utils/StaticClass.phpt @@ -20,10 +20,14 @@ class TestClass } } -Assert::exception(function () { - new TestClass; -}, Error::class, 'Class TestClass is static and cannot be instantiated.'); - -Assert::exception(function () { - TestClass::methodA(); -}, Nette\MemberAccessException::class, 'Call to undefined static method TestClass::methodA(), did you mean method()?'); +Assert::exception( + fn() => new TestClass, + Error::class, + 'Class TestClass is static and cannot be instantiated.', +); + +Assert::exception( + fn() => TestClass::methodA(), + Nette\MemberAccessException::class, + 'Call to undefined static method TestClass::methodA(), did you mean method()?', +); diff --git a/tests/Utils/Strings.Regexp.errors.backtrack.phpt b/tests/Utils/Strings.Regexp.errors.backtrack.phpt index 22975d572..304f310bb 100644 --- a/tests/Utils/Strings.Regexp.errors.backtrack.phpt +++ b/tests/Utils/Strings.Regexp.errors.backtrack.phpt @@ -16,21 +16,29 @@ require __DIR__ . '/../bootstrap.php'; ini_set('pcre.backtrack_limit', '3'); // forces PREG_BACKTRACK_LIMIT_ERROR ini_set('pcre.jit', '0'); -Assert::exception(function () { - Strings::split('0123456789', '#.*\d\d#'); -}, Nette\Utils\RegexpException::class, 'Backtrack limit was exhausted (pattern: #.*\d\d#)'); - -Assert::exception(function () { - Strings::match('0123456789', '#.*\d\d#'); -}, Nette\Utils\RegexpException::class, 'Backtrack limit was exhausted (pattern: #.*\d\d#)'); - -Assert::exception(function () { - Strings::matchAll('0123456789', '#.*\d\d#'); -}, Nette\Utils\RegexpException::class, 'Backtrack limit was exhausted (pattern: #.*\d\d#)'); - -Assert::exception(function () { - Strings::replace('0123456789', '#.*\d\d#', 'x'); -}, Nette\Utils\RegexpException::class, 'Backtrack limit was exhausted (pattern: #.*\d\d#)'); +Assert::exception( + fn() => Strings::split('0123456789', '#.*\d\d#'), + Nette\Utils\RegexpException::class, + 'Backtrack limit was exhausted (pattern: #.*\d\d#)', +); + +Assert::exception( + fn() => Strings::match('0123456789', '#.*\d\d#'), + Nette\Utils\RegexpException::class, + 'Backtrack limit was exhausted (pattern: #.*\d\d#)', +); + +Assert::exception( + fn() => Strings::matchAll('0123456789', '#.*\d\d#'), + Nette\Utils\RegexpException::class, + 'Backtrack limit was exhausted (pattern: #.*\d\d#)', +); + +Assert::exception( + fn() => Strings::replace('0123456789', '#.*\d\d#', 'x'), + Nette\Utils\RegexpException::class, + 'Backtrack limit was exhausted (pattern: #.*\d\d#)', +); function cb() @@ -39,6 +47,8 @@ function cb() } -Assert::exception(function () { - Strings::replace('0123456789', '#.*\d\d#', Closure::fromCallable('cb')); -}, Nette\Utils\RegexpException::class, 'Backtrack limit was exhausted (pattern: #.*\d\d#)'); +Assert::exception( + fn() => Strings::replace('0123456789', '#.*\d\d#', Closure::fromCallable('cb')), + Nette\Utils\RegexpException::class, + 'Backtrack limit was exhausted (pattern: #.*\d\d#)', +); diff --git a/tests/Utils/Strings.Regexp.errors.compilation.phpt b/tests/Utils/Strings.Regexp.errors.compilation.phpt index 3a9f58207..e8f00d3b9 100644 --- a/tests/Utils/Strings.Regexp.errors.compilation.phpt +++ b/tests/Utils/Strings.Regexp.errors.compilation.phpt @@ -13,25 +13,35 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -Assert::exception(function () { - Strings::split('0123456789', '#*#'); -}, Nette\Utils\RegexpException::class, 'Compilation failed: %a% in pattern: #*#'); - -Assert::exception(function () { - Strings::match('0123456789', '#*#'); -}, Nette\Utils\RegexpException::class, 'Compilation failed: %a% in pattern: #*#'); - -Assert::exception(function () { - Strings::matchAll('0123456789', '#*#'); -}, Nette\Utils\RegexpException::class, 'Compilation failed: %a% in pattern: #*#'); - -Assert::exception(function () { - Strings::replace('0123456789', '#*#', 'x'); -}, Nette\Utils\RegexpException::class, 'Compilation failed: %a% in pattern: #*#'); - -Assert::exception(function () { - Strings::replace('0123456789', ['##', '#*#'], 'x'); -}, Nette\Utils\RegexpException::class, 'Compilation failed: %a% in pattern: ## or #*#'); +Assert::exception( + fn() => Strings::split('0123456789', '#*#'), + Nette\Utils\RegexpException::class, + 'Compilation failed: %a% in pattern: #*#', +); + +Assert::exception( + fn() => Strings::match('0123456789', '#*#'), + Nette\Utils\RegexpException::class, + 'Compilation failed: %a% in pattern: #*#', +); + +Assert::exception( + fn() => Strings::matchAll('0123456789', '#*#'), + Nette\Utils\RegexpException::class, + 'Compilation failed: %a% in pattern: #*#', +); + +Assert::exception( + fn() => Strings::replace('0123456789', '#*#', 'x'), + Nette\Utils\RegexpException::class, + 'Compilation failed: %a% in pattern: #*#', +); + +Assert::exception( + fn() => Strings::replace('0123456789', ['##', '#*#'], 'x'), + Nette\Utils\RegexpException::class, + 'Compilation failed: %a% in pattern: ## or #*#', +); function cb() @@ -40,10 +50,14 @@ function cb() } -Assert::exception(function () { - Strings::replace('0123456789', '#*#', Closure::fromCallable('cb')); -}, Nette\Utils\RegexpException::class, 'Compilation failed: %a% in pattern: #*#'); +Assert::exception( + fn() => Strings::replace('0123456789', '#*#', Closure::fromCallable('cb')), + Nette\Utils\RegexpException::class, + 'Compilation failed: %a% in pattern: #*#', +); -Assert::exception(function () { - Strings::replace('0123456789', ['##', '#*#'], Closure::fromCallable('cb')); -}, Nette\Utils\RegexpException::class, 'Compilation failed: %a% in pattern: ## or #*#'); +Assert::exception( + fn() => Strings::replace('0123456789', ['##', '#*#'], Closure::fromCallable('cb')), + Nette\Utils\RegexpException::class, + 'Compilation failed: %a% in pattern: ## or #*#', +); diff --git a/tests/Utils/Strings.Regexp.errors.utf8.phpt b/tests/Utils/Strings.Regexp.errors.utf8.phpt index c134e46e2..3ee2b428c 100644 --- a/tests/Utils/Strings.Regexp.errors.utf8.phpt +++ b/tests/Utils/Strings.Regexp.errors.utf8.phpt @@ -13,21 +13,29 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -Assert::exception(function () { - Strings::split("0123456789\xFF", '#\d#u'); -}, Nette\Utils\RegexpException::class, 'Malformed UTF-8 data (pattern: #\d#u)'); - -Assert::exception(function () { - Strings::match("0123456789\xFF", '#\d#u'); -}, Nette\Utils\RegexpException::class, 'Malformed UTF-8 data (pattern: #\d#u)'); - -Assert::exception(function () { - Strings::matchAll("0123456789\xFF", '#\d#u'); -}, Nette\Utils\RegexpException::class, 'Malformed UTF-8 data (pattern: #\d#u)'); - -Assert::exception(function () { - Strings::replace("0123456789\xFF", '#\d#u', 'x'); -}, Nette\Utils\RegexpException::class, 'Malformed UTF-8 data (pattern: #\d#u)'); +Assert::exception( + fn() => Strings::split("0123456789\xFF", '#\d#u'), + Nette\Utils\RegexpException::class, + 'Malformed UTF-8 data (pattern: #\d#u)', +); + +Assert::exception( + fn() => Strings::match("0123456789\xFF", '#\d#u'), + Nette\Utils\RegexpException::class, + 'Malformed UTF-8 data (pattern: #\d#u)', +); + +Assert::exception( + fn() => Strings::matchAll("0123456789\xFF", '#\d#u'), + Nette\Utils\RegexpException::class, + 'Malformed UTF-8 data (pattern: #\d#u)', +); + +Assert::exception( + fn() => Strings::replace("0123456789\xFF", '#\d#u', 'x'), + Nette\Utils\RegexpException::class, + 'Malformed UTF-8 data (pattern: #\d#u)', +); function cb() @@ -36,6 +44,8 @@ function cb() } -Assert::exception(function () { - Strings::replace("0123456789\xFF", '#\d#u', Closure::fromCallable('cb')); -}, Nette\Utils\RegexpException::class, 'Malformed UTF-8 data (pattern: #\d#u)'); +Assert::exception( + fn() => Strings::replace("0123456789\xFF", '#\d#u', Closure::fromCallable('cb')), + Nette\Utils\RegexpException::class, + 'Malformed UTF-8 data (pattern: #\d#u)', +); diff --git a/tests/Utils/Strings.chr().phpt b/tests/Utils/Strings.chr().phpt index 53a3844f1..7db83f5ab 100644 --- a/tests/Utils/Strings.chr().phpt +++ b/tests/Utils/Strings.chr().phpt @@ -25,7 +25,9 @@ Assert::same("\u{10000}", Strings::chr(0x010000)); Assert::same("\u{10FFFF}", Strings::chr(0x10FFFF)); foreach ([-1, 0xD800, 0xDFFF, 0x110000] as $code) { - Assert::exception(function () use ($code) { - Strings::chr($code); - }, Nette\InvalidArgumentException::class, 'Code point must be in range 0x0 to 0xD7FF or 0xE000 to 0x10FFFF.'); + Assert::exception( + fn() => Strings::chr($code), + Nette\InvalidArgumentException::class, + 'Code point must be in range 0x0 to 0xD7FF or 0xE000 to 0x10FFFF.', + ); } diff --git a/tests/Utils/Strings.contains().phpt b/tests/Utils/Strings.contains().phpt index bb734ff0c..972b7bfc3 100644 --- a/tests/Utils/Strings.contains().phpt +++ b/tests/Utils/Strings.contains().phpt @@ -21,9 +21,11 @@ Assert::true(Strings::contains('123', '1')); Assert::false(Strings::contains('', 'foo')); if (PHP_VERSION_ID < 80000) { - Assert::error(function () { - Assert::false(Strings::contains('', '')); - }, E_WARNING, 'strpos(): Empty needle'); + Assert::error( + fn() => Assert::false(Strings::contains('', '')), + E_WARNING, + 'strpos(): Empty needle', + ); } else { Assert::true(Strings::contains('', '')); } diff --git a/tests/Utils/Strings.endsWith().phpt b/tests/Utils/Strings.endsWith().phpt index 81ff4da2f..6525fdd73 100644 --- a/tests/Utils/Strings.endsWith().phpt +++ b/tests/Utils/Strings.endsWith().phpt @@ -13,9 +13,10 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -Assert::exception(function () { - Strings::endsWith('123', null); -}, TypeError::class); +Assert::exception( + fn() => Strings::endsWith('123', null), + TypeError::class, +); Assert::true(Strings::endsWith('123', ''), "endsWith('123', '')"); Assert::true(Strings::endsWith('123', '3'), "endsWith('123', '3')"); Assert::false(Strings::endsWith('123', '2'), "endsWith('123', '2')"); diff --git a/tests/Utils/Strings.replace().errors.callback.phpt b/tests/Utils/Strings.replace().errors.callback.phpt index d29ead08b..f7e0493c3 100644 --- a/tests/Utils/Strings.replace().errors.callback.phpt +++ b/tests/Utils/Strings.replace().errors.callback.phpt @@ -14,12 +14,10 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -Assert::error(function () { - Strings::replace('hello', '#.+#', function ($m) { - $a++; // E_NOTICE - return strtoupper($m[0]); - }); -}, ...(PHP_VERSION_ID < 80000 ? [E_NOTICE, 'Undefined variable: a'] : [E_WARNING, 'Undefined variable $a'])); +Assert::error(fn() => Strings::replace('hello', '#.+#', function ($m) { + $a++; // E_NOTICE + return strtoupper($m[0]); +}), ...(PHP_VERSION_ID < 80000 ? [E_NOTICE, 'Undefined variable: a'] : [E_WARNING, 'Undefined variable $a'])); Assert::same('HELLO', Strings::replace('hello', '#.+#', function ($m) { @@ -28,6 +26,8 @@ Assert::same('HELLO', Strings::replace('hello', '#.+#', function ($m) { })); -Assert::exception(function () { - Strings::replace('hello', '#.+#', [stdClass::class, 'foobar']); -}, InvalidStateException::class, "Callback 'stdClass::foobar' is not callable."); +Assert::exception( + fn() => Strings::replace('hello', '#.+#', [stdClass::class, 'foobar']), + InvalidStateException::class, + "Callback 'stdClass::foobar' is not callable.", +); diff --git a/tests/Utils/Strings.startsWith().phpt b/tests/Utils/Strings.startsWith().phpt index eeed92076..5945f4bc6 100644 --- a/tests/Utils/Strings.startsWith().phpt +++ b/tests/Utils/Strings.startsWith().phpt @@ -13,9 +13,10 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -Assert::exception(function () { - Strings::startsWith('123', null); -}, TypeError::class); +Assert::exception( + fn() => Strings::startsWith('123', null), + TypeError::class, +); Assert::true(Strings::startsWith('123', ''), "startsWith('123', '')"); Assert::true(Strings::startsWith('123', '1'), "startsWith('123', '1')"); Assert::false(Strings::startsWith('123', '2'), "startsWith('123', '2')"); diff --git a/tests/Utils/Strings.toAscii().phpt b/tests/Utils/Strings.toAscii().phpt index 56cc5c8b5..1d6c4aee9 100644 --- a/tests/Utils/Strings.toAscii().phpt +++ b/tests/Utils/Strings.toAscii().phpt @@ -21,9 +21,12 @@ Assert::same('', Strings::toAscii("\u{10000}")); // U+10000 Assert::same('', Strings::toAscii("\u{A4}")); // non-ASCII char Assert::same('a b', Strings::toAscii("a\u{A0}b")); // non-breaking space Assert::same('Tarikh', Strings::toAscii("Ta\u{2BE}rikh")); // Taʾrikh -Assert::exception(function () { - Strings::toAscii("0123456789\xFF"); -}, Nette\Utils\RegexpException::class, null, PREG_BAD_UTF8_ERROR); +Assert::exception( + fn() => Strings::toAscii("0123456789\xFF"), + Nette\Utils\RegexpException::class, + null, + PREG_BAD_UTF8_ERROR, +); if (class_exists('Transliterator') && Transliterator::create('Any-Latin; Latin-ASCII')) { Assert::same('Athena->Moskva', Strings::toAscii("\u{391}\u{3B8}\u{3AE}\u{3BD}\u{3B1}\u{2192}\u{41C}\u{43E}\u{441}\u{43A}\u{432}\u{430}")); // Αθήνα→Москва diff --git a/tests/Utils/Strings.trim().phpt b/tests/Utils/Strings.trim().phpt index e9224837a..b271f9ca7 100644 --- a/tests/Utils/Strings.trim().phpt +++ b/tests/Utils/Strings.trim().phpt @@ -18,6 +18,8 @@ Assert::same('a b', Strings::trim(' a b ')); Assert::same(' a b ', Strings::trim(' a b ', '')); Assert::same('e', Strings::trim("\u{158}e-", "\u{158}-")); // Ře- -Assert::exception(function () { - Strings::trim("\xC2x\xA0"); -}, Nette\Utils\RegexpException::class, null); +Assert::exception( + fn() => Strings::trim("\xC2x\xA0"), + Nette\Utils\RegexpException::class, + null, +); diff --git a/tests/Utils/Strings.webalize().phpt b/tests/Utils/Strings.webalize().phpt index fa7314110..995f44fc0 100644 --- a/tests/Utils/Strings.webalize().phpt +++ b/tests/Utils/Strings.webalize().phpt @@ -20,6 +20,9 @@ if (class_exists('Transliterator') && Transliterator::create('Any-Latin; Latin-A } Assert::same('a-b', Strings::webalize("a\u{A0}b")); // non-breaking space -Assert::exception(function () { - Strings::toAscii("0123456789\xFF"); -}, Nette\Utils\RegexpException::class, null, PREG_BAD_UTF8_ERROR); +Assert::exception( + fn() => Strings::toAscii("0123456789\xFF"), + Nette\Utils\RegexpException::class, + null, + PREG_BAD_UTF8_ERROR, +); diff --git a/tests/Utils/Type.fromReflection.function.81.phpt b/tests/Utils/Type.fromReflection.function.81.phpt index aa58483c4..450369de4 100644 --- a/tests/Utils/Type.fromReflection.function.81.phpt +++ b/tests/Utils/Type.fromReflection.function.81.phpt @@ -43,7 +43,7 @@ Assert::same(['mixed'], $type->getNames()); Assert::same('mixed', (string) $type); -$type = Type::fromReflection(new ReflectionFunction(function (): Bar&Foo {})); +$type = Type::fromReflection(new ReflectionFunction(function (): Bar & Foo {})); Assert::same(['Bar', 'Foo'], $type->getNames()); Assert::same('Bar&Foo', (string) $type); diff --git a/tests/Utils/Validators.assert().phpt b/tests/Utils/Validators.assert().phpt index e561c4bb7..6604a82e2 100644 --- a/tests/Utils/Validators.assert().phpt +++ b/tests/Utils/Validators.assert().phpt @@ -13,46 +13,68 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -Assert::exception(function () { - Validators::assert(true, 'int'); -}, Nette\Utils\AssertionException::class, 'The variable expects to be int, bool given.'); - -Assert::exception(function () { - Validators::assert('', 'int'); -}, Nette\Utils\AssertionException::class, "The variable expects to be int, string '' given."); - -Assert::exception(function () { - Validators::assert(str_repeat('x', 1000), 'int'); -}, Nette\Utils\AssertionException::class, 'The variable expects to be int, string given.'); - -Assert::exception(function () { - Validators::assert('1.0', 'int|float'); -}, Nette\Utils\AssertionException::class, "The variable expects to be int or float, string '1.0' given."); - -Assert::exception(function () { - Validators::assert(null, 'int'); -}, Nette\Utils\AssertionException::class, 'The variable expects to be int, null given.'); - -Assert::exception(function () { - Validators::assert(1.0, 'int'); -}, Nette\Utils\AssertionException::class, 'The variable expects to be int, float 1.0 given.'); - -Assert::exception(function () { - Validators::assert(1, 'float'); -}, Nette\Utils\AssertionException::class, 'The variable expects to be float, int 1 given.'); - -Assert::exception(function () { - Validators::assert([], 'int'); -}, Nette\Utils\AssertionException::class, 'The variable expects to be int, array given.'); - -Assert::exception(function () { - Validators::assert(new stdClass, 'int'); -}, Nette\Utils\AssertionException::class, 'The variable expects to be int, object stdClass given.'); - -Assert::exception(function () { - Validators::assert(1, 'string|integer:2..5', 'variable'); -}, Nette\Utils\AssertionException::class, 'The variable expects to be string or integer in range 2..5, int 1 given.'); - -Assert::exception(function () { - Validators::assert('x', '?int'); -}, Nette\Utils\AssertionException::class, "The variable expects to be ?int, string 'x' given."); +Assert::exception( + fn() => Validators::assert(true, 'int'), + Nette\Utils\AssertionException::class, + 'The variable expects to be int, bool given.', +); + +Assert::exception( + fn() => Validators::assert('', 'int'), + Nette\Utils\AssertionException::class, + "The variable expects to be int, string '' given.", +); + +Assert::exception( + fn() => Validators::assert(str_repeat('x', 1000), 'int'), + Nette\Utils\AssertionException::class, + 'The variable expects to be int, string given.', +); + +Assert::exception( + fn() => Validators::assert('1.0', 'int|float'), + Nette\Utils\AssertionException::class, + "The variable expects to be int or float, string '1.0' given.", +); + +Assert::exception( + fn() => Validators::assert(null, 'int'), + Nette\Utils\AssertionException::class, + 'The variable expects to be int, null given.', +); + +Assert::exception( + fn() => Validators::assert(1.0, 'int'), + Nette\Utils\AssertionException::class, + 'The variable expects to be int, float 1.0 given.', +); + +Assert::exception( + fn() => Validators::assert(1, 'float'), + Nette\Utils\AssertionException::class, + 'The variable expects to be float, int 1 given.', +); + +Assert::exception( + fn() => Validators::assert([], 'int'), + Nette\Utils\AssertionException::class, + 'The variable expects to be int, array given.', +); + +Assert::exception( + fn() => Validators::assert(new stdClass, 'int'), + Nette\Utils\AssertionException::class, + 'The variable expects to be int, object stdClass given.', +); + +Assert::exception( + fn() => Validators::assert(1, 'string|integer:2..5', 'variable'), + Nette\Utils\AssertionException::class, + 'The variable expects to be string or integer in range 2..5, int 1 given.', +); + +Assert::exception( + fn() => Validators::assert('x', '?int'), + Nette\Utils\AssertionException::class, + "The variable expects to be ?int, string 'x' given.", +); diff --git a/tests/Utils/Validators.assertField().phpt b/tests/Utils/Validators.assertField().phpt index 80d15cd56..052d1b6f5 100644 --- a/tests/Utils/Validators.assertField().phpt +++ b/tests/Utils/Validators.assertField().phpt @@ -15,16 +15,21 @@ require __DIR__ . '/../bootstrap.php'; $arr = ['first' => true]; -Assert::exception(function () use ($arr) { - Validators::assertField(null, 'foo', 'foo'); -}, TypeError::class); +Assert::exception( + fn() => Validators::assertField(null, 'foo', 'foo'), + TypeError::class, +); -Assert::exception(function () use ($arr) { - Validators::assertField($arr, 'second', 'int'); -}, Nette\Utils\AssertionException::class, "Missing item 'second' in array."); +Assert::exception( + fn() => Validators::assertField($arr, 'second', 'int'), + Nette\Utils\AssertionException::class, + "Missing item 'second' in array.", +); Validators::assertField($arr, 'first'); -Assert::exception(function () use ($arr) { - Validators::assertField($arr, 'first', 'int'); -}, Nette\Utils\AssertionException::class, "The item 'first' in array expects to be int, bool given."); +Assert::exception( + fn() => Validators::assertField($arr, 'first', 'int'), + Nette\Utils\AssertionException::class, + "The item 'first' in array expects to be int, bool given.", +); From 85e5f2fac072bcf88bfc1d836bf942b508ca3dfc Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 19:15:56 +0100 Subject: [PATCH 11/30] added property typehints --- src/Iterators/CachingIterator.php | 3 +-- src/Utils/ArrayList.php | 3 +-- src/Utils/Html.php | 12 +++++------- src/Utils/Image.php | 3 +-- src/Utils/Paginator.php | 12 ++++-------- src/Utils/Type.php | 11 +++-------- tests/Utils/SmartObject.arrayProperty.phpt | 2 +- 7 files changed, 16 insertions(+), 30 deletions(-) diff --git a/src/Iterators/CachingIterator.php b/src/Iterators/CachingIterator.php index cf8f6785f..f368d1a60 100644 --- a/src/Iterators/CachingIterator.php +++ b/src/Iterators/CachingIterator.php @@ -28,8 +28,7 @@ class CachingIterator extends \CachingIterator implements \Countable { use Nette\SmartObject; - /** @var int */ - private $counter = 0; + private int $counter = 0; public function __construct($iterator) diff --git a/src/Utils/ArrayList.php b/src/Utils/ArrayList.php index de9220922..938a921fd 100644 --- a/src/Utils/ArrayList.php +++ b/src/Utils/ArrayList.php @@ -20,8 +20,7 @@ class ArrayList implements \ArrayAccess, \Countable, \IteratorAggregate { use Nette\SmartObject; - /** @var mixed[] */ - private $list = []; + private array $list = []; /** diff --git a/src/Utils/Html.php b/src/Utils/Html.php index b052b1735..67c9e9036 100644 --- a/src/Utils/Html.php +++ b/src/Utils/Html.php @@ -238,10 +238,9 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** @var array element's attributes */ public $attrs = []; - /** @var bool use XHTML syntax? */ - public static $xhtml = false; + public static bool $xhtml = false; - /** @var array void elements */ + /** void elements */ public static $emptyElements = [ 'img' => 1, 'hr' => 1, 'br' => 1, 'input' => 1, 'meta' => 1, 'area' => 1, 'embed' => 1, 'keygen' => 1, 'source' => 1, 'base' => 1, 'col' => 1, 'link' => 1, 'param' => 1, 'basefont' => 1, 'frame' => 1, @@ -251,11 +250,10 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** @var array nodes */ protected $children = []; - /** @var string element's name */ - private $name; + /** element's name */ + private string $name = ''; - /** @var bool is element empty? */ - private $isEmpty; + private bool $isEmpty = false; /** diff --git a/src/Utils/Image.php b/src/Utils/Image.php index 2db8490ca..af8169a82 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -126,8 +126,7 @@ class Image private const Formats = [self::JPEG => 'jpeg', self::PNG => 'png', self::GIF => 'gif', self::WEBP => 'webp', self::AVIF => 'avif', self::BMP => 'bmp']; - /** @var resource|\GdImage */ - private $image; + private \GdImage $image; /** diff --git a/src/Utils/Paginator.php b/src/Utils/Paginator.php index 4517a8cc3..636570ac3 100644 --- a/src/Utils/Paginator.php +++ b/src/Utils/Paginator.php @@ -34,17 +34,13 @@ class Paginator { use Nette\SmartObject; - /** @var int */ - private $base = 1; + private int $base = 1; - /** @var int */ - private $itemsPerPage = 1; + private int $itemsPerPage = 1; - /** @var int */ - private $page = 1; + private int $page = 1; - /** @var int|null */ - private $itemCount; + private ?int $itemCount = null; /** diff --git a/src/Utils/Type.php b/src/Utils/Type.php index 9e7822f8e..067faa2b2 100644 --- a/src/Utils/Type.php +++ b/src/Utils/Type.php @@ -17,14 +17,9 @@ */ final class Type { - /** @var array */ - private $types; - - /** @var bool */ - private $single; - - /** @var string |, & */ - private $kind; + private array $types; + private bool $single; + private string $kind; // | & /** diff --git a/tests/Utils/SmartObject.arrayProperty.phpt b/tests/Utils/SmartObject.arrayProperty.phpt index bc6f0ba1c..f935ff943 100644 --- a/tests/Utils/SmartObject.arrayProperty.phpt +++ b/tests/Utils/SmartObject.arrayProperty.phpt @@ -18,7 +18,7 @@ class TestClass { use Nette\SmartObject; - private $items = []; + private array $items = []; public function &getItems() From 35e81ad7c43f1fefdd36240945bfeec5ddfdc43c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 12 Dec 2021 18:05:45 +0100 Subject: [PATCH 12/30] added PHP 8 typehints --- src/Iterators/CachingIterator.php | 6 +- src/Iterators/Mapper.php | 3 +- src/SmartObject.php | 20 ++--- src/StaticClass.php | 3 +- src/Translator.php | 4 +- src/Utils/ArrayHash.php | 6 +- src/Utils/ArrayList.php | 8 +- src/Utils/Arrays.php | 43 ++++------ src/Utils/Callback.php | 15 ++-- src/Utils/DateTime.php | 25 ++---- src/Utils/Helpers.php | 10 +-- src/Utils/Html.php | 75 +++++------------ src/Utils/Image.php | 82 +++++++------------ src/Utils/Json.php | 6 +- src/Utils/ObjectHelpers.php | 4 +- src/Utils/Paginator.php | 12 +-- src/Utils/Reflection.php | 10 +-- src/Utils/Strings.php | 9 +- src/Utils/Type.php | 11 ++- src/Utils/Validators.php | 31 +++---- tests/Utils/Arrays.get().phpt | 2 +- tests/Utils/Arrays.getKeyOffset().phpt | 1 - tests/Utils/Arrays.getRef().phpt | 2 +- tests/Utils/Arrays.pick().phpt | 2 +- tests/Utils/Arrays.renameKey().phpt | 2 +- tests/Utils/DateTime.createFromFormat.phpt | 6 -- .../Strings.replace().errors.callback.phpt | 8 -- 27 files changed, 138 insertions(+), 268 deletions(-) diff --git a/src/Iterators/CachingIterator.php b/src/Iterators/CachingIterator.php index f368d1a60..55368d9d7 100644 --- a/src/Iterators/CachingIterator.php +++ b/src/Iterators/CachingIterator.php @@ -147,9 +147,8 @@ public function rewind(): void /** * Returns the next key. - * @return mixed */ - public function getNextKey() + public function getNextKey(): mixed { return $this->getInnerIterator()->key(); } @@ -157,9 +156,8 @@ public function getNextKey() /** * Returns the next element. - * @return mixed */ - public function getNextValue() + public function getNextValue(): mixed { return $this->getInnerIterator()->current(); } diff --git a/src/Iterators/Mapper.php b/src/Iterators/Mapper.php index 1a8647c60..87823baf9 100644 --- a/src/Iterators/Mapper.php +++ b/src/Iterators/Mapper.php @@ -27,8 +27,7 @@ public function __construct(\Traversable $iterator, callable $callback) } - #[\ReturnTypeWillChange] - public function current() + public function current(): mixed { return ($this->callback)(parent::current(), parent::key()); } diff --git a/src/SmartObject.php b/src/SmartObject.php index 7d4f30368..f7824c981 100644 --- a/src/SmartObject.php +++ b/src/SmartObject.php @@ -24,7 +24,7 @@ trait SmartObject /** * @throws MemberAccessException */ - public function __call(string $name, array $args) + public function __call(string $name, array $args): mixed { $class = static::class; @@ -37,26 +37,27 @@ public function __call(string $name, array $args) } elseif ($handlers !== null) { throw new UnexpectedValueException("Property $class::$$name must be iterable or null, " . gettype($handlers) . ' given.'); } - } else { - ObjectHelpers::strictCall($class, $name); + + return null; } + + ObjectHelpers::strictCall($class, $name); } /** * @throws MemberAccessException */ - public static function __callStatic(string $name, array $args) + public static function __callStatic(string $name, array $args): mixed { ObjectHelpers::strictStaticCall(static::class, $name); } /** - * @return mixed * @throws MemberAccessException if the property is not defined. */ - public function &__get(string $name) + public function &__get(string $name): mixed { $class = static::class; @@ -87,11 +88,9 @@ public function &__get(string $name) /** - * @param mixed $value - * @return void * @throws MemberAccessException if the property is not defined or is read-only */ - public function __set(string $name, $value) + public function __set(string $name, mixed $value): void { $class = static::class; @@ -121,10 +120,9 @@ public function __set(string $name, $value) /** - * @return void * @throws MemberAccessException */ - public function __unset(string $name) + public function __unset(string $name): void { $class = static::class; if (!ObjectHelpers::hasProperty($class, $name)) { diff --git a/src/StaticClass.php b/src/StaticClass.php index 8fed0ef31..c719e3b6f 100644 --- a/src/StaticClass.php +++ b/src/StaticClass.php @@ -27,10 +27,9 @@ final public function __construct() /** * Call to undefined static method. - * @return void * @throws MemberAccessException */ - public static function __callStatic(string $name, array $args) + public static function __callStatic(string $name, array $args): mixed { Utils\ObjectHelpers::strictStaticCall(static::class, $name); } diff --git a/src/Translator.php b/src/Translator.php index 0f343a274..e8c5f7d06 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -17,10 +17,8 @@ interface Translator { /** * Translates the given string. - * @param mixed $message - * @param mixed ...$parameters */ - function translate($message, ...$parameters): string; + function translate(mixed $message, mixed ...$parameters): string; } diff --git a/src/Utils/ArrayHash.php b/src/Utils/ArrayHash.php index 46cad2ba0..a2ed381a7 100644 --- a/src/Utils/ArrayHash.php +++ b/src/Utils/ArrayHash.php @@ -21,9 +21,8 @@ class ArrayHash extends \stdClass implements \ArrayAccess, \Countable, \Iterator /** * Transforms array to ArrayHash. * @param array $array - * @return static */ - public static function from(array $array, bool $recursive = true) + public static function from(array $array, bool $recursive = true): static { $obj = new static; foreach ($array as $key => $value) { @@ -75,8 +74,7 @@ public function offsetSet($key, $value): void * @param string|int $key * @return T */ - #[\ReturnTypeWillChange] - public function offsetGet($key) + public function offsetGet($key): mixed { return $this->$key; } diff --git a/src/Utils/ArrayList.php b/src/Utils/ArrayList.php index 938a921fd..54684c751 100644 --- a/src/Utils/ArrayList.php +++ b/src/Utils/ArrayList.php @@ -26,9 +26,8 @@ class ArrayList implements \ArrayAccess, \Countable, \IteratorAggregate /** * Transforms array to ArrayList. * @param array $array - * @return static */ - public static function from(array $array) + public static function from(array $array): static { if (!Arrays::isList($array)) { throw new Nette\InvalidArgumentException('Array is not valid list.'); @@ -85,8 +84,7 @@ public function offsetSet($index, $value): void * @return T * @throws Nette\OutOfRangeException */ - #[\ReturnTypeWillChange] - public function offsetGet($index) + public function offsetGet($index): mixed { if (!is_int($index) || $index < 0 || $index >= count($this->list)) { throw new Nette\OutOfRangeException('Offset invalid or out of range'); @@ -125,7 +123,7 @@ public function offsetUnset($index): void * Prepends a item. * @param T $value */ - public function prepend($value): void + public function prepend(mixed $value): void { $first = array_slice($this->list, 0, 1); $this->offsetSet(0, $value); diff --git a/src/Utils/Arrays.php b/src/Utils/Arrays.php index 2aea25fa9..9f79fbe8f 100644 --- a/src/Utils/Arrays.php +++ b/src/Utils/Arrays.php @@ -29,7 +29,7 @@ class Arrays * @return ?T * @throws Nette\InvalidArgumentException if item does not exist and default value is not provided */ - public static function get(array $array, $key, $default = null) + public static function get(array $array, string|int|array $key, mixed $default = null): mixed { foreach (is_array($key) ? $key : [$key] as $k) { if (is_array($array) && array_key_exists($k, $array)) { @@ -55,7 +55,7 @@ public static function get(array $array, $key, $default = null) * @return ?T * @throws Nette\InvalidArgumentException if traversed item is not an array */ - public static function &getRef(array &$array, $key) + public static function &getRef(array &$array, string|int|array $key): mixed { foreach (is_array($key) ? $key : [$key] as $k) { if (is_array($array) || $array === null) { @@ -94,10 +94,8 @@ public static function mergeTree(array $array1, array $array2): array /** * Returns zero-indexed position of given array key. Returns null if key is not found. - * @param array-key $key - * @return int|null offset if it is found, null otherwise */ - public static function getKeyOffset(array $array, $key): ?int + public static function getKeyOffset(array $array, string|int $key): ?int { return Helpers::falseToNull(array_search(self::toKey($key), array_keys($array), true)); } @@ -114,9 +112,8 @@ public static function searchKey(array $array, $key): ?int /** * Tests an array for the presence of value. - * @param mixed $value */ - public static function contains(array $array, $value): bool + public static function contains(array $array, mixed $value): bool { return in_array($value, $array, true); } @@ -128,7 +125,7 @@ public static function contains(array $array, $value): bool * @param array $array * @return ?T */ - public static function first(array $array) + public static function first(array $array): mixed { return count($array) ? reset($array) : null; } @@ -140,7 +137,7 @@ public static function first(array $array) * @param array $array * @return ?T */ - public static function last(array $array) + public static function last(array $array): mixed { return count($array) ? end($array) : null; } @@ -149,9 +146,8 @@ public static function last(array $array) /** * Inserts the contents of the $inserted array into the $array immediately after the $key. * If $key is null (or does not exist), it is inserted at the beginning. - * @param array-key|null $key */ - public static function insertBefore(array &$array, $key, array $inserted): void + public static function insertBefore(array &$array, string|int|null $key, array $inserted): void { $offset = $key === null ? 0 : (int) self::getKeyOffset($array, $key); $array = array_slice($array, 0, $offset, true) @@ -163,9 +159,8 @@ public static function insertBefore(array &$array, $key, array $inserted): void /** * Inserts the contents of the $inserted array into the $array before the $key. * If $key is null (or does not exist), it is inserted at the end. - * @param array-key|null $key */ - public static function insertAfter(array &$array, $key, array $inserted): void + public static function insertAfter(array &$array, string|int|null $key, array $inserted): void { if ($key === null || ($offset = self::getKeyOffset($array, $key)) === null) { $offset = count($array) - 1; @@ -179,10 +174,8 @@ public static function insertAfter(array &$array, $key, array $inserted): void /** * Renames key in array. - * @param array-key $oldKey - * @param array-key $newKey */ - public static function renameKey(array &$array, $oldKey, $newKey): bool + public static function renameKey(array &$array, string|int $oldKey, string|int $newKey): bool { $offset = self::getKeyOffset($array, $oldKey); if ($offset === null) { @@ -225,9 +218,8 @@ public static function flatten(array $array, bool $preserveKeys = false): array /** * Checks if the array is indexed in ascending order of numeric keys from zero, a.k.a list. - * @param mixed $value */ - public static function isList($value): bool + public static function isList(mixed $value): bool { return is_array($value) && (PHP_VERSION_ID < 80100 ? !$value || array_keys($value) === range(0, count($value) - 1) @@ -239,9 +231,8 @@ public static function isList($value): bool /** * Reformats table to associative tree. Path looks like 'field|field[]field->field=field'. * @param string|string[] $path - * @return array|\stdClass */ - public static function associate(array $array, $path) + public static function associate(array $array, $path): array|\stdClass { $parts = is_array($path) ? $path @@ -293,9 +284,8 @@ public static function associate(array $array, $path) /** * Normalizes array to associative array. Replace numeric keys with their values, the new value will be $filling. - * @param mixed $filling */ - public static function normalize(array $array, $filling = null): array + public static function normalize(array $array, mixed $filling = null): array { $res = []; foreach ($array as $k => $v) { @@ -311,12 +301,11 @@ public static function normalize(array $array, $filling = null): array * or returns $default, if provided. * @template T * @param array $array - * @param array-key $key * @param ?T $default * @return ?T * @throws Nette\InvalidArgumentException if item does not exist and default value is not provided */ - public static function pick(array &$array, $key, $default = null) + public static function pick(array &$array, string|int $key, mixed $default = null): mixed { if (array_key_exists($key, $array)) { $value = $array[$key]; @@ -415,7 +404,7 @@ public static function invokeMethod(iterable $objects, string $method, ...$args) * @param T $object * @return T */ - public static function toObject(iterable $array, $object) + public static function toObject(iterable $array, object $object): object { foreach ($array as $k => $v) { $object->$k = $v; @@ -427,10 +416,8 @@ public static function toObject(iterable $array, $object) /** * Converts value to array key. - * @param mixed $value - * @return array-key */ - public static function toKey($value) + public static function toKey(mixed $value): int|string { return key([$value => null]); } diff --git a/src/Utils/Callback.php b/src/Utils/Callback.php index f7a0f39ad..1b9583c3d 100644 --- a/src/Utils/Callback.php +++ b/src/Utils/Callback.php @@ -22,9 +22,8 @@ final class Callback /** * Invokes internal PHP function with own error handler. - * @return mixed */ - public static function invokeSafe(string $function, array $args, callable $onError) + public static function invokeSafe(string $function, array $args, callable $onError): mixed { $prev = set_error_handler(function ($severity, $message, $file) use ($onError, &$prev, $function): ?bool { if ($file === __FILE__) { @@ -51,11 +50,10 @@ public static function invokeSafe(string $function, array $args, callable $onErr /** * Checks that $callable is valid PHP callback. Otherwise throws exception. If the $syntax is set to true, only verifies * that $callable has a valid structure to be used as a callback, but does not verify if the class or method actually exists. - * @param mixed $callable * @return callable * @throws Nette\InvalidArgumentException */ - public static function check($callable, bool $syntax = false) + public static function check(mixed $callable, bool $syntax = false) { if (!is_callable($callable, $syntax)) { throw new Nette\InvalidArgumentException( @@ -71,9 +69,8 @@ public static function check($callable, bool $syntax = false) /** * Converts PHP callback to textual form. Class or method may not exists. - * @param mixed $callable */ - public static function toString($callable): string + public static function toString(mixed $callable): string { if ($callable instanceof \Closure) { $inner = self::unwrap($callable); @@ -88,10 +85,9 @@ public static function toString($callable): string /** * Returns reflection for method or function used in PHP callback. * @param callable $callable type check is escalated to ReflectionException - * @return \ReflectionMethod|\ReflectionFunction * @throws \ReflectionException if callback is not valid */ - public static function toReflection($callable): \ReflectionFunctionAbstract + public static function toReflection($callable): \ReflectionMethod|\ReflectionFunction { if ($callable instanceof \Closure) { $callable = self::unwrap($callable); @@ -120,9 +116,8 @@ public static function isStatic(callable $callable): bool /** * Unwraps closure created by Closure::fromCallable(). - * @return callable|array */ - public static function unwrap(\Closure $closure) + public static function unwrap(\Closure $closure): callable|array { $r = new \ReflectionFunction($closure); if (substr($r->name, -1) === '}') { diff --git a/src/Utils/DateTime.php b/src/Utils/DateTime.php index e53f41de0..963407c0d 100644 --- a/src/Utils/DateTime.php +++ b/src/Utils/DateTime.php @@ -40,11 +40,9 @@ class DateTime extends \DateTime implements \JsonSerializable /** * Creates a DateTime object from a string, UNIX timestamp, or other DateTimeInterface object. - * @param string|int|\DateTimeInterface $time - * @return static * @throws \Exception if the date and time are not valid. */ - public static function from($time) + public static function from(string|int|\DateTimeInterface|null $time): static { if ($time instanceof \DateTimeInterface) { return new static($time->format('Y-m-d H:i:s.u'), $time->getTimezone()); @@ -64,7 +62,6 @@ public static function from($time) /** * Creates DateTime object. - * @return static * @throws Nette\InvalidArgumentException if the date and time are not valid. */ public static function fromParts( @@ -74,7 +71,8 @@ public static function fromParts( int $hour = 0, int $minute = 0, float $second = 0.0, - ) { + ): static + { $s = sprintf('%04d-%02d-%02d %02d:%02d:%02.5F', $year, $month, $day, $hour, $minute, $second); if ( !checkdate($month, $day, $year) @@ -94,22 +92,18 @@ public static function fromParts( /** * Returns new DateTime object formatted according to the specified format. - * @param string $format The format the $time parameter should be in - * @param string $time - * @param string|\DateTimeZone $timezone (default timezone is used if null is passed) - * @return static|false */ - #[\ReturnTypeWillChange] - public static function createFromFormat($format, $time, $timezone = null) + public static function createFromFormat( + string $format, + string $time, + string|\DateTimeZone|null $timezone = null, + ): static|false { if ($timezone === null) { $timezone = new \DateTimeZone(date_default_timezone_get()); } elseif (is_string($timezone)) { $timezone = new \DateTimeZone($timezone); - - } elseif (!$timezone instanceof \DateTimeZone) { - throw new Nette\InvalidArgumentException('Invalid timezone given'); } $date = parent::createFromFormat($format, $time, $timezone); @@ -137,9 +131,8 @@ public function __toString(): string /** * Creates a copy with a modified time. - * @return static */ - public function modifyClone(string $modify = '') + public function modifyClone(string $modify = ''): static { $dolly = clone $this; return $modify ? $dolly->modify($modify) : $dolly; diff --git a/src/Utils/Helpers.php b/src/Utils/Helpers.php index 224a1fe5c..f27b9e7be 100644 --- a/src/Utils/Helpers.php +++ b/src/Utils/Helpers.php @@ -45,10 +45,8 @@ public static function getLastError(): string /** * Converts false to null, does not change other values. - * @param mixed $value - * @return mixed */ - public static function falseToNull($value) + public static function falseToNull(mixed $value): mixed { return $value === false ? null : $value; } @@ -56,12 +54,8 @@ public static function falseToNull($value) /** * Returns value clamped to the inclusive range of min and max. - * @param int|float $value - * @param int|float $min - * @param int|float $max - * @return int|float */ - public static function clamp($value, $min, $max) + public static function clamp(int|float $value, int|float $min, int|float $max): int|float { if ($min > $max) { throw new Nette\InvalidArgumentException("Minimum ($min) is not less than maximum ($max)."); diff --git a/src/Utils/Html.php b/src/Utils/Html.php index 67c9e9036..28f3e41d5 100644 --- a/src/Utils/Html.php +++ b/src/Utils/Html.php @@ -259,9 +259,8 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** * Constructs new HTML element. * @param array|string $attrs element's attributes or plain text content - * @return static */ - public static function el(?string $name = null, $attrs = null) + public static function el(?string $name = null, array|string|null $attrs = null): static { $el = new static; $parts = explode(' ', (string) $name, 2); @@ -287,7 +286,7 @@ public static function el(?string $name = null, $attrs = null) /** * Returns an object representing HTML text. */ - public static function fromHtml(string $html): self + public static function fromHtml(string $html): static { return (new static)->setHtml($html); } @@ -296,7 +295,7 @@ public static function fromHtml(string $html): self /** * Returns an object representing plain text. */ - public static function fromText(string $text): self + public static function fromText(string $text): static { return (new static)->setText($text); } @@ -331,9 +330,8 @@ public static function htmlToText(string $html): string /** * Changes element's name. - * @return static */ - final public function setName(string $name, ?bool $isEmpty = null) + final public function setName(string $name, ?bool $isEmpty = null): static { $this->name = $name; $this->isEmpty = $isEmpty ?? isset(static::$emptyElements[$name]); @@ -361,9 +359,8 @@ final public function isEmpty(): bool /** * Sets multiple attributes. - * @return static */ - public function addAttributes(array $attrs) + public function addAttributes(array $attrs): static { $this->attrs = array_merge($this->attrs, $attrs); return $this; @@ -372,11 +369,8 @@ public function addAttributes(array $attrs) /** * Appends value to element's attribute. - * @param mixed $value - * @param mixed $option - * @return static */ - public function appendAttribute(string $name, $value, $option = true) + public function appendAttribute(string $name, mixed $value, mixed $option = true): static { if (is_array($value)) { $prev = isset($this->attrs[$name]) ? (array) $this->attrs[$name] : []; @@ -398,10 +392,8 @@ public function appendAttribute(string $name, $value, $option = true) /** * Sets element's attribute. - * @param mixed $value - * @return static */ - public function setAttribute(string $name, $value) + public function setAttribute(string $name, mixed $value): static { $this->attrs[$name] = $value; return $this; @@ -410,9 +402,8 @@ public function setAttribute(string $name, $value) /** * Returns element's attribute. - * @return mixed */ - public function getAttribute(string $name) + public function getAttribute(string $name): mixed { return $this->attrs[$name] ?? null; } @@ -420,9 +411,8 @@ public function getAttribute(string $name) /** * Unsets element's attribute. - * @return static */ - public function removeAttribute(string $name) + public function removeAttribute(string $name): static { unset($this->attrs[$name]); return $this; @@ -431,9 +421,8 @@ public function removeAttribute(string $name) /** * Unsets element's attributes. - * @return static */ - public function removeAttributes(array $attributes) + public function removeAttributes(array $attributes): static { foreach ($attributes as $name) { unset($this->attrs[$name]); @@ -445,9 +434,8 @@ public function removeAttributes(array $attributes) /** * Overloaded setter for element's attribute. - * @param mixed $value */ - final public function __set(string $name, $value): void + final public function __set(string $name, mixed $value): void { $this->attrs[$name] = $value; } @@ -455,9 +443,8 @@ final public function __set(string $name, $value): void /** * Overloaded getter for element's attribute. - * @return mixed */ - final public function &__get(string $name) + final public function &__get(string $name): mixed { return $this->attrs[$name]; } @@ -483,9 +470,8 @@ final public function __unset(string $name): void /** * Overloaded setter for element's attribute. - * @return mixed */ - final public function __call(string $m, array $args) + final public function __call(string $m, array $args): mixed { $p = substr($m, 0, 3); if ($p === 'get' || $p === 'set' || $p === 'add') { @@ -514,9 +500,8 @@ final public function __call(string $m, array $args) /** * Special setter for element's attribute. - * @return static */ - final public function href(string $path, ?array $query = null) + final public function href(string $path, ?array $query = null): static { if ($query) { $query = http_build_query($query, '', '&'); @@ -532,10 +517,8 @@ final public function href(string $path, ?array $query = null) /** * Setter for data-* attributes. Booleans are converted to 'true' resp. 'false'. - * @param mixed $value - * @return static */ - public function data(string $name, $value = null) + public function data(string $name, mixed $value = null): static { if (func_num_args() === 1) { $this->attrs['data'] = $name; @@ -551,10 +534,8 @@ public function data(string $name, $value = null) /** * Sets element's HTML content. - * @param HtmlStringable|string $html - * @return static */ - final public function setHtml($html) + final public function setHtml(HtmlStringable|string $html): static { $this->children = [(string) $html]; return $this; @@ -572,10 +553,8 @@ final public function getHtml(): string /** * Sets element's textual content. - * @param HtmlStringable|string|int|float $text - * @return static */ - final public function setText($text) + final public function setText(HtmlStringable|string|int|float $text): static { if (!$text instanceof HtmlStringable) { $text = htmlspecialchars((string) $text, ENT_NOQUOTES, 'UTF-8'); @@ -597,10 +576,8 @@ final public function getText(): string /** * Adds new element's child. - * @param HtmlStringable|string $child Html node or raw HTML string - * @return static */ - final public function addHtml($child) + final public function addHtml(HtmlStringable|string $child): static { return $this->insert(null, $child); } @@ -608,10 +585,8 @@ final public function addHtml($child) /** * Appends plain-text string to element content. - * @param HtmlStringable|string|int|float $text - * @return static */ - public function addText($text) + public function addText(HtmlStringable|string|int|float $text): static { if (!$text instanceof HtmlStringable) { $text = htmlspecialchars((string) $text, ENT_NOQUOTES, 'UTF-8'); @@ -623,10 +598,8 @@ public function addText($text) /** * Creates and adds a new Html child. - * @param array|string $attrs element's attributes or raw HTML string - * @return static created element */ - final public function create(string $name, $attrs = null) + final public function create(string $name, array|string|null $attrs = null): static { $this->insert(null, $child = static::el($name, $attrs)); return $child; @@ -635,10 +608,8 @@ final public function create(string $name, $attrs = null) /** * Inserts child node. - * @param HtmlStringable|string $child Html node or raw HTML string - * @return static */ - public function insert(?int $index, $child, bool $replace = false) + public function insert(?int $index, HtmlStringable|string $child, bool $replace = false): static { $child = $child instanceof self ? $child : (string) $child; if ($index === null) { // append @@ -666,10 +637,8 @@ final public function offsetSet($index, $child): void /** * Returns child node (\ArrayAccess implementation). * @param int $index - * @return HtmlStringable|string */ - #[\ReturnTypeWillChange] - final public function offsetGet($index) + final public function offsetGet($index): HtmlStringable|string { return $this->children[$index]; } diff --git a/src/Utils/Image.php b/src/Utils/Image.php index af8169a82..54ac21b9b 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -92,7 +92,7 @@ * @method array ttfText($size, $angle, $x, $y, $color, string $fontfile, string $text) * @property-read int $width * @property-read int $height - * @property-read resource|\GdImage $imageResource + * @property-read \GdImage $imageResource */ class Image { @@ -147,9 +147,8 @@ public static function rgb(int $red, int $green, int $blue, int $transparency = * Reads an image from a file and returns its type in $type. * @throws Nette\NotSupportedException if gd extension is not loaded * @throws UnknownImageFileException if file not found or file type is not known - * @return static */ - public static function fromFile(string $file, ?int &$type = null) + public static function fromFile(string $file, ?int &$type = null): static { if (!extension_loaded('gd')) { throw new Nette\NotSupportedException('PHP extension GD is not loaded.'); @@ -166,11 +165,10 @@ public static function fromFile(string $file, ?int &$type = null) /** * Reads an image from a string and returns its type in $type. - * @return static * @throws Nette\NotSupportedException if gd extension is not loaded * @throws ImageException */ - public static function fromString(string $s, ?int &$type = null) + public static function fromString(string $s, ?int &$type = null): static { if (!extension_loaded('gd')) { throw new Nette\NotSupportedException('PHP extension GD is not loaded.'); @@ -185,7 +183,7 @@ public static function fromString(string $s, ?int &$type = null) } - private static function invokeSafe(string $func, string $arg, string $message, string $callee): self + private static function invokeSafe(string $func, string $arg, string $message, string $callee): static { $errors = []; $res = Callback::invokeSafe($func, [$arg], function (string $message) use (&$errors): void { @@ -204,10 +202,9 @@ private static function invokeSafe(string $func, string $arg, string $message, s /** * Creates a new true color image of the given dimensions. The default color is black. - * @return static * @throws Nette\NotSupportedException if gd extension is not loaded */ - public static function fromBlank(int $width, int $height, ?array $color = null) + public static function fromBlank(int $width, int $height, ?array $color = null): static { if (!extension_loaded('gd')) { throw new Nette\NotSupportedException('PHP extension GD is not loaded.'); @@ -289,9 +286,8 @@ public static function typeToMimeType(int $type): string /** * Wraps GD image. - * @param resource|\GdImage $image */ - public function __construct($image) + public function __construct(\GdImage $image) { $this->setImageResource($image); imagesavealpha($image, true); @@ -318,15 +314,9 @@ public function getHeight(): int /** * Sets image resource. - * @param resource|\GdImage $image - * @return static */ - protected function setImageResource($image) + protected function setImageResource(\GdImage $image): static { - if (!$image instanceof \GdImage && !(is_resource($image) && get_resource_type($image) === 'gd')) { - throw new Nette\InvalidArgumentException('Image is not valid.'); - } - $this->image = $image; return $this; } @@ -334,21 +324,17 @@ protected function setImageResource($image) /** * Returns image GD resource. - * @return resource|\GdImage */ - public function getImageResource() + public function getImageResource(): \GdImage { return $this->image; } /** - * Scales an image. - * @param int|string|null $width in pixels or percent - * @param int|string|null $height in pixels or percent - * @return static + * Scales an image. Width and height accept pixels or percent. */ - public function resize($width, $height, int $flags = self::FIT) + public function resize(int|string|null $width, int|string|null $height, int $flags = self::FIT): static { if ($flags & self::EXACT) { return $this->resize($width, $height, self::FILL)->crop('50%', '50%', $width, $height); @@ -382,9 +368,7 @@ public function resize($width, $height, int $flags = self::FIT) /** - * Calculates dimensions of resized image. - * @param int|string|null $newWidth in pixels or percent - * @param int|string|null $newHeight in pixels or percent + * Calculates dimensions of resized image. Width and height accept pixels or percent. */ public static function calculateSize( int $srcWidth, @@ -451,14 +435,9 @@ public static function calculateSize( /** - * Crops image. - * @param int|string $left in pixels or percent - * @param int|string $top in pixels or percent - * @param int|string $width in pixels or percent - * @param int|string $height in pixels or percent - * @return static + * Crops image. Arguments accepts pixels or percent. */ - public function crop($left, $top, $width, $height) + public function crop(int|string $left, int|string $top, int|string $width, int|string $height): static { [$r['x'], $r['y'], $r['width'], $r['height']] = static::calculateCutout($this->getWidth(), $this->getHeight(), $left, $top, $width, $height); @@ -476,13 +455,16 @@ public function crop($left, $top, $width, $height) /** - * Calculates dimensions of cutout in image. - * @param int|string $left in pixels or percent - * @param int|string $top in pixels or percent - * @param int|string $newWidth in pixels or percent - * @param int|string $newHeight in pixels or percent + * Calculates dimensions of cutout in image. Arguments accepts pixels or percent. */ - public static function calculateCutout(int $srcWidth, int $srcHeight, $left, $top, $newWidth, $newHeight): array + public static function calculateCutout( + int $srcWidth, + int $srcHeight, + int|string $left, + int|string $top, + int|string $newWidth, + int|string $newHeight, + ): array { if (self::isPercent($newWidth)) { $newWidth = (int) round($srcWidth / 100 * $newWidth); @@ -518,9 +500,8 @@ public static function calculateCutout(int $srcWidth, int $srcHeight, $left, $to /** * Sharpens image a little bit. - * @return static */ - public function sharpen() + public function sharpen(): static { imageconvolution($this->image, [ // my magic numbers ;) [-1, -1, -1], @@ -532,13 +513,10 @@ public function sharpen() /** - * Puts another image into this image. - * @param int|string $left in pixels or percent - * @param int|string $top in pixels or percent + * Puts another image into this image. Left and top accepts pixels or percent. * @param int $opacity 0..100 - * @return static */ - public function place(self $image, $left = 0, $top = 0, int $opacity = 100) + public function place(self $image, int|string $left = 0, int|string $top = 0, int $opacity = 100): static { $opacity = max(0, min(100, $opacity)); if ($opacity === 0) { @@ -685,10 +663,9 @@ private function output(int $type, ?int $quality, ?string $file = null): void /** * Call to undefined method. - * @return mixed * @throws Nette\MemberAccessException */ - public function __call(string $name, array $args) + public function __call(string $name, array $args): mixed { $function = 'image' . $name; if (!function_exists($function)) { @@ -717,7 +694,7 @@ public function __call(string $name, array $args) } $res = $function($this->image, ...$args); - return $res instanceof \GdImage || (is_resource($res) && get_resource_type($res) === 'gd') + return $res instanceof \GdImage ? $this->setImageResource($res) : $res; } @@ -731,10 +708,7 @@ public function __clone() } - /** - * @param int|string $num in pixels or percent - */ - private static function isPercent(&$num): bool + private static function isPercent(int|string &$num): bool { if (is_string($num) && substr($num, -1) === '%') { $num = (float) substr($num, 0, -1); diff --git a/src/Utils/Json.php b/src/Utils/Json.php index 91b8f56d3..3a9850b7a 100644 --- a/src/Utils/Json.php +++ b/src/Utils/Json.php @@ -27,10 +27,9 @@ final class Json /** * Converts value to JSON format. The flag can be Json::PRETTY, which formats JSON for easier reading and clarity, * and Json::ESCAPE_UNICODE for ASCII output. - * @param mixed $value * @throws JsonException */ - public static function encode($value, int $flags = 0): string + public static function encode(mixed $value, int $flags = 0): string { $flags = ($flags & self::ESCAPE_UNICODE ? 0 : JSON_UNESCAPED_UNICODE) | JSON_UNESCAPED_SLASHES @@ -48,10 +47,9 @@ public static function encode($value, int $flags = 0): string /** * Parses JSON to PHP value. The flag can be Json::FORCE_ARRAY, which forces an array instead of an object as the return value. - * @return mixed * @throws JsonException */ - public static function decode(string $json, int $flags = 0) + public static function decode(string $json, int $flags = 0): mixed { $value = json_decode($json, null, 512, $flags | JSON_BIGINT_AS_STRING); if ($error = json_last_error()) { diff --git a/src/Utils/ObjectHelpers.php b/src/Utils/ObjectHelpers.php index a85184b1f..f1969c2d2 100644 --- a/src/Utils/ObjectHelpers.php +++ b/src/Utils/ObjectHelpers.php @@ -205,10 +205,10 @@ private static function parseFullDoc(\ReflectionClass $rc, string $pattern): arr /** * Checks if the public non-static property exists. - * @return bool|string returns 'event' if the property exists and has event like name + * Returns 'event' if the property exists and has event like name * @internal */ - public static function hasProperty(string $class, string $name) + public static function hasProperty(string $class, string $name): bool|string { static $cache; $prop = &$cache[$class][$name]; diff --git a/src/Utils/Paginator.php b/src/Utils/Paginator.php index 636570ac3..c0e031828 100644 --- a/src/Utils/Paginator.php +++ b/src/Utils/Paginator.php @@ -45,9 +45,8 @@ class Paginator /** * Sets current page number. - * @return static */ - public function setPage(int $page) + public function setPage(int $page): static { $this->page = $page; return $this; @@ -105,9 +104,8 @@ public function getLastItemOnPage(): int /** * Sets first page (base) number. - * @return static */ - public function setBase(int $base) + public function setBase(int $base): static { $this->base = $base; return $this; @@ -168,9 +166,8 @@ public function getPageCount(): ?int /** * Sets the number of items to display on a single page. - * @return static */ - public function setItemsPerPage(int $itemsPerPage) + public function setItemsPerPage(int $itemsPerPage): static { $this->itemsPerPage = max(1, $itemsPerPage); return $this; @@ -188,9 +185,8 @@ public function getItemsPerPage(): int /** * Sets the total number of items. - * @return static */ - public function setItemCount(?int $itemCount = null) + public function setItemCount(?int $itemCount = null): static { $this->itemCount = $itemCount === null ? null : max(0, $itemCount); return $this; diff --git a/src/Utils/Reflection.php b/src/Utils/Reflection.php index 1303c7710..0d92d57a8 100644 --- a/src/Utils/Reflection.php +++ b/src/Utils/Reflection.php @@ -82,10 +82,7 @@ public static function getPropertyType(\ReflectionProperty $prop): ?string } - /** - * @param \ReflectionFunction|\ReflectionMethod|\ReflectionParameter|\ReflectionProperty $reflection - */ - private static function getType($reflection, ?\ReflectionType $type): ?string + private static function getType(\ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $reflection, ?\ReflectionType $type): ?string { if ($type === null) { return null; @@ -104,10 +101,9 @@ private static function getType($reflection, ?\ReflectionType $type): ?string /** * Returns the default value of parameter. If it is a constant, it returns its value. - * @return mixed * @throws \ReflectionException If the parameter does not have a default value or the constant cannot be resolved */ - public static function getParameterDefaultValue(\ReflectionParameter $param) + public static function getParameterDefaultValue(\ReflectionParameter $param): mixed { if ($param->isDefaultValueConstant()) { $const = $orig = $param->getDefaultValueConstantName(); @@ -374,7 +370,7 @@ private static function parseUseStatements(string $code, ?string $forClass = nul } - private static function fetch(array &$tokens, $take): ?string + private static function fetch(array &$tokens, string|int|array $take): ?string { $res = null; while ($token = current($tokens)) { diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index ee7c493cf..f672fe887 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -528,10 +528,13 @@ public static function matchAll(string $subject, string $pattern, int $flags = 0 /** * Replaces all occurrences matching regular expression $pattern which can be string or array in the form `pattern => replacement`. - * @param string|array $pattern - * @param string|callable $replacement */ - public static function replace(string $subject, $pattern, $replacement = '', int $limit = -1): string + public static function replace( + string $subject, + string|array $pattern, + string|callable $replacement = '', + int $limit = -1, + ): string { if (is_object($replacement) || is_array($replacement)) { if (!is_callable($replacement, false, $textual)) { diff --git a/src/Utils/Type.php b/src/Utils/Type.php index 067faa2b2..b0629c868 100644 --- a/src/Utils/Type.php +++ b/src/Utils/Type.php @@ -25,9 +25,10 @@ final class Type /** * Creates a Type object based on reflection. Resolves self, static and parent to the actual class name. * If the subject has no type, it returns null. - * @param \ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $reflection */ - public static function fromReflection($reflection): ?self + public static function fromReflection( + \ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $reflection, + ): ?self { if ($reflection instanceof \ReflectionMethod) { $type = $reflection->getReturnType() ?? (PHP_VERSION_ID >= 80100 ? $reflection->getTentativeReturnType() : null); @@ -84,9 +85,11 @@ public static function fromString(string $type): self /** * Resolves 'self', 'static' and 'parent' to the actual class name. - * @param \ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $reflection */ - public static function resolve(string $type, $reflection): string + public static function resolve( + string $type, + \ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $reflection, + ): string { $lower = strtolower($type); if ($reflection instanceof \ReflectionFunction) { diff --git a/src/Utils/Validators.php b/src/Utils/Validators.php index 22468ebe0..923fdbb44 100644 --- a/src/Utils/Validators.php +++ b/src/Utils/Validators.php @@ -87,10 +87,9 @@ class Validators /** * Verifies that the value is of expected types separated by pipe. - * @param mixed $value * @throws AssertionException */ - public static function assert($value, string $expected, string $label = 'variable'): void + public static function assert(mixed $value, string $expected, string $label = 'variable'): void { if (!static::is($value, $expected)) { $expected = str_replace(['|', ':'], [' or ', ' in range '], $expected); @@ -110,7 +109,6 @@ public static function assert($value, string $expected, string $label = 'variabl /** * Verifies that element $key in array is of expected types separated by pipe. * @param mixed[] $array - * @param int|string $key * @throws AssertionException */ public static function assertField( @@ -131,9 +129,8 @@ public static function assertField( /** * Verifies that the value is of expected types separated by pipe. - * @param mixed $value */ - public static function is($value, string $expected): bool + public static function is(mixed $value, string $expected): bool { foreach (explode('|', $expected) as $item) { if (substr($item, -2) === '[]') { @@ -209,9 +206,8 @@ public static function everyIs(iterable $values, string $expected): bool /** * Checks if the value is an integer or a float. - * @param mixed $value */ - public static function isNumber($value): bool + public static function isNumber(mixed $value): bool { return is_int($value) || is_float($value); } @@ -219,9 +215,8 @@ public static function isNumber($value): bool /** * Checks if the value is an integer or a integer written in a string. - * @param mixed $value */ - public static function isNumericInt($value): bool + public static function isNumericInt(mixed $value): bool { return is_int($value) || (is_string($value) && preg_match('#^[+-]?[0-9]+$#D', $value)); } @@ -229,9 +224,8 @@ public static function isNumericInt($value): bool /** * Checks if the value is a number or a number written in a string. - * @param mixed $value */ - public static function isNumeric($value): bool + public static function isNumeric(mixed $value): bool { return is_float($value) || is_int($value) || (is_string($value) && preg_match('#^[+-]?([0-9]++\.?[0-9]*|\.[0-9]+)$#D', $value)); } @@ -239,9 +233,8 @@ public static function isNumeric($value): bool /** * Checks if the value is a syntactically correct callback. - * @param mixed $value */ - public static function isCallable($value): bool + public static function isCallable(mixed $value): bool { return $value && is_callable($value, true); } @@ -249,9 +242,8 @@ public static function isCallable($value): bool /** * Checks if the value is a valid UTF-8 string. - * @param mixed $value */ - public static function isUnicode($value): bool + public static function isUnicode(mixed $value): bool { return is_string($value) && preg_match('##u', $value); } @@ -259,9 +251,8 @@ public static function isUnicode($value): bool /** * Checks if the value is 0, '', false or null. - * @param mixed $value */ - public static function isNone($value): bool + public static function isNone(mixed $value): bool { return $value == null; // intentionally == } @@ -276,10 +267,9 @@ public static function isMixed(): bool /** * Checks if a variable is a zero-based integer indexed array. - * @param mixed $value * @deprecated use Nette\Utils\Arrays::isList */ - public static function isList($value): bool + public static function isList(mixed $value): bool { return Arrays::isList($value); } @@ -288,9 +278,8 @@ public static function isList($value): bool /** * Checks if the value is in the given range [min, max], where the upper or lower limit can be omitted (null). * Numbers, strings and DateTime objects can be compared. - * @param mixed $value */ - public static function isInRange($value, array $range): bool + public static function isInRange(mixed $value, array $range): bool { if ($value === null || !(isset($range[0]) || isset($range[1]))) { return false; diff --git a/tests/Utils/Arrays.get().phpt b/tests/Utils/Arrays.get().phpt index 9b4e7d7c9..42760e943 100644 --- a/tests/Utils/Arrays.get().phpt +++ b/tests/Utils/Arrays.get().phpt @@ -22,7 +22,7 @@ $arr = [ ]; test('Single item', function () use ($arr) { - Assert::same('first', Arrays::get($arr, null)); + Assert::same('first', Arrays::get($arr, '')); Assert::same('second', Arrays::get($arr, 1)); Assert::same('second', Arrays::get($arr, 1, 'x')); Assert::same('x', Arrays::get($arr, 'undefined', 'x')); diff --git a/tests/Utils/Arrays.getKeyOffset().phpt b/tests/Utils/Arrays.getKeyOffset().phpt index 357467755..2a2826f00 100644 --- a/tests/Utils/Arrays.getKeyOffset().phpt +++ b/tests/Utils/Arrays.getKeyOffset().phpt @@ -24,6 +24,5 @@ Assert::same(3, Arrays::getKeyOffset($arr, '1')); Assert::same(3, Arrays::getKeyOffset($arr, 1)); Assert::same(2, Arrays::getKeyOffset($arr, 7)); Assert::same(1, Arrays::getKeyOffset($arr, 0)); -Assert::same(0, Arrays::getKeyOffset($arr, null)); Assert::same(0, Arrays::getKeyOffset($arr, '')); Assert::null(Arrays::getKeyOffset($arr, 'undefined')); diff --git a/tests/Utils/Arrays.getRef().phpt b/tests/Utils/Arrays.getRef().phpt index 4d4e80fad..d5675611d 100644 --- a/tests/Utils/Arrays.getRef().phpt +++ b/tests/Utils/Arrays.getRef().phpt @@ -23,7 +23,7 @@ $arr = [ test('Single item', function () use ($arr) { $dolly = $arr; - $item = &Arrays::getRef($dolly, null); + $item = &Arrays::getRef($dolly, ''); $item = 'changed'; Assert::same([ '' => 'changed', diff --git a/tests/Utils/Arrays.pick().phpt b/tests/Utils/Arrays.pick().phpt index 458d8a025..c257e21a4 100644 --- a/tests/Utils/Arrays.pick().phpt +++ b/tests/Utils/Arrays.pick().phpt @@ -20,7 +20,7 @@ $arr = [ ]; test('Single item', function () use ($arr) { - Assert::same('null', Arrays::pick($arr, null)); + Assert::same('null', Arrays::pick($arr, '')); Assert::same('first', Arrays::pick($arr, 1)); Assert::same('x', Arrays::pick($arr, 1, 'x')); Assert::exception( diff --git a/tests/Utils/Arrays.renameKey().phpt b/tests/Utils/Arrays.renameKey().phpt index c852df90f..64f58ee35 100644 --- a/tests/Utils/Arrays.renameKey().phpt +++ b/tests/Utils/Arrays.renameKey().phpt @@ -36,7 +36,7 @@ Assert::same([ 'new1' => 'third', ], $arr); -Arrays::renameKey($arr, null, 'new3'); +Arrays::renameKey($arr, '', 'new3'); Assert::same([ 'new3' => 'first', 'new2' => 'second', diff --git a/tests/Utils/DateTime.createFromFormat.phpt b/tests/Utils/DateTime.createFromFormat.phpt index 04bfc3aa7..321d43f99 100644 --- a/tests/Utils/DateTime.createFromFormat.phpt +++ b/tests/Utils/DateTime.createFromFormat.phpt @@ -22,10 +22,4 @@ Assert::same('2050-08-13 11:40:00.123450', DateTime::createFromFormat('Y-m-d H:i Assert::same('Europe/Prague', DateTime::createFromFormat('Y', '2050')->getTimezone()->getName()); Assert::same('Europe/Bratislava', DateTime::createFromFormat('Y', '2050', 'Europe/Bratislava')->getTimezone()->getName()); -Assert::exception( - fn() => DateTime::createFromFormat('Y-m-d H:i:s', '2050-08-13 11:40:00', 5), - Nette\InvalidArgumentException::class, - 'Invalid timezone given', -); - Assert::false(DateTime::createFromFormat('Y-m-d', '2014-10')); diff --git a/tests/Utils/Strings.replace().errors.callback.phpt b/tests/Utils/Strings.replace().errors.callback.phpt index f7e0493c3..0932254f2 100644 --- a/tests/Utils/Strings.replace().errors.callback.phpt +++ b/tests/Utils/Strings.replace().errors.callback.phpt @@ -6,7 +6,6 @@ declare(strict_types=1); -use Nette\InvalidStateException; use Nette\Utils\Strings; use Tester\Assert; @@ -24,10 +23,3 @@ Assert::same('HELLO', Strings::replace('hello', '#.+#', function ($m) { preg_match('#\d#u', "0123456789\xFF"); // Malformed UTF-8 data return strtoupper($m[0]); })); - - -Assert::exception( - fn() => Strings::replace('hello', '#.+#', [stdClass::class, 'foobar']), - InvalidStateException::class, - "Callback 'stdClass::foobar' is not callable.", -); From ab3099b81f85b2f5d68f00192e9eb09c46d7ad38 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 11 Mar 2021 21:55:53 +0100 Subject: [PATCH 13/30] 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 a4cd12634..000000000 --- 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 d2e219489..000000000 --- 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 75c48b6ed..000000000 --- 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 92d8a4c3a..000000000 --- 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 25adc9520..000000000 --- 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 f8aa3f408..000000000 --- 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 184152c02..000000000 --- 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 3ed69fc71e698deedd7efa3124abc0c8dc470b93 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 22 Apr 2021 18:17:33 +0200 Subject: [PATCH 14/30] tests: added --- .../SmartObject.undeclaredMethod.native.phpt | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 tests/Utils/SmartObject.undeclaredMethod.native.phpt diff --git a/tests/Utils/SmartObject.undeclaredMethod.native.phpt b/tests/Utils/SmartObject.undeclaredMethod.native.phpt new file mode 100644 index 000000000..b62ea0e01 --- /dev/null +++ b/tests/Utils/SmartObject.undeclaredMethod.native.phpt @@ -0,0 +1,163 @@ +privateMethod(); + } + + + public function callPrivateStatic() + { + static::privateStaticMethod(); + } + + + private function callPrivateParent() + { + } +} + + +class InterClass extends ParentClass +{ + public function callParents() + { + parent::callParents(); + } +} + + +class ChildClass extends InterClass +{ + public function callParents() + { + parent::callParents(); + } + + + public function callMissingParent() + { + parent::callMissingParent(); + } + + + public static function callMissingParentStatic() + { + parent::callMissingParentStatic(); + } + + + public function callPrivateParent() + { + parent::callPrivateParent(); + } + + + protected function protectedMethod() + { + } + + + protected static function protectedStaticMethod() + { + } + + + private function privateMethod() + { + } + + + private static function privateStaticMethod() + { + } +} + + + +$obj = new ParentClass; +Assert::exception( + fn() => $obj->undef(), + Error::class, + 'Call to undefined method ParentClass::undef()', +); + +$obj = new ChildClass; +Assert::exception( + fn() => $obj->undef(), + Error::class, + 'Call to undefined method ChildClass::undef()', +); + +Assert::exception( + fn() => $obj->callParents(), + Error::class, + 'Call to undefined method ParentClass::callParents()', +); + +Assert::exception( + fn() => $obj->callMissingParent(), + Error::class, + 'Call to undefined method InterClass::callMissingParent()', +); + +Assert::exception( + fn() => $obj->callMissingParentStatic(), + Error::class, + 'Call to undefined method InterClass::callMissingParentStatic()', +); + +Assert::exception( + fn() => $obj::callMissingParentStatic(), + Error::class, + 'Call to undefined method InterClass::callMissingParentStatic()', +); + +Assert::exception( + fn() => $obj->callPrivateParent(), + Error::class, + 'Call to private method ParentClass::callPrivateParent() from scope ChildClass', +); + +Assert::exception( + fn() => $obj->protectedMethod(), + Error::class, + 'Call to protected method ChildClass::protectedMethod() from global scope', +); + +Assert::exception( + fn() => $obj->protectedStaticMethod(), + Error::class, + 'Call to protected method ChildClass::protectedStaticMethod() from global scope', +); + +Assert::exception( + fn() => $obj::protectedStaticMethod(), + Error::class, + 'Call to protected method ChildClass::protectedStaticMethod() from global scope', +); + +Assert::exception( + fn() => $obj->callPrivate(), + Error::class, + 'Call to private method ChildClass::privateMethod() from scope ParentClass', +); + +Assert::exception( + fn() => $obj->callPrivateStatic(), + Error::class, + 'Call to private method ChildClass::privateStaticMethod() from scope ParentClass', +); From fd48f67210e274541221652b1294d4d96886ae06 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 28 Jul 2021 12:42:14 +0200 Subject: [PATCH 15/30] used native PHP 8 functions --- src/Utils/Callback.php | 4 ++-- src/Utils/Html.php | 4 ++-- src/Utils/Image.php | 2 +- src/Utils/Strings.php | 6 +++--- src/Utils/Validators.php | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Utils/Callback.php b/src/Utils/Callback.php index 1b9583c3d..496c1e7ab 100644 --- a/src/Utils/Callback.php +++ b/src/Utils/Callback.php @@ -93,7 +93,7 @@ public static function toReflection($callable): \ReflectionMethod|\ReflectionFun $callable = self::unwrap($callable); } - if (is_string($callable) && strpos($callable, '::')) { + if (is_string($callable) && str_contains($callable, '::')) { return new \ReflectionMethod($callable); } elseif (is_array($callable)) { return new \ReflectionMethod($callable[0], $callable[1]); @@ -120,7 +120,7 @@ public static function isStatic(callable $callable): bool public static function unwrap(\Closure $closure): callable|array { $r = new \ReflectionFunction($closure); - if (substr($r->name, -1) === '}') { + if (str_ends_with($r->name, '}')) { return $closure; } elseif ($obj = $r->getClosureThis()) { diff --git a/src/Utils/Html.php b/src/Utils/Html.php index 28f3e41d5..4043fbdbb 100644 --- a/src/Utils/Html.php +++ b/src/Utils/Html.php @@ -815,14 +815,14 @@ final public function attributes(): string $value = (string) $value; } - $q = strpos($value, '"') === false ? '"' : "'"; + $q = str_contains($value, '"') ? "'" : '"'; $s .= ' ' . $key . '=' . $q . str_replace( ['&', $q, '<'], ['&', $q === '"' ? '"' : ''', self::$xhtml ? '<' : '<'], $value, ) - . (strpos($value, '`') !== false && strpbrk($value, ' <>"\'') === false ? ' ' : '') + . (str_contains($value, '`') && strpbrk($value, ' <>"\'') === false ? ' ' : '') . $q; } diff --git a/src/Utils/Image.php b/src/Utils/Image.php index 54ac21b9b..3f8ae35aa 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -710,7 +710,7 @@ public function __clone() private static function isPercent(int|string &$num): bool { - if (is_string($num) && substr($num, -1) === '%') { + if (is_string($num) && str_ends_with($num, '%')) { $num = (float) substr($num, 0, -1); return true; } elseif (is_int($num) || $num === (string) (int) $num) { diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index f672fe887..9267c0189 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -63,7 +63,7 @@ public static function chr(int $code): string */ public static function startsWith(string $haystack, string $needle): bool { - return strncmp($haystack, $needle, strlen($needle)) === 0; + return str_starts_with($haystack, $needle); } @@ -72,7 +72,7 @@ public static function startsWith(string $haystack, string $needle): bool */ public static function endsWith(string $haystack, string $needle): bool { - return $needle === '' || substr($haystack, -strlen($needle)) === $needle; + return str_ends_with($haystack, $needle); } @@ -81,7 +81,7 @@ public static function endsWith(string $haystack, string $needle): bool */ public static function contains(string $haystack, string $needle): bool { - return strpos($haystack, $needle) !== false; + return str_contains($haystack, $needle); } diff --git a/src/Utils/Validators.php b/src/Utils/Validators.php index 923fdbb44..19f2cca5c 100644 --- a/src/Utils/Validators.php +++ b/src/Utils/Validators.php @@ -133,13 +133,13 @@ public static function assertField( public static function is(mixed $value, string $expected): bool { foreach (explode('|', $expected) as $item) { - if (substr($item, -2) === '[]') { + if (str_ends_with($item, '[]')) { if (is_iterable($value) && self::everyIs($value, substr($item, 0, -2))) { return true; } continue; - } elseif (substr($item, 0, 1) === '?') { + } elseif (str_starts_with($item, '?')) { $item = substr($item, 1); if ($value === null) { return true; From 96d090dfa010f72dc5f9695fae046b201b0088fa Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 27 Aug 2021 11:40:10 +0200 Subject: [PATCH 16/30] Reflection: uses PhpToken --- src/Utils/Reflection.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Utils/Reflection.php b/src/Utils/Reflection.php index 0d92d57a8..d2d118d0b 100644 --- a/src/Utils/Reflection.php +++ b/src/Utils/Reflection.php @@ -284,7 +284,7 @@ public static function getUseStatements(\ReflectionClass $class): array private static function parseUseStatements(string $code, ?string $forClass = null): array { try { - $tokens = token_get_all($code, TOKEN_PARSE); + $tokens = \PhpToken::tokenize($code, TOKEN_PARSE); } catch (\ParseError $e) { trigger_error($e->getMessage(), E_USER_NOTICE); $tokens = []; @@ -297,7 +297,7 @@ private static function parseUseStatements(string $code, ?string $forClass = nul while ($token = current($tokens)) { next($tokens); - switch (is_array($token) ? $token[0] : $token) { + switch ($token->id) { case T_NAMESPACE: $namespace = ltrim(self::fetch($tokens, $nameTokens) . '\\', '\\'); $uses = []; @@ -353,11 +353,11 @@ private static function parseUseStatements(string $code, ?string $forClass = nul case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: - case '{': + case ord('{'): $level++; break; - case '}': + case ord('}'): if ($level === $classLevel) { $class = $classLevel = null; } @@ -374,10 +374,9 @@ private static function fetch(array &$tokens, string|int|array $take): ?string { $res = null; while ($token = current($tokens)) { - [$token, $s] = is_array($token) ? $token : [$token, $token]; - if (in_array($token, (array) $take, true)) { - $res .= $s; - } elseif (!in_array($token, [T_DOC_COMMENT, T_WHITESPACE, T_COMMENT], true)) { + if ($token->is($take)) { + $res .= $token->text; + } elseif (!$token->is([T_DOC_COMMENT, T_WHITESPACE, T_COMMENT])) { break; } From 490d0bb300feb7b762e0f88935a68c9dc4d2d0aa Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 01:23:10 +0200 Subject: [PATCH 17/30] Reflection: getReturnType(), getParameterType(), getPropertyType() return objects Type (BC break) --- src/Utils/Reflection.php | 33 ++--------- .../Utils/Reflection.getParameterType.81.phpt | 37 ++++-------- tests/Utils/Reflection.getParameterType.phpt | 29 +++------- .../Utils/Reflection.getPropertyType.81.phpt | 37 ++++-------- tests/Utils/Reflection.getPropertyType.phpt | 27 +++------ tests/Utils/Reflection.getReturnType.81.phpt | 56 ++++++------------- tests/Utils/Reflection.getReturnType.phpt | 38 +++++-------- 7 files changed, 72 insertions(+), 185 deletions(-) diff --git a/src/Utils/Reflection.php b/src/Utils/Reflection.php index d2d118d0b..79545e4a4 100644 --- a/src/Utils/Reflection.php +++ b/src/Utils/Reflection.php @@ -51,51 +51,30 @@ public static function isClassKeyword(string $name): bool /** * Returns the type of return value of given function or method and normalizes `self`, `static`, and `parent` to actual class names. * If the function does not have a return type, it returns null. - * If the function has union or intersection type, it throws Nette\InvalidStateException. */ - public static function getReturnType(\ReflectionFunctionAbstract $func): ?string + public static function getReturnType(\ReflectionFunctionAbstract $func): ?Type { - $type = $func->getReturnType() ?? (PHP_VERSION_ID >= 80100 && $func instanceof \ReflectionMethod ? $func->getTentativeReturnType() : null); - return self::getType($func, $type); + return Type::fromReflection($func); } /** * Returns the type of given parameter and normalizes `self` and `parent` to the actual class names. * If the parameter does not have a type, it returns null. - * If the parameter has union or intersection type, it throws Nette\InvalidStateException. */ - public static function getParameterType(\ReflectionParameter $param): ?string + public static function getParameterType(\ReflectionParameter $param): ?Type { - return self::getType($param, $param->getType()); + return Type::fromReflection($param); } /** * Returns the type of given property and normalizes `self` and `parent` to the actual class names. * If the property does not have a type, it returns null. - * If the property has union or intersection type, it throws Nette\InvalidStateException. */ - public static function getPropertyType(\ReflectionProperty $prop): ?string + public static function getPropertyType(\ReflectionProperty $prop): ?Type { - return self::getType($prop, $prop->getType()); - } - - - private static function getType(\ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $reflection, ?\ReflectionType $type): ?string - { - if ($type === null) { - return null; - - } elseif ($type instanceof \ReflectionNamedType) { - return Type::resolve($type->getName(), $reflection); - - } elseif ($type instanceof \ReflectionUnionType || $type instanceof \ReflectionIntersectionType) { - throw new Nette\InvalidStateException('The ' . self::toString($reflection) . ' is not expected to have a union or intersection type.'); - - } else { - throw new Nette\InvalidStateException('Unexpected type of ' . self::toString($reflection)); - } + return Type::fromReflection($prop); } diff --git a/tests/Utils/Reflection.getParameterType.81.phpt b/tests/Utils/Reflection.getParameterType.81.phpt index 893f721d9..5adb2643c 100644 --- a/tests/Utils/Reflection.getParameterType.81.phpt +++ b/tests/Utils/Reflection.getParameterType.81.phpt @@ -43,34 +43,17 @@ class AExt extends A $method = new ReflectionMethod('A', 'method'); $params = $method->getParameters(); -Assert::same('Undeclared', Reflection::getParameterType($params[0])); -Assert::same('Test\B', Reflection::getParameterType($params[1])); -Assert::same('array', Reflection::getParameterType($params[2])); -Assert::same('callable', Reflection::getParameterType($params[3])); -Assert::same('A', Reflection::getParameterType($params[4])); +Assert::same('Undeclared', (string) Reflection::getParameterType($params[0])); +Assert::same('Test\B', (string) Reflection::getParameterType($params[1])); +Assert::same('array', (string) Reflection::getParameterType($params[2])); +Assert::same('callable', (string) Reflection::getParameterType($params[3])); +Assert::same('A', (string) Reflection::getParameterType($params[4])); Assert::null(Reflection::getParameterType($params[5])); -Assert::same('Test\B', Reflection::getParameterType($params[6])); -Assert::same('mixed', Reflection::getParameterType($params[7])); - -Assert::exception( - fn() => Reflection::getParameterType($params[8]), - Nette\InvalidStateException::class, - 'The $union in A::method() is not expected to have a union or intersection type.', -); - -Assert::exception( - fn() => Reflection::getParameterType($params[9]), - Nette\InvalidStateException::class, - 'The $nullableUnion in A::method() is not expected to have a union or intersection type.', -); - -Assert::exception( - fn() => Reflection::getParameterType($params[10]), - Nette\InvalidStateException::class, - 'The $intersection in A::method() is not expected to have a union or intersection type.', -); - +Assert::same('?Test\B', (string) Reflection::getParameterType($params[6])); +Assert::same('mixed', (string) Reflection::getParameterType($params[7])); +Assert::same('A|array', (string) Reflection::getParameterType($params[8], false)); +Assert::same('A|array|null', (string) Reflection::getParameterType($params[9], false)); $method = new ReflectionMethod('AExt', 'methodExt'); $params = $method->getParameters(); -Assert::same('A', Reflection::getParameterType($params[0])); +Assert::same('A', (string) Reflection::getParameterType($params[0])); diff --git a/tests/Utils/Reflection.getParameterType.phpt b/tests/Utils/Reflection.getParameterType.phpt index 182b9539a..616c67325 100644 --- a/tests/Utils/Reflection.getParameterType.phpt +++ b/tests/Utils/Reflection.getParameterType.phpt @@ -41,29 +41,16 @@ class AExt extends A $method = new ReflectionMethod('A', 'method'); $params = $method->getParameters(); -Assert::same('Undeclared', Reflection::getParameterType($params[0])); -Assert::same('Test\B', Reflection::getParameterType($params[1])); -Assert::same('array', Reflection::getParameterType($params[2])); -Assert::same('callable', Reflection::getParameterType($params[3])); -Assert::same('A', Reflection::getParameterType($params[4])); +Assert::same('Undeclared', (string) Reflection::getParameterType($params[0])); +Assert::same('Test\B', (string) Reflection::getParameterType($params[1])); +Assert::same('array', (string) Reflection::getParameterType($params[2])); +Assert::same('callable', (string) Reflection::getParameterType($params[3])); +Assert::same('A', (string) Reflection::getParameterType($params[4])); Assert::null(Reflection::getParameterType($params[5])); -Assert::same('Test\B', Reflection::getParameterType($params[6])); -Assert::same('mixed', Reflection::getParameterType($params[7])); - -Assert::exception( - fn() => Reflection::getParameterType($params[8]), - Nette\InvalidStateException::class, - 'The $union in A::method() is not expected to have a union or intersection type.', -); - -Assert::exception( - fn() => Reflection::getParameterType($params[9]), - Nette\InvalidStateException::class, - 'The $nullableUnion in A::method() is not expected to have a union or intersection type.', -); - +Assert::same('?Test\B', (string) Reflection::getParameterType($params[6])); +Assert::same('mixed', (string) Reflection::getParameterType($params[7])); $method = new ReflectionMethod('AExt', 'methodExt'); $params = $method->getParameters(); -Assert::same('A', Reflection::getParameterType($params[0])); +Assert::same('A', (string) Reflection::getParameterType($params[0])); diff --git a/tests/Utils/Reflection.getPropertyType.81.phpt b/tests/Utils/Reflection.getPropertyType.81.phpt index 39a35dfd8..38d42c4e0 100644 --- a/tests/Utils/Reflection.getPropertyType.81.phpt +++ b/tests/Utils/Reflection.getPropertyType.81.phpt @@ -26,7 +26,7 @@ class A public mixed $mixed; public array|self $union; public array|self|null $nullableUnion; - public AExt & A $intersection; + public AExt&A $intersection; } class AExt extends A @@ -37,33 +37,16 @@ class AExt extends A $class = new ReflectionClass('A'); $props = $class->getProperties(); -Assert::same('Undeclared', Reflection::getPropertyType($props[0])); -Assert::same('Test\B', Reflection::getPropertyType($props[1])); -Assert::same('array', Reflection::getPropertyType($props[2])); -Assert::same('A', Reflection::getPropertyType($props[3])); +Assert::same('Undeclared', (string) Reflection::getPropertyType($props[0])); +Assert::same('Test\B', (string) Reflection::getPropertyType($props[1])); +Assert::same('array', (string) Reflection::getPropertyType($props[2])); +Assert::same('A', (string) Reflection::getPropertyType($props[3])); Assert::null(Reflection::getPropertyType($props[4])); -Assert::same('Test\B', Reflection::getPropertyType($props[5])); -Assert::same('mixed', Reflection::getPropertyType($props[6])); - -Assert::exception( - fn() => Reflection::getPropertyType($props[7]), - Nette\InvalidStateException::class, - 'The A::$union is not expected to have a union or intersection type.', -); - -Assert::exception( - fn() => Reflection::getPropertyType($props[8]), - Nette\InvalidStateException::class, - 'The A::$nullableUnion is not expected to have a union or intersection type.', -); - -Assert::exception( - fn() => Reflection::getPropertyType($props[9]), - Nette\InvalidStateException::class, - 'The A::$intersection is not expected to have a union or intersection type.', -); - +Assert::same('?Test\B', (string) Reflection::getPropertyType($props[5])); +Assert::same('mixed', (string) Reflection::getPropertyType($props[6])); +Assert::same('A|array', (string) Reflection::getPropertyType($props[7], false)); +Assert::same('A|array|null', (string) Reflection::getPropertyType($props[8], false)); $class = new ReflectionClass('AExt'); $props = $class->getProperties(); -Assert::same('A', Reflection::getPropertyType($props[0])); +Assert::same('A', (string) Reflection::getPropertyType($props[0])); diff --git a/tests/Utils/Reflection.getPropertyType.phpt b/tests/Utils/Reflection.getPropertyType.phpt index fa4fbe477..44abc0630 100644 --- a/tests/Utils/Reflection.getPropertyType.phpt +++ b/tests/Utils/Reflection.getPropertyType.phpt @@ -35,27 +35,14 @@ class AExt extends A $class = new ReflectionClass('A'); $props = $class->getProperties(); -Assert::same('Undeclared', Reflection::getPropertyType($props[0])); -Assert::same('Test\B', Reflection::getPropertyType($props[1])); -Assert::same('array', Reflection::getPropertyType($props[2])); -Assert::same('A', Reflection::getPropertyType($props[3])); +Assert::same('Undeclared', (string) Reflection::getPropertyType($props[0])); +Assert::same('Test\B', (string) Reflection::getPropertyType($props[1])); +Assert::same('array', (string) Reflection::getPropertyType($props[2])); +Assert::same('A', (string) Reflection::getPropertyType($props[3])); Assert::null(Reflection::getPropertyType($props[4])); -Assert::same('Test\B', Reflection::getPropertyType($props[5])); -Assert::same('mixed', Reflection::getPropertyType($props[6])); - -Assert::exception( - fn() => Reflection::getPropertyType($props[7]), - Nette\InvalidStateException::class, - 'The A::$union is not expected to have a union or intersection type.', -); - -Assert::exception( - fn() => Reflection::getPropertyType($props[8]), - Nette\InvalidStateException::class, - 'The A::$nullableUnion is not expected to have a union or intersection type.', -); - +Assert::same('?Test\B', (string) Reflection::getPropertyType($props[5])); +Assert::same('mixed', (string) Reflection::getPropertyType($props[6])); $class = new ReflectionClass('AExt'); $props = $class->getProperties(); -Assert::same('A', Reflection::getPropertyType($props[0])); +Assert::same('A', (string) Reflection::getPropertyType($props[0])); diff --git a/tests/Utils/Reflection.getReturnType.81.phpt b/tests/Utils/Reflection.getReturnType.81.phpt index 871276ad5..f98bb946d 100644 --- a/tests/Utils/Reflection.getReturnType.81.phpt +++ b/tests/Utils/Reflection.getReturnType.81.phpt @@ -66,7 +66,7 @@ class A } - public function intersectionType(): AExt & A + public function intersectionType(): AExt&A { } } @@ -99,65 +99,45 @@ function unionType(): array|A } -function intersectionType(): AExt & A +function intersectionType(): AExt&A { } Assert::null(Reflection::getReturnType(new ReflectionMethod(A::class, 'noType'))); -Assert::same('Test\B', Reflection::getReturnType(new ReflectionMethod(A::class, 'classType'))); +Assert::same('Test\B', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'classType'))); -Assert::same('string', Reflection::getReturnType(new ReflectionMethod(A::class, 'nativeType'))); +Assert::same('string', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'nativeType'))); -Assert::same('A', Reflection::getReturnType(new ReflectionMethod(A::class, 'selfType'))); +Assert::same('A', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'selfType'))); -Assert::same('A', Reflection::getReturnType(new ReflectionMethod(A::class, 'staticType'))); +Assert::same('A', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'staticType'))); -Assert::same('Test\B', Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableClassType'))); +Assert::same('?Test\B', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableClassType'))); -Assert::same('string', Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableNativeType'))); +Assert::same('?string', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableNativeType'))); -Assert::same('A', Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableSelfType'))); +Assert::same('?A', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableSelfType'))); -Assert::exception( - fn() => Reflection::getReturnType(new ReflectionMethod(A::class, 'unionType')), - Nette\InvalidStateException::class, - 'The A::unionType() is not expected to have a union or intersection type.', -); +Assert::same('A|array', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'unionType'))); -Assert::exception( - fn() => Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableUnionType')), - Nette\InvalidStateException::class, - 'The A::nullableUnionType() is not expected to have a union or intersection type.', -); +Assert::same('A|array|null', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableUnionType'))); -Assert::exception( - fn() => Reflection::getReturnType(new ReflectionMethod(A::class, 'intersectionType')), - Nette\InvalidStateException::class, - 'The A::intersectionType() is not expected to have a union or intersection type.', -); +Assert::same('AExt&A', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'intersectionType'))); -Assert::same('A', Reflection::getReturnType(new ReflectionMethod(AExt::class, 'parentTypeExt'))); +Assert::same('A', (string) Reflection::getReturnType(new ReflectionMethod(AExt::class, 'parentTypeExt'))); Assert::null(Reflection::getReturnType(new ReflectionFunction('noType'))); -Assert::same('Test\B', Reflection::getReturnType(new ReflectionFunction('classType'))); +Assert::same('Test\B', (string) Reflection::getReturnType(new ReflectionFunction('classType'))); -Assert::same('string', Reflection::getReturnType(new ReflectionFunction('nativeType'))); +Assert::same('string', (string) Reflection::getReturnType(new ReflectionFunction('nativeType'))); -Assert::exception( - fn() => Reflection::getReturnType(new ReflectionFunction('unionType')), - Nette\InvalidStateException::class, - 'The unionType() is not expected to have a union or intersection type.', -); +Assert::same('A|array', (string) Reflection::getReturnType(new ReflectionFunction('unionType'))); -Assert::exception( - fn() => Reflection::getReturnType(new ReflectionFunction('intersectionType')), - Nette\InvalidStateException::class, - 'The intersectionType() is not expected to have a union or intersection type.', -); +Assert::same('AExt&A', (string) Reflection::getReturnType(new ReflectionFunction('intersectionType'))); // tentative type -Assert::same('int', Reflection::getReturnType(new ReflectionMethod(ArrayObject::class, 'count'))); +Assert::same('int', (string) Reflection::getReturnType(new ReflectionMethod(ArrayObject::class, 'count'))); diff --git a/tests/Utils/Reflection.getReturnType.phpt b/tests/Utils/Reflection.getReturnType.phpt index 16f57a5a8..93c0db963 100644 --- a/tests/Utils/Reflection.getReturnType.phpt +++ b/tests/Utils/Reflection.getReturnType.phpt @@ -95,42 +95,30 @@ function unionType(): array|A Assert::null(Reflection::getReturnType(new ReflectionMethod(A::class, 'noType'))); -Assert::same('Test\B', Reflection::getReturnType(new ReflectionMethod(A::class, 'classType'))); +Assert::same('Test\B', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'classType'))); -Assert::same('string', Reflection::getReturnType(new ReflectionMethod(A::class, 'nativeType'))); +Assert::same('string', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'nativeType'))); -Assert::same('A', Reflection::getReturnType(new ReflectionMethod(A::class, 'selfType'))); +Assert::same('A', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'selfType'))); -Assert::same('A', Reflection::getReturnType(new ReflectionMethod(A::class, 'staticType'))); +Assert::same('A', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'staticType'))); -Assert::same('Test\B', Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableClassType'))); +Assert::same('?Test\B', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableClassType'))); -Assert::same('string', Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableNativeType'))); +Assert::same('?string', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableNativeType'))); -Assert::same('A', Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableSelfType'))); +Assert::same('?A', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableSelfType'))); -Assert::exception( - fn() => Reflection::getReturnType(new ReflectionMethod(A::class, 'unionType')), - Nette\InvalidStateException::class, - 'The A::unionType() is not expected to have a union or intersection type.', -); +Assert::same('A|array', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'unionType'))); -Assert::exception( - fn() => Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableUnionType')), - Nette\InvalidStateException::class, - 'The A::nullableUnionType() is not expected to have a union or intersection type.', -); +Assert::same('A|array|null', (string) Reflection::getReturnType(new ReflectionMethod(A::class, 'nullableUnionType'))); -Assert::same('A', Reflection::getReturnType(new ReflectionMethod(AExt::class, 'parentTypeExt'))); +Assert::same('A', (string) Reflection::getReturnType(new ReflectionMethod(AExt::class, 'parentTypeExt'))); Assert::null(Reflection::getReturnType(new ReflectionFunction('noType'))); -Assert::same('Test\B', Reflection::getReturnType(new ReflectionFunction('classType'))); +Assert::same('Test\B', (string) Reflection::getReturnType(new ReflectionFunction('classType'))); -Assert::same('string', Reflection::getReturnType(new ReflectionFunction('nativeType'))); +Assert::same('string', (string) Reflection::getReturnType(new ReflectionFunction('nativeType'))); -Assert::exception( - fn() => Reflection::getReturnType(new ReflectionFunction('unionType')), - Nette\InvalidStateException::class, - 'The unionType() is not expected to have a union or intersection type.', -); +Assert::same('A|array', (string) Reflection::getReturnType(new ReflectionFunction('unionType'))); From aa3002f5fe92b9ec1ea6a5729a1791cd42cb7f5f Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 26 Sep 2021 12:34:29 +0200 Subject: [PATCH 18/30] Html: removed $xhtml (BC break) --- src/Utils/Html.php | 12 +++------ tests/Utils/Html.basic.phpt | 50 ++++++++++++++----------------------- 2 files changed, 22 insertions(+), 40 deletions(-) diff --git a/src/Utils/Html.php b/src/Utils/Html.php index 4043fbdbb..071105eee 100644 --- a/src/Utils/Html.php +++ b/src/Utils/Html.php @@ -238,8 +238,6 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** @var array element's attributes */ public $attrs = []; - public static bool $xhtml = false; - /** void elements */ public static $emptyElements = [ 'img' => 1, 'hr' => 1, 'br' => 1, 'input' => 1, 'meta' => 1, 'area' => 1, 'embed' => 1, 'keygen' => 1, @@ -748,7 +746,7 @@ final public function __toString(): string final public function startTag(): string { return $this->name - ? '<' . $this->name . $this->attributes() . (static::$xhtml && $this->isEmpty ? ' />' : '>') + ? '<' . $this->name . $this->attributes() . '>' : ''; } @@ -779,11 +777,7 @@ final public function attributes(): string continue; } elseif ($value === true) { - if (static::$xhtml) { - $s .= ' ' . $key . '="' . $key . '"'; - } else { - $s .= ' ' . $key; - } + $s .= ' ' . $key; continue; @@ -819,7 +813,7 @@ final public function attributes(): string $s .= ' ' . $key . '=' . $q . str_replace( ['&', $q, '<'], - ['&', $q === '"' ? '"' : ''', self::$xhtml ? '<' : '<'], + ['&', $q === '"' ? '"' : ''', '<'], $value, ) . (str_contains($value, '`') && strpbrk($value, ' <>"\'') === false ? ' ' : '') diff --git a/tests/Utils/Html.basic.phpt b/tests/Utils/Html.basic.phpt index 6e4f5c1a7..064405e5f 100644 --- a/tests/Utils/Html.basic.phpt +++ b/tests/Utils/Html.basic.phpt @@ -14,63 +14,55 @@ require __DIR__ . '/../bootstrap.php'; test('', function () { - Html::$xhtml = true; $el = Html::el('img')->src('image.gif')->alt(''); - Assert::same('', (string) $el); - Assert::same('', $el->toHtml()); - Assert::same('', $el->startTag()); + Assert::same('', (string) $el); + Assert::same('', $el->toHtml()); + Assert::same('', $el->startTag()); Assert::same('', $el->endTag()); }); test('', function () { - Html::$xhtml = true; $el = Html::el('img')->setAttribute('src', 'image.gif')->setAttribute('alt', ''); - Assert::same('', (string) $el); - Assert::same('', $el->startTag()); + Assert::same('', (string) $el); + Assert::same('', $el->startTag()); Assert::same('', $el->endTag()); }); test('', function () { - Html::$xhtml = true; $el = Html::el('img')->accesskey(0, true)->alt('alt', false); - Assert::same('', (string) $el); - Assert::same('', (string) $el->accesskey(1, true)); - Assert::same('', (string) $el->accesskey(1, false)); - Assert::same('', (string) $el->accesskey(0, true)); - Assert::same('', (string) $el->accesskey(0)); + Assert::same('', (string) $el); + Assert::same('', (string) $el->accesskey(1, true)); + Assert::same('', (string) $el->accesskey(1, false)); + Assert::same('', (string) $el->accesskey(0, true)); + Assert::same('', (string) $el->accesskey(0)); unset($el->accesskey); - Assert::same('', (string) $el); + Assert::same('', (string) $el); }); test('', function () { - Html::$xhtml = true; $el = Html::el('img')->appendAttribute('accesskey', 0)->setAttribute('alt', false); - Assert::same('', (string) $el); - Assert::same('', (string) $el->appendAttribute('accesskey', 1)); - Assert::same('', (string) $el->appendAttribute('accesskey', 1, false)); - Assert::same('', (string) $el->appendAttribute('accesskey', 0)); - Assert::same('', (string) $el->setAttribute('accesskey', 0)); - Assert::same('', (string) $el->removeAttribute('accesskey')); + Assert::same('', (string) $el); + Assert::same('', (string) $el->appendAttribute('accesskey', 1)); + Assert::same('', (string) $el->appendAttribute('accesskey', 1, false)); + Assert::same('', (string) $el->appendAttribute('accesskey', 0)); + Assert::same('', (string) $el->setAttribute('accesskey', 0)); + Assert::same('', (string) $el->removeAttribute('accesskey')); }); test('', function () { $el = Html::el('img')->src('image.gif')->alt('')->setText('any content'); - Assert::same('', (string) $el); - Assert::same('', $el->startTag()); - Assert::same('', $el->endTag()); - - Html::$xhtml = false; Assert::same('', (string) $el); + Assert::same('', $el->startTag()); + Assert::same('', $el->endTag()); }); test('', function () { - Html::$xhtml = false; $el = Html::el('img')->setSrc('image.gif')->setAlt('alt1')->setAlt('alt2'); Assert::same('alt2', (string) $el); Assert::same('image.gif', $el->getSrc()); @@ -104,10 +96,6 @@ test('small & big numbers', function () { test('attributes escaping', function () { - Html::$xhtml = true; - Assert::same('', (string) Html::el('a')->one('"')->two("'")->three('<>')->four('&')); - - Html::$xhtml = false; Assert::same('', (string) Html::el('a')->one('"')->two("'")->three('<>')->four('&')); Assert::same('', (string) Html::el('a')->one('``xx')); // mXSS }); From 8f128f6cf0d36ebeb882c4d8a01821e63192c1b7 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 9 Jan 2022 12:59:27 +0100 Subject: [PATCH 19/30] Strings, Arrays, Json, Image: $flags replaced with parameters --- src/Utils/Arrays.php | 3 +- src/Utils/Image.php | 29 ++++++++++++------- src/Utils/Json.php | 28 +++++++++++++----- src/Utils/Strings.php | 45 ++++++++++++++++++++++------- tests/Utils/Arrays.grep().phpt | 5 ++++ tests/Utils/Image.resize.phpt | 40 +++++++++++++++++++++++++ tests/Utils/Json.decode().phpt | 1 + tests/Utils/Json.encode().phpt | 2 ++ tests/Utils/Strings.match().phpt | 10 +++++-- tests/Utils/Strings.matchAll().phpt | 21 ++++++++++++-- tests/Utils/Strings.split().phpt | 16 ++++++++++ 11 files changed, 167 insertions(+), 33 deletions(-) diff --git a/src/Utils/Arrays.php b/src/Utils/Arrays.php index 9f79fbe8f..d028a87cd 100644 --- a/src/Utils/Arrays.php +++ b/src/Utils/Arrays.php @@ -196,8 +196,9 @@ public static function renameKey(array &$array, string|int $oldKey, string|int $ * @param string[] $array * @return string[] */ - public static function grep(array $array, string $pattern, int $flags = 0): array + public static function grep(array $array, string $pattern, bool|int $invert = false): array { + $flags = $invert ? PREG_GREP_INVERT : 0; return Strings::pcre('preg_grep', [$pattern, $array, $flags]); } diff --git a/src/Utils/Image.php b/src/Utils/Image.php index 3f8ae35aa..7ae32ebef 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -98,7 +98,7 @@ class Image { use Nette\SmartObject; - /** {@link resize()} only shrinks images */ + /** @deprecated */ public const SHRINK_ONLY = 0b0001; /** {@link resize()} will ignore aspect ratio */ @@ -333,14 +333,20 @@ public function getImageResource(): \GdImage /** * Scales an image. Width and height accept pixels or percent. + * @param self::FIT|self::FILL|self::STRETCH|self::EXACT $mode */ - public function resize(int|string|null $width, int|string|null $height, int $flags = self::FIT): static + public function resize( + int|string|null $width, + int|string|null $height, + int $mode = self::FIT, + bool $shrinkOnly = false, + ): static { - if ($flags & self::EXACT) { + if ($mode & self::EXACT) { return $this->resize($width, $height, self::FILL)->crop('50%', '50%', $width, $height); } - [$newWidth, $newHeight] = static::calculateSize($this->getWidth(), $this->getHeight(), $width, $height, $flags); + [$newWidth, $newHeight] = static::calculateSize($this->getWidth(), $this->getHeight(), $width, $height, $mode, $shrinkOnly); if ($newWidth !== $this->getWidth() || $newHeight !== $this->getHeight()) { // resize $newImage = static::fromBlank($newWidth, $newHeight, self::rgb(0, 0, 0, 127))->getImageResource(); @@ -369,15 +375,18 @@ public function resize(int|string|null $width, int|string|null $height, int $fla /** * Calculates dimensions of resized image. Width and height accept pixels or percent. + * @param self::FIT|self::FILL|self::STRETCH $mode */ public static function calculateSize( int $srcWidth, int $srcHeight, $newWidth, $newHeight, - int $flags = self::FIT, + int $mode = self::FIT, + bool $shrinkOnly = false, ): array { + $shrinkOnly = $shrinkOnly || ($mode & self::SHRINK_ONLY); // back compatibility if ($newWidth === null) { } elseif (self::isPercent($newWidth)) { $newWidth = (int) round($srcWidth / 100 * abs($newWidth)); @@ -389,17 +398,17 @@ public static function calculateSize( if ($newHeight === null) { } elseif (self::isPercent($newHeight)) { $newHeight = (int) round($srcHeight / 100 * abs($newHeight)); - $flags |= empty($percents) ? 0 : self::STRETCH; + $mode |= empty($percents) ? 0 : self::STRETCH; } else { $newHeight = abs($newHeight); } - if ($flags & self::STRETCH) { // non-proportional + if ($mode & self::STRETCH) { // non-proportional if (!$newWidth || !$newHeight) { throw new Nette\InvalidArgumentException('For stretching must be both width and height specified.'); } - if ($flags & self::SHRINK_ONLY) { + if ($shrinkOnly) { $newWidth = (int) round($srcWidth * min(1, $newWidth / $srcWidth)); $newHeight = (int) round($srcHeight * min(1, $newHeight / $srcHeight)); } @@ -417,11 +426,11 @@ public static function calculateSize( $scale[] = $newHeight / $srcHeight; } - if ($flags & self::FILL) { + if ($mode & self::FILL) { $scale = [max($scale)]; } - if ($flags & self::SHRINK_ONLY) { + if ($shrinkOnly) { $scale[] = 1; } diff --git a/src/Utils/Json.php b/src/Utils/Json.php index 3a9850b7a..9fc320018 100644 --- a/src/Utils/Json.php +++ b/src/Utils/Json.php @@ -25,15 +25,25 @@ final class Json /** - * Converts value to JSON format. The flag can be Json::PRETTY, which formats JSON for easier reading and clarity, - * and Json::ESCAPE_UNICODE for ASCII output. + * Converts value to JSON format. Use $pretty for easier reading and clarity and $escapeUnicode for ASCII output. * @throws JsonException */ - public static function encode(mixed $value, int $flags = 0): string + public static function encode( + mixed $value, + bool|int $pretty = false, + bool $escapeUnicode = false, + ): string { - $flags = ($flags & self::ESCAPE_UNICODE ? 0 : JSON_UNESCAPED_UNICODE) + $flags = 0; + if (is_int($pretty)) { // back compatibility + $escapeUnicode = $pretty & self::ESCAPE_UNICODE; + $flags = $pretty & ~self::ESCAPE_UNICODE; + $pretty = false; + } + + $flags |= ($escapeUnicode ? 0 : JSON_UNESCAPED_UNICODE) + | ($pretty ? JSON_PRETTY_PRINT : 0) | JSON_UNESCAPED_SLASHES - | ($flags & ~self::ESCAPE_UNICODE) | (defined('JSON_PRESERVE_ZERO_FRACTION') ? JSON_PRESERVE_ZERO_FRACTION : 0); // since PHP 5.6.6 & PECL JSON-C 1.3.7 $json = json_encode($value, $flags); @@ -46,11 +56,15 @@ public static function encode(mixed $value, int $flags = 0): string /** - * Parses JSON to PHP value. The flag can be Json::FORCE_ARRAY, which forces an array instead of an object as the return value. + * Parses JSON to PHP value. Parameter $forceArray forces an array instead of an object as the return value. * @throws JsonException */ - public static function decode(string $json, int $flags = 0): mixed + public static function decode(string $json, bool|int $forceArray = false): mixed { + $flags = is_int($forceArray) // back compatibility + ? $forceArray + : ($forceArray ? JSON_OBJECT_AS_ARRAY : 0); + $value = json_decode($json, null, 512, $flags | JSON_BIGINT_AS_STRING); if ($error = json_last_error()) { throw new JsonException(json_last_error_msg(), $error); diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index 9267c0189..e16ef1c2c 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -483,20 +483,35 @@ private static function pos(string $haystack, string $needle, int $nth = 1): ?in /** * Splits a string into array by the regular expression. Parenthesized expression in the delimiter are captured. - * Parameter $flags can be any combination of PREG_SPLIT_NO_EMPTY and PREG_OFFSET_CAPTURE flags. */ - public static function split(string $subject, string $pattern, int $flags = 0): array - { + public static function split( + string $subject, + string $pattern, + bool|int $captureOffset = false, + bool $skipEmpty = false, + ): array + { + $flags = is_int($captureOffset) && $captureOffset // back compatibility + ? $captureOffset + : ($captureOffset ? PREG_SPLIT_OFFSET_CAPTURE : 0) | ($skipEmpty ? PREG_SPLIT_NO_EMPTY : 0); return self::pcre('preg_split', [$pattern, $subject, -1, $flags | PREG_SPLIT_DELIM_CAPTURE]); } /** * Checks if given string matches a regular expression pattern and returns an array with first found match and each subpattern. - * Parameter $flags can be any combination of PREG_OFFSET_CAPTURE and PREG_UNMATCHED_AS_NULL flags. */ - public static function match(string $subject, string $pattern, int $flags = 0, int $offset = 0): ?array - { + public static function match( + string $subject, + string $pattern, + bool|int $captureOffset = false, + int $offset = 0, + bool $unmatchedAsNull = false, + ): ?array + { + $flags = is_int($captureOffset) && $captureOffset // back compatibility + ? $captureOffset + : ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0); if ($offset > strlen($subject)) { return null; } @@ -508,11 +523,21 @@ public static function match(string $subject, string $pattern, int $flags = 0, i /** - * Finds all occurrences matching regular expression pattern and returns a two-dimensional array. Result is array of matches (ie uses by default PREG_SET_ORDER). - * Parameter $flags can be any combination of PREG_OFFSET_CAPTURE, PREG_UNMATCHED_AS_NULL and PREG_PATTERN_ORDER flags. + * Finds all occurrences matching regular expression pattern and returns a two-dimensional array. + * Result is array of matches (ie uses by default PREG_SET_ORDER). */ - public static function matchAll(string $subject, string $pattern, int $flags = 0, int $offset = 0): array - { + public static function matchAll( + string $subject, + string $pattern, + bool|int $captureOffset = false, + int $offset = 0, + bool $unmatchedAsNull = false, + bool $patternOrder = false, + ): array + { + $flags = is_int($captureOffset) && $captureOffset // back compatibility + ? $captureOffset + : ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0) | ($patternOrder ? PREG_PATTERN_ORDER : 0); if ($offset > strlen($subject)) { return []; } diff --git a/tests/Utils/Arrays.grep().phpt b/tests/Utils/Arrays.grep().phpt index f356405d3..f8613b8ae 100644 --- a/tests/Utils/Arrays.grep().phpt +++ b/tests/Utils/Arrays.grep().phpt @@ -21,3 +21,8 @@ Assert::same([ 0 => 'a', 2 => 'c', ], Arrays::grep(['a', '1', 'c'], '#\d#', PREG_GREP_INVERT)); + +Assert::same([ + 0 => 'a', + 2 => 'c', +], Arrays::grep(['a', '1', 'c'], '#\d#', invert: true)); diff --git a/tests/Utils/Image.resize.phpt b/tests/Utils/Image.resize.phpt index 474169068..6300df62f 100644 --- a/tests/Utils/Image.resize.phpt +++ b/tests/Utils/Image.resize.phpt @@ -44,6 +44,14 @@ test('resizing Y shrink', function () use ($main) { }); +test('resizing Y shrink', function () use ($main) { + $image = clone $main; + $image->resize(null, 150, shrinkOnly: true); + Assert::same(176, $image->width); + Assert::same(104, $image->height); +}); + + test('resizing X Y shrink', function () use ($main) { $image = clone $main; $image->resize(300, 150, Image::SHRINK_ONLY); @@ -52,6 +60,14 @@ test('resizing X Y shrink', function () use ($main) { }); +test('resizing X Y shrink', function () use ($main) { + $image = clone $main; + $image->resize(300, 150, shrinkOnly: true); + Assert::same(176, $image->width); + Assert::same(104, $image->height); +}); + + test('resizing X Y', function () use ($main) { $image = clone $main; $image->resize(300, 150); @@ -76,6 +92,14 @@ test('resizing X Y shrink stretch', function () use ($main) { }); +test('resizing X Y shrink stretch', function () use ($main) { + $image = clone $main; + $image->resize(300, 100, Image::STRETCH, shrinkOnly: true); + Assert::same(176, $image->width); + Assert::same(100, $image->height); +}); + + test('resizing X%', function () use ($main) { $image = clone $main; $image->resize('110%', null); @@ -108,6 +132,14 @@ test('flipping Y shrink', function () use ($main) { }); +test('flipping Y shrink', function () use ($main) { + $image = clone $main; + $image->resize(null, -150, shrinkOnly: true); + Assert::same(176, $image->width); + Assert::same(104, $image->height); +}); + + test('flipping X Y shrink', function () use ($main) { $image = clone $main; $image->resize(-300, -150, Image::SHRINK_ONLY); @@ -116,6 +148,14 @@ test('flipping X Y shrink', function () use ($main) { }); +test('flipping X Y shrink', function () use ($main) { + $image = clone $main; + $image->resize(-300, -150, shrinkOnly: true); + Assert::same(176, $image->width); + Assert::same(104, $image->height); +}); + + test('exact resize', function () use ($main) { $image = clone $main; $image->resize(300, 150, Image::EXACT); diff --git a/tests/Utils/Json.decode().phpt b/tests/Utils/Json.decode().phpt index 1f71fad08..a32a51637 100644 --- a/tests/Utils/Json.decode().phpt +++ b/tests/Utils/Json.decode().phpt @@ -20,6 +20,7 @@ Assert::null(Json::decode(' null')); Assert::equal((object) ['a' => 1], Json::decode('{"a":1}')); Assert::same(['a' => 1], Json::decode('{"a":1}', Json::FORCE_ARRAY)); +Assert::same(['a' => 1], Json::decode('{"a":1}', forceArray: true)); Assert::exception( diff --git a/tests/Utils/Json.encode().phpt b/tests/Utils/Json.encode().phpt index bf2c02d97..4ef5d4166 100644 --- a/tests/Utils/Json.encode().phpt +++ b/tests/Utils/Json.encode().phpt @@ -38,10 +38,12 @@ Assert::same('"\u2028\u2029"', Json::encode("\u{2028}\u{2029}")); // ESCAPE_UNICODE Assert::same('"/I\u00f1t\u00ebrn\u00e2ti\u00f4n\u00e0liz\u00e6ti\u00f8n"', Json::encode("/I\u{F1}t\u{EB}rn\u{E2}ti\u{F4}n\u{E0}liz\u{E6}ti\u{F8}n", Json::ESCAPE_UNICODE)); Assert::same('"\u2028\u2029"', Json::encode("\u{2028}\u{2029}", Json::ESCAPE_UNICODE)); +Assert::same('"\u2028\u2029"', Json::encode("\u{2028}\u{2029}", escapeUnicode: true)); // JSON_PRETTY_PRINT Assert::same("[\n 1,\n 2,\n 3\n]", Json::encode([1, 2, 3], Json::PRETTY)); +Assert::same("[\n 1,\n 2,\n 3\n]", Json::encode([1, 2, 3], pretty: true)); Assert::exception( diff --git a/tests/Utils/Strings.match().phpt b/tests/Utils/Strings.match().phpt index 5814b5753..5b4196180 100644 --- a/tests/Utils/Strings.match().phpt +++ b/tests/Utils/Strings.match().phpt @@ -20,8 +20,12 @@ Assert::same(['hell', 'l'], Strings::match('hello world!', '#([e-l])+#')); Assert::same(['hell'], Strings::match('hello world!', '#[e-l]+#')); Assert::same([['hell', 0]], Strings::match('hello world!', '#[e-l]+#', PREG_OFFSET_CAPTURE)); +Assert::same([['hell', 0]], Strings::match('hello world!', '#[e-l]+#', captureOffset: true)); -Assert::same(['ll'], Strings::match('hello world!', '#[e-l]+#', 0, 2)); +Assert::same(['e', null], Strings::match('hello world!', '#e(x)*#', unmatchedAsNull: true)); +Assert::same(['e', null], Strings::match('hello world!', '#e(x)*#', 0, 0, unmatchedAsNull: true)); // $flags = 0 -Assert::null(Strings::match('hello world!', '', 0, 50)); -Assert::null(Strings::match('', '', 0, 1)); +Assert::same(['ll'], Strings::match('hello world!', '#[e-l]+#', offset: 2)); + +Assert::null(Strings::match('hello world!', '', offset: 50)); +Assert::null(Strings::match('', '', offset: 1)); diff --git a/tests/Utils/Strings.matchAll().phpt b/tests/Utils/Strings.matchAll().phpt index 384bbc18a..257887f95 100644 --- a/tests/Utils/Strings.matchAll().phpt +++ b/tests/Utils/Strings.matchAll().phpt @@ -32,14 +32,31 @@ Assert::same([ [['k', 14], ['k', 14], ['', 15]], ], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', PREG_OFFSET_CAPTURE)); +Assert::same([ + [['lu', 2], ['l', 2], ['u', 3]], + [['ou', 6], ['o', 6], ['u', 7]], + [['k', 10], ['k', 10], ['', 11]], + [['k', 14], ['k', 14], ['', 15]], +], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', captureOffset: true)); + Assert::same([ [['lu', 2], ['ou', 6], ['k', 10], ['k', 14]], [['l', 2], ['o', 6], ['k', 10], ['k', 14]], [['u', 3], ['u', 7], ['', 11], ['', 15]], ], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER)); -Assert::same([['l'], ['k'], ['k']], Strings::matchAll('žluťoučký kůň', '#[e-l]+#u', 0, 2)); +Assert::same([ + [['lu', 2], ['ou', 6], ['k', 10], ['k', 14]], + [['l', 2], ['o', 6], ['k', 10], ['k', 14]], + [['u', 3], ['u', 7], ['', 11], ['', 15]], +], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', captureOffset: true, patternOrder: true)); + +Assert::same([['l'], ['k'], ['k']], Strings::matchAll('žluťoučký kůň', '#[e-l]+#u', offset: 2)); Assert::same([['ll', 'l']], Strings::matchAll('hello world!', '#[e-l]+#', PREG_PATTERN_ORDER, 2)); +Assert::same([['ll', 'l']], Strings::matchAll('hello world!', '#[e-l]+#', offset: 2, patternOrder: true)); + +Assert::same([['e', null]], Strings::matchAll('hello world!', '#e(x)*#', unmatchedAsNull: true)); +Assert::same([['e', null]], Strings::matchAll('hello world!', '#e(x)*#', 0, 0, unmatchedAsNull: true)); // $flags = 0 -Assert::same([], Strings::matchAll('hello world!', '', 0, 50)); +Assert::same([], Strings::matchAll('hello world!', '', offset: 50)); diff --git a/tests/Utils/Strings.split().phpt b/tests/Utils/Strings.split().phpt index b291e9613..3a57a4c4e 100644 --- a/tests/Utils/Strings.split().phpt +++ b/tests/Utils/Strings.split().phpt @@ -29,6 +29,14 @@ Assert::same([ 'c', ], Strings::split('a, b, c', '#(,)\s*#', PREG_SPLIT_NO_EMPTY)); +Assert::same([ + 'a', + ',', + 'b', + ',', + 'c', +], Strings::split('a, b, c', '#(,)\s*#', skipEmpty: true)); + Assert::same([ ['a', 0], [',', 1], @@ -36,3 +44,11 @@ Assert::same([ [',', 4], ['c', 6], ], Strings::split('a, b, c', '#(,)\s*#', PREG_SPLIT_OFFSET_CAPTURE)); + +Assert::same([ + ['a', 0], + [',', 1], + ['b', 3], + [',', 4], + ['c', 6], +], Strings::split('a, b, c', '#(,)\s*#', captureOffset: true)); From 8e0c1e442ff38a625de7e1f2ccdf7d5b56e14041 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 25 Oct 2021 15:57:10 +0200 Subject: [PATCH 20/30] Strings::replace() added parameters $captureOffset, $unmatchedAsNull --- src/Utils/Strings.php | 5 ++++- tests/Utils/Strings.replace().phpt | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index e16ef1c2c..0979fd455 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -559,6 +559,8 @@ public static function replace( string|array $pattern, string|callable $replacement = '', int $limit = -1, + bool $captureOffset = false, + bool $unmatchedAsNull = false, ): string { if (is_object($replacement) || is_array($replacement)) { @@ -566,7 +568,8 @@ public static function replace( throw new Nette\InvalidStateException("Callback '$textual' is not callable."); } - return self::pcre('preg_replace_callback', [$pattern, $replacement, $subject, $limit]); + $flags = ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0); + return self::pcre('preg_replace_callback', [$pattern, $replacement, $subject, $limit, 0, $flags]); } elseif (is_array($pattern) && is_string(key($pattern))) { $replacement = array_values($pattern); diff --git a/tests/Utils/Strings.replace().phpt b/tests/Utils/Strings.replace().phpt index 5dda17322..8c8c0a5dc 100644 --- a/tests/Utils/Strings.replace().phpt +++ b/tests/Utils/Strings.replace().phpt @@ -34,3 +34,7 @@ Assert::same('#@ @@@#d!', Strings::replace('hello world!', [ ])); Assert::same(' !', Strings::replace('hello world!', '#\w#')); Assert::same(' !', Strings::replace('hello world!', ['#\w#'])); + +// flags & callback +Assert::same('hell0o worl9d!', Strings::replace('hello world!', '#[e-l]+#', fn($m) => implode('', $m[0]), captureOffset: true)); +Strings::replace('hello world!', '#e(x)*#', fn($m) => Assert::null($m[1]), unmatchedAsNull: true); From e5ab46351dfddbf842f5996f0d06e6be0ed59daf Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 27 Oct 2021 13:15:19 +0200 Subject: [PATCH 21/30] Strings::split() added parameter $limit --- src/Utils/Strings.php | 3 ++- tests/Utils/Strings.split().phpt | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index 0979fd455..74adccd12 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -489,12 +489,13 @@ public static function split( string $pattern, bool|int $captureOffset = false, bool $skipEmpty = false, + int $limit = -1, ): array { $flags = is_int($captureOffset) && $captureOffset // back compatibility ? $captureOffset : ($captureOffset ? PREG_SPLIT_OFFSET_CAPTURE : 0) | ($skipEmpty ? PREG_SPLIT_NO_EMPTY : 0); - return self::pcre('preg_split', [$pattern, $subject, -1, $flags | PREG_SPLIT_DELIM_CAPTURE]); + return self::pcre('preg_split', [$pattern, $subject, $limit, $flags | PREG_SPLIT_DELIM_CAPTURE]); } diff --git a/tests/Utils/Strings.split().phpt b/tests/Utils/Strings.split().phpt index 3a57a4c4e..9638b2710 100644 --- a/tests/Utils/Strings.split().phpt +++ b/tests/Utils/Strings.split().phpt @@ -52,3 +52,5 @@ Assert::same([ [',', 4], ['c', 6], ], Strings::split('a, b, c', '#(,)\s*#', captureOffset: true)); + +Assert::same(['a', ',', 'b, c'], Strings::split('a, b, c', '#(,)\s*#', limit: 2)); From ef54d69712fa39b9fef0f1f0d6ad619f0c97d1b5 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 27 Oct 2021 01:21:23 +0200 Subject: [PATCH 22/30] Strings: added support for UTF8 offsets in regexp --- src/Utils/Strings.php | 69 +++++++++++++++++++++++++++-- tests/Utils/Strings.match().phpt | 13 +++++- tests/Utils/Strings.matchAll().phpt | 17 +++++++ tests/Utils/Strings.replace().phpt | 6 +++ tests/Utils/Strings.split().phpt | 30 ++++++++++--- 5 files changed, 123 insertions(+), 12 deletions(-) diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index 74adccd12..ceac2a213 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -490,12 +490,19 @@ public static function split( bool|int $captureOffset = false, bool $skipEmpty = false, int $limit = -1, + bool $utf8 = false, ): array { $flags = is_int($captureOffset) && $captureOffset // back compatibility ? $captureOffset : ($captureOffset ? PREG_SPLIT_OFFSET_CAPTURE : 0) | ($skipEmpty ? PREG_SPLIT_NO_EMPTY : 0); - return self::pcre('preg_split', [$pattern, $subject, $limit, $flags | PREG_SPLIT_DELIM_CAPTURE]); + $pattern .= $utf8 ? 'u' : ''; + $m = self::pcre('preg_split', [$pattern, $subject, $limit, $flags | PREG_SPLIT_DELIM_CAPTURE]); + if ($utf8 && ($flags & PREG_SPLIT_OFFSET_CAPTURE)) { + return self::bytesToChars($subject, [$m])[0]; + } + + return $m; } @@ -508,18 +515,30 @@ public static function match( bool|int $captureOffset = false, int $offset = 0, bool $unmatchedAsNull = false, + bool $utf8 = false, ): ?array { $flags = is_int($captureOffset) && $captureOffset // back compatibility ? $captureOffset : ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0); + if ($utf8) { + $offset = strlen(self::substring($subject, 0, $offset)); + $pattern .= 'u'; + } + if ($offset > strlen($subject)) { return null; } - return self::pcre('preg_match', [$pattern, $subject, &$m, $flags, $offset]) - ? $m - : null; + if (!self::pcre('preg_match', [$pattern, $subject, &$m, $flags, $offset])) { + return null; + } + + if ($utf8 && ($flags & PREG_OFFSET_CAPTURE)) { + return self::bytesToChars($subject, [$m])[0]; + } + + return $m; } @@ -534,11 +553,17 @@ public static function matchAll( int $offset = 0, bool $unmatchedAsNull = false, bool $patternOrder = false, + bool $utf8 = false, ): array { $flags = is_int($captureOffset) && $captureOffset // back compatibility ? $captureOffset : ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0) | ($patternOrder ? PREG_PATTERN_ORDER : 0); + if ($utf8) { + $offset = strlen(self::substring($subject, 0, $offset)); + $pattern .= 'u'; + } + if ($offset > strlen($subject)) { return []; } @@ -548,6 +573,10 @@ public static function matchAll( ($flags & PREG_PATTERN_ORDER) ? $flags : ($flags | PREG_SET_ORDER), $offset, ]); + if ($utf8 && ($flags & PREG_OFFSET_CAPTURE)) { + return self::bytesToChars($subject, $m); + } + return $m; } @@ -562,6 +591,7 @@ public static function replace( int $limit = -1, bool $captureOffset = false, bool $unmatchedAsNull = false, + bool $utf8 = false, ): string { if (is_object($replacement) || is_array($replacement)) { @@ -570,6 +600,13 @@ public static function replace( } $flags = ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0); + if ($utf8) { + $pattern .= 'u'; + if ($captureOffset) { + $replacement = fn($m) => $replacement(self::bytesToChars($subject, [$m])[0]); + } + } + return self::pcre('preg_replace_callback', [$pattern, $replacement, $subject, $limit, 0, $flags]); } elseif (is_array($pattern) && is_string(key($pattern))) { @@ -577,10 +614,34 @@ public static function replace( $pattern = array_keys($pattern); } + if ($utf8) { + $pattern = array_map(fn($item) => $item . 'u', (array) $pattern); + } + return self::pcre('preg_replace', [$pattern, $replacement, $subject, $limit]); } + private static function bytesToChars(string $s, array $groups): array + { + $lastBytes = $lastChars = 0; + foreach ($groups as &$matches) { + foreach ($matches as &$match) { + if ($match[1] > $lastBytes) { + $lastChars += self::length(substr($s, $lastBytes, $match[1] - $lastBytes)); + } elseif ($match[1] < $lastBytes) { + $lastChars -= self::length(substr($s, $match[1], $lastBytes - $match[1])); + } + + $lastBytes = $match[1]; + $match[1] = $lastChars; + } + } + + return $groups; + } + + /** @internal */ public static function pcre(string $func, array $args) { diff --git a/tests/Utils/Strings.match().phpt b/tests/Utils/Strings.match().phpt index 5b4196180..67d88e7c6 100644 --- a/tests/Utils/Strings.match().phpt +++ b/tests/Utils/Strings.match().phpt @@ -19,13 +19,22 @@ Assert::same(['hell', 'l'], Strings::match('hello world!', '#([e-l])+#')); Assert::same(['hell'], Strings::match('hello world!', '#[e-l]+#')); -Assert::same([['hell', 0]], Strings::match('hello world!', '#[e-l]+#', PREG_OFFSET_CAPTURE)); -Assert::same([['hell', 0]], Strings::match('hello world!', '#[e-l]+#', captureOffset: true)); +Assert::same([[' ', 12]], Strings::match('россия - враг', '#\s+#u', PREG_OFFSET_CAPTURE)); +Assert::same([[' ', 12]], Strings::match('россия - враг', '#\s+#u', captureOffset: true)); +Assert::same([[' ', 6]], Strings::match('россия - враг', '#\s+#u', captureOffset: true, utf8: true)); Assert::same(['e', null], Strings::match('hello world!', '#e(x)*#', unmatchedAsNull: true)); Assert::same(['e', null], Strings::match('hello world!', '#e(x)*#', 0, 0, unmatchedAsNull: true)); // $flags = 0 Assert::same(['ll'], Strings::match('hello world!', '#[e-l]+#', offset: 2)); +Assert::same(['l'], Strings::match('žluťoučký kůň', '#[e-l]+#u', offset: 2)); + +Assert::same(['k'], Strings::match('žluťoučký kůň', '#[e-l]+#u', utf8: true, offset: 2)); + +Assert::same(['žluťoučký'], Strings::match('žluťoučký kůň', '#\w+#', utf8: true)); // without modifier + +Assert::same([['k', 7]], Strings::match('žluťoučký kůň', '#[e-l]+#u', captureOffset: true, utf8: true, offset: 2)); + Assert::null(Strings::match('hello world!', '', offset: 50)); Assert::null(Strings::match('', '', offset: 1)); diff --git a/tests/Utils/Strings.matchAll().phpt b/tests/Utils/Strings.matchAll().phpt index 257887f95..002b43599 100644 --- a/tests/Utils/Strings.matchAll().phpt +++ b/tests/Utils/Strings.matchAll().phpt @@ -45,14 +45,31 @@ Assert::same([ [['u', 3], ['u', 7], ['', 11], ['', 15]], ], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER)); +Assert::same([ + [['lu', 1], ['l', 1], ['u', 2]], + [['ou', 4], ['o', 4], ['u', 5]], + [['k', 7], ['k', 7], ['', 8]], + [['k', 10], ['k', 10], ['', 11]], +], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', captureOffset: true, utf8: true)); + Assert::same([ [['lu', 2], ['ou', 6], ['k', 10], ['k', 14]], [['l', 2], ['o', 6], ['k', 10], ['k', 14]], [['u', 3], ['u', 7], ['', 11], ['', 15]], ], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', captureOffset: true, patternOrder: true)); +Assert::same([ + [['lu', 1], ['ou', 4], ['k', 7], ['k', 10]], + [['l', 1], ['o', 4], ['k', 7], ['k', 10]], + [['u', 2], ['u', 5], ['', 8], ['', 11]], +], Strings::matchAll('žluťoučký kůň!', '#([a-z])([a-z]*)#u', captureOffset: true, patternOrder: true, utf8: true)); + Assert::same([['l'], ['k'], ['k']], Strings::matchAll('žluťoučký kůň', '#[e-l]+#u', offset: 2)); +Assert::same([['k'], ['k']], Strings::matchAll('žluťoučký kůň', '#[e-l]+#u', offset: 2, utf8: true)); + +Assert::same([['žluťoučký'], ['kůň']], Strings::matchAll('žluťoučký kůň', '#\w+#', utf8: true)); // without modifier + Assert::same([['ll', 'l']], Strings::matchAll('hello world!', '#[e-l]+#', PREG_PATTERN_ORDER, 2)); Assert::same([['ll', 'l']], Strings::matchAll('hello world!', '#[e-l]+#', offset: 2, patternOrder: true)); diff --git a/tests/Utils/Strings.replace().phpt b/tests/Utils/Strings.replace().phpt index 8c8c0a5dc..5029ed17b 100644 --- a/tests/Utils/Strings.replace().phpt +++ b/tests/Utils/Strings.replace().phpt @@ -37,4 +37,10 @@ Assert::same(' !', Strings::replace('hello world!', ['#\w#'])); // flags & callback Assert::same('hell0o worl9d!', Strings::replace('hello world!', '#[e-l]+#', fn($m) => implode('', $m[0]), captureOffset: true)); +Assert::same('žl1uťoučk7ý k10ůň!', Strings::replace('žluťoučký kůň!', '#[e-l]+#u', fn($m) => implode('', $m[0]), captureOffset: true, utf8: true)); Strings::replace('hello world!', '#e(x)*#', fn($m) => Assert::null($m[1]), unmatchedAsNull: true); + +// utf-8 without modifier +Assert::same('* *', Strings::replace('Россия агрессор', '#\w+#', fn() => '*', utf8: true)); +Assert::same('* *', Strings::replace('Россия агрессор', '#\w+#', '*', utf8: true)); +Assert::same('* *', Strings::replace('Россия агрессор', ['#\w+#'], '*', utf8: true)); diff --git a/tests/Utils/Strings.split().phpt b/tests/Utils/Strings.split().phpt index 9638b2710..d888ffca9 100644 --- a/tests/Utils/Strings.split().phpt +++ b/tests/Utils/Strings.split().phpt @@ -46,11 +46,29 @@ Assert::same([ ], Strings::split('a, b, c', '#(,)\s*#', PREG_SPLIT_OFFSET_CAPTURE)); Assert::same([ - ['a', 0], - [',', 1], - ['b', 3], - [',', 4], - ['c', 6], -], Strings::split('a, b, c', '#(,)\s*#', captureOffset: true)); + ['ž', 0], + ['lu', 2], + ['ť', 4], + ['ou', 6], + ['č', 8], + ['k', 10], + ['ý ', 11], + ['k', 14], + ['ůň', 15], +], Strings::split('žluťoučký kůň', '#([a-z]+)\s*#u', captureOffset: true)); + +Assert::same([ + ['ž', 0], + ['lu', 1], + ['ť', 3], + ['ou', 4], + ['č', 6], + ['k', 7], + ['ý ', 8], + ['k', 10], + ['ůň', 11], +], Strings::split('žluťoučký kůň', '#([a-z]+)\s*#u', captureOffset: true, utf8: true)); + +Assert::same(['', ' ', ''], Strings::split('žluťoučký kůň', '#\w+#', utf8: true)); // without modifier Assert::same(['a', ',', 'b, c'], Strings::split('a, b, c', '#(,)\s*#', limit: 2)); From 4020d6fbd75dd751c641382064e1216a21602ffc Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Nov 2021 23:15:10 +0100 Subject: [PATCH 23/30] added Strings::ord() --- src/Utils/Strings.php | 18 ++++++++++++++ tests/Utils/Strings.ord().phpt | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/Utils/Strings.ord().phpt diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index ceac2a213..4f7682c1e 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -58,6 +58,24 @@ public static function chr(int $code): string } + /** + * Returns a code point of specific character in UTF-8 (number in range 0x0000..D7FF or 0xE000..10FFFF). + */ + public static function ord(string $c): int + { + if (!extension_loaded('iconv')) { + throw new Nette\NotSupportedException(__METHOD__ . '() requires ICONV extension that is not loaded.'); + } + + $tmp = iconv('UTF-8', 'UTF-32BE//IGNORE', $c); + if (!$tmp) { + throw new Nette\InvalidArgumentException('Invalid UTF-8 character "' . ($c === '' ? '' : '\x' . strtoupper(bin2hex($c))) . '".'); + } + + return unpack('N', $tmp)[1]; + } + + /** * Starts the $haystack string with the prefix $needle? */ diff --git a/tests/Utils/Strings.ord().phpt b/tests/Utils/Strings.ord().phpt new file mode 100644 index 000000000..9d5e763e5 --- /dev/null +++ b/tests/Utils/Strings.ord().phpt @@ -0,0 +1,44 @@ + Strings::ord("\u{D800}"), + Nette\InvalidArgumentException::class, + 'Invalid UTF-8 character "\xEDA080".', +); + +Assert::exception( + fn() => Strings::ord(''), + Nette\InvalidArgumentException::class, + 'Invalid UTF-8 character "".', +); + +Assert::exception( + fn() => Strings::ord("\xFF"), + Nette\InvalidArgumentException::class, + 'Invalid UTF-8 character "\xFF".', +); From 4b122ae1473c72f875f3c6685d5544eed4e4e2ec Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 16 Nov 2021 14:45:46 +0100 Subject: [PATCH 24/30] Translator: changed interface, accepts and returns string|Stringable [Closes #231] --- src/Translator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Translator.php b/src/Translator.php index e8c5f7d06..f973f5f15 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -18,7 +18,7 @@ interface Translator /** * Translates the given string. */ - function translate(mixed $message, mixed ...$parameters): string; + function translate(string|\Stringable $message, mixed ...$parameters): string|\Stringable; } From f31ee44d23045a2a63a03d788baac0f44333de8a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 11 Dec 2021 19:06:33 +0100 Subject: [PATCH 25/30] Reflection::getParameterDefaultValue() is deprecated Since PHP 8.0 ReflectionParameter::getDefaultValue() correctly returns value or throws exception when constant cannot be resolved --- src/Utils/Reflection.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Utils/Reflection.php b/src/Utils/Reflection.php index 79545e4a4..c3c58dc99 100644 --- a/src/Utils/Reflection.php +++ b/src/Utils/Reflection.php @@ -79,8 +79,7 @@ public static function getPropertyType(\ReflectionProperty $prop): ?Type /** - * Returns the default value of parameter. If it is a constant, it returns its value. - * @throws \ReflectionException If the parameter does not have a default value or the constant cannot be resolved + * @deprecated use ReflectionParameter::getDefaultValue() */ public static function getParameterDefaultValue(\ReflectionParameter $param): mixed { From 67dc7f966f81e5a2e2bb610976b6d7fd46f2f50b Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 5 Jan 2022 01:57:14 +0100 Subject: [PATCH 26/30] added Helpers::compare() --- src/Utils/Helpers.php | 19 ++++++++++++ tests/Utils/Helpers.compare().phpt | 49 ++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 tests/Utils/Helpers.compare().phpt diff --git a/src/Utils/Helpers.php b/src/Utils/Helpers.php index f27b9e7be..1471e5351 100644 --- a/src/Utils/Helpers.php +++ b/src/Utils/Helpers.php @@ -82,4 +82,23 @@ public static function getSuggestion(array $possibilities, string $value): ?stri return $best; } + + + /** + * Compares two values. Recognizes operators: >, >=, <, <=, =, ==, ===, !=, !==, <> + */ + public static function compare(mixed $l, string $operator, mixed $r): bool + { + return match ($operator) { + '>' => $l > $r, + '>=' => $l >= $r, + '<' => $l < $r, + '<=' => $l <= $r, + '=', '==' => $l == $r, + '===' => $l === $r, + '!=', '<>' => $l != $r, + '!==' => $l !== $r, + default => throw new Nette\InvalidArgumentException("Unknown operator '$operator'"), + }; + } } diff --git a/tests/Utils/Helpers.compare().phpt b/tests/Utils/Helpers.compare().phpt new file mode 100644 index 000000000..f0e0cae28 --- /dev/null +++ b/tests/Utils/Helpers.compare().phpt @@ -0,0 +1,49 @@ +', 1)); +Assert::false(Helpers::compare(1, '>', 2)); +Assert::false(Helpers::compare(1, '<', 1)); +Assert::true(Helpers::compare(1, '<', 2)); + +Assert::true(Helpers::compare(1, '>=', 1)); +Assert::false(Helpers::compare(1, '>=', 2)); +Assert::true(Helpers::compare(1, '<=', 1)); +Assert::true(Helpers::compare(1, '<=', 2)); + +Assert::true(Helpers::compare(1, '=', 1)); +Assert::true(Helpers::compare(1.0, '=', 1)); +Assert::false(Helpers::compare(1, '=', 2)); + +Assert::true(Helpers::compare(1, '==', 1)); +Assert::true(Helpers::compare(1.0, '==', 1)); +Assert::false(Helpers::compare(1, '==', 2)); + +Assert::true(Helpers::compare(1, '===', 1)); +Assert::false(Helpers::compare(1.0, '===', 1)); +Assert::false(Helpers::compare(1, '===', 2)); + +Assert::false(Helpers::compare(1, '<>', 1)); +Assert::false(Helpers::compare(1.0, '<>', 1)); +Assert::true(Helpers::compare(1, '<>', 2)); + +Assert::false(Helpers::compare(1, '!=', 1)); +Assert::false(Helpers::compare(1.0, '!=', 1)); +Assert::true(Helpers::compare(1, '!=', 2)); + +Assert::false(Helpers::compare(1, '!==', 1)); +Assert::true(Helpers::compare(1.0, '!==', 1)); +Assert::true(Helpers::compare(1, '!==', 2)); + +Assert::exception( + fn() => Helpers::compare(1, 'x', 1), + Nette\InvalidArgumentException::class, + "Unknown operator 'x'", +); From 4f5ac1af8a588053f3bcad28fe201df606b95a1a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 21 Jan 2022 08:08:02 +0100 Subject: [PATCH 27/30] Json: added decodeFile() --- src/Utils/Json.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Utils/Json.php b/src/Utils/Json.php index 9fc320018..5711e6d37 100644 --- a/src/Utils/Json.php +++ b/src/Utils/Json.php @@ -72,4 +72,19 @@ public static function decode(string $json, bool|int $forceArray = false): mixed return $value; } + + + /** + * Converts given JSON file to PHP value. + * @throws JsonException + */ + public static function decodeFile(string $file, bool|int $forceArray = false): mixed + { + if (!is_file($file)) { + throw new Nette\IOException("File '$file' does not exist."); + } + + $input = file_get_contents($file); + return self::decode($input, $forceArray); + } } From 05d81ef94fa7a2f07dae74199616a9e6e3713865 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 24 Feb 2022 07:05:24 +0100 Subject: [PATCH 28/30] RegexpException: uses preg_last_error_msg() --- src/Utils/Strings.php | 2 +- src/Utils/exceptions.php | 8 -------- tests/Utils/Arrays.grep().errors.phpt | 2 +- tests/Utils/Strings.Regexp.errors.backtrack.phpt | 10 +++++----- tests/Utils/Strings.Regexp.errors.utf8.phpt | 10 +++++----- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index 4f7682c1e..f7e83ed08 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -671,7 +671,7 @@ public static function pcre(string $func, array $args) if (($code = preg_last_error()) // run-time error, but preg_last_error & return code are liars && ($res === null || !in_array($func, ['preg_filter', 'preg_replace_callback', 'preg_replace'], true)) ) { - throw new RegexpException((RegexpException::MESSAGES[$code] ?? 'Unknown error') + throw new RegexpException(preg_last_error_msg() . ' (pattern: ' . implode(' or ', (array) $args[0]) . ')', $code); } diff --git a/src/Utils/exceptions.php b/src/Utils/exceptions.php index c45e54306..069c313c6 100644 --- a/src/Utils/exceptions.php +++ b/src/Utils/exceptions.php @@ -39,14 +39,6 @@ class JsonException extends \Exception */ class RegexpException extends \Exception { - public const MESSAGES = [ - PREG_INTERNAL_ERROR => 'Internal error', - PREG_BACKTRACK_LIMIT_ERROR => 'Backtrack limit was exhausted', - PREG_RECURSION_LIMIT_ERROR => 'Recursion limit was exhausted', - PREG_BAD_UTF8_ERROR => 'Malformed UTF-8 data', - PREG_BAD_UTF8_OFFSET_ERROR => 'Offset didn\'t correspond to the begin of a valid UTF-8 code point', - 6 => 'Failed due to limited JIT stack space', // PREG_JIT_STACKLIMIT_ERROR - ]; } diff --git a/tests/Utils/Arrays.grep().errors.phpt b/tests/Utils/Arrays.grep().errors.phpt index 89ea411ff..775405ddd 100644 --- a/tests/Utils/Arrays.grep().errors.phpt +++ b/tests/Utils/Arrays.grep().errors.phpt @@ -23,5 +23,5 @@ Assert::exception( Assert::exception( fn() => Arrays::grep(['a', "1\xFF", 'c'], '#\d#u'), Nette\Utils\RegexpException::class, - 'Malformed UTF-8 data (pattern: #\d#u)', + 'Malformed UTF-8 characters, possibly incorrectly encoded (pattern: #\d#u)', ); diff --git a/tests/Utils/Strings.Regexp.errors.backtrack.phpt b/tests/Utils/Strings.Regexp.errors.backtrack.phpt index 304f310bb..ed63ca1c2 100644 --- a/tests/Utils/Strings.Regexp.errors.backtrack.phpt +++ b/tests/Utils/Strings.Regexp.errors.backtrack.phpt @@ -19,25 +19,25 @@ ini_set('pcre.jit', '0'); Assert::exception( fn() => Strings::split('0123456789', '#.*\d\d#'), Nette\Utils\RegexpException::class, - 'Backtrack limit was exhausted (pattern: #.*\d\d#)', + 'Backtrack limit exhausted (pattern: #.*\d\d#)', ); Assert::exception( fn() => Strings::match('0123456789', '#.*\d\d#'), Nette\Utils\RegexpException::class, - 'Backtrack limit was exhausted (pattern: #.*\d\d#)', + 'Backtrack limit exhausted (pattern: #.*\d\d#)', ); Assert::exception( fn() => Strings::matchAll('0123456789', '#.*\d\d#'), Nette\Utils\RegexpException::class, - 'Backtrack limit was exhausted (pattern: #.*\d\d#)', + 'Backtrack limit exhausted (pattern: #.*\d\d#)', ); Assert::exception( fn() => Strings::replace('0123456789', '#.*\d\d#', 'x'), Nette\Utils\RegexpException::class, - 'Backtrack limit was exhausted (pattern: #.*\d\d#)', + 'Backtrack limit exhausted (pattern: #.*\d\d#)', ); @@ -50,5 +50,5 @@ function cb() Assert::exception( fn() => Strings::replace('0123456789', '#.*\d\d#', Closure::fromCallable('cb')), Nette\Utils\RegexpException::class, - 'Backtrack limit was exhausted (pattern: #.*\d\d#)', + 'Backtrack limit exhausted (pattern: #.*\d\d#)', ); diff --git a/tests/Utils/Strings.Regexp.errors.utf8.phpt b/tests/Utils/Strings.Regexp.errors.utf8.phpt index 3ee2b428c..99446829c 100644 --- a/tests/Utils/Strings.Regexp.errors.utf8.phpt +++ b/tests/Utils/Strings.Regexp.errors.utf8.phpt @@ -16,25 +16,25 @@ require __DIR__ . '/../bootstrap.php'; Assert::exception( fn() => Strings::split("0123456789\xFF", '#\d#u'), Nette\Utils\RegexpException::class, - 'Malformed UTF-8 data (pattern: #\d#u)', + 'Malformed UTF-8 characters, possibly incorrectly encoded (pattern: #\d#u)', ); Assert::exception( fn() => Strings::match("0123456789\xFF", '#\d#u'), Nette\Utils\RegexpException::class, - 'Malformed UTF-8 data (pattern: #\d#u)', + 'Malformed UTF-8 characters, possibly incorrectly encoded (pattern: #\d#u)', ); Assert::exception( fn() => Strings::matchAll("0123456789\xFF", '#\d#u'), Nette\Utils\RegexpException::class, - 'Malformed UTF-8 data (pattern: #\d#u)', + 'Malformed UTF-8 characters, possibly incorrectly encoded (pattern: #\d#u)', ); Assert::exception( fn() => Strings::replace("0123456789\xFF", '#\d#u', 'x'), Nette\Utils\RegexpException::class, - 'Malformed UTF-8 data (pattern: #\d#u)', + 'Malformed UTF-8 characters, possibly incorrectly encoded (pattern: #\d#u)', ); @@ -47,5 +47,5 @@ function cb() Assert::exception( fn() => Strings::replace("0123456789\xFF", '#\d#u', Closure::fromCallable('cb')), Nette\Utils\RegexpException::class, - 'Malformed UTF-8 data (pattern: #\d#u)', + 'Malformed UTF-8 characters, possibly incorrectly encoded (pattern: #\d#u)', ); From fac1f2b0967504bd39926904446f95b8026c02ed Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 1 Mar 2022 18:48:08 +0100 Subject: [PATCH 29/30] some methods use real default values instead of nulls (BC break) --- src/Utils/Html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils/Html.php b/src/Utils/Html.php index 071105eee..270b07900 100644 --- a/src/Utils/Html.php +++ b/src/Utils/Html.php @@ -499,7 +499,7 @@ final public function __call(string $m, array $args): mixed /** * Special setter for element's attribute. */ - final public function href(string $path, ?array $query = null): static + final public function href(string $path, array $query = []): static { if ($query) { $query = http_build_query($query, '', '&'); From 712f0cfd27668dcc05dfca1e10d4167d4ebe2241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20H=C5=AFla?= Date: Wed, 30 Nov 2022 12:59:34 +0100 Subject: [PATCH 30/30] Strings: added base64UrlEncode() and base64UrlDecode() --- src/Utils/Strings.php | 31 ++++++++++++++++++++++++++++++ tests/Utils/Strings.base64Url.phpt | 31 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/Utils/Strings.base64Url.phpt diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index f7e83ed08..b762c5005 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -640,6 +640,37 @@ public static function replace( } + /** + * Encodes string into Base64 URL encoding. + */ + public static function base64UrlEncode(string $s): string + { + return strtr(rtrim(base64_encode($s), '='), ['+' => '-', '/' => '_']); + } + + + /** + * Decodes string from Base64 URL encoding. + * @throws Nette\InvalidArgumentException if input is malformed + */ + public static function base64UrlDecode(string $s): string + { + $padding = match (strlen($s) % 4) { + 0 => '', + 2 => '==', + 3 => '=', + default => throw new Nette\InvalidArgumentException('Invalid base64url string length.'), + }; + + $s = base64_decode(strtr($s, ['-' => '+', '_' => '/']) . $padding, true); + if ($s === false) { + throw new Nette\InvalidArgumentException('Invalid base64 string.'); + } + + return $s; + } + + private static function bytesToChars(string $s, array $groups): array { $lastBytes = $lastChars = 0; diff --git a/tests/Utils/Strings.base64Url.phpt b/tests/Utils/Strings.base64Url.phpt new file mode 100644 index 000000000..7d98ee100 --- /dev/null +++ b/tests/Utils/Strings.base64Url.phpt @@ -0,0 +1,31 @@ + Strings::base64UrlDecode('A'), + Nette\InvalidArgumentException::class, + 'Invalid base64url string length.', +); + +Assert::exception( + fn() => Strings::base64UrlDecode('A#'), + Nette\InvalidArgumentException::class, + 'Invalid base64 string.', +);