From e01c29be32f70ab7ced64540e8f2f0932a0175d8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Oct 2016 19:06:18 -0700 Subject: [PATCH] fixed regression on static calls for functions/filters/tests --- CHANGELOG | 2 +- lib/Twig/Node/Expression/Call.php | 15 ++++++++++++- .../Fixtures/expressions/magic_call.test | 22 +++++++++---------- .../Tests/Fixtures/functions/magic_call.test | 8 +++++++ .../Fixtures/functions/magic_call53.test | 12 ++++++++++ test/Twig/Tests/IntegrationTest.php | 21 ++++++++++++++++++ 6 files changed, 67 insertions(+), 13 deletions(-) create mode 100644 test/Twig/Tests/Fixtures/functions/magic_call.test create mode 100644 test/Twig/Tests/Fixtures/functions/magic_call53.test diff --git a/CHANGELOG b/CHANGELOG index 2561b4ea8..37a05c825 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,6 @@ * 1.26.1 (2016-XX-XX) - * n/a + * fixed regression on static calls for functions/filters/tests * 1.26.0 (2016-10-02) diff --git a/lib/Twig/Node/Expression/Call.php b/lib/Twig/Node/Expression/Call.php index 224c22dc4..1865043cc 100644 --- a/lib/Twig/Node/Expression/Call.php +++ b/lib/Twig/Node/Expression/Call.php @@ -219,6 +219,9 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression private function getCallableParameters($callable, $isVariadic) { list($r, $_) = $this->reflectCallable($callable); + if (null === $r) { + return array(); + } $parameters = $r->getParameters(); if ($this->hasNode('node')) { @@ -259,14 +262,24 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression } if (is_array($callable)) { + if (!method_exists($callable[0], $callable[1])) { + // __call() + return array(null, array()); + } $r = new ReflectionMethod($callable[0], $callable[1]); } elseif (is_object($callable) && !$callable instanceof Closure) { $r = new ReflectionObject($callable); $r = $r->getMethod('__invoke'); $callable = array($callable, '__invoke'); } elseif (is_string($callable) && false !== $pos = strpos($callable, '::')) { + $class = substr($callable, 0, $pos); + $method = substr($callable, $pos + 2); + if (!method_exists($class, $method)) { + // __staticCall() + return array(null, array()); + } $r = new ReflectionMethod($callable); - $callable = array(substr($callable, 0, $pos), substr($callable, $pos + 2)); + $callable = array($class, $method); } else { $r = new ReflectionFunction($callable); } diff --git a/test/Twig/Tests/Fixtures/expressions/magic_call.test b/test/Twig/Tests/Fixtures/expressions/magic_call.test index 159db96f5..1a27a2d6f 100644 --- a/test/Twig/Tests/Fixtures/expressions/magic_call.test +++ b/test/Twig/Tests/Fixtures/expressions/magic_call.test @@ -6,21 +6,21 @@ Twig supports __call() for attributes --DATA-- class TestClassForMagicCallAttributes { - public function getBar() - { - return 'bar_from_getbar'; - } - - public function __call($method, $arguments) - { - if ('foo' === $method) + public function getBar() { - return 'foo_from_call'; + return 'bar_from_getbar'; } - return false; - } + public function __call($method, $arguments) + { + if ('foo' === $method) { + return 'foo_from_call'; + } + + return false; + } } + return array('foo' => new TestClassForMagicCallAttributes()) --EXPECT-- foo_from_call diff --git a/test/Twig/Tests/Fixtures/functions/magic_call.test b/test/Twig/Tests/Fixtures/functions/magic_call.test new file mode 100644 index 000000000..933544312 --- /dev/null +++ b/test/Twig/Tests/Fixtures/functions/magic_call.test @@ -0,0 +1,8 @@ +--TEST-- +__call calls +--TEMPLATE-- +{{ 'foo'|magic_call }} +--DATA-- +return array() +--EXPECT-- +magic_foo diff --git a/test/Twig/Tests/Fixtures/functions/magic_call53.test b/test/Twig/Tests/Fixtures/functions/magic_call53.test new file mode 100644 index 000000000..a0f55e116 --- /dev/null +++ b/test/Twig/Tests/Fixtures/functions/magic_call53.test @@ -0,0 +1,12 @@ +--TEST-- +__staticCall calls +--CONDITION-- +version_compare(phpversion(), '5.3.0', '>=') +--TEMPLATE-- +{{ 'foo'|magic_call_string }} +{{ 'foo'|magic_call_array }} +--DATA-- +return array() +--EXPECT-- +static_magic_foo +static_magic_foo diff --git a/test/Twig/Tests/IntegrationTest.php b/test/Twig/Tests/IntegrationTest.php index d4d578149..0647891b6 100644 --- a/test/Twig/Tests/IntegrationTest.php +++ b/test/Twig/Tests/IntegrationTest.php @@ -143,6 +143,9 @@ class TwigTestExtension extends Twig_Extension new Twig_SimpleFilter('preserves_safety', array($this, 'preserves_safety'), array('preserves_safety' => array('html'))), new Twig_SimpleFilter('static_call_string', 'TwigTestExtension::staticCall'), new Twig_SimpleFilter('static_call_array', array('TwigTestExtension', 'staticCall')), + new Twig_SimpleFilter('magic_call', array($this, 'magicCall')), + new Twig_SimpleFilter('magic_call_string', 'TwigTestExtension::magicStaticCall'), + new Twig_SimpleFilter('magic_call_array', array('TwigTestExtension', 'magicStaticCall')), new Twig_SimpleFilter('*_path', array($this, 'dynamic_path')), new Twig_SimpleFilter('*_foo_*_bar', array($this, 'dynamic_foo')), ); @@ -230,4 +233,22 @@ class TwigTestExtension extends Twig_Extension { return false !== strpos($value, ' '); } + + public function __call($method, $arguments) + { + if ('magicCall' !== $method) { + throw new BadMethodCallException('Unexpected call to __call'); + } + + return 'magic_'.$arguments[0]; + } + + public static function __callStatic($method, $arguments) + { + if ('magicStaticCall' !== $method) { + throw new BadMethodCallException('Unexpected call to __callStatic'); + } + + return 'static_magic_'.$arguments[0]; + } }