From 98a57eb0cd11c4bd123c2f20a39a3a58116b3a7c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 13 Oct 2026 01:37:12 +0200 Subject: [PATCH] added support for PHP 8.6 --- .github/workflows/tests.yml | 2 +- composer.json | 2 +- readme.md | 2 +- src/Utils/DateTime.php | 2 +- tests/Utils/Image.alpha1.phpt | 2 +- tests/Utils/Image.alpha2.phpt | 15 +++++++-------- tests/Utils/Image.drawing.phpt | 6 ++---- tests/Utils/Image.place.phpt | 3 +-- tests/Utils/Image.resize.phpt | 8 ++++---- tests/Utils/Json.decode().phpt | 14 +++++++------- tests/bootstrap.php | 14 ++++++++++++++ 11 files changed, 40 insertions(+), 30 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 094f2005c..e23de5003 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest] - php: ['8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] + php: ['8.0', '8.1', '8.2', '8.3', '8.4', '8.5', '8.6'] fail-fast: false diff --git a/composer.json b/composer.json index b17ea832b..d85a619ae 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": "8.0 - 8.5" + "php": "8.0 - 8.6" }, "require-dev": { "nette/tester": "^2.5", diff --git a/readme.md b/readme.md index 46e255170..481ea256d 100644 --- a/readme.md +++ b/readme.md @@ -41,7 +41,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.5. +Nette Utils 4.0 is compatible with PHP 8.0 to 8.6.   diff --git a/src/Utils/DateTime.php b/src/Utils/DateTime.php index 78aed52d5..48aa9d29b 100644 --- a/src/Utils/DateTime.php +++ b/src/Utils/DateTime.php @@ -163,7 +163,7 @@ function ($m) use (&$relPart) { ); if ($ctr) { - parent::__construct($absPart, $timezone); + parent::__construct(trim($absPart), $timezone); $this->handleErrors($datetime); } elseif (trim($absPart)) { parent::modify($absPart) && $this->handleErrors($datetime); diff --git a/tests/Utils/Image.alpha1.phpt b/tests/Utils/Image.alpha1.phpt index 14c396067..590e77251 100644 --- a/tests/Utils/Image.alpha1.phpt +++ b/tests/Utils/Image.alpha1.phpt @@ -28,4 +28,4 @@ Assert::same($image->toString(), (string) $image); $image = Image::fromBlank(200, 100, Image::rgb(255, 128, 0, 60)); $image->crop(0, 0, '60%', '60%'); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha1.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.alpha1.png', $image); diff --git a/tests/Utils/Image.alpha2.phpt b/tests/Utils/Image.alpha2.phpt index cecb50320..8178bce5a 100644 --- a/tests/Utils/Image.alpha2.phpt +++ b/tests/Utils/Image.alpha2.phpt @@ -6,7 +6,6 @@ */ use Nette\Utils\Image; -use Tester\Assert; require __DIR__ . '/../bootstrap.php'; @@ -14,34 +13,34 @@ require __DIR__ . '/../bootstrap.php'; $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha1.png'); $image->place(Image::fromFile(__DIR__ . '/fixtures.images/alpha2.png'), 0, 0, 100); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha2.100.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.alpha2.100.png', $image); $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha1.png'); $image->place(Image::fromFile(__DIR__ . '/fixtures.images/alpha2.png'), 0, 0, 99); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha2.99.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.alpha2.99.png', $image); $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha1.png'); $image->place(Image::fromFile(__DIR__ . '/fixtures.images/alpha2.png'), 0, 0, 50); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha2.50.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.alpha2.50.png', $image); $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha1.png'); $image->place(Image::fromFile(__DIR__ . '/fixtures.images/alpha2.png'), 0, 0, 1); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha2.1.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.alpha2.1.png', $image); $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha1.png'); $image->place(Image::fromFile(__DIR__ . '/fixtures.images/alpha2.png'), 0, 0, 0); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha2.0.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.alpha2.0.png', $image); $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha1.png'); $image->place(Image::fromFile(__DIR__ . '/fixtures.images/alpha3.gif'), 0, 0, 100); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha2.100b.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.alpha2.100b.png', $image); $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha1.png'); $image->place(Image::fromFile(__DIR__ . '/fixtures.images/alpha3.gif'), 0, 0, 50); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha2.50b.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.alpha2.50b.png', $image); diff --git a/tests/Utils/Image.drawing.phpt b/tests/Utils/Image.drawing.phpt index 08a292127..844a29a10 100644 --- a/tests/Utils/Image.drawing.phpt +++ b/tests/Utils/Image.drawing.phpt @@ -7,8 +7,6 @@ use Nette\Utils\Image; use Nette\Utils\ImageColor; -use Tester\Assert; - require __DIR__ . '/../bootstrap.php'; @@ -33,11 +31,11 @@ $image->filledEllipse(187, 125, $radius, $radius, Image::rgb(0, 0, 255, 75)); $image->copyResampled($image, 200, 200, 0, 0, 80, 80, $size, $size); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.drawing.1.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.drawing.1.png', $image); // palette-based image $image = Image::fromFile(__DIR__ . '/fixtures.images/logo.gif'); $image->filledEllipse(100, 50, 50, 50, Image::rgb(255, 255, 0, 75)); $image->filledEllipse(100, 150, 50, 50, Image::rgb(255, 255, 0, 75)); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.drawing.2.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.drawing.2.png', $image); diff --git a/tests/Utils/Image.place.phpt b/tests/Utils/Image.place.phpt index c0a884223..6dfb5fcca 100644 --- a/tests/Utils/Image.place.phpt +++ b/tests/Utils/Image.place.phpt @@ -6,7 +6,6 @@ */ use Nette\Utils\Image; -use Tester\Assert; require __DIR__ . '/../bootstrap.php'; @@ -17,4 +16,4 @@ $rectangle = Image::fromBlank(50, 50, Image::rgb(255, 255, 255)); $image = Image::fromBlank(100, 100, Image::rgb(0, 0, 0)); $image->place($rectangle, '37.5%', '50%'); -Assert::same(file_get_contents(__DIR__ . '/expected/Image.place.png'), $image->toString($image::PNG)); +assertImage(__DIR__ . '/expected/Image.place.png', $image); diff --git a/tests/Utils/Image.resize.phpt b/tests/Utils/Image.resize.phpt index 22ce97645..d28960171 100644 --- a/tests/Utils/Image.resize.phpt +++ b/tests/Utils/Image.resize.phpt @@ -133,26 +133,26 @@ test('rotate', function () use ($main) { test('alpha crop', function () use ($main) { $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha1.png'); $image->crop(1, 1, 8, 8); - Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha.crop.png'), $image->toString($image::PNG)); + assertImage(__DIR__ . '/expected/Image.alpha.crop.png', $image); }); test('alpha resize', function () use ($main) { $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha1.png'); $image->resize(20, 20); - Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha.resize1.png'), $image->toString($image::PNG)); + assertImage(__DIR__ . '/expected/Image.alpha.resize1.png', $image); }); test('alpha flip', function () use ($main) { $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha1.png'); $image->resize(-10, -10); - Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha.flip1.png'), $image->toString($image::PNG)); + assertImage(__DIR__ . '/expected/Image.alpha.flip1.png', $image); }); test('palette alpha resize', function () use ($main) { $image = Image::fromFile(__DIR__ . '/fixtures.images/alpha3.gif'); $image->resize(20, 20); - Assert::same(file_get_contents(__DIR__ . '/expected/Image.alpha.resize2.png'), $image->toString($image::PNG)); + assertImage(__DIR__ . '/expected/Image.alpha.resize2.png', $image); }); diff --git a/tests/Utils/Json.decode().phpt b/tests/Utils/Json.decode().phpt index 41b07c533..d6a4ebdff 100644 --- a/tests/Utils/Json.decode().phpt +++ b/tests/Utils/Json.decode().phpt @@ -24,42 +24,42 @@ Assert::same(['a' => 1], Json::decode('{"a":1}', forceArrays: true)); Assert::exception( fn() => Json::decode(''), Nette\Utils\JsonException::class, - 'Syntax error', + 'Syntax error%a?%', ); Assert::exception( fn() => Json::decode('NULL'), Nette\Utils\JsonException::class, - 'Syntax error', + 'Syntax error%a?%', ); Assert::exception( fn() => Json::decode('{'), Nette\Utils\JsonException::class, - 'Syntax error', + 'Syntax error%a?%', ); Assert::exception( fn() => Json::decode('{}}'), Nette\Utils\JsonException::class, - 'Syntax error', + 'Syntax error%a?%', ); Assert::exception( fn() => Json::decode("\x00"), Nette\Utils\JsonException::class, - defined('JSON_C_VERSION') ? 'Syntax error' : 'Control character error, possibly incorrectly encoded', + defined('JSON_C_VERSION') ? 'Syntax error%a?%' : 'Control character error, possibly incorrectly encoded%a?%', ); Assert::exception( fn() => Json::decode('{"\u0000": 1}'), Nette\Utils\JsonException::class, - 'The decoded property name is invalid', + 'The decoded property name is invalid%a?%', ); @@ -71,7 +71,7 @@ Assert::equal((object) ["\"\x00" => 1], Json::decode('{"\"\u0000": 1}')); Assert::exception( fn() => Json::decode("\"\xC1\xBF\""), Nette\Utils\JsonException::class, - 'Malformed UTF-8 characters, possibly incorrectly encoded', + 'Malformed UTF-8 characters, possibly incorrectly encoded%a?%', ); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 908b83df3..eca5f2273 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -33,3 +33,17 @@ function getTempDir(): string return $dir; } + + +/** + * Compares the pixels of the images, as the bytes of a PNG depend on the version of GD. + */ +function assertImage(string $expectedFile, Nette\Utils\Image $actual): void +{ + $normalize = function (Nette\Utils\Image $image): string { + $image = clone $image; + $image->paletteToTrueColor(); + return $image->toString(Nette\Utils\Image::PNG); + }; + Tester\Assert::same($normalize(Nette\Utils\Image::fromFile($expectedFile)), $normalize($actual)); +}