diff --git a/.travis.yml b/.travis.yml index 5f054be60..df21c774e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,18 @@ env: before_install: - phpenv config-rm xdebug.ini || return 0 + - echo memory_limit = -1 >> ~/.phpenv/versions/$TRAVIS_PHP_VERSION/etc/conf.d/travis.ini install: - travis_retry composer install + - | + # install the phpunit-bridge with PHP 7.4 when testing nightly + if [[ $TRAVIS_PHP_VERSION = nightly ]]; then + (cd / && wget https://storage.googleapis.com/travis-ci-language-archives/php/binaries/ubuntu/16.04/x86_64/php-7.4.tar.bz2 -O - | tar -xj) + phpenv global 7.4; + ./vendor/bin/simple-phpunit install; + phpenv global nightly; + fi - (cd extra/cssinliner-extra && travis_retry composer install) - (cd extra/html-extra && travis_retry composer install) - (cd extra/inky-extra && travis_retry composer install) @@ -39,6 +48,7 @@ matrix: - php: 7.2 - php: 7.3 - php: 7.4 + - php: nightly # Drupal does not support 3.x yet #- stage: integration tests # php: 7.3 diff --git a/CHANGELOG b/CHANGELOG index 39f7c3444..2a2aae98f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -34,9 +34,9 @@ * bumped minimum PHP version to 7.2 * removed PSR-0 classes -# 2.12.6 (2020-XX-XX) +# 2.13.0 (2020-XX-XX) - * n/a + * Drop support for PHP 7.0 # 2.12.5 (2020-02-11) @@ -342,7 +342,8 @@ # 1.43.0 (2020-XX-XX) - * Drop PHP 5.5 and 5.6 support + * Fix PHP 8 compatibility + * Drop PHP 5.5 5.6, and 7.0 support * Fix ambiguous syntax parsing # 1.42.5 (2020-02-11) diff --git a/composer.json b/composer.json index cc7da8e84..414a0668e 100644 --- a/composer.json +++ b/composer.json @@ -5,6 +5,8 @@ "keywords": ["templating"], "homepage": "https://twig.symfony.com", "license": "BSD-3-Clause", + "minimum-stability": "dev", + "prefer-stable": true, "authors": [ { "name": "Fabien Potencier", @@ -23,7 +25,7 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.2.5|^8.0", "symfony/polyfill-mbstring": "^1.3", "symfony/polyfill-ctype": "^1.8" }, diff --git a/extra/cssinliner-extra/composer.json b/extra/cssinliner-extra/composer.json index 133cdbc1a..582529b4f 100644 --- a/extra/cssinliner-extra/composer.json +++ b/extra/cssinliner-extra/composer.json @@ -5,6 +5,8 @@ "keywords": ["twig", "css", "inlining"], "homepage": "https://twig.symfony.com", "license": "MIT", + "minimum-stability": "dev", + "prefer-stable": true, "authors": [ { "name": "Fabien Potencier", @@ -14,7 +16,7 @@ } ], "require": { - "php": "^7.1.3", + "php": "^7.1.3|^8.0", "tijsverkoyen/css-to-inline-styles": "^2.0", "twig/twig": "^2.4|^3.0" }, diff --git a/extra/html-extra/composer.json b/extra/html-extra/composer.json index 2a9ee3717..ddc8f8782 100644 --- a/extra/html-extra/composer.json +++ b/extra/html-extra/composer.json @@ -5,6 +5,8 @@ "keywords": ["twig", "html"], "homepage": "https://twig.symfony.com", "license": "MIT", + "minimum-stability": "dev", + "prefer-stable": true, "authors": [ { "name": "Fabien Potencier", @@ -14,7 +16,7 @@ } ], "require": { - "php": "^7.1.3", + "php": "^7.1.3|^8.0", "symfony/mime": "^4.3|^5.0", "twig/twig": "^2.4|^3.0" }, diff --git a/extra/inky-extra/composer.json b/extra/inky-extra/composer.json index c8a0d02b1..5628138f8 100644 --- a/extra/inky-extra/composer.json +++ b/extra/inky-extra/composer.json @@ -5,6 +5,8 @@ "keywords": ["twig", "inky", "email", "emails"], "homepage": "https://twig.symfony.com", "license": "MIT", + "minimum-stability": "dev", + "prefer-stable": true, "authors": [ { "name": "Fabien Potencier", @@ -14,7 +16,7 @@ } ], "require": { - "php": "^7.1.3", + "php": "^7.1.3|^8.0", "lorenzo/pinky": "^1.0.5", "twig/twig": "^2.4|^3.0" }, diff --git a/extra/intl-extra/composer.json b/extra/intl-extra/composer.json index d361b03e1..39733d750 100644 --- a/extra/intl-extra/composer.json +++ b/extra/intl-extra/composer.json @@ -5,6 +5,8 @@ "keywords": ["twig", "intl"], "homepage": "https://twig.symfony.com", "license": "MIT", + "minimum-stability": "dev", + "prefer-stable": true, "authors": [ { "name": "Fabien Potencier", @@ -14,7 +16,7 @@ } ], "require": { - "php": "^7.1.3", + "php": "^7.1.3|^8.0", "twig/twig": "^2.4|^3.0", "symfony/intl": "^4.3|^5.0" }, diff --git a/extra/markdown-extra/composer.json b/extra/markdown-extra/composer.json index 8ae373090..7d4e6aff8 100644 --- a/extra/markdown-extra/composer.json +++ b/extra/markdown-extra/composer.json @@ -5,6 +5,8 @@ "keywords": ["twig", "html", "markdown"], "homepage": "https://twig.symfony.com", "license": "MIT", + "minimum-stability": "dev", + "prefer-stable": true, "authors": [ { "name": "Fabien Potencier", @@ -14,7 +16,7 @@ } ], "require": { - "php": "^7.1.3", + "php": "^7.1.3|^8.0", "twig/twig": "^2.4|^3.0" }, "require-dev": { diff --git a/extra/string-extra/composer.json b/extra/string-extra/composer.json index 758386fc1..9308782a5 100644 --- a/extra/string-extra/composer.json +++ b/extra/string-extra/composer.json @@ -5,6 +5,8 @@ "keywords": ["twig", "html", "string", "unicode"], "homepage": "https://twig.symfony.com", "license": "MIT", + "minimum-stability": "dev", + "prefer-stable": true, "authors": [ { "name": "Fabien Potencier", @@ -14,7 +16,7 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.2.5|^8.0", "symfony/string": "^5.0", "twig/twig": "^2.4|^3.0" }, diff --git a/extra/twig-extra-bundle/composer.json b/extra/twig-extra-bundle/composer.json index 06267b382..4275d7bb1 100644 --- a/extra/twig-extra-bundle/composer.json +++ b/extra/twig-extra-bundle/composer.json @@ -5,6 +5,8 @@ "keywords": ["twig", "extra", "bundle"], "homepage": "https://twig.symfony.com", "license": "MIT", + "minimum-stability": "dev", + "prefer-stable": true, "authors": [ { "name": "Fabien Potencier", @@ -14,7 +16,7 @@ } ], "require": { - "php": "^7.1.3", + "php": "^7.1.3|^8.0", "symfony/framework-bundle": "^4.3|^5.0", "symfony/twig-bundle": "^4.3|^5.0", "twig/twig": "^2.4|^3.0" diff --git a/src/Node/EmbedNode.php b/src/Node/EmbedNode.php index 68f5791ae..903c3f6c7 100644 --- a/src/Node/EmbedNode.php +++ b/src/Node/EmbedNode.php @@ -23,7 +23,7 @@ use Twig\Node\Expression\ConstantExpression; class EmbedNode extends IncludeNode { // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module) - public function __construct(string $name, int $index, AbstractExpression $variables = null, bool $only = false, bool $ignoreMissing = false, int $lineno, string $tag = null) + public function __construct(string $name, int $index, ?AbstractExpression $variables, bool $only, bool $ignoreMissing, int $lineno, string $tag = null) { parent::__construct(new ConstantExpression('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag); diff --git a/src/Node/Expression/BlockReferenceExpression.php b/src/Node/Expression/BlockReferenceExpression.php index 4362be992..b1e2a8f7b 100644 --- a/src/Node/Expression/BlockReferenceExpression.php +++ b/src/Node/Expression/BlockReferenceExpression.php @@ -22,7 +22,7 @@ use Twig\Node\Node; */ class BlockReferenceExpression extends AbstractExpression { - public function __construct(Node $name, Node $template = null, int $lineno, string $tag = null) + public function __construct(Node $name, ?Node $template, int $lineno, string $tag = null) { $nodes = ['name' => $name]; if (null !== $template) { diff --git a/src/Node/Expression/CallExpression.php b/src/Node/Expression/CallExpression.php index 27b290b0f..2a3319951 100644 --- a/src/Node/Expression/CallExpression.php +++ b/src/Node/Expression/CallExpression.php @@ -258,7 +258,8 @@ abstract class CallExpression extends AbstractExpression $isPhpVariadic = false; if ($isVariadic) { $argument = end($parameters); - if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && [] === $argument->getDefaultValue()) { + $isArray = $argument && $argument->hasType() && 'array' === $argument->getType()->getName(); + if ($isArray && $argument->isDefaultValueAvailable() && [] === $argument->getDefaultValue()) { array_pop($parameters); } elseif ($argument && $argument->isVariadic()) { array_pop($parameters); diff --git a/src/Node/ForNode.php b/src/Node/ForNode.php index fd7ea689e..04addfbfe 100644 --- a/src/Node/ForNode.php +++ b/src/Node/ForNode.php @@ -25,7 +25,7 @@ class ForNode extends Node { private $loop; - public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, $ifexpr = null, Node $body, Node $else = null, int $lineno, string $tag = null) + public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, ?Node $ifexpr, Node $body, ?Node $else, int $lineno, string $tag = null) { $body = new Node([$body, $this->loop = new ForLoopNode($lineno, $tag)]); diff --git a/src/Node/IfNode.php b/src/Node/IfNode.php index bfc5371af..5fa20082a 100644 --- a/src/Node/IfNode.php +++ b/src/Node/IfNode.php @@ -21,7 +21,7 @@ use Twig\Compiler; */ class IfNode extends Node { - public function __construct(Node $tests, Node $else = null, int $lineno, string $tag = null) + public function __construct(Node $tests, ?Node $else, int $lineno, string $tag = null) { $nodes = ['tests' => $tests]; if (null !== $else) { diff --git a/src/Node/IncludeNode.php b/src/Node/IncludeNode.php index c59235365..d01f1fca3 100644 --- a/src/Node/IncludeNode.php +++ b/src/Node/IncludeNode.php @@ -22,7 +22,7 @@ use Twig\Node\Expression\AbstractExpression; */ class IncludeNode extends Node implements NodeOutputInterface { - public function __construct(AbstractExpression $expr, AbstractExpression $variables = null, bool $only = false, bool $ignoreMissing = false, int $lineno, string $tag = null) + public function __construct(AbstractExpression $expr, ?AbstractExpression $variables, bool $only, bool $ignoreMissing, int $lineno, string $tag = null) { $nodes = ['expr' => $expr]; if (null !== $variables) { diff --git a/src/Node/WithNode.php b/src/Node/WithNode.php index ec3f069dd..56a334496 100644 --- a/src/Node/WithNode.php +++ b/src/Node/WithNode.php @@ -20,7 +20,7 @@ use Twig\Compiler; */ class WithNode extends Node { - public function __construct(Node $body, Node $variables = null, bool $only = false, int $lineno, string $tag = null) + public function __construct(Node $body, ?Node $variables, bool $only, int $lineno, string $tag = null) { $nodes = ['body' => $body]; if (null !== $variables) { diff --git a/tests/Fixtures/regression/simple_xml_element.test b/tests/Fixtures/regression/simple_xml_element.test index 41e62c07c..ae633c881 100644 --- a/tests/Fixtures/regression/simple_xml_element.test +++ b/tests/Fixtures/regression/simple_xml_element.test @@ -1,5 +1,7 @@ --TEST-- Twig is able to deal with SimpleXMLElement instances as variables +--CONDITION-- +version_compare(phpversion(), '8.0', '<') --TEMPLATE-- Hello '{{ images.image.0.group }}'! {{ images.image.0.group.attributes.myattr }} diff --git a/tests/Fixtures/tests/in.test b/tests/Fixtures/tests/in.test index 01bcb90ea..a8e35f527 100644 --- a/tests/Fixtures/tests/in.test +++ b/tests/Fixtures/tests/in.test @@ -43,7 +43,6 @@ Twig supports the in operator {{ ''~dir_object in dir_object ? 'KO' : 'OK' }} {{ resource in [''~resource] ? 'KO' : 'OK' }} -{{ resource in [resource + 1 - 1] ? 'KO' : 'OK' }} {{ dir_object in [''~dir_object] ? 'KO' : 'OK' }} {{ 5 in 125 ? 'KO' : 'OK' }} @@ -106,7 +105,6 @@ OK OK OK -OK OK OK diff --git a/tests/Node/Expression/CallTest.php b/tests/Node/Expression/CallTest.php index 172ec80d3..4bfbbe424 100644 --- a/tests/Node/Expression/CallTest.php +++ b/tests/Node/Expression/CallTest.php @@ -61,6 +61,10 @@ class CallTest extends TestCase public function testResolveArgumentsWithMissingValueForOptionalArgument() { + if (\PHP_VERSION_ID >= 80000) { + $this->markTestSkipped('substr_compare() has a default value in 8.0, so the test does not work anymore, one should find another PHP built-in function for this test to work in PHP 8.'); + } + $this->expectException(SyntaxError::class); $this->expectExceptionMessage('Argument "case_sensitivity" could not be assigned for function "substr_compare(main_str, str, offset, length, case_sensitivity)" because it is mapped to an internal PHP function which cannot determine default value for optional argument "length".');