diff --git a/.github/workflows/unittests.yml b/.github/workflows/unittests.yml index 97bcf1d3..250245ec 100644 --- a/.github/workflows/unittests.yml +++ b/.github/workflows/unittests.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: os: ['ubuntu-latest'] - php: ['8.1', '8.2', '8.3'] + php: ['8.1', '8.2', '8.3', '8.4'] steps: - name: Set locales run: | diff --git a/composer.json b/composer.json index 17ae72b6..d9c1877e 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ } ], "require": { - "php": "~8.1.0 || ~8.2.0 || ~8.3.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "ext-dom": "*", "ext-gettext": "*", "ext-simplexml": "*", diff --git a/composer.lock b/composer.lock index 51610267..b270188a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7c8d4ab932aea5ac49373502f5c5539a", + "content-hash": "070a0e5770a4dab12e3e5c1a6ec82eb0", "packages": [ { "name": "symfony/polyfill-mbstring", @@ -903,16 +903,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.11", + "version": "1.12.12", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "0d1fc20a962a91be578bcfe7cf939e6e1a2ff733" + "reference": "b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0d1fc20a962a91be578bcfe7cf939e6e1a2ff733", - "reference": "0d1fc20a962a91be578bcfe7cf939e6e1a2ff733", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0", + "reference": "b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0", "shasum": "" }, "require": { @@ -957,7 +957,7 @@ "type": "github" } ], - "time": "2024-11-17T14:08:01+00:00" + "time": "2024-11-28T22:13:23+00:00" }, { "name": "phpunit/php-code-coverage", @@ -3135,16 +3135,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -3182,7 +3182,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -3198,7 +3198,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/event-dispatcher", @@ -3282,16 +3282,16 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { @@ -3338,7 +3338,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -3354,7 +3354,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/filesystem", @@ -3488,16 +3488,16 @@ }, { "name": "symfony/options-resolver", - "version": "v6.4.13", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "0a62a9f2504a8dd27083f89d21894ceb01cc59db" + "reference": "368128ad168f20e22c32159b9f761e456cec0c78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0a62a9f2504a8dd27083f89d21894ceb01cc59db", - "reference": "0a62a9f2504a8dd27083f89d21894ceb01cc59db", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/368128ad168f20e22c32159b9f761e456cec0c78", + "reference": "368128ad168f20e22c32159b9f761e456cec0c78", "shasum": "" }, "require": { @@ -3535,7 +3535,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.4.13" + "source": "https://github.com/symfony/options-resolver/tree/v6.4.16" }, "funding": [ { @@ -3551,7 +3551,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2024-11-20T10:57:02+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4010,16 +4010,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { @@ -4073,7 +4073,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -4089,7 +4089,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/stopwatch", @@ -4296,7 +4296,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "~8.1.0 || ~8.2.0 || ~8.3.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "ext-dom": "*", "ext-gettext": "*", "ext-simplexml": "*" diff --git a/doc/en/book.xml b/doc/en/book.xml index 45fe1aa2..a98b01ef 100644 --- a/doc/en/book.xml +++ b/doc/en/book.xml @@ -1383,6 +1383,18 @@ this page has been readed ${page/countRead} times"/> NE (not equal) + + + !== : + EQQ (strictly equal) + + + + + === : + NEE (strictly not equal) + + && : diff --git a/rector.php b/rector.php index f7488e53..7770db97 100644 --- a/rector.php +++ b/rector.php @@ -2,10 +2,8 @@ declare(strict_types=1); -use Rector\CodeQuality\Rector\FuncCall\IntvalToTypeCastRector; use Rector\Config\RectorConfig; use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; -use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector; use Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector; use Rector\Php80\Rector\FunctionLike\MixedTypeRector; @@ -19,14 +17,12 @@ ->withImportNames() ->withSkip([ StringClassNameToClassConstantRector::class, - JsonThrowOnErrorRector::class, FirstClassCallableRector::class, MixedTypeRector::class, ]) ->withPhpSets(php81: true) ->withPreparedSets(deadCode: true) ->withRules([ - IntvalToTypeCastRector::class, AddLiteralSeparatorToNumberRector::class, ClosureToArrowFunctionRector::class, ]); diff --git a/src/Context.php b/src/Context.php index da790811..434ac56a 100644 --- a/src/Context.php +++ b/src/Context.php @@ -401,7 +401,7 @@ private static function pathError(mixed $base, string $path, string $current, ?s * * @throws Exception\VariableNotFoundException */ - public static function path(mixed $base, string $path, bool $nothrow = null): mixed + public static function path(mixed $base, string $path, bool $nothrow = false): mixed { if ($base === null) { if ($nothrow) { diff --git a/src/Dom/Element.php b/src/Dom/Element.php index b3ab350c..63cefb8c 100644 --- a/src/Dom/Element.php +++ b/src/Dom/Element.php @@ -462,7 +462,7 @@ public function generateHead(CodeWriter $codewriter): void } } - public function generateContent(CodeWriter $codewriter, bool $realContent = null): void + public function generateContent(CodeWriter $codewriter, bool $realContent = false): void { if (!$this->isEmptyNode($codewriter->getOutputMode())) { if ($realContent || count($this->contentAttributes) === 0) { diff --git a/src/Dom/SaxXmlParser.php b/src/Dom/SaxXmlParser.php index 6629261e..787f5fca 100644 --- a/src/Dom/SaxXmlParser.php +++ b/src/Dom/SaxXmlParser.php @@ -112,7 +112,7 @@ public function parseFile(DocumentBuilder $builder, string $src): DocumentBuilde * @throws ParserException * @throws TemplateException */ - public function parseString(DocumentBuilder $builder, string $src, string $filename = null): DocumentBuilder + public function parseString(DocumentBuilder $builder, string $src, null|string $filename = null): DocumentBuilder { try { $builder->setEncoding($this->input_encoding); diff --git a/src/Dom/XmlnsState.php b/src/Dom/XmlnsState.php index 319137c3..2ab15102 100644 --- a/src/Dom/XmlnsState.php +++ b/src/Dom/XmlnsState.php @@ -31,7 +31,7 @@ class XmlnsState /** Create a new XMLNS state inheriting provided aliases. * @param array $prefix_to_uri */ - public function __construct(private array $prefix_to_uri, private string $current_default) + public function __construct(private array $prefix_to_uri, private readonly string $current_default) { } diff --git a/src/NothingKeyword.php b/src/NothingKeyword.php index 46e983a6..348317e5 100644 --- a/src/NothingKeyword.php +++ b/src/NothingKeyword.php @@ -30,9 +30,6 @@ public function count(): int { return 0; } - /** - * @return null - */ public function jsonSerialize(): ?string { return null; diff --git a/src/PHPTAL.php b/src/PHPTAL.php index 3f2932cc..47f2dc5f 100644 --- a/src/PHPTAL.php +++ b/src/PHPTAL.php @@ -256,7 +256,7 @@ public function setTemplate(?string $path): PhpTalInterface * * @return $this */ - public function setSource(string $src, ?string $path = null): PhpTalInterface + public function setSource(string $src, null|string $path = null): PhpTalInterface { $this->prepared = false; $this->functionName = null; diff --git a/src/Php/CodeWriter.php b/src/Php/CodeWriter.php index 6291dd85..81a0e3e0 100644 --- a/src/Php/CodeWriter.php +++ b/src/Php/CodeWriter.php @@ -179,7 +179,7 @@ public function splitExpression(string $src): array preg_match_all('/(?:[^;]+|;;)+/sm', $src, $array); $array = $array[0]; foreach ($array as &$a) { - $a = str_replace(';;', ';', (string) $a); + $a = str_replace(';;', ';', $a); } return $array; } @@ -270,7 +270,7 @@ public function flushHtml(): void * * @param bool $called_from_macro for error checking: unbuffered output doesn't support that */ - public function doDoctype(bool $called_from_macro = null): void + public function doDoctype(bool $called_from_macro = false): void { if ($this->doctype) { $code = '$ctx->setDocType(' . $this->str($this->doctype) . @@ -284,7 +284,7 @@ public function doDoctype(bool $called_from_macro = null): void * * @param bool $called_from_macro for error checking: unbuffered output doesn't support that */ - public function doXmlDeclaration(bool $called_from_macro = null): void + public function doXmlDeclaration(bool $called_from_macro = false): void { if ($this->xmldeclaration && $this->getOutputMode() !== PHPTAL::HTML5) { $code = '$ctx->setXmlDeclaration(' . $this->str($this->xmldeclaration) . @@ -367,7 +367,7 @@ public function doForeach(string $out, string $source): void /** * @throws PhpTalException */ - public function doEnd(string $expects = null): void + public function doEnd(null|string $expects = null): void { if (count($this->segments) === 0) { if ($expects === null) { diff --git a/src/Php/Transformer.php b/src/Php/Transformer.php index e5b53b4a..76394124 100644 --- a/src/Php/Transformer.php +++ b/src/Php/Transformer.php @@ -55,6 +55,7 @@ class Transformer private static array $TranslationTable = [ 'not' => '!', 'ne' => '!=', + 'nee' => '!==', 'and' => '&&', 'or' => '||', 'lt' => '<', @@ -62,6 +63,7 @@ class Transformer 'ge' => '>=', 'le' => '<=', 'eq' => '==', + 'eqq' => '===', ]; /** diff --git a/src/PhpTalInterface.php b/src/PhpTalInterface.php index 1238e26d..5f057cfa 100644 --- a/src/PhpTalInterface.php +++ b/src/PhpTalInterface.php @@ -28,11 +28,11 @@ public function setTemplate(string $path): self; * Use setTemplate() or addSourceResolver() whenever possible. * * @param string $src The phptal template source. - * @param string $path Fake and 'unique' template path. + * @param null|string $path Fake and 'unique' template path. * * @return $this */ - public function setSource(string $src, string $path = null): self; + public function setSource(string $src, null|string $path = null): self; /** * Specify where to look for templates. diff --git a/tests/PhpModeTestTestCase.php b/tests/PhpModeTest.php similarity index 96% rename from tests/PhpModeTestTestCase.php rename to tests/PhpModeTest.php index 1c04b48b..7d599654 100644 --- a/tests/PhpModeTestTestCase.php +++ b/tests/PhpModeTest.php @@ -22,7 +22,7 @@ use Tests\Testcase\PhpTalTestCase; use Tests\Testhelper\Helper; -class PhpModeTestTestCase extends PhpTalTestCase +class PhpModeTest extends PhpTalTestCase { public function tearDown(): void { diff --git a/tests/ReadableErrorTest.php b/tests/ReadableErrorTest.php index 4c679381..4914ecbf 100644 --- a/tests/ReadableErrorTest.php +++ b/tests/ReadableErrorTest.php @@ -88,7 +88,7 @@ public function testLocalMacroNotExists(): void $this->assertThrowsInLine(5, 'input/error-13.html'); } - public function assertThrowsInLine(int $line, string $file, string $expected_file = null): void + public function assertThrowsInLine(int $line, string $file, null|string $expected_file = null): void { $tpl = null; try { diff --git a/tests/TalesPhpWithReplaceTestTestCase.php b/tests/TalesPhpWithReplaceTest.php similarity index 95% rename from tests/TalesPhpWithReplaceTestTestCase.php rename to tests/TalesPhpWithReplaceTest.php index 2e76f344..ab938b82 100644 --- a/tests/TalesPhpWithReplaceTestTestCase.php +++ b/tests/TalesPhpWithReplaceTest.php @@ -22,7 +22,7 @@ use Tests\Testcase\PhpTalTestCase; use Tests\Testhelper\Helper; -class TalesPhpWithReplaceTestTestCase extends PhpTalTestCase +class TalesPhpWithReplaceTest extends PhpTalTestCase { public function testMix(): void { diff --git a/tests/Testhelper/CountableImpl.php b/tests/Testhelper/CountableImpl.php index 355bdadd..58228f97 100644 --- a/tests/Testhelper/CountableImpl.php +++ b/tests/Testhelper/CountableImpl.php @@ -24,7 +24,7 @@ class CountableImpl implements Countable { private readonly int $cnt; - public function __construct(int $cnt = null) + public function __construct(null|int $cnt = null) { $this->cnt = $cnt ?? 0; } diff --git a/tests/Testhelper/DummyClass.php b/tests/Testhelper/DummyClass.php index 7e713e3f..3d9c8f7a 100644 --- a/tests/Testhelper/DummyClass.php +++ b/tests/Testhelper/DummyClass.php @@ -20,9 +20,6 @@ class DummyClass { - /** - * @var null - */ public $foo; /** diff --git a/tests/PhpTransformerTestTestCase.php b/tests/TransformerTest.php similarity index 97% rename from tests/PhpTransformerTestTestCase.php rename to tests/TransformerTest.php index ac3f4552..682676e8 100644 --- a/tests/PhpTransformerTestTestCase.php +++ b/tests/TransformerTest.php @@ -22,7 +22,7 @@ use PhpTal\Php\Transformer; use Tests\Testcase\PhpTalTestCase; -class PhpTransformerTestTestCase extends PhpTalTestCase +class TransformerTest extends PhpTalTestCase { public function testBooleanOperators(): void { @@ -150,6 +150,9 @@ public function testKeywords(): void { static::assertSame('true != false', Transformer::transform('true ne false')); static::assertSame('$test == null', Transformer::transform('test eq null')); + + static::assertSame('true !== false', Transformer::transform('true nee false')); + static::assertSame('$test === null', Transformer::transform('test eqq null')); } public function testTernaryOperator(): void