[ Index ] |
PHP Cross Reference of phpBB-3.1.12-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of Twig. 5 * 6 * (c) 2009 Fabien Potencier 7 * (c) 2009 Armin Ronacher 8 * 9 * For the full copyright and license information, please view the LICENSE 10 * file that was distributed with this source code. 11 */ 12 13 /** 14 * Parses expressions. 15 * 16 * This parser implements a "Precedence climbing" algorithm. 17 * 18 * @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm 19 * @see http://en.wikipedia.org/wiki/Operator-precedence_parser 20 * 21 * @author Fabien Potencier <fabien@symfony.com> 22 */ 23 class Twig_ExpressionParser 24 { 25 const OPERATOR_LEFT = 1; 26 const OPERATOR_RIGHT = 2; 27 28 protected $parser; 29 protected $unaryOperators; 30 protected $binaryOperators; 31 32 public function __construct(Twig_Parser $parser, array $unaryOperators, array $binaryOperators) 33 { 34 $this->parser = $parser; 35 $this->unaryOperators = $unaryOperators; 36 $this->binaryOperators = $binaryOperators; 37 } 38 39 public function parseExpression($precedence = 0) 40 { 41 $expr = $this->getPrimary(); 42 $token = $this->parser->getCurrentToken(); 43 while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) { 44 $op = $this->binaryOperators[$token->getValue()]; 45 $this->parser->getStream()->next(); 46 47 if (isset($op['callable'])) { 48 $expr = call_user_func($op['callable'], $this->parser, $expr); 49 } else { 50 $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']); 51 $class = $op['class']; 52 $expr = new $class($expr, $expr1, $token->getLine()); 53 } 54 55 $token = $this->parser->getCurrentToken(); 56 } 57 58 if (0 === $precedence) { 59 return $this->parseConditionalExpression($expr); 60 } 61 62 return $expr; 63 } 64 65 protected function getPrimary() 66 { 67 $token = $this->parser->getCurrentToken(); 68 69 if ($this->isUnary($token)) { 70 $operator = $this->unaryOperators[$token->getValue()]; 71 $this->parser->getStream()->next(); 72 $expr = $this->parseExpression($operator['precedence']); 73 $class = $operator['class']; 74 75 return $this->parsePostfixExpression(new $class($expr, $token->getLine())); 76 } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '(')) { 77 $this->parser->getStream()->next(); 78 $expr = $this->parseExpression(); 79 $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed'); 80 81 return $this->parsePostfixExpression($expr); 82 } 83 84 return $this->parsePrimaryExpression(); 85 } 86 87 protected function parseConditionalExpression($expr) 88 { 89 while ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, '?')) { 90 if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { 91 $expr2 = $this->parseExpression(); 92 if ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { 93 $expr3 = $this->parseExpression(); 94 } else { 95 $expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine()); 96 } 97 } else { 98 $expr2 = $expr; 99 $expr3 = $this->parseExpression(); 100 } 101 102 $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine()); 103 } 104 105 return $expr; 106 } 107 108 protected function isUnary(Twig_Token $token) 109 { 110 return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]); 111 } 112 113 protected function isBinary(Twig_Token $token) 114 { 115 return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]); 116 } 117 118 public function parsePrimaryExpression() 119 { 120 $token = $this->parser->getCurrentToken(); 121 switch ($token->getType()) { 122 case Twig_Token::NAME_TYPE: 123 $this->parser->getStream()->next(); 124 switch ($token->getValue()) { 125 case 'true': 126 case 'TRUE': 127 $node = new Twig_Node_Expression_Constant(true, $token->getLine()); 128 break; 129 130 case 'false': 131 case 'FALSE': 132 $node = new Twig_Node_Expression_Constant(false, $token->getLine()); 133 break; 134 135 case 'none': 136 case 'NONE': 137 case 'null': 138 case 'NULL': 139 $node = new Twig_Node_Expression_Constant(null, $token->getLine()); 140 break; 141 142 default: 143 if ('(' === $this->parser->getCurrentToken()->getValue()) { 144 $node = $this->getFunctionNode($token->getValue(), $token->getLine()); 145 } else { 146 $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine()); 147 } 148 } 149 break; 150 151 case Twig_Token::NUMBER_TYPE: 152 $this->parser->getStream()->next(); 153 $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); 154 break; 155 156 case Twig_Token::STRING_TYPE: 157 case Twig_Token::INTERPOLATION_START_TYPE: 158 $node = $this->parseStringExpression(); 159 break; 160 161 case Twig_Token::OPERATOR_TYPE: 162 if (preg_match(Twig_Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) { 163 // in this context, string operators are variable names 164 $this->parser->getStream()->next(); 165 $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine()); 166 break; 167 } elseif (isset($this->unaryOperators[$token->getValue()])) { 168 $class = $this->unaryOperators[$token->getValue()]['class']; 169 170 $ref = new ReflectionClass($class); 171 $negClass = 'Twig_Node_Expression_Unary_Neg'; 172 $posClass = 'Twig_Node_Expression_Unary_Pos'; 173 if (!(in_array($ref->getName(), array($negClass, $posClass)) || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass))) { 174 throw new Twig_Error_Syntax(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getFilename()); 175 } 176 177 $this->parser->getStream()->next(); 178 $expr = $this->parsePrimaryExpression(); 179 180 $node = new $class($expr, $token->getLine()); 181 break; 182 } 183 184 default: 185 if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) { 186 $node = $this->parseArrayExpression(); 187 } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) { 188 $node = $this->parseHashExpression(); 189 } else { 190 throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getFilename()); 191 } 192 } 193 194 return $this->parsePostfixExpression($node); 195 } 196 197 public function parseStringExpression() 198 { 199 $stream = $this->parser->getStream(); 200 201 $nodes = array(); 202 // a string cannot be followed by another string in a single expression 203 $nextCanBeString = true; 204 while (true) { 205 if ($nextCanBeString && $token = $stream->nextIf(Twig_Token::STRING_TYPE)) { 206 $nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); 207 $nextCanBeString = false; 208 } elseif ($stream->nextIf(Twig_Token::INTERPOLATION_START_TYPE)) { 209 $nodes[] = $this->parseExpression(); 210 $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); 211 $nextCanBeString = true; 212 } else { 213 break; 214 } 215 } 216 217 $expr = array_shift($nodes); 218 foreach ($nodes as $node) { 219 $expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getLine()); 220 } 221 222 return $expr; 223 } 224 225 public function parseArrayExpression() 226 { 227 $stream = $this->parser->getStream(); 228 $stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected'); 229 230 $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); 231 $first = true; 232 while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { 233 if (!$first) { 234 $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma'); 235 236 // trailing ,? 237 if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { 238 break; 239 } 240 } 241 $first = false; 242 243 $node->addElement($this->parseExpression()); 244 } 245 $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed'); 246 247 return $node; 248 } 249 250 public function parseHashExpression() 251 { 252 $stream = $this->parser->getStream(); 253 $stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected'); 254 255 $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); 256 $first = true; 257 while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { 258 if (!$first) { 259 $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma'); 260 261 // trailing ,? 262 if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { 263 break; 264 } 265 } 266 $first = false; 267 268 // a hash key can be: 269 // 270 // * a number -- 12 271 // * a string -- 'a' 272 // * a name, which is equivalent to a string -- a 273 // * an expression, which must be enclosed in parentheses -- (1 + 2) 274 if (($token = $stream->nextIf(Twig_Token::STRING_TYPE)) || ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) || $token = $stream->nextIf(Twig_Token::NUMBER_TYPE)) { 275 $key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); 276 } elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { 277 $key = $this->parseExpression(); 278 } else { 279 $current = $stream->getCurrent(); 280 281 throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $this->parser->getFilename()); 282 } 283 284 $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); 285 $value = $this->parseExpression(); 286 287 $node->addElement($value, $key); 288 } 289 $stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed'); 290 291 return $node; 292 } 293 294 public function parsePostfixExpression($node) 295 { 296 while (true) { 297 $token = $this->parser->getCurrentToken(); 298 if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) { 299 if ('.' == $token->getValue() || '[' == $token->getValue()) { 300 $node = $this->parseSubscriptExpression($node); 301 } elseif ('|' == $token->getValue()) { 302 $node = $this->parseFilterExpression($node); 303 } else { 304 break; 305 } 306 } else { 307 break; 308 } 309 } 310 311 return $node; 312 } 313 314 public function getFunctionNode($name, $line) 315 { 316 switch ($name) { 317 case 'parent': 318 $this->parseArguments(); 319 if (!count($this->parser->getBlockStack())) { 320 throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden.', $line, $this->parser->getFilename()); 321 } 322 323 if (!$this->parser->getParent() && !$this->parser->hasTraits()) { 324 throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getFilename()); 325 } 326 327 return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line); 328 case 'block': 329 return new Twig_Node_Expression_BlockReference($this->parseArguments()->getNode(0), false, $line); 330 case 'attribute': 331 $args = $this->parseArguments(); 332 if (count($args) < 2) { 333 throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getFilename()); 334 } 335 336 return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line); 337 default: 338 if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) { 339 $arguments = new Twig_Node_Expression_Array(array(), $line); 340 foreach ($this->parseArguments() as $n) { 341 $arguments->addElement($n); 342 } 343 344 $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line); 345 $node->setAttribute('safe', true); 346 347 return $node; 348 } 349 350 $args = $this->parseArguments(true); 351 $class = $this->getFunctionNodeClass($name, $line); 352 353 return new $class($name, $args, $line); 354 } 355 } 356 357 public function parseSubscriptExpression($node) 358 { 359 $stream = $this->parser->getStream(); 360 $token = $stream->next(); 361 $lineno = $token->getLine(); 362 $arguments = new Twig_Node_Expression_Array(array(), $lineno); 363 $type = Twig_Template::ANY_CALL; 364 if ($token->getValue() == '.') { 365 $token = $stream->next(); 366 if ( 367 $token->getType() == Twig_Token::NAME_TYPE 368 || 369 $token->getType() == Twig_Token::NUMBER_TYPE 370 || 371 ($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue())) 372 ) { 373 $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); 374 375 if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { 376 $type = Twig_Template::METHOD_CALL; 377 foreach ($this->parseArguments() as $n) { 378 $arguments->addElement($n); 379 } 380 } 381 } else { 382 throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename()); 383 } 384 385 if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { 386 if (!$arg instanceof Twig_Node_Expression_Constant) { 387 throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename()); 388 } 389 390 $name = $arg->getAttribute('value'); 391 392 if ($this->parser->isReservedMacroName($name)) { 393 throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $this->parser->getFilename()); 394 } 395 396 $node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno); 397 $node->setAttribute('safe', true); 398 399 return $node; 400 } 401 } else { 402 $type = Twig_Template::ARRAY_CALL; 403 404 // slice? 405 $slice = false; 406 if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) { 407 $slice = true; 408 $arg = new Twig_Node_Expression_Constant(0, $token->getLine()); 409 } else { 410 $arg = $this->parseExpression(); 411 } 412 413 if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { 414 $slice = true; 415 } 416 417 if ($slice) { 418 if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { 419 $length = new Twig_Node_Expression_Constant(null, $token->getLine()); 420 } else { 421 $length = $this->parseExpression(); 422 } 423 424 $class = $this->getFilterNodeClass('slice', $token->getLine()); 425 $arguments = new Twig_Node(array($arg, $length)); 426 $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine()); 427 428 $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); 429 430 return $filter; 431 } 432 433 $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); 434 } 435 436 return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno); 437 } 438 439 public function parseFilterExpression($node) 440 { 441 $this->parser->getStream()->next(); 442 443 return $this->parseFilterExpressionRaw($node); 444 } 445 446 public function parseFilterExpressionRaw($node, $tag = null) 447 { 448 while (true) { 449 $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE); 450 451 $name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); 452 if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) { 453 $arguments = new Twig_Node(); 454 } else { 455 $arguments = $this->parseArguments(true); 456 } 457 458 $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine()); 459 460 $node = new $class($node, $name, $arguments, $token->getLine(), $tag); 461 462 if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) { 463 break; 464 } 465 466 $this->parser->getStream()->next(); 467 } 468 469 return $node; 470 } 471 472 /** 473 * Parses arguments. 474 * 475 * @param bool $namedArguments Whether to allow named arguments or not 476 * @param bool $definition Whether we are parsing arguments for a function definition 477 * 478 * @return Twig_Node 479 * 480 * @throws Twig_Error_Syntax 481 */ 482 public function parseArguments($namedArguments = false, $definition = false) 483 { 484 $args = array(); 485 $stream = $this->parser->getStream(); 486 487 $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); 488 while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) { 489 if (!empty($args)) { 490 $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); 491 } 492 493 if ($definition) { 494 $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name'); 495 $value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine()); 496 } else { 497 $value = $this->parseExpression(); 498 } 499 500 $name = null; 501 if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) { 502 if (!$value instanceof Twig_Node_Expression_Name) { 503 throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given.', get_class($value)), $token->getLine(), $this->parser->getFilename()); 504 } 505 $name = $value->getAttribute('name'); 506 507 if ($definition) { 508 $value = $this->parsePrimaryExpression(); 509 510 if (!$this->checkConstantExpression($value)) { 511 throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $this->parser->getFilename()); 512 } 513 } else { 514 $value = $this->parseExpression(); 515 } 516 } 517 518 if ($definition) { 519 if (null === $name) { 520 $name = $value->getAttribute('name'); 521 $value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine()); 522 } 523 $args[$name] = $value; 524 } else { 525 if (null === $name) { 526 $args[] = $value; 527 } else { 528 $args[$name] = $value; 529 } 530 } 531 } 532 $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); 533 534 return new Twig_Node($args); 535 } 536 537 public function parseAssignmentExpression() 538 { 539 $targets = array(); 540 while (true) { 541 $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to'); 542 $value = $token->getValue(); 543 if (in_array(strtolower($value), array('true', 'false', 'none', 'null'))) { 544 throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $value), $token->getLine(), $this->parser->getFilename()); 545 } 546 $targets[] = new Twig_Node_Expression_AssignName($value, $token->getLine()); 547 548 if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { 549 break; 550 } 551 } 552 553 return new Twig_Node($targets); 554 } 555 556 public function parseMultitargetExpression() 557 { 558 $targets = array(); 559 while (true) { 560 $targets[] = $this->parseExpression(); 561 if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { 562 break; 563 } 564 } 565 566 return new Twig_Node($targets); 567 } 568 569 protected function getFunctionNodeClass($name, $line) 570 { 571 $env = $this->parser->getEnvironment(); 572 573 if (false === $function = $env->getFunction($name)) { 574 $e = new Twig_Error_Syntax(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getFilename()); 575 $e->addSuggestions($name, array_keys($env->getFunctions())); 576 577 throw $e; 578 } 579 580 if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) { 581 $message = sprintf('Twig Function "%s" is deprecated', $function->getName()); 582 if (!is_bool($function->getDeprecatedVersion())) { 583 $message .= sprintf(' since version %s', $function->getDeprecatedVersion()); 584 } 585 if ($function->getAlternative()) { 586 $message .= sprintf('. Use "%s" instead', $function->getAlternative()); 587 } 588 $message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line); 589 590 @trigger_error($message, E_USER_DEPRECATED); 591 } 592 593 if ($function instanceof Twig_SimpleFunction) { 594 return $function->getNodeClass(); 595 } 596 597 return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function'; 598 } 599 600 protected function getFilterNodeClass($name, $line) 601 { 602 $env = $this->parser->getEnvironment(); 603 604 if (false === $filter = $env->getFilter($name)) { 605 $e = new Twig_Error_Syntax(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getFilename()); 606 $e->addSuggestions($name, array_keys($env->getFilters())); 607 608 throw $e; 609 } 610 611 if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) { 612 $message = sprintf('Twig Filter "%s" is deprecated', $filter->getName()); 613 if (!is_bool($filter->getDeprecatedVersion())) { 614 $message .= sprintf(' since version %s', $filter->getDeprecatedVersion()); 615 } 616 if ($filter->getAlternative()) { 617 $message .= sprintf('. Use "%s" instead', $filter->getAlternative()); 618 } 619 $message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line); 620 621 @trigger_error($message, E_USER_DEPRECATED); 622 } 623 624 if ($filter instanceof Twig_SimpleFilter) { 625 return $filter->getNodeClass(); 626 } 627 628 return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter'; 629 } 630 631 // checks that the node only contains "constant" elements 632 protected function checkConstantExpression(Twig_NodeInterface $node) 633 { 634 if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array 635 || $node instanceof Twig_Node_Expression_Unary_Neg || $node instanceof Twig_Node_Expression_Unary_Pos 636 )) { 637 return false; 638 } 639 640 foreach ($node as $n) { 641 if (!$this->checkConstantExpression($n)) { 642 return false; 643 } 644 } 645 646 return true; 647 } 648 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Jan 11 00:25:41 2018 | Cross-referenced by PHPXref 0.7.1 |