public function getFunctionNode($name, $line) { $args = $this->parseArguments(); switch ($name) { case 'parent': if (!count($this->parser->getBlockStack())) { throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line); } if (!$this->parser->getParent() && !$this->parser->hasTraits()) { throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line); } return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line); case 'block': return new Twig_Node_Expression_BlockReference($args->getNode(0), false, $line); case 'attribute': if (count($args) < 2) { throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line); } return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_TemplateInterface::ANY_CALL, $line); default: if (null !== ($alias = $this->parser->getImportedFunction($name))) { $arguments = new Twig_Node_Expression_Array(array(), $line); foreach ($args as $n) { $arguments->addElement($n); } $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line); $node->setAttribute('safe', true); return $node; } $class = $this->getFunctionNodeClass($name); return new $class($name, $args, $line); } }
public function parseSubscriptExpression($node) { $stream = $this->parser->getStream(); $token = $stream->next(); $lineno = $token->getLine(); $arguments = new Twig_Node_Expression_Array(array(), $lineno); $type = Twig_Template::ANY_CALL; if ($token->getValue() == '.') { $token = $stream->next(); if ($token->getType() == Twig_Token::NAME_TYPE || $token->getType() == Twig_Token::NUMBER_TYPE || $token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue())) { $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { $type = Twig_TemplateInterface::METHOD_CALL; foreach ($this->parseArguments() as $n) { $arguments->addElement($n); } } } else { throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename()); } if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { if (!$arg instanceof Twig_Node_Expression_Constant) { throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename()); } $node = new Twig_Node_Expression_MethodCall($node, 'get' . $arg->getAttribute('value'), $arguments, $lineno); $node->setAttribute('safe', true); return $node; } } else { $type = Twig_Template::ARRAY_CALL; // slice? $slice = false; if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) { $slice = true; $arg = new Twig_Node_Expression_Constant(0, $token->getLine()); } else { $arg = $this->parseExpression(); } if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { $slice = true; } if ($slice) { if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { $length = new Twig_Node_Expression_Constant(null, $token->getLine()); } else { $length = $this->parseExpression(); } $class = $this->getFilterNodeClass('slice', $token->getLine()); $arguments = new Twig_Node(array($arg, $length)); $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine()); $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); return $filter; } $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); } return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno); }
public function parseSubscriptExpression($node) { $stream = $this->parser->getStream(); $token = $stream->next(); $lineno = $token->getLine(); $arguments = new Twig_Node_Expression_Array(array(), $lineno); $type = Twig_Template::ANY_CALL; if ($token->getValue() == '.') { $token = $stream->next(); if ($token->getType() == Twig_Token::NAME_TYPE || $token->getType() == Twig_Token::NUMBER_TYPE || $token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue())) { $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { $type = Twig_Template::METHOD_CALL; foreach ($this->parseArguments() as $n) { $arguments->addElement($n); } } } else { throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename()); } if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { if (!$arg instanceof Twig_Node_Expression_Constant) { throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename()); } $name = $arg->getAttribute('value'); $node = new Twig_Node_Expression_MethodCall($node, 'macro_' . $name, $arguments, $lineno); $node->setAttribute('safe', true); return $node; } if ($node instanceof Twig_Node_Expression_Name && null !== ($symbol = $this->parser->getImportedSymbol('types', $node->getAttribute('name'))) && false === $this->parser->getEnvironment()->hasExtension('sandbox')) { $class = $symbol['name']; if (0 === strcasecmp($class, 'array')) { $type = Twig_Template::ARRAY_CALL; return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno); } if (!class_exists($class)) { throw new Twig_Error_Syntax(sprintf('Class "%s" set for %s was not found.', $class, $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename()); } $name = $arg->getAttribute('value'); if (Twig_Template::METHOD_CALL !== $type) { $vars = get_class_vars($class); if (isset($vars[$name])) { if ($this->parser->getEnvironment()->hasExtension('sandbox')) { $this->parser->getEnvironment()->getExtension('sandbox')->checkPropertyAllowed($class, $name); } return new Twig_Node_Expression_GetProperty($node, $name, $lineno); } } $methods = array_change_key_case(array_flip(get_class_methods($class))); $lcItem = strtolower($name); if (isset($methods[$lcItem])) { $method = (string) $name; } elseif (isset($methods['get' . $lcItem])) { $method = 'get' . $name; } elseif (isset($methods['is' . $lcItem])) { $method = 'is' . $name; } elseif (isset($methods['__call'])) { $method = (string) $name; } if (isset($method)) { return new Twig_Node_Expression_MethodCall($node, $method, $arguments, $lineno); } } } else { $type = Twig_Template::ARRAY_CALL; // slice? $slice = false; if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) { $slice = true; $arg = new Twig_Node_Expression_Constant(0, $token->getLine()); } else { $arg = $this->parseExpression(); } if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { $slice = true; } if ($slice) { if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { $length = new Twig_Node_Expression_Constant(null, $token->getLine()); } else { $length = $this->parseExpression(); } $class = $this->getFilterNodeClass('slice', $token->getLine()); $arguments = new Twig_Node(array($arg, $length)); $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine()); $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); return $filter; } $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); } return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno); }