From b98f431828d1e30fe9a3634fdbd4a818930772e5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 15 Oct 2016 11:18:26 -0700 Subject: [PATCH 1/2] fixed typo --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 90be316d3..0ac2add98 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,6 @@ * 1.26.2 (2016-XX-XX) - * Fixed template paths when a template name contains a protocol like vfs:// + * fixed template paths when a template name contains a protocol like vfs:// * improved debugging with Twig_Sandbox_SecurityError exceptions for disallowed methods and properties * 1.26.1 (2016-10-05) From d77f3dd34b92a9632a3ac676aa3478d1fe09d4ea Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Oct 2016 11:22:54 -0700 Subject: [PATCH 2/2] deprecated Parser::getFilename() --- CHANGELOG | 3 ++- composer.json | 2 +- doc/deprecated.rst | 3 +++ ext/twig/php_twig.h | 2 +- lib/Twig/Environment.php | 2 +- lib/Twig/ExpressionParser.php | 37 ++++++++++++++++---------------- lib/Twig/Extension/Core.php | 2 +- lib/Twig/Parser.php | 23 ++++++++++++-------- lib/Twig/TokenParser/Extends.php | 8 ++++--- lib/Twig/TokenParser/Sandbox.php | 7 +++--- 10 files changed, 51 insertions(+), 38 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0ac2add98..2dcd446da 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ -* 1.26.2 (2016-XX-XX) +* 1.27.0 (2016-XX-XX) + * deprecated Parser::getFilename() * fixed template paths when a template name contains a protocol like vfs:// * improved debugging with Twig_Sandbox_SecurityError exceptions for disallowed methods and properties diff --git a/composer.json b/composer.json index 350381cdc..afe30b00a 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.26-dev" + "dev-master": "1.27-dev" } } } diff --git a/doc/deprecated.rst b/doc/deprecated.rst index 801228da7..61eb4ce52 100644 --- a/doc/deprecated.rst +++ b/doc/deprecated.rst @@ -20,6 +20,9 @@ Token Parsers * ``Twig_TokenParserBrokerInterface`` * ``Twig_TokenParserBroker`` +* As of Twig 1.27, ``Twig_Parser::getFilename()`` is deprecated. From a token + parser, use ``$this->parser->getStream()->getFilename()`` instead. + Extensions ---------- diff --git a/ext/twig/php_twig.h b/ext/twig/php_twig.h index c09867ff1..f1be50962 100644 --- a/ext/twig/php_twig.h +++ b/ext/twig/php_twig.h @@ -15,7 +15,7 @@ #ifndef PHP_TWIG_H #define PHP_TWIG_H -#define PHP_TWIG_VERSION "1.26.2-DEV" +#define PHP_TWIG_VERSION "1.27.0-DEV" #include "php.h" diff --git a/lib/Twig/Environment.php b/lib/Twig/Environment.php index bdf531f8f..2b8d0e914 100644 --- a/lib/Twig/Environment.php +++ b/lib/Twig/Environment.php @@ -16,7 +16,7 @@ */ class Twig_Environment { - const VERSION = '1.26.2-DEV'; + const VERSION = '1.27.0-DEV'; protected $charset; protected $loader; diff --git a/lib/Twig/ExpressionParser.php b/lib/Twig/ExpressionParser.php index d128e7241..c43ed341c 100644 --- a/lib/Twig/ExpressionParser.php +++ b/lib/Twig/ExpressionParser.php @@ -171,7 +171,7 @@ class Twig_ExpressionParser $negClass = 'Twig_Node_Expression_Unary_Neg'; $posClass = 'Twig_Node_Expression_Unary_Pos'; if (!(in_array($ref->getName(), array($negClass, $posClass)) || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass))) { - throw new Twig_Error_Syntax(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getFilename()); + throw new Twig_Error_Syntax(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getFilename()); } $this->parser->getStream()->next(); @@ -187,7 +187,7 @@ class Twig_ExpressionParser } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) { $node = $this->parseHashExpression(); } else { - throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getFilename()); + throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getFilename()); } } @@ -278,7 +278,7 @@ class Twig_ExpressionParser } else { $current = $stream->getCurrent(); - 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()); + 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(), $stream->getFilename()); } $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); @@ -317,11 +317,11 @@ class Twig_ExpressionParser case 'parent': $this->parseArguments(); if (!count($this->parser->getBlockStack())) { - throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden.', $line, $this->parser->getFilename()); + throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getFilename()); } 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, $this->parser->getFilename()); + throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getFilename()); } return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line); @@ -330,7 +330,7 @@ class Twig_ExpressionParser case 'attribute': $args = $this->parseArguments(); if (count($args) < 2) { - throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getFilename()); + throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getFilename()); } return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line); @@ -379,18 +379,18 @@ class Twig_ExpressionParser } } } else { - throw new Twig_Error_Syntax('Expected name or number.', $lineno, $this->parser->getFilename()); + throw new Twig_Error_Syntax('Expected name or number.', $lineno, $stream->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()); + throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getFilename()); } $name = $arg->getAttribute('value'); if ($this->parser->isReservedMacroName($name)) { - throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $this->parser->getFilename()); + throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getFilename()); } $node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno); @@ -500,7 +500,7 @@ class Twig_ExpressionParser $name = null; if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) { if (!$value instanceof Twig_Node_Expression_Name) { - throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given.', get_class($value)), $token->getLine(), $this->parser->getFilename()); + throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given.', get_class($value)), $token->getLine(), $stream->getFilename()); } $name = $value->getAttribute('name'); @@ -508,7 +508,7 @@ class Twig_ExpressionParser $value = $this->parsePrimaryExpression(); if (!$this->checkConstantExpression($value)) { - 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()); + 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(), $stream->getFilename()); } } else { $value = $this->parseExpression(); @@ -536,16 +536,17 @@ class Twig_ExpressionParser public function parseAssignmentExpression() { + $stream = $this->parser->getStream(); $targets = array(); while (true) { - $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to'); + $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to'); $value = $token->getValue(); if (in_array(strtolower($value), array('true', 'false', 'none', 'null'))) { - throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $this->parser->getFilename()); + throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getFilename()); } $targets[] = new Twig_Node_Expression_AssignName($value, $token->getLine()); - if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { + if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { break; } } @@ -571,7 +572,7 @@ class Twig_ExpressionParser $env = $this->parser->getEnvironment(); if (false === $function = $env->getFunction($name)) { - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getFilename()); + $e = new Twig_Error_Syntax(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getFilename()); $e->addSuggestions($name, array_keys($env->getFunctions())); throw $e; @@ -585,7 +586,7 @@ class Twig_ExpressionParser if ($function->getAlternative()) { $message .= sprintf('. Use "%s" instead', $function->getAlternative()); } - $message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line); + $message .= sprintf(' in %s at line %d.', $this->parser->getStream()->getFilename(), $line); @trigger_error($message, E_USER_DEPRECATED); } @@ -602,7 +603,7 @@ class Twig_ExpressionParser $env = $this->parser->getEnvironment(); if (false === $filter = $env->getFilter($name)) { - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getFilename()); + $e = new Twig_Error_Syntax(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getFilename()); $e->addSuggestions($name, array_keys($env->getFilters())); throw $e; @@ -616,7 +617,7 @@ class Twig_ExpressionParser if ($filter->getAlternative()) { $message .= sprintf('. Use "%s" instead', $filter->getAlternative()); } - $message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line); + $message .= sprintf(' in %s at line %d.', $this->parser->getStream()->getFilename(), $line); @trigger_error($message, E_USER_DEPRECATED); } diff --git a/lib/Twig/Extension/Core.php b/lib/Twig/Extension/Core.php index ffa8968fd..e6c85215f 100644 --- a/lib/Twig/Extension/Core.php +++ b/lib/Twig/Extension/Core.php @@ -319,7 +319,7 @@ class Twig_Extension_Core extends Twig_Extension } } - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" test.', $name), $line, $parser->getFilename()); + $e = new Twig_Error_Syntax(sprintf('Unknown "%s" test.', $name), $line, $stream->getFilename()); $e->addSuggestions($name, array_keys($env->getTests())); throw $e; diff --git a/lib/Twig/Parser.php b/lib/Twig/Parser.php index 1f66cfa41..c52b04ece 100644 --- a/lib/Twig/Parser.php +++ b/lib/Twig/Parser.php @@ -52,8 +52,13 @@ class Twig_Parser implements Twig_ParserInterface return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); } + /** + * @deprecated since 1.20 (to be removed in 2.0). Use $parser->getStream()->getFilename() instead. + */ public function getFilename() { + @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use $parser->getStream()->getFilename() instead.', __METHOD__), E_USER_DEPRECATED); + return $this->stream->getFilename(); } @@ -104,7 +109,7 @@ class Twig_Parser implements Twig_ParserInterface } } catch (Twig_Error_Syntax $e) { if (!$e->getTemplateFile()) { - $e->setTemplateFile($this->getFilename()); + $e->setTemplateFile($this->stream->getFilename()); } if (!$e->getTemplateLine()) { @@ -114,7 +119,7 @@ class Twig_Parser implements Twig_ParserInterface throw $e; } - $node = new Twig_Node_Module(new Twig_Node_Body(array($body)), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->embeddedTemplates, $this->getFilename(), $stream->getSource()); + $node = new Twig_Node_Module(new Twig_Node_Body(array($body)), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->embeddedTemplates, $this->stream->getFilename(), $stream->getSource()); $traverser = new Twig_NodeTraverser($this->env, $this->visitors); @@ -151,7 +156,7 @@ class Twig_Parser implements Twig_ParserInterface $token = $this->getCurrentToken(); if ($token->getType() !== Twig_Token::NAME_TYPE) { - throw new Twig_Error_Syntax('A block must start with a tag name.', $token->getLine(), $this->getFilename()); + throw new Twig_Error_Syntax('A block must start with a tag name.', $token->getLine(), $this->stream->getFilename()); } if (null !== $test && call_user_func($test, $token)) { @@ -169,13 +174,13 @@ class Twig_Parser implements Twig_ParserInterface $subparser = $this->handlers->getTokenParser($token->getValue()); if (null === $subparser) { if (null !== $test) { - $e = new Twig_Error_Syntax(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->getFilename()); + $e = new Twig_Error_Syntax(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getFilename()); if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) { $e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno)); } } else { - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->getFilename()); + $e = new Twig_Error_Syntax(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getFilename()); $e->addSuggestions($token->getValue(), array_keys($this->env->getTags())); } @@ -191,7 +196,7 @@ class Twig_Parser implements Twig_ParserInterface break; default: - throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', 0, $this->getFilename()); + throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', 0, $this->stream->getFilename()); } } @@ -255,7 +260,7 @@ class Twig_Parser implements Twig_ParserInterface public function setMacro($name, Twig_Node_Macro $node) { if ($this->isReservedMacroName($name)) { - throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->getLine(), $this->getFilename()); + throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->getLine(), $this->stream->getFilename()); } $this->macros[$name] = $node; @@ -373,10 +378,10 @@ class Twig_Parser implements Twig_ParserInterface (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface) ) { if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) { - throw new Twig_Error_Syntax('A template that extends another one cannot start with a byte order mark (BOM); it must be removed.', $node->getLine(), $this->getFilename()); + throw new Twig_Error_Syntax('A template that extends another one cannot start with a byte order mark (BOM); it must be removed.', $node->getLine(), $this->stream->getFilename()); } - throw new Twig_Error_Syntax('A template that extends another one cannot include contents outside Twig blocks. Did you forget to put the contents inside a {% block %} tag?', $node->getLine(), $this->getFilename()); + throw new Twig_Error_Syntax('A template that extends another one cannot include contents outside Twig blocks. Did you forget to put the contents inside a {% block %} tag?', $node->getLine(), $this->stream->getFilename()); } // bypass "set" nodes as they "capture" the output diff --git a/lib/Twig/TokenParser/Extends.php b/lib/Twig/TokenParser/Extends.php index 510417ad1..0b7829995 100644 --- a/lib/Twig/TokenParser/Extends.php +++ b/lib/Twig/TokenParser/Extends.php @@ -21,16 +21,18 @@ class Twig_TokenParser_Extends extends Twig_TokenParser { public function parse(Twig_Token $token) { + $stream = $this->parser->getStream(); + if (!$this->parser->isMainScope()) { - throw new Twig_Error_Syntax('Cannot extend from a block.', $token->getLine(), $this->parser->getFilename()); + throw new Twig_Error_Syntax('Cannot extend from a block.', $token->getLine(), $stream->getFilename()); } if (null !== $this->parser->getParent()) { - throw new Twig_Error_Syntax('Multiple extends tags are forbidden.', $token->getLine(), $this->parser->getFilename()); + throw new Twig_Error_Syntax('Multiple extends tags are forbidden.', $token->getLine(), $stream->getFilename()); } $this->parser->setParent($this->parser->getExpressionParser()->parseExpression()); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(Twig_Token::BLOCK_END_TYPE); } public function getTag() diff --git a/lib/Twig/TokenParser/Sandbox.php b/lib/Twig/TokenParser/Sandbox.php index 1feadd084..43de36d8e 100644 --- a/lib/Twig/TokenParser/Sandbox.php +++ b/lib/Twig/TokenParser/Sandbox.php @@ -24,9 +24,10 @@ class Twig_TokenParser_Sandbox extends Twig_TokenParser { public function parse(Twig_Token $token) { - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $stream = $this->parser->getStream(); + $stream->expect(Twig_Token::BLOCK_END_TYPE); $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(Twig_Token::BLOCK_END_TYPE); // in a sandbox tag, only include tags are allowed if (!$body instanceof Twig_Node_Include) { @@ -36,7 +37,7 @@ class Twig_TokenParser_Sandbox extends Twig_TokenParser } if (!$node instanceof Twig_Node_Include) { - throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section.', $node->getLine(), $this->parser->getFilename()); + throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section.', $node->getLine(), $stream->getFilename()); } } }