From 23b8cdc5f836ed616fb355343cbbce7c0723e340 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 15:30:47 +0100 Subject: [PATCH 01/15] opened 4.0-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index fa164d856..cbf355074 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 facbb481b42dfbdc503f1ab0482e66ddef674b72 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 17:40:17 +0100 Subject: [PATCH 02/15] requires PHP 8.0 --- .github/workflows/coding-style.yml | 2 +- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 4 ++-- composer.json | 2 +- readme.md | 1 + 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index 003ba9265..16e97d13c 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.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 b0692d716..f985b0526 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer install --no-progress --prefer-dist diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0c574b8c9..4470d3019 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - php: ['7.2', '7.3', '7.4', '8.0', '8.1'] + php: ['8.0', '8.1'] fail-fast: false @@ -37,7 +37,7 @@ jobs: - uses: actions/checkout@v2 - 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 cbf355074..12dccc022 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": ">=7.2 <8.2" + "php": ">=8.0 <8.2" }, "require-dev": { "nette/tester": "~2.0", diff --git a/readme.md b/readme.md index 81ed0e919..2508385a3 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.1 - Nette Utils 3.2 is compatible with PHP 7.2 to 8.1 - 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 1cfb5418c744ef9eab094f0ddee72413f6ebac94 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 16:43:25 +0100 Subject: [PATCH 03/15] composer: updated dependencies --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 12dccc022..8548e9731 100644 --- a/composer.json +++ b/composer.json @@ -18,8 +18,8 @@ "php": ">=8.0 <8.2" }, "require-dev": { - "nette/tester": "~2.0", - "tracy/tracy": "^2.3", + "nette/tester": "^2.4", + "tracy/tracy": "^2.8", "phpstan/phpstan": "^0.12" }, "conflict": { From 0c5fcc9be8bee65c05c2c5712ae6d4d37ff97636 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 12:47:36 +0200 Subject: [PATCH 04/15] removed support for PHP 7 --- src/Utils/Html.php | 10 +- src/Utils/Image.php | 10 +- src/Utils/Reflection.php | 6 +- src/Utils/Type.php | 4 +- .../Utils/Reflection.getParameterType.80.phpt | 70 --------- tests/Utils/Reflection.getParameterType.phpt | 28 +++- .../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 +-- 14 files changed, 122 insertions(+), 382 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/Html.php b/src/Utils/Html.php index cf6289336..c0a82e5c9 100644 --- a/src/Utils/Html.php +++ b/src/Utils/Html.php @@ -763,15 +763,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 1c305714a..08aabbc0a 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -591,15 +591,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 818643f11..9215e8520 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()); } @@ -319,9 +319,7 @@ private static function parseUseStatements(string $code, string $forClass = null $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 257cc2968..58faa363f 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 869266982..9ffa52501 100644 --- a/tests/Utils/Reflection.getParameterType.phpt +++ b/tests/Utils/Reflection.getParameterType.phpt @@ -16,8 +16,18 @@ require __DIR__ . '/../bootstrap.php'; class A { - public function method(Undeclared $undeclared, B $b, array $array, callable $callable, self $self, $none, ?B $nullable) - { + public function method( + Undeclared $undeclared, + B $b, + array $array, + callable $callable, + self $self, + $none, + ?B $nullable, + mixed $mixed, + array|self $union, + array|self|null $nullableUnion, + ) { } } @@ -38,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 96c251ac9..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 0206d6ae90d804e3c9b8cd88e8ab089f9d5bb6e7 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 2 Mar 2021 15:50:58 +0100 Subject: [PATCH 05/15] 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 73d5cecd9..f5f36172d 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 06/15] coding style --- ecs.php | 2 +- src/Iterators/CachingIterator.php | 2 +- src/Utils/Callback.php | 2 +- src/Utils/DateTime.php | 6 +-- src/Utils/Html.php | 2 +- src/Utils/Image.php | 12 ++--- src/Utils/ObjectHelpers.php | 18 ++++---- src/Utils/Random.php | 9 ++-- src/Utils/Strings.php | 2 +- src/Utils/Type.php | 30 +++++------- 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 +- .../fixtures.reflection/defaultValue.php | 2 +- 28 files changed, 124 insertions(+), 133 deletions(-) diff --git a/ecs.php b/ecs.php index d655ffcc4..4dd357154 100644 --- a/ecs.php +++ b/ecs.php @@ -9,7 +9,7 @@ return function (Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator $containerConfigurator): void { - $containerConfigurator->import(PRESET_DIR . '/php71.php'); + $containerConfigurator->import(PRESET_DIR . '/php80.php'); $parameters = $containerConfigurator->parameters(); diff --git a/src/Iterators/CachingIterator.php b/src/Iterators/CachingIterator.php index e2e5e4c1a..cb99645b3 100644 --- a/src/Iterators/CachingIterator.php +++ b/src/Iterators/CachingIterator.php @@ -47,7 +47,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 f5f36172d..9d5146082 100644 --- a/src/Utils/Callback.php +++ b/src/Utils/Callback.php @@ -60,7 +60,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)), ); } return $callable; diff --git a/src/Utils/DateTime.php b/src/Utils/DateTime.php index 320ccc773..661b01c99 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; /** @@ -72,7 +72,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/Html.php b/src/Utils/Html.php index c0a82e5c9..169fc551c 100644 --- a/src/Utils/Html.php +++ b/src/Utils/Html.php @@ -844,7 +844,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 08aabbc0a..690723daf 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -338,7 +338,7 @@ public function resize($width, $height, int $flags = self::FIT) $newWidth, $newHeight, $this->getWidth(), - $this->getHeight() + $this->getHeight(), ); $this->image = $newImage; } @@ -360,7 +360,7 @@ public static function calculateSize( int $srcHeight, $newWidth, $newHeight, - int $flags = self::FIT + int $flags = self::FIT, ): array { if ($newWidth === null) { } elseif (self::isPercent($newWidth)) { @@ -550,7 +550,7 @@ public function place(self $image, $left = 0, $top = 0, int $opacity = 100) 0, 0, $width, - $height + $height, ); return $this; } @@ -580,7 +580,7 @@ public function save(string $file, int $quality = null, int $type = null): void */ 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); }); } @@ -667,13 +667,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 c0fda7d8c..8d973c04f 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]+(?:\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) [ \t]+ [^\s$]+ [ \t]+ \$ (\w+) ()~mx', (string) $rc->getDocComment(), $matches, - PREG_SET_ORDER + PREG_SET_ORDER, ); $props = []; @@ -196,7 +196,7 @@ private static function parseFullDoc(\ReflectionClass $rc, string $pattern): arr $traits += $trait->getTraits(); } } 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 2403b4d3d..0ac9d152c 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 e5e626b43..815086c2b 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -184,7 +184,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 58faa363f..707a1e38c 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 { @@ -140,7 +140,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); } @@ -221,27 +221,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 60e0eaab3..9b787ad41 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."); } @@ -116,7 +116,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)) { throw new AssertionException('Missing ' . str_replace('%', $key, $label) . '.'); @@ -310,14 +310,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 eed82ec59..074bf0b1f 100644 --- a/tests/Utils/Arrays.every().phpt +++ b/tests/Utils/Arrays.every().phpt @@ -18,7 +18,7 @@ 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 +29,7 @@ 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 +40,7 @@ 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 +51,7 @@ 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 +62,7 @@ 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 +73,7 @@ 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 +84,7 @@ 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.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 5cdabdedf..2970e9059 100644 --- a/tests/Utils/Arrays.map().phpt +++ b/tests/Utils/Arrays.map().phpt @@ -18,7 +18,7 @@ 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 +29,7 @@ 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 +40,7 @@ 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 +51,7 @@ 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.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 3cbfadb3a..7a34bc26e 100644 --- a/tests/Utils/Arrays.some().phpt +++ b/tests/Utils/Arrays.some().phpt @@ -18,7 +18,7 @@ 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 +29,7 @@ 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 +40,7 @@ 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 +51,7 @@ 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 +62,7 @@ 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 +73,7 @@ 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 +84,7 @@ 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); diff --git a/tests/Utils/Callback.invokeSafe.phpt b/tests/Utils/Callback.invokeSafe.phpt index 80df9ff07..4ac046d31 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::same('preg_match(): Delimiter must not be alphanumeric or backslash', $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 ab7a1e275..c8a6f95cd 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 e5b48af6a..e9910d26c 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/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 dc06fcac24788626d76479113094c808749be07b Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 19:15:56 +0100 Subject: [PATCH 07/15] 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 cb99645b3..e8e64f3a2 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 0a694652d..b8c39c7ef 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 169fc551c..152640b23 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 690723daf..db6d00557 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -125,8 +125,7 @@ class Image private const FORMATS = [self::JPEG => 'jpeg', self::PNG => 'png', self::GIF => 'gif', self::WEBP => 'webp', self::BMP => 'bmp']; - /** @var resource|\GdImage */ - private $image; + private \GdImage $image; /** diff --git a/src/Utils/Paginator.php b/src/Utils/Paginator.php index 57733bceb..dd42a5af3 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 707a1e38c..2fa3b085a 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 11fd345798060d09723fbc69a1e67b40ff97c5d1 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 19 Sep 2021 19:04:54 +0200 Subject: [PATCH 08/15] 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 | 10 +-- src/Utils/DateTime.php | 25 ++---- src/Utils/Helpers.php | 10 +-- src/Utils/Html.php | 75 +++++------------ src/Utils/Image.php | 80 +++++++------------ src/Utils/Json.php | 6 +- src/Utils/ObjectHelpers.php | 4 +- src/Utils/Paginator.php | 12 +-- src/Utils/Reflection.php | 10 +-- src/Utils/Strings.php | 10 ++- src/Utils/Type.php | 13 +-- 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 | 4 - .../Strings.replace().errors.callback.phpt | 5 -- 27 files changed, 133 insertions(+), 264 deletions(-) diff --git a/src/Iterators/CachingIterator.php b/src/Iterators/CachingIterator.php index e8e64f3a2..d4e09f003 100644 --- a/src/Iterators/CachingIterator.php +++ b/src/Iterators/CachingIterator.php @@ -146,9 +146,8 @@ public function rewind(): void /** * Returns the next key. - * @return mixed */ - public function getNextKey() + public function getNextKey(): mixed { return $this->getInnerIterator()->key(); } @@ -156,9 +155,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 2128fdfd0..5c7735de9 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,27 +37,26 @@ 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; @@ -79,11 +78,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; @@ -103,10 +100,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..37522695b 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): void { 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 5de178e20..f69ab58bb 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) { @@ -73,8 +72,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 b8c39c7ef..c22c96a46 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.'); @@ -84,8 +83,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'); @@ -122,7 +120,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 775b6517b..81d030936 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)) { @@ -53,7 +53,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) { @@ -90,10 +90,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)); } @@ -110,9 +108,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); } @@ -124,7 +121,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; } @@ -136,7 +133,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; } @@ -145,9 +142,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) @@ -159,9 +155,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; @@ -174,10 +169,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) { @@ -219,9 +212,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) && (!$value || array_keys($value) === range(0, count($value) - 1)); } @@ -230,9 +222,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 @@ -285,9 +276,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) { @@ -302,12 +292,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]; @@ -401,7 +390,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; @@ -412,10 +401,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 9d5146082..735eac57b 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__) { @@ -50,11 +49,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( @@ -69,9 +67,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,7 +85,6 @@ 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 diff --git a/src/Utils/DateTime.php b/src/Utils/DateTime.php index 661b01c99..48e50334a 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()); @@ -63,7 +61,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( @@ -73,7 +70,7 @@ 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) @@ -92,22 +89,17 @@ 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 $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); @@ -135,9 +127,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 5e033fe48..1551e1f19 100644 --- a/src/Utils/Helpers.php +++ b/src/Utils/Helpers.php @@ -43,10 +43,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; } @@ -54,12 +52,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 \InvalidArgumentException("Minimum ($min) is not less than maximum ($max)."); diff --git a/src/Utils/Html.php b/src/Utils/Html.php index 152640b23..e18e1c934 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 $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] : []; @@ -397,10 +391,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; @@ -409,9 +401,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; } @@ -419,9 +410,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; @@ -430,9 +420,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]); @@ -443,9 +432,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; } @@ -453,9 +441,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]; } @@ -481,9 +468,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') { @@ -512,9 +498,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, '', '&'); @@ -529,10 +514,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; @@ -547,10 +530,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; @@ -568,10 +549,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'); @@ -592,10 +571,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); } @@ -603,10 +580,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'); @@ -617,10 +592,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 $attrs = null): static { $this->insert(null, $child = static::el($name, $attrs)); return $child; @@ -629,10 +602,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 @@ -660,10 +631,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 db6d00557..650976a84 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 { @@ -146,9 +146,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.'); @@ -168,11 +167,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.'); @@ -191,10 +189,9 @@ public static function fromString(string $s, int &$type = null) /** * 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.'); @@ -259,9 +256,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); @@ -288,14 +284,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; } @@ -303,21 +294,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); @@ -350,9 +337,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, @@ -419,14 +404,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); @@ -443,14 +423,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); } @@ -479,9 +461,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], @@ -493,13 +474,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) { @@ -646,10 +624,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)) { @@ -677,7 +654,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; } @@ -691,10 +668,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 782c1ff2b..9f06a7f05 100644 --- a/src/Utils/Json.php +++ b/src/Utils/Json.php @@ -29,10 +29,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 @@ -49,10 +48,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 { $forceArray = (bool) ($flags & self::FORCE_ARRAY); $value = json_decode($json, $forceArray, 512, JSON_BIGINT_AS_STRING); diff --git a/src/Utils/ObjectHelpers.php b/src/Utils/ObjectHelpers.php index 8d973c04f..57bb70bad 100644 --- a/src/Utils/ObjectHelpers.php +++ b/src/Utils/ObjectHelpers.php @@ -202,10 +202,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 dd42a5af3..ab3de1582 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 6be5b2e8c..1c6aeb642 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(); @@ -362,7 +358,7 @@ private static function parseUseStatements(string $code, string $forClass = null } - 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 815086c2b..f6bfb9f44 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -511,11 +511,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)) { throw new Nette\InvalidStateException("Callback '$textual' is not callable."); diff --git a/src/Utils/Type.php b/src/Utils/Type.php index 2fa3b085a..760e4205d 100644 --- a/src/Utils/Type.php +++ b/src/Utils/Type.php @@ -25,10 +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); } else { @@ -83,10 +83,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) { return $type; diff --git a/src/Utils/Validators.php b/src/Utils/Validators.php index 9b787ad41..645211d51 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); @@ -109,7 +108,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( @@ -129,9 +127,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) === '[]') { @@ -200,9 +197,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); } @@ -210,9 +206,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)); } @@ -220,9 +215,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]+$#D', $value)); } @@ -230,9 +224,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); } @@ -240,9 +233,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); } @@ -250,9 +242,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 == } @@ -267,10 +258,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); } @@ -279,9 +269,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 277af3bf3..9a3195a30 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 ad242bb90..d45af2b53 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 b81ea0d89..787400df3 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(function () use ($arr) { 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 08ffdd709..321d43f99 100644 --- a/tests/Utils/DateTime.createFromFormat.phpt +++ b/tests/Utils/DateTime.createFromFormat.phpt @@ -22,8 +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::error(function () { - 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 d29ead08b..5643940af 100644 --- a/tests/Utils/Strings.replace().errors.callback.phpt +++ b/tests/Utils/Strings.replace().errors.callback.phpt @@ -26,8 +26,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(function () { - Strings::replace('hello', '#.+#', [stdClass::class, 'foobar']); -}, InvalidStateException::class, "Callback 'stdClass::foobar' is not callable."); From ab3653d647997765b0cff5e542a139cfbbcd53c4 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 11 Mar 2021 21:55:53 +0100 Subject: [PATCH 09/15] 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 43c67c9ec306f12765f53dfb81e22849a5194e06 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 22 Apr 2021 18:17:33 +0200 Subject: [PATCH 10/15] tests: added --- .../SmartObject.undeclaredMethod.native.phpt | 149 ++++++++++++++++++ 1 file changed, 149 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..d5d62e120 --- /dev/null +++ b/tests/Utils/SmartObject.undeclaredMethod.native.phpt @@ -0,0 +1,149 @@ +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() + { + } +} + + + +Assert::exception(function () { + $obj = new ParentClass; + $obj->undef(); +}, Error::class, 'Call to undefined method ParentClass::undef()'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj->undef(); +}, Error::class, 'Call to undefined method ChildClass::undef()'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj->callParents(); +}, Error::class, 'Call to undefined method ParentClass::callParents()'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj->callMissingParent(); +}, Error::class, 'Call to undefined method InterClass::callMissingParent()'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj->callMissingParentStatic(); +}, Error::class, 'Call to undefined method InterClass::callMissingParentStatic()'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj::callMissingParentStatic(); +}, Error::class, 'Call to undefined method InterClass::callMissingParentStatic()'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj->callPrivateParent(); +}, Error::class, 'Call to private method ParentClass::callPrivateParent() from scope ChildClass'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj->protectedMethod(); +}, Error::class, 'Call to protected method ChildClass::protectedMethod() from global scope'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj->protectedStaticMethod(); +}, Error::class, 'Call to protected method ChildClass::protectedStaticMethod() from global scope'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj::protectedStaticMethod(); +}, Error::class, 'Call to protected method ChildClass::protectedStaticMethod() from global scope'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj->callPrivate(); +}, Error::class, 'Call to private method ChildClass::privateMethod() from scope ParentClass'); + +Assert::exception(function () { + $obj = new ChildClass; + $obj->callPrivateStatic(); +}, Error::class, 'Call to private method ChildClass::privateStaticMethod() from scope ParentClass'); From ae2abdda6163ec0536ddc160f7058f5a89c76660 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 28 Jul 2021 12:42:14 +0200 Subject: [PATCH 11/15] 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 735eac57b..98acea615 100644 --- a/src/Utils/Callback.php +++ b/src/Utils/Callback.php @@ -93,7 +93,7 @@ public static function toReflection($callable): \ReflectionFunctionAbstract $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 { $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 e18e1c934..b5e9cc831 100644 --- a/src/Utils/Html.php +++ b/src/Utils/Html.php @@ -806,14 +806,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 650976a84..8d4238e8c 100644 --- a/src/Utils/Image.php +++ b/src/Utils/Image.php @@ -670,7 +670,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 f6bfb9f44..6e7b35cf0 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -62,7 +62,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); } @@ -71,7 +71,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); } @@ -80,7 +80,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 645211d51..b9ee50b20 100644 --- a/src/Utils/Validators.php +++ b/src/Utils/Validators.php @@ -131,12 +131,12 @@ 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 cdc6deeb7ed6b376768f1fd71e0176e3f1212887 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 27 Aug 2021 11:40:10 +0200 Subject: [PATCH 12/15] 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 1c6aeb642..cb1c10beb 100644 --- a/src/Utils/Reflection.php +++ b/src/Utils/Reflection.php @@ -277,7 +277,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 = []; @@ -289,7 +289,7 @@ private static function parseUseStatements(string $code, string $forClass = null 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 = []; @@ -342,11 +342,11 @@ private static function parseUseStatements(string $code, string $forClass = null case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: - case '{': + case ord('{'): $level++; break; - case '}': + case ord('}'): if ($level === $classLevel) { $class = $classLevel = null; } @@ -362,10 +362,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; } next($tokens); From c18603cf1ef26ddc37e23c59a1b65ab0fa18419f Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 01:23:10 +0200 Subject: [PATCH 13/15] Reflection: getReturnType(), getParameterType(), getPropertyType() return objects Type (BC break) --- src/Utils/Reflection.php | 33 +++------------ .../Utils/Reflection.getParameterType.81.phpt | 31 +++++--------- tests/Utils/Reflection.getParameterType.phpt | 25 ++++------- .../Utils/Reflection.getPropertyType.81.phpt | 29 ++++--------- tests/Utils/Reflection.getPropertyType.phpt | 23 ++++------ tests/Utils/Reflection.getReturnType.81.phpt | 42 +++++++------------ tests/Utils/Reflection.getReturnType.phpt | 32 ++++++-------- 7 files changed, 69 insertions(+), 146 deletions(-) diff --git a/src/Utils/Reflection.php b/src/Utils/Reflection.php index cb1c10beb..bdfa47fc4 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 15d75986f..5adb2643c 100644 --- a/tests/Utils/Reflection.getParameterType.81.phpt +++ b/tests/Utils/Reflection.getParameterType.81.phpt @@ -43,28 +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(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.'); - -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::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 9e00ed6d9..616c67325 100644 --- a/tests/Utils/Reflection.getParameterType.phpt +++ b/tests/Utils/Reflection.getParameterType.phpt @@ -41,25 +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(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.'); - +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 d7905d6d6..38d42c4e0 100644 --- a/tests/Utils/Reflection.getPropertyType.81.phpt +++ b/tests/Utils/Reflection.getPropertyType.81.phpt @@ -37,27 +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(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(function () use ($props) { - 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 161e4ac7e..44abc0630 100644 --- a/tests/Utils/Reflection.getPropertyType.phpt +++ b/tests/Utils/Reflection.getPropertyType.phpt @@ -35,23 +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(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::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 704c55dff..c0b8cfb57 100644 --- a/tests/Utils/Reflection.getReturnType.81.phpt +++ b/tests/Utils/Reflection.getReturnType.81.phpt @@ -106,48 +106,38 @@ 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(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::same('A|array', (string) Reflection::getReturnType(new \ReflectionMethod(A::class, 'unionType'))); -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::same('A|array|null', (string) Reflection::getReturnType(new \ReflectionMethod(A::class, 'nullableUnionType'))); -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::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(function () { - 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(function () { - 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 351d098c4..e4002c5dd 100644 --- a/tests/Utils/Reflection.getReturnType.phpt +++ b/tests/Utils/Reflection.getReturnType.phpt @@ -95,36 +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(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::same('A|array', (string) Reflection::getReturnType(new \ReflectionMethod(A::class, 'unionType'))); -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::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(function () { - 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 75af0ff0bf4db0df8aa07ea07a94437d0291b631 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 26 Sep 2021 12:34:29 +0200 Subject: [PATCH 14/15] 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 b5e9cc831..81bad0a4e 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, @@ -740,7 +738,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() . '>' : ''; } @@ -771,11 +769,7 @@ final public function attributes(): string continue; } elseif ($value === true) { - if (static::$xhtml) { - $s .= ' ' . $key . '="' . $key . '"'; - } else { - $s .= ' ' . $key; - } + $s .= ' ' . $key; continue; } elseif (is_array($value)) { @@ -810,7 +804,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 1cbe252831209efd60614f72453aee8ba9792d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bar=C3=A1=C5=A1ek?= Date: Tue, 12 Oct 2021 18:47:55 +0200 Subject: [PATCH 15/15] Validators::isEmail: Add check for DNS nameservers. --- src/Utils/Validators.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Utils/Validators.php b/src/Utils/Validators.php index b9ee50b20..1e4d49fbf 100644 --- a/src/Utils/Validators.php +++ b/src/Utils/Validators.php @@ -294,11 +294,11 @@ public static function isInRange(mixed $value, array $range): bool /** * Checks if the value is a valid email address. It does not verify that the domain actually exists, only the syntax is verified. */ - public static function isEmail(string $value): bool + public static function isEmail(string $value, bool $checkDns = false): bool { $atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]"; // RFC 5322 unquoted characters in local-part $alpha = "a-z\x80-\xFF"; // superset of IDN - return (bool) preg_match(<<