From: fabien Date: Mon, 12 Oct 2009 17:05:12 +0000 (+0000) Subject: added support for method calls with arguments X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=7fa1167b2d7a8df6137dbdb0bca3b6cea442cea5;p=konrad%2Ftwig.git added support for method calls with arguments git-svn-id: http://svn.twig-project.org/trunk@35 93ef8e89-cb99-4229-a87c-7fa0fa45744b --- diff --git a/lib/Twig/ExpressionParser.php b/lib/Twig/ExpressionParser.php index 6cb5441..fbcd1c3 100644 --- a/lib/Twig/ExpressionParser.php +++ b/lib/Twig/ExpressionParser.php @@ -313,12 +313,15 @@ class Twig_ExpressionParser { $token = $this->parser->getStream()->next(); $lineno = $token->getLine(); + $arguments = array(); if ($token->getValue() == '.') { $token = $this->parser->getStream()->next(); if ($token->getType() == Twig_Token::NAME_TYPE || $token->getType() == Twig_Token::NUMBER_TYPE) { $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); + + $arguments = $this->parseArguments(); } else { @@ -331,7 +334,7 @@ class Twig_ExpressionParser $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ']'); } - return new Twig_Node_Expression_GetAttr($node, $arg, $lineno, $token->getValue()); + return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $lineno, $token->getValue()); } public function parseFilterExpression($node) @@ -342,24 +345,33 @@ class Twig_ExpressionParser { $this->parser->getStream()->next(); $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE); - $args = array(); - if ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '(')) + + $filters[] = array($token->getValue(), $this->parseArguments()); + } + + return new Twig_Node_Expression_Filter($node, $filters, $lineno); + } + + public function parseArguments() + { + if (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '(')) + { + return array(); + } + + $args = array(); + $this->parser->getStream()->next(); + while (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ')')) + { + if (!empty($args)) { - $this->parser->getStream()->next(); - while (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ')')) - { - if (!empty($args)) - { - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ','); - } - $args[] = $this->parseExpression(); - } - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ')'); + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ','); } - $filters[] = array($token->getValue(), $args); + $args[] = $this->parseExpression(); } + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ')'); - return new Twig_Node_Expression_Filter($node, $filters, $lineno); + return $args; } public function parseAssignmentExpression() diff --git a/lib/Twig/Node/Expression/GetAttr.php b/lib/Twig/Node/Expression/GetAttr.php index 1a03623..ad59f2f 100644 --- a/lib/Twig/Node/Expression/GetAttr.php +++ b/lib/Twig/Node/Expression/GetAttr.php @@ -13,12 +13,14 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression implements Twig_ { protected $node; protected $attr; + protected $arguments; - public function __construct(Twig_Node $node, $attr, $lineno, $token_value) + public function __construct(Twig_Node $node, $attr, $arguments, $lineno, $token_value) { parent::__construct($lineno); $this->node = $node; $this->attr = $attr; + $this->arguments = $arguments; $this->token_value = $token_value; } @@ -44,11 +46,22 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression implements Twig_ ->subcompile($this->node) ->raw(', ') ->subcompile($this->attr) + ->raw(', array(') ; - if ('[' == $this->token_value) # Don't look for functions if they're using foo[bar] + foreach ($this->arguments as $node) { - $compiler->raw(', false'); + $compiler + ->subcompile($node) + ->raw(', ') + ; + } + + $compiler->raw(')'); + + if ('[' == $this->token_value) // Don't look for functions if they're using foo[bar] + { + $compiler->raw(', true'); } $compiler->raw(')'); diff --git a/lib/Twig/Template.php b/lib/Twig/Template.php index 43a4918..f22b0ce 100644 --- a/lib/Twig/Template.php +++ b/lib/Twig/Template.php @@ -43,15 +43,24 @@ abstract class Twig_Template implements Twig_TemplateInterface throw new Twig_RuntimeError(sprintf('The filter "%s" does not exist', $name)); } - protected function getAttribute($object, $item) + protected function getAttribute($object, $item, array $arguments = array(), $arrayOnly = false) { $item = (string) $item; - if (is_array($object) && isset($object[$item])) + if ( + is_array($object) && isset($object[$item]) + || + is_object($object) && $object instanceof ArrayAccess && isset($object[$item]) + ) { return $object[$item]; } + if ($arrayOnly) + { + return null; + } + if ( !is_object($object) || ( @@ -68,6 +77,6 @@ abstract class Twig_Template implements Twig_TemplateInterface $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method); } - return $object->$method(); + return call_user_func_array(array($object, $method), $arguments); } } diff --git a/test/fixtures/expressions/array_call.test b/test/fixtures/expressions/array_call.test new file mode 100644 index 0000000..f3df328 --- /dev/null +++ b/test/fixtures/expressions/array_call.test @@ -0,0 +1,14 @@ +--TEST-- +Twig supports method calls +--TEMPLATE-- +{{ items.foo }} +{{ items['foo'] }} +{{ items[foo] }} +{{ items[items[foo]] }} +--DATA-- +return array('foo' => 'bar', 'items' => array('foo' => 'bar', 'bar' => 'foo')) +--EXPECT-- +bar +bar +foo +bar diff --git a/test/fixtures/expressions/method_call.test b/test/fixtures/expressions/method_call.test new file mode 100644 index 0000000..adea3b3 --- /dev/null +++ b/test/fixtures/expressions/method_call.test @@ -0,0 +1,16 @@ +--TEST-- +Twig supports method calls +--TEMPLATE-- +{{ items.foo.foo }} +{{ items.foo.bar }} +{{ items.foo['bar'] }} +{{ items.foo.bar('a', 43) }} +{{ items.foo.bar(foo) }} +--DATA-- +return array('foo' => 'bar', 'items' => array('foo' => new Foo(), 'bar' => 'foo')) +--EXPECT-- +foo +bar + +bar_a-43 +bar_bar diff --git a/test/unit/integrationTest.php b/test/unit/integrationTest.php index 3f72464..cb5e14e 100644 --- a/test/unit/integrationTest.php +++ b/test/unit/integrationTest.php @@ -17,7 +17,20 @@ Twig_Autoloader::register(); require_once dirname(__FILE__).'/../lib/Twig_Loader_Var.php'; -$t = new LimeTest(42); +class Foo +{ + public function bar($param1 = null, $param2 = null) + { + return 'bar'.($param1 ? '_'.$param1 : '').($param2 ? '-'.$param2 : ''); + } + + public function getFoo() + { + return 'foo'; + } +} + +$t = new LimeTest(44); $fixturesDir = realpath(dirname(__FILE__).'/../fixtures/'); foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file)