diff --git a/.travis.yml b/.travis.yml index dbac5f6f4..f3434a38a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,34 +15,36 @@ 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 - - ([[ $TRAVIS_PHP_VERSION = 7.0 ]] || (cd extra/cssinliner-extra && travis_retry composer install)) - - ([[ $TRAVIS_PHP_VERSION = 7.0 ]] || (cd extra/html-extra && travis_retry composer install)) - - ([[ $TRAVIS_PHP_VERSION = 7.0 ]] || (cd extra/inky-extra && travis_retry composer install)) - - ([[ $TRAVIS_PHP_VERSION = 7.0 ]] || (cd extra/intl-extra && travis_retry composer install)) - - ([[ $TRAVIS_PHP_VERSION = 7.0 ]] || (cd extra/markdown-extra && travis_retry composer install)) - - ([[ $TRAVIS_PHP_VERSION < 7.2 ]] || (cd extra/string-extra && 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 script: - ./vendor/bin/simple-phpunit - - ([[ $TRAVIS_PHP_VERSION = 7.0 ]] || (cd extra/cssinliner-extra && ./vendor/bin/simple-phpunit)) - - ([[ $TRAVIS_PHP_VERSION = 7.0 ]] || (cd extra/html-extra && ./vendor/bin/simple-phpunit)) - - ([[ $TRAVIS_PHP_VERSION = 7.0 ]] || (cd extra/inky-extra && ./vendor/bin/simple-phpunit)) - - ([[ $TRAVIS_PHP_VERSION = 7.0 ]] || (cd extra/intl-extra && ./vendor/bin/simple-phpunit)) - - ([[ $TRAVIS_PHP_VERSION = 7.0 ]] || (cd extra/markdown-extra && ./vendor/bin/simple-phpunit)) + - (cd extra/cssinliner-extra && ./vendor/bin/simple-phpunit) + - (cd extra/html-extra && ./vendor/bin/simple-phpunit) + - (cd extra/inky-extra && ./vendor/bin/simple-phpunit) + - (cd extra/intl-extra && ./vendor/bin/simple-phpunit) + - (cd extra/markdown-extra && ./vendor/bin/simple-phpunit) - ([[ $TRAVIS_PHP_VERSION < 7.2 ]] || (cd extra/string-extra && ./vendor/bin/simple-phpunit)) matrix: fast_finish: true include: - - php: 7.0 - dist: trusty - php: 7.1 - php: 7.2 - php: 7.3 - php: 7.4 + - php: nightly - stage: integration tests php: 7.3 script: ./drupal_test.sh diff --git a/CHANGELOG b/CHANGELOG index ab73d4d77..66707ba98 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -306,7 +306,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 0d1c0ad1b..9ed20b6be 100644 --- a/composer.json +++ b/composer.json @@ -5,6 +5,7 @@ "keywords": ["templating"], "homepage": "https://twig.symfony.com", "license": "BSD-3-Clause", + "minimum-stability": "dev", "authors": [ { "name": "Fabien Potencier", @@ -23,7 +24,7 @@ } ], "require": { - "php": "^7.0", + "php": "^7.1.3|^8.0", "symfony/polyfill-mbstring": "^1.3", "symfony/polyfill-ctype": "^1.8" }, diff --git a/doc/intro.rst b/doc/intro.rst index c477c7838..3011f13a3 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -26,7 +26,7 @@ Slim, Yii, Laravel, and Codeigniter — just to name a few. Prerequisites ------------- -Twig needs at least **PHP 7.0.0** to run. +Twig needs at least **PHP 7.1.3** to run. Installation ------------ diff --git a/src/Node/EmbedNode.php b/src/Node/EmbedNode.php index 4a1ef6fc5..016c17f87 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 c68989ae7..8a6db4d00 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 4ecd2c111..e182b0280 100644 --- a/src/Node/Expression/CallExpression.php +++ b/src/Node/Expression/CallExpression.php @@ -259,7 +259,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 54afe9383..d5c34e617 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, AbstractExpression $ifexpr = null, Node $body, Node $else = null, int $lineno, string $tag = null) + public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, ?AbstractExpression $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 814a6f3a9..8ba23ddb6 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 d45303016..3bc91295b 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 74d1ea0a3..07a1c4e30 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 42f7703c6..20c3d947b 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".');