Skip to content

Commit

Permalink
made Resource::getAttribute() more generic (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
fabpot committed Jun 7, 2010
1 parent d46517f commit f2bb0aa
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 29 deletions.
9 changes: 8 additions & 1 deletion lib/Twig/ExpressionParser.php
Expand Up @@ -370,21 +370,28 @@ public function parseSubscriptExpression($node)
$token = $this->parser->getStream()->next();
$lineno = $token->getLine();
$arguments = new Twig_Node();
$type = Twig_Node_Expression_GetAttr::TYPE_ANY;
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);

if ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '(')) {
$type = Twig_Node_Expression_GetAttr::TYPE_METHOD;
}

$arguments = $this->parseArguments();
} else {
throw new Twig_SyntaxError('Expected name or number', $lineno);
}
} else {
$type = Twig_Node_Expression_GetAttr::TYPE_ARRAY;

$arg = $this->parseExpression();
$this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ']');
}

return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $lineno, $token->getValue());
return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $lineno, $type);
}

public function parseFilterExpression($node)
Expand Down
20 changes: 10 additions & 10 deletions lib/Twig/Node/Expression/GetAttr.php
Expand Up @@ -11,9 +11,13 @@
*/
class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
{
public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_NodeInterface $arguments, $lineno, $token_value = null)
const TYPE_ANY = 'any';
const TYPE_ARRAY = 'array';
const TYPE_METHOD = 'method';

public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_NodeInterface $arguments, $lineno, $type = self::TYPE_ANY)
{
parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('token_value' => $token_value), $lineno);
parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type), $lineno);
}

public function compile($compiler)
Expand All @@ -33,13 +37,9 @@ public function compile($compiler)
;
}

$compiler->raw(')');

// Don't look for functions if they're using foo[bar]
if ('[' == $this['token_value']) {
$compiler->raw(', true');
}

$compiler->raw(')');
$compiler
->raw('), ')
->repr($this['type'])
->raw(')');
}
}
35 changes: 24 additions & 11 deletions lib/Twig/Resource.php
Expand Up @@ -37,30 +37,43 @@ protected function getContext($context, $item)
throw new InvalidArgumentException(sprintf('Item "%s" from context does not exist.', $item));
}

protected function getAttribute($object, $item, array $arguments = array(), $arrayOnly = false)
protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_Node_Expression_GetAttr::TYPE_ANY)
{
$item = (string) $item;
// array
if (Twig_Node_Expression_GetAttr::TYPE_METHOD !== $type) {
if ((is_array($object) || is_object($object) && $object instanceof ArrayAccess) && isset($object[$item])) {
return $object[$item];
}

if (Twig_Node_Expression_GetAttr::TYPE_ARRAY === $type) {
if (!$this->env->isStrictVariables()) {
return null;
}

if ((is_array($object) || is_object($object) && $object instanceof ArrayAccess) && isset($object[$item])) {
return $object[$item];
throw new InvalidArgumentException(sprintf('Key "%s" for array "%s" does not exist.', $item, $object));
}
}

if ($arrayOnly || !is_object($object)) {
if (!is_object($object)) {
if (!$this->env->isStrictVariables()) {
return null;
}

throw new InvalidArgumentException(sprintf('Key "%s" for array "%s" does not exist.', $item, $object));
throw new InvalidArgumentException(sprintf('Item "%s" for "%s" does not exist.', $item, $object));
}

if (isset($object->$item)) {
if ($this->env->hasExtension('sandbox')) {
$this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item);
}
// object property
if (Twig_Node_Expression_GetAttr::TYPE_METHOD !== $type) {
if (isset($object->$item)) {
if ($this->env->hasExtension('sandbox')) {
$this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item);
}

return $object->$item;
return $object->$item;
}
}

// object method
$class = get_class($object);

if (!isset($this->cache[$class])) {
Expand Down
15 changes: 8 additions & 7 deletions test/Twig/Tests/Node/Expression/GetAttrTest.php
Expand Up @@ -24,12 +24,12 @@ public function testConstructor()
new Twig_Node_Expression_Name('foo', 0),
new Twig_Node_Expression_Constant('bar', 0),
));
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0, '[');
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0, Twig_Node_Expression_GetAttr::TYPE_ARRAY);

$this->assertEquals($expr, $node->node);
$this->assertEquals($attr, $node->attribute);
$this->assertEquals($args, $node->arguments);
$this->assertEquals('[', $node['token_value']);
$this->assertEquals(Twig_Node_Expression_GetAttr::TYPE_ARRAY, $node['type']);
}

/**
Expand All @@ -49,17 +49,18 @@ public function getTests()
$attr = new Twig_Node_Expression_Constant('bar', 0);
$args = new Twig_Node();
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0);
$tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array())');
$tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array(), "any")');

$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0, Twig_Node_Expression_GetAttr::TYPE_ARRAY);
$tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array(), "array")');

$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0, '[');
$tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array(), true)');

$args = new Twig_Node(array(
new Twig_Node_Expression_Name('foo', 0),
new Twig_Node_Expression_Constant('bar', 0),
));
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0);
$tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array($this->getContext($context, \'foo\'), "bar", ))');
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0, Twig_Node_Expression_GetAttr::TYPE_METHOD);
$tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array($this->getContext($context, \'foo\'), "bar", ), "method")');

return $tests;
}
Expand Down

0 comments on commit f2bb0aa

Please sign in to comment.