Commit 9a6d466a authored by Crise's avatar Crise

Twig 2.0.0 major version upgrade

parent 2aaa191c
......@@ -57,7 +57,7 @@ class TwigResponse extends WebResponse
'debug' => Util::isDebug(),
'auto_reload' => true,
'cache' => DCBASE_CACHE_PATH . 'templates/',
'autoescape' => true
'autoescape' => 'html'
));
// add namespaces, dcbase_root is potentially dangerous
......@@ -208,7 +208,7 @@ class TwigResponse extends WebResponse
$json_data = null;
try
{
$json_data = $this->twig->getLoader()->getSource($file);
$json_data = $this->twig->getLoader()->getSourceContext($file)->getCode();;
}
catch (Twig_Error_Loader $e) { /* ... */ }
......
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
@trigger_error('The Twig_Autoloader class is deprecated since version 1.21 and will be removed in 2.0. Use Composer instead.', E_USER_DEPRECATED);
/**
* Autoloads Twig classes.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since 1.21 and will be removed in 2.0. Use Composer instead. 2.0.
*/
class Twig_Autoloader
{
/**
* Registers Twig_Autoloader as an SPL autoloader.
*
* @param bool $prepend whether to prepend the autoloader or not
*/
public static function register($prepend = false)
{
@trigger_error('Using Twig_Autoloader is deprecated since version 1.21. Use Composer instead.', E_USER_DEPRECATED);
if (PHP_VERSION_ID < 50300) {
spl_autoload_register(array(__CLASS__, 'autoload'));
} else {
spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
}
}
/**
* Handles autoloading of classes.
*
* @param string $class a class name
*/
public static function autoload($class)
{
if (0 !== strpos($class, 'Twig')) {
return;
}
if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
require $file;
}
}
}
......@@ -16,21 +16,13 @@
*/
abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface
{
final public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
final public function enterNode(Twig_Node $node, Twig_Environment $env)
{
if (!$node instanceof Twig_Node) {
throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.');
}
return $this->doEnterNode($node, $env);
}
final public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
final public function leaveNode(Twig_Node $node, Twig_Environment $env)
{
if (!$node instanceof Twig_Node) {
throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.');
}
return $this->doLeaveNode($node, $env);
}
......
* 2.0.0 (2017-12-05)
* removed the C extension
* moved Twig_Environment::getAttribute() to twig_get_attribute()
* removed Twig_Environment::getLexer(), Twig_Environment::getParser(), Twig_Environment::getCompiler()
* removed Twig_Compiler::getFilename()
* added hasser support in Twig_Template::getAttribute()
* sped up the json_encode filter
* removed reserved macro names; all names can be used as macro
* removed Twig_Template::getEnvironment()
* changed _self variable to return the current template name
* made the loader a required argument of Twig_Environment constructor
* removed Twig_Environment::clearTemplateCache()
* removed Twig_Autoloader (use Composer instead)
* removed `true` as an equivalent to `html` for the auto-escaping strategy
* removed pre-1.8 autoescape tag syntax
* dropped support for PHP 5.x
* removed the ability to register a global variable after the runtime or the extensions have been initialized
* improved the performance of the filesystem loader
* removed features that were deprecated in 1.x
* 1.30.1 (2017-XX-XX)
* n/a
* 1.30.0 (2016-12-23)
* added Twig_FactoryRuntimeLoader
......@@ -168,7 +193,7 @@
* fixed limited RCEs when in sandbox mode
* deprecated Twig_Template::getEnvironment()
* deprecated the _self variable for usage outside of the from and import tags
* added Twig_BaseNodeVisitor to ease the compatibility of node visitors
* added Twig_BaseNodeVisitor to ease the compatibility of node visitors
between 1.x and 2.x
* 1.19.0 (2015-07-31)
......
......@@ -12,11 +12,9 @@
/**
* Implements a no-cache strategy.
*
* @final
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Cache_Null implements Twig_CacheInterface
final class Twig_Cache_Null implements Twig_CacheInterface
{
public function generateKey($name, $className)
{
......
......@@ -15,32 +15,21 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Compiler implements Twig_CompilerInterface
class Twig_Compiler
{
protected $lastLine;
protected $source;
protected $indentation;
protected $env;
protected $debugInfo = array();
protected $sourceOffset;
protected $sourceLine;
protected $filename;
private $lastLine;
private $source;
private $indentation;
private $env;
private $debugInfo = array();
private $sourceOffset;
private $sourceLine;
public function __construct(Twig_Environment $env)
{
$this->env = $env;
}
/**
* @deprecated since 1.25 (to be removed in 2.0)
*/
public function getFilename()
{
@trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
return $this->filename;
}
/**
* Returns the environment instance related to this compiler.
*
......@@ -64,12 +53,12 @@ class Twig_Compiler implements Twig_CompilerInterface
/**
* Compiles a node.
*
* @param Twig_NodeInterface $node The node to compile
* @param int $indentation The current indentation
* @param Twig_Node $node The node to compile
* @param int $indentation The current indentation
*
* @return $this
*/
public function compile(Twig_NodeInterface $node, $indentation = 0)
public function compile(Twig_Node $node, $indentation = 0)
{
$this->lastLine = null;
$this->source = '';
......@@ -79,17 +68,12 @@ class Twig_Compiler implements Twig_CompilerInterface
$this->sourceLine = 1;
$this->indentation = $indentation;
if ($node instanceof Twig_Node_Module) {
// to be removed in 2.0
$this->filename = $node->getTemplateName();
}
$node->compile($this);
return $this;
}
public function subcompile(Twig_NodeInterface $node, $raw = true)
public function subcompile(Twig_Node $node, $raw = true)
{
if (false === $raw) {
$this->source .= str_repeat(' ', $this->indentation * 4);
......@@ -119,9 +103,8 @@ class Twig_Compiler implements Twig_CompilerInterface
*
* @return $this
*/
public function write()
public function write(...$strings)
{
$strings = func_get_args();
foreach ($strings as $string) {
$this->source .= str_repeat(' ', $this->indentation * 4).$string;
}
......@@ -129,22 +112,6 @@ class Twig_Compiler implements Twig_CompilerInterface
return $this;
}
/**
* Appends an indentation to the current PHP code after compilation.
*
* @return $this
*
* @deprecated since 1.27 (to be removed in 2.0).
*/
public function addIndentation()
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use write(\'\') instead.', E_USER_DEPRECATED);
$this->source .= str_repeat(' ', $this->indentation * 4);
return $this;
}
/**
* Adds a quoted string to the compiled code.
*
......@@ -207,22 +174,12 @@ class Twig_Compiler implements Twig_CompilerInterface
*
* @return $this
*/
public function addDebugInfo(Twig_NodeInterface $node)
public function addDebugInfo(Twig_Node $node)
{
if ($node->getTemplateLine() != $this->lastLine) {
$this->write(sprintf("// line %d\n", $node->getTemplateLine()));
// when mbstring.func_overload is set to 2
// mb_substr_count() replaces substr_count()
// but they have different signatures!
if (((int) ini_get('mbstring.func_overload')) & 2) {
@trigger_error('Support for having "mbstring.func_overload" different from 0 is deprecated version 1.29 and will be removed in 2.0.', E_USER_DEPRECATED);
// this is much slower than the "right" version
$this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n");
} else {
$this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
}
$this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
$this->sourceOffset = strlen($this->source);
$this->debugInfo[$this->sourceLine] = $node->getTemplateLine();
......
<?php
/*
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Interface implemented by compiler classes.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since 1.12 (to be removed in 3.0)
*/
interface Twig_CompilerInterface
{
/**
* Compiles a node.
*
* @return $this
*/
public function compile(Twig_NodeInterface $node);
/**
* Gets the current PHP code after compilation.
*
* @return string The PHP code
*/
public function getSource();
}
This diff is collapsed.
......@@ -33,12 +33,9 @@
*/
class Twig_Error extends Exception
{
protected $lineno;
// to be renamed to name in 2.0
protected $filename;
protected $rawMessage;
protected $previous;
private $lineno;
private $name;
private $rawMessage;
private $sourcePath;
private $sourceCode;
......@@ -61,6 +58,8 @@ class Twig_Error extends Exception
*/
public function __construct($message, $lineno = -1, $source = null, Exception $previous = null)
{
parent::__construct('', 0, $previous);
if (null === $source) {
$name = null;
} elseif (!$source instanceof Twig_Source) {
......@@ -71,15 +70,9 @@ class Twig_Error extends Exception
$this->sourceCode = $source->getCode();
$this->sourcePath = $source->getPath();
}
if (PHP_VERSION_ID < 50300) {
$this->previous = $previous;
parent::__construct('');
} else {
parent::__construct('', 0, $previous);
}
$this->lineno = $lineno;
$this->filename = $name;
$this->name = $name;
if (-1 === $lineno || null === $name || null === $this->sourcePath) {
$this->guessTemplateInfo();
......@@ -100,67 +93,6 @@ class Twig_Error extends Exception
return $this->rawMessage;
}
/**
* Gets the logical name where the error occurred.
*
* @return string The name
*
* @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead.
*/
public function getTemplateFile()
{
@trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
return $this->filename;
}
/**
* Sets the logical name where the error occurred.
*
* @param string $name The name
*
* @deprecated since 1.27 (to be removed in 2.0). Use setSourceContext() instead.
*/
public function setTemplateFile($name)
{
@trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
$this->filename = $name;
$this->updateRepr();
}
/**
* Gets the logical name where the error occurred.
*
* @return string The name
*
* @deprecated since 1.29 (to be removed in 2.0). Use getSourceContext() instead.
*/
public function getTemplateName()
{
@trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
return $this->filename;
}
/**
* Sets the logical name where the error occurred.
*
* @param string $name The name
*
* @deprecated since 1.29 (to be removed in 2.0). Use setSourceContext() instead.
*/
public function setTemplateName($name)
{
@trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
$this->filename = $name;
$this->sourceCode = $this->sourcePath = null;
$this->updateRepr();
}
/**
* Gets the template line where the error occurred.
*
......@@ -190,7 +122,7 @@ class Twig_Error extends Exception
*/
public function getSourceContext()
{
return $this->filename ? new Twig_Source($this->sourceCode, $this->filename, $this->sourcePath) : null;
return $this->name ? new Twig_Source($this->sourceCode, $this->name, $this->sourcePath) : null;
}
/**
......@@ -199,10 +131,10 @@ class Twig_Error extends Exception
public function setSourceContext(Twig_Source $source = null)
{
if (null === $source) {
$this->sourceCode = $this->filename = $this->sourcePath = null;
$this->sourceCode = $this->name = $this->sourcePath = null;
} else {
$this->sourceCode = $source->getCode();
$this->filename = $source->getName();
$this->name = $source->getName();
$this->sourcePath = $source->getPath();
}
......@@ -215,35 +147,13 @@ class Twig_Error extends Exception
$this->updateRepr();
}
/**
* For PHP < 5.3.0, provides access to the getPrevious() method.
*
* @param string $method The method name
* @param array $arguments The parameters to be passed to the method
*
* @return Exception The previous exception or null
*
* @throws BadMethodCallException
*/
public function __call($method, $arguments)
{
if ('getprevious' == strtolower($method)) {
return $this->previous;
}
throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method));
}
public function appendMessage($rawMessage)
{
$this->rawMessage .= $rawMessage;
$this->updateRepr();
}
/**
* @internal
*/
protected function updateRepr()
private function updateRepr()
{
$this->message = $this->rawMessage;
......@@ -266,11 +176,11 @@ class Twig_Error extends Exception
$questionMark = true;
}
if ($this->filename) {
if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
$name = sprintf('"%s"', $this->filename);
if ($this->name) {
if (is_string($this->name) || (is_object($this->name) && method_exists($this->name, '__toString'))) {
$name = sprintf('"%s"', $this->name);
} else {
$name = json_encode($this->filename);
$name = json_encode($this->name);
}
$this->message .= sprintf(' in %s', $name);
}
......@@ -288,25 +198,17 @@ class Twig_Error extends Exception
}
}
/**
* @internal
*/
protected function guessTemplateInfo()
private function guessTemplateInfo()
{
$template = null;
$templateClass = null;
if (PHP_VERSION_ID >= 50306) {
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
} else {
$backtrace = debug_backtrace();
}
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
foreach ($backtrace as $trace) {
if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
$currentClass = get_class($trace['object']);
$isEmbedContainer = 0 === strpos($templateClass, $currentClass);
if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) {
if (null === $this->name || ($this->name == $trace['object']->getTemplateName() && !$isEmbedContainer)) {
$template = $trace['object'];
$templateClass = get_class($trace['object']);
}
......@@ -314,8 +216,8 @@ class Twig_Error extends Exception
}
// update template name
if (null !== $template && null === $this->filename) {
$this->filename = $template->getTemplateName();
if (null !== $template && null === $this->name) {
$this->name = $template->getTemplateName();
}
// update template path if any
......@@ -338,7 +240,7 @@ class Twig_Error extends Exception
}
$exceptions = array($e = $this);
while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) {
while ($e = $e->getPrevious()) {
$exceptions[] = $e;
}
......
......@@ -24,20 +24,6 @@ class Twig_Error_Syntax extends Twig_Error
* @param array $items An array of possible items
*/
public function addSuggestions($name, array $items)
{
if (!$alternatives = self::computeAlternatives($name, $items)) {
return;
}
$this->appendMessage(sprintf(' Did you mean "%s"?', implode('", "', $alternatives)));
}
/**
* @internal
*
* To be merged with the addSuggestions() method in 2.0.
*/
public static function computeAlternatives($name, $items)
{
$alternatives = array();
foreach ($items as $item) {
......@@ -46,8 +32,13 @@ class Twig_Error_Syntax extends Twig_Error
$alternatives[$item] = $lev;
}
}
if (!$alternatives) {
return;
}
asort($alternatives);
return array_keys($alternatives);
$this->appendMessage(sprintf(' Did you mean "%s"?', implode('", "', array_keys($alternatives))));
}
}
......@@ -10,20 +10,8 @@
*/
/**
* Adds an exists() method for loaders.
*
* @author Florin Patan <florinpatan@gmail.com>
*
* @deprecated since 1.12 (to be removed in 3.0)
* Empty interface for Twig 1.x compatibility.
*/
interface Twig_ExistsLoaderInterface
interface Twig_ExistsLoaderInterface extends Twig_LoaderInterface
{
/**
* Check if we have the source code of a template, given its name.
*
* @param string $name The name of the template to check if we can load
*
* @return bool If the template source code is handled by this loader or not
*/
public function exists($name);
}
......@@ -27,27 +27,17 @@ class Twig_ExpressionParser
const OPERATOR_LEFT = 1;
const OPERATOR_RIGHT = 2;
protected $parser;
protected $unaryOperators;
protected $binaryOperators;
private $parser;
private $env;
private $unaryOperators;
private $binaryOperators;
public function __construct(Twig_Parser $parser, $env = null)
public function __construct(Twig_Parser $parser, Twig_Environment $env)
{
$this->parser = $parser;
if ($env instanceof Twig_Environment) {
$this->env = $env;
$this->unaryOperators = $env->getUnaryOperators();
$this->binaryOperators = $env->getBinaryOperators();
} else {
@trigger_error('Passing the operators as constructor arguments to '.__METHOD__.' is deprecated since version 1.27. Pass the environment instead.', E_USER_DEPRECATED);
$this->env = $parser->getEnvironment();
$this->unaryOperators = func_get_arg(1);
$this->binaryOperators = func_get_arg(2);
}
$this->env = $env;
$this->unaryOperators = $env->getUnaryOperators();
$this->binaryOperators = $env->getBinaryOperators();
}
public function parseExpression($precedence = 0)
......@@ -63,7 +53,7 @@ class Twig_ExpressionParser
} elseif ('is' === $token->getValue()) {
$expr = $this->parseTestExpression($expr);
} elseif (isset($op['callable'])) {
$expr = call_user_func($op['callable'], $this->parser, $expr);
$expr = $op['callable']($this->parser, $expr);
} else {
$expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
$class = $op['class'];
......@@ -80,7 +70,7 @@ class Twig_ExpressionParser
return $expr;
}
protected function getPrimary()
private function getPrimary()
{
$token = $this->parser->getCurrentToken();
......@@ -102,7 +92,7 @@ class Twig_ExpressionParser
return $this->parsePrimaryExpression();
}
protected function parseConditionalExpression($expr)
private function parseConditionalExpression($expr)
{
while ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, '?')) {
if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
......@@ -123,12 +113,12 @@ class Twig_ExpressionParser
return $expr;
}
protected function isUnary(Twig_Token $token)
private function isUnary(Twig_Token $token)
{
return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]);
}
protected function isBinary(Twig_Token $token)
private function isBinary(Twig_Token $token)
{
return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]);