Updating Twig to version v1.16.0 moving to vendor folder see #7320
parent
ed2d3f0f7d
commit
b1d261db6f
@ -1,176 +0,0 @@ |
||||
<?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. |
||||
*/ |
||||
|
||||
/** |
||||
* Twig base exception. |
||||
* |
||||
* @package twig |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
class Twig_Error extends Exception |
||||
{ |
||||
protected $lineno; |
||||
protected $filename; |
||||
protected $rawMessage; |
||||
protected $previous; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param string $message The error message |
||||
* @param integer $lineno The template line where the error occurred |
||||
* @param string $filename The template file name where the error occurred |
||||
* @param Exception $previous The previous exception |
||||
*/ |
||||
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null) |
||||
{ |
||||
if (-1 === $lineno || null === $filename) { |
||||
if ($trace = $this->getTemplateTrace()) { |
||||
if (-1 === $lineno) { |
||||
$lineno = $this->guessTemplateLine($trace); |
||||
} |
||||
|
||||
if (null === $filename) { |
||||
$filename = $trace['object']->getTemplateName(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
$this->lineno = $lineno; |
||||
$this->filename = $filename; |
||||
$this->rawMessage = $message; |
||||
|
||||
$this->updateRepr(); |
||||
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) { |
||||
$this->previous = $previous; |
||||
parent::__construct($this->message); |
||||
} else { |
||||
parent::__construct($this->message, 0, $previous); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Gets the raw message. |
||||
* |
||||
* @return string The raw message |
||||
*/ |
||||
public function getRawMessage() |
||||
{ |
||||
return $this->rawMessage; |
||||
} |
||||
|
||||
/** |
||||
* Gets the filename where the error occurred. |
||||
* |
||||
* @return string The filename |
||||
*/ |
||||
public function getTemplateFile() |
||||
{ |
||||
return $this->filename; |
||||
} |
||||
|
||||
/** |
||||
* Sets the filename where the error occurred. |
||||
* |
||||
* @param string $filename The filename |
||||
*/ |
||||
public function setTemplateFile($filename) |
||||
{ |
||||
$this->filename = $filename; |
||||
|
||||
$this->updateRepr(); |
||||
} |
||||
|
||||
/** |
||||
* Gets the template line where the error occurred. |
||||
* |
||||
* @return integer The template line |
||||
*/ |
||||
public function getTemplateLine() |
||||
{ |
||||
return $this->lineno; |
||||
} |
||||
|
||||
/** |
||||
* Sets the template line where the error occurred. |
||||
* |
||||
* @param integer $lineno The template line |
||||
*/ |
||||
public function setTemplateLine($lineno) |
||||
{ |
||||
$this->lineno = $lineno; |
||||
|
||||
$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 |
||||
*/ |
||||
public function __call($method, $arguments) |
||||
{ |
||||
if ('getprevious' == strtolower($method)) { |
||||
return $this->previous; |
||||
} |
||||
|
||||
throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method)); |
||||
} |
||||
|
||||
protected function updateRepr() |
||||
{ |
||||
$this->message = $this->rawMessage; |
||||
|
||||
$dot = false; |
||||
if ('.' === substr($this->message, -1)) { |
||||
$this->message = substr($this->message, 0, -1); |
||||
$dot = true; |
||||
} |
||||
|
||||
if (null !== $this->filename) { |
||||
$this->message .= sprintf(' in %s', is_string($this->filename) ? '"'.$this->filename.'"' : json_encode($this->filename)); |
||||
} |
||||
|
||||
if ($this->lineno >= 0) { |
||||
$this->message .= sprintf(' at line %d', $this->lineno); |
||||
} |
||||
|
||||
if ($dot) { |
||||
$this->message .= '.'; |
||||
} |
||||
} |
||||
|
||||
protected function getTemplateTrace() |
||||
{ |
||||
foreach (debug_backtrace() as $trace) { |
||||
if (isset($trace['object']) && $trace['object'] instanceof Twig_Template) { |
||||
return $trace; |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected function guessTemplateLine($trace) |
||||
{ |
||||
if (isset($trace['line'])) { |
||||
foreach ($trace['object']->getDebugInfo() as $codeLine => $templateLine) { |
||||
if ($codeLine <= $trace['line']) { |
||||
return $templateLine; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return -1; |
||||
} |
||||
} |
||||
@ -1,20 +0,0 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2010 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Exception thrown when an error occurs during template loading. |
||||
* |
||||
* @package twig |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
class Twig_Error_Loader extends Twig_Error |
||||
{ |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -1,77 +0,0 @@ |
||||
<?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. |
||||
*/ |
||||
class Twig_Extension_Escaper extends Twig_Extension |
||||
{ |
||||
protected $autoescape; |
||||
|
||||
public function __construct($autoescape = true) |
||||
{ |
||||
$this->autoescape = $autoescape; |
||||
} |
||||
|
||||
/** |
||||
* Returns the token parser instances to add to the existing list. |
||||
* |
||||
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances |
||||
*/ |
||||
public function getTokenParsers() |
||||
{ |
||||
return array(new Twig_TokenParser_AutoEscape()); |
||||
} |
||||
|
||||
/** |
||||
* Returns the node visitor instances to add to the existing list. |
||||
* |
||||
* @return array An array of Twig_NodeVisitorInterface instances |
||||
*/ |
||||
public function getNodeVisitors() |
||||
{ |
||||
return array(new Twig_NodeVisitor_Escaper()); |
||||
} |
||||
|
||||
/** |
||||
* Returns a list of filters to add to the existing list. |
||||
* |
||||
* @return array An array of filters |
||||
*/ |
||||
public function getFilters() |
||||
{ |
||||
return array( |
||||
'raw' => new Twig_Filter_Function('twig_raw_filter', array('is_safe' => array('all'))), |
||||
); |
||||
} |
||||
|
||||
public function isGlobal() |
||||
{ |
||||
return $this->autoescape; |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of the extension. |
||||
* |
||||
* @return string The extension name |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'escaper'; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Marks a variable as being safe. |
||||
* |
||||
* @param string $string A PHP variable |
||||
*/ |
||||
function twig_raw_filter($string) |
||||
{ |
||||
return $string; |
||||
} |
||||
|
||||
@ -1,38 +0,0 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2010 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Represents a template filter. |
||||
* |
||||
* @package twig |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
interface Twig_FilterInterface |
||||
{ |
||||
/** |
||||
* Compiles a filter. |
||||
* |
||||
* @return string The PHP code for the filter |
||||
*/ |
||||
function compile(); |
||||
|
||||
function needsEnvironment(); |
||||
|
||||
function needsContext(); |
||||
|
||||
function getSafe(Twig_Node $filterArgs); |
||||
|
||||
function getPreEscape(); |
||||
|
||||
function setArguments($arguments); |
||||
|
||||
function getArguments(); |
||||
} |
||||
@ -1,100 +0,0 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2011 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Loads templates from other loaders. |
||||
* |
||||
* @package twig |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
class Twig_Loader_Chain implements Twig_LoaderInterface |
||||
{ |
||||
protected $loaders; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param Twig_LoaderInterface[] $loaders An array of loader instances |
||||
*/ |
||||
public function __construct(array $loaders = array()) |
||||
{ |
||||
$this->loaders = array(); |
||||
foreach ($loaders as $loader) { |
||||
$this->addLoader($loader); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Adds a loader instance. |
||||
* |
||||
* @param Twig_LoaderInterface $loader A Loader instance |
||||
*/ |
||||
public function addLoader(Twig_LoaderInterface $loader) |
||||
{ |
||||
$this->loaders[] = $loader; |
||||
} |
||||
|
||||
/** |
||||
* Gets the source code of a template, given its name. |
||||
* |
||||
* @param string $name The name of the template to load |
||||
* |
||||
* @return string The template source code |
||||
*/ |
||||
public function getSource($name) |
||||
{ |
||||
foreach ($this->loaders as $loader) { |
||||
try { |
||||
return $loader->getSource($name); |
||||
} catch (Twig_Error_Loader $e) { |
||||
} |
||||
} |
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); |
||||
} |
||||
|
||||
/** |
||||
* Gets the cache key to use for the cache for a given template name. |
||||
* |
||||
* @param string $name The name of the template to load |
||||
* |
||||
* @return string The cache key |
||||
*/ |
||||
public function getCacheKey($name) |
||||
{ |
||||
foreach ($this->loaders as $loader) { |
||||
try { |
||||
return $loader->getCacheKey($name); |
||||
} catch (Twig_Error_Loader $e) { |
||||
} |
||||
} |
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); |
||||
} |
||||
|
||||
/** |
||||
* Returns true if the template is still fresh. |
||||
* |
||||
* @param string $name The template name |
||||
* @param timestamp $time The last modification time of the cached template |
||||
*/ |
||||
public function isFresh($name, $time) |
||||
{ |
||||
foreach ($this->loaders as $loader) { |
||||
try { |
||||
return $loader->isFresh($name, $time); |
||||
} catch (Twig_Error_Loader $e) { |
||||
} |
||||
} |
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); |
||||
} |
||||
} |
||||
@ -1,152 +0,0 @@ |
||||
<?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. |
||||
*/ |
||||
|
||||
/** |
||||
* Loads template from the filesystem. |
||||
* |
||||
* @package twig |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
class Twig_Loader_Filesystem implements Twig_LoaderInterface |
||||
{ |
||||
protected $paths; |
||||
protected $cache; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param string|array $paths A path or an array of paths where to look for templates |
||||
*/ |
||||
public function __construct($paths) |
||||
{ |
||||
$this->setPaths($paths); |
||||
} |
||||
|
||||
/** |
||||
* Returns the paths to the templates. |
||||
* |
||||
* @return array The array of paths where to look for templates |
||||
*/ |
||||
public function getPaths() |
||||
{ |
||||
return $this->paths; |
||||
} |
||||
|
||||
/** |
||||
* Sets the paths where templates are stored. |
||||
* |
||||
* @param string|array $paths A path or an array of paths where to look for templates |
||||
*/ |
||||
public function setPaths($paths) |
||||
{ |
||||
if (!is_array($paths)) { |
||||
$paths = array($paths); |
||||
} |
||||
|
||||
$this->paths = array(); |
||||
foreach ($paths as $path) { |
||||
$this->addPath($path); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Adds a path where templates are stored. |
||||
* |
||||
* @param string $path A path where to look for templates |
||||
*/ |
||||
public function addPath($path) |
||||
{ |
||||
// invalidate the cache |
||||
$this->cache = array(); |
||||
|
||||
if (!is_dir($path)) { |
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path)); |
||||
} |
||||
|
||||
$this->paths[] = $path; |
||||
} |
||||
|
||||
/** |
||||
* Gets the source code of a template, given its name. |
||||
* |
||||
* @param string $name The name of the template to load |
||||
* |
||||
* @return string The template source code |
||||
*/ |
||||
public function getSource($name) |
||||
{ |
||||
return file_get_contents($this->findTemplate($name)); |
||||
} |
||||
|
||||
/** |
||||
* Gets the cache key to use for the cache for a given template name. |
||||
* |
||||
* @param string $name The name of the template to load |
||||
* |
||||
* @return string The cache key |
||||
*/ |
||||
public function getCacheKey($name) |
||||
{ |
||||
return $this->findTemplate($name); |
||||
} |
||||
|
||||
/** |
||||
* Returns true if the template is still fresh. |
||||
* |
||||
* @param string $name The template name |
||||
* @param timestamp $time The last modification time of the cached template |
||||
*/ |
||||
public function isFresh($name, $time) |
||||
{ |
||||
return filemtime($this->findTemplate($name)) < $time; |
||||
} |
||||
|
||||
protected function findTemplate($name) |
||||
{ |
||||
// normalize name |
||||
$name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/')); |
||||
|
||||
if (isset($this->cache[$name])) { |
||||
return $this->cache[$name]; |
||||
} |
||||
|
||||
$this->validateName($name); |
||||
|
||||
foreach ($this->paths as $path) { |
||||
if (is_file($path.'/'.$name)) { |
||||
return $this->cache[$name] = $path.'/'.$name; |
||||
} |
||||
} |
||||
|
||||
throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths))); |
||||
} |
||||
|
||||
protected function validateName($name) |
||||
{ |
||||
if (false !== strpos($name, "\0")) { |
||||
throw new Twig_Error_Loader('A template name cannot contain NUL bytes.'); |
||||
} |
||||
|
||||
$parts = explode('/', $name); |
||||
$level = 0; |
||||
foreach ($parts as $part) { |
||||
if ('..' === $part) { |
||||
--$level; |
||||
} elseif ('.' !== $part) { |
||||
++$level; |
||||
} |
||||
|
||||
if ($level < 0) { |
||||
throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,61 +0,0 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2009 Fabien Potencier |
||||
* (c) 2009 Armin Ronacher |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
class Twig_Node_Expression_Filter extends Twig_Node_Expression |
||||
{ |
||||
public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null) |
||||
{ |
||||
parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag); |
||||
} |
||||
|
||||
public function compile(Twig_Compiler $compiler) |
||||
{ |
||||
$name = $this->getNode('filter')->getAttribute('value'); |
||||
|
||||
if (false === $filter = $compiler->getEnvironment()->getFilter($name)) { |
||||
$message = sprintf('The filter "%s" does not exist', $name); |
||||
if ($alternatives = $compiler->getEnvironment()->computeAlternatives($name, array_keys($compiler->getEnvironment()->getFilters()))) { |
||||
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); |
||||
} |
||||
|
||||
throw new Twig_Error_Syntax($message, $this->getLine()); |
||||
} |
||||
|
||||
$this->compileFilter($compiler, $filter); |
||||
} |
||||
|
||||
protected function compileFilter(Twig_Compiler $compiler, Twig_FilterInterface $filter) |
||||
{ |
||||
$compiler |
||||
->raw($filter->compile().'(') |
||||
->raw($filter->needsEnvironment() ? '$this->env, ' : '') |
||||
->raw($filter->needsContext() ? '$context, ' : '') |
||||
; |
||||
|
||||
foreach ($filter->getArguments() as $argument) { |
||||
$compiler |
||||
->string($argument) |
||||
->raw(', ') |
||||
; |
||||
} |
||||
|
||||
$compiler->subcompile($this->getNode('node')); |
||||
|
||||
foreach ($this->getNode('arguments') as $node) { |
||||
$compiler |
||||
->raw(', ') |
||||
->subcompile($node) |
||||
; |
||||
} |
||||
|
||||
$compiler->raw(')'); |
||||
} |
||||
} |
||||
@ -1,66 +0,0 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2010 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
class Twig_Node_Expression_Function extends Twig_Node_Expression |
||||
{ |
||||
public function __construct($name, Twig_NodeInterface $arguments, $lineno) |
||||
{ |
||||
parent::__construct(array('arguments' => $arguments), array('name' => $name), $lineno); |
||||
} |
||||
|
||||
public function compile(Twig_Compiler $compiler) |
||||
{ |
||||
$name = $this->getAttribute('name'); |
||||
|
||||
if (false === $function = $compiler->getEnvironment()->getFunction($name)) { |
||||
$message = sprintf('The function "%s" does not exist', $name); |
||||
if ($alternatives = $compiler->getEnvironment()->computeAlternatives($name, array_keys($compiler->getEnvironment()->getFunctions()))) { |
||||
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); |
||||
} |
||||
|
||||
throw new Twig_Error_Syntax($message, $this->getLine()); |
||||
} |
||||
|
||||
$compiler->raw($function->compile().'('); |
||||
|
||||
$first = true; |
||||
|
||||
if ($function->needsEnvironment()) { |
||||
$compiler->raw('$this->env'); |
||||
$first = false; |
||||
} |
||||
|
||||
if ($function->needsContext()) { |
||||
if (!$first) { |
||||
$compiler->raw(', '); |
||||
} |
||||
$compiler->raw('$context'); |
||||
$first = false; |
||||
} |
||||
|
||||
foreach ($function->getArguments() as $argument) { |
||||
if (!$first) { |
||||
$compiler->raw(', '); |
||||
} |
||||
$compiler->string($argument); |
||||
$first = false; |
||||
} |
||||
|
||||
foreach ($this->getNode('arguments') as $node) { |
||||
if (!$first) { |
||||
$compiler->raw(', '); |
||||
} |
||||
$compiler->subcompile($node); |
||||
$first = false; |
||||
} |
||||
|
||||
$compiler->raw(')'); |
||||
} |
||||
} |
||||
@ -1,54 +0,0 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2010 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
class Twig_Node_Expression_Test extends Twig_Node_Expression |
||||
{ |
||||
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno) |
||||
{ |
||||
parent::__construct(array('node' => $node, 'arguments' => $arguments), array('name' => $name), $lineno); |
||||
} |
||||
|
||||
public function compile(Twig_Compiler $compiler) |
||||
{ |
||||
$name = $this->getAttribute('name'); |
||||
$testMap = $compiler->getEnvironment()->getTests(); |
||||
if (!isset($testMap[$name])) { |
||||
$message = sprintf('The test "%s" does not exist', $name); |
||||
if ($alternatives = $compiler->getEnvironment()->computeAlternatives($name, array_keys($compiler->getEnvironment()->getTests()))) { |
||||
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); |
||||
} |
||||
|
||||
throw new Twig_Error_Syntax($message, $this->getLine()); |
||||
} |
||||
|
||||
$name = $this->getAttribute('name'); |
||||
$node = $this->getNode('node'); |
||||
|
||||
$compiler |
||||
->raw($testMap[$name]->compile().'(') |
||||
->subcompile($node) |
||||
; |
||||
|
||||
if (null !== $this->getNode('arguments')) { |
||||
$compiler->raw(', '); |
||||
|
||||
$max = count($this->getNode('arguments')) - 1; |
||||
foreach ($this->getNode('arguments') as $i => $arg) { |
||||
$compiler->subcompile($arg); |
||||
|
||||
if ($i != $max) { |
||||
$compiler->raw(', '); |
||||
} |
||||
} |
||||
} |
||||
|
||||
$compiler->raw(')'); |
||||
} |
||||
} |
||||
@ -1,89 +0,0 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2009 Fabien Potencier |
||||
* (c) 2009 Armin Ronacher |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Loops over each item of a sequence. |
||||
* |
||||
* <pre> |
||||
* <ul> |
||||
* {% for user in users %} |
||||
* <li>{{ user.username|e }}</li> |
||||
* {% endfor %} |
||||
* </ul> |
||||
* </pre> |
||||
*/ |
||||
class Twig_TokenParser_For extends Twig_TokenParser |
||||
{ |
||||
/** |
||||
* Parses a token and returns a node. |
||||
* |
||||
* @param Twig_Token $token A Twig_Token instance |
||||
* |
||||
* @return Twig_NodeInterface A Twig_NodeInterface instance |
||||
*/ |
||||
public function parse(Twig_Token $token) |
||||
{ |
||||
$lineno = $token->getLine(); |
||||
$targets = $this->parser->getExpressionParser()->parseAssignmentExpression(); |
||||
$this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, 'in'); |
||||
$seq = $this->parser->getExpressionParser()->parseExpression(); |
||||
|
||||
$ifexpr = null; |
||||
if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'if')) { |
||||
$this->parser->getStream()->next(); |
||||
$ifexpr = $this->parser->getExpressionParser()->parseExpression(); |
||||
} |
||||
|
||||
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); |
||||
$body = $this->parser->subparse(array($this, 'decideForFork')); |
||||
if ($this->parser->getStream()->next()->getValue() == 'else') { |
||||
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); |
||||
$else = $this->parser->subparse(array($this, 'decideForEnd'), true); |
||||
} else { |
||||
$else = null; |
||||
} |
||||
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); |
||||
|
||||
if (count($targets) > 1) { |
||||
$keyTarget = $targets->getNode(0); |
||||
$keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->getLine()); |
||||
$valueTarget = $targets->getNode(1); |
||||
$valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine()); |
||||
} else { |
||||
$keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno); |
||||
$valueTarget = $targets->getNode(0); |
||||
$valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine()); |
||||
} |
||||
|
||||
return new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag()); |
||||
} |
||||
|
||||
public function decideForFork(Twig_Token $token) |
||||
{ |
||||
return $token->test(array('else', 'endfor')); |
||||
} |
||||
|
||||
public function decideForEnd(Twig_Token $token) |
||||
{ |
||||
return $token->test('endfor'); |
||||
} |
||||
|
||||
/** |
||||
* Gets the tag name associated with this token parser. |
||||
* |
||||
* @return string The tag name |
||||
*/ |
||||
public function getTag() |
||||
{ |
||||
return 'for'; |
||||
} |
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
; top-most EditorConfig file |
||||
root = true |
||||
|
||||
; Unix-style newlines |
||||
[*] |
||||
end_of_line = LF |
||||
|
||||
[*.php] |
||||
indent_style = space |
||||
indent_size = 4 |
||||
|
||||
[*.test] |
||||
indent_style = space |
||||
indent_size = 4 |
||||
|
||||
[*.rst] |
||||
indent_style = space |
||||
indent_size = 4 |
||||
@ -0,0 +1,2 @@ |
||||
/ext/twig/autom4te.cache/ |
||||
|
||||
@ -0,0 +1,21 @@ |
||||
language: php |
||||
|
||||
php: |
||||
- 5.2 |
||||
- 5.3 |
||||
- 5.4 |
||||
- 5.5 |
||||
- hhvm |
||||
|
||||
env: |
||||
- TWIG_EXT=no |
||||
- TWIG_EXT=yes |
||||
|
||||
before_script: |
||||
- if [ "$TWIG_EXT" == "yes" ]; then sh -c "cd ext/twig && phpize && ./configure --enable-twig && make && sudo make install"; fi |
||||
- if [ "$TWIG_EXT" == "yes" ]; then echo "extension=twig.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi |
||||
|
||||
matrix: |
||||
exclude: |
||||
- php: hhvm |
||||
env: TWIG_EXT=yes |
||||
@ -0,0 +1,684 @@ |
||||
* 1.16.0 (2014-07-05) |
||||
|
||||
* changed url_encode to always encode according to RFC 3986 |
||||
* fixed inheritance in a 'use'-hierarchy |
||||
* removed the __toString policy check when the sandbox is disabled |
||||
* fixed recursively calling blocks in templates with inheritance |
||||
|
||||
* 1.15.1 (2014-02-13) |
||||
|
||||
* fixed the conversion of the special '0000-00-00 00:00' date |
||||
* added an error message when trying to import an undefined block from a trait |
||||
* fixed a C extension crash when accessing defined but uninitialized property. |
||||
|
||||
* 1.15.0 (2013-12-06) |
||||
|
||||
* made ignoreStrictCheck in Template::getAttribute() works with __call() methods throwing BadMethodCallException |
||||
* added min and max functions |
||||
* added the round filter |
||||
* fixed a bug that prevented the optimizers to be enabled/disabled selectively |
||||
* fixed first and last filters for UTF-8 strings |
||||
* added a source function to include the content of a template without rendering it |
||||
* fixed the C extension sandbox behavior when get or set is prepend to method name |
||||
|
||||
* 1.14.2 (2013-10-30) |
||||
|
||||
* fixed error filename/line when an error occurs in an included file |
||||
* allowed operators that contain whitespaces to have more than one whitespace |
||||
* allowed tests to be made of 1 or 2 words (like "same as" or "divisible by") |
||||
|
||||
* 1.14.1 (2013-10-15) |
||||
|
||||
* made it possible to use named operators as variables |
||||
* fixed the possibility to have a variable named 'matches' |
||||
* added support for PHP 5.5 DateTimeInterface |
||||
|
||||
* 1.14.0 (2013-10-03) |
||||
|
||||
* fixed usage of the html_attr escaping strategy to avoid double-escaping with the html strategy |
||||
* added new operators: ends with, starts with, and matches |
||||
* fixed some compatibility issues with HHVM |
||||
* added a way to add custom escaping strategies |
||||
* fixed the C extension compilation on Windows |
||||
* fixed the batch filter when using a fill argument with an exact match of elements to batch |
||||
* fixed the filesystem loader cache when a template name exists in several namespaces |
||||
* fixed template_from_string when the template includes or extends other ones |
||||
* fixed a crash of the C extension on an edge case |
||||
|
||||
* 1.13.2 (2013-08-03) |
||||
|
||||
* fixed the error line number for an error occurs in and embedded template |
||||
* fixed crashes of the C extension on some edge cases |
||||
|
||||
* 1.13.1 (2013-06-06) |
||||
|
||||
* added the possibility to ignore the filesystem constructor argument in Twig_Loader_Filesystem |
||||
* fixed Twig_Loader_Chain::exists() for a loader which implements Twig_ExistsLoaderInterface |
||||
* adjusted backtrace call to reduce memory usage when an error occurs |
||||
* added support for object instances as the second argument of the constant test |
||||
* fixed the include function when used in an assignment |
||||
|
||||
* 1.13.0 (2013-05-10) |
||||
|
||||
* fixed getting a numeric-like item on a variable ('09' for instance) |
||||
* fixed getting a boolean or float key on an array, so it is consistent with PHP's array access: |
||||
`{{ array[false] }}` behaves the same as `echo $array[false];` (equals `$array[0]`) |
||||
* made the escape filter 20% faster for happy path (escaping string for html with UTF-8) |
||||
* changed ☃ to § in tests |
||||
* enforced usage of named arguments after positional ones |
||||
|
||||
* 1.12.3 (2013-04-08) |
||||
|
||||
* fixed a security issue in the filesystem loader where it was possible to include a template one |
||||
level above the configured path |
||||
* fixed fatal error that should be an exception when adding a filter/function/test too late |
||||
* added a batch filter |
||||
* added support for encoding an array as query string in the url_encode filter |
||||
|
||||
* 1.12.2 (2013-02-09) |
||||
|
||||
* fixed the timezone used by the date filter and function when the given date contains a timezone (like 2010-01-28T15:00:00+02:00) |
||||
* fixed globals when getGlobals is called early on |
||||
* added the first and last filter |
||||
|
||||
* 1.12.1 (2013-01-15) |
||||
|
||||
* added support for object instances as the second argument of the constant function |
||||
* relaxed globals management to avoid a BC break |
||||
* added support for {{ some_string[:2] }} |
||||
|
||||
* 1.12.0 (2013-01-08) |
||||
|
||||
* added verbatim as an alias for the raw tag to avoid confusion with the raw filter |
||||
* fixed registration of tests and functions as anonymous functions |
||||
* fixed globals management |
||||
|
||||
* 1.12.0-RC1 (2012-12-29) |
||||
|
||||
* added an include function (does the same as the include tag but in a more flexible way) |
||||
* added the ability to use any PHP callable to define filters, functions, and tests |
||||
* added a syntax error when using a loop variable that is not defined |
||||
* added the ability to set default values for macro arguments |
||||
* added support for named arguments for filters, tests, and functions |
||||
* moved filters/functions/tests syntax errors to the parser |
||||
* added support for extended ternary operator syntaxes |
||||
|
||||
* 1.11.1 (2012-11-11) |
||||
|
||||
* fixed debug info line numbering (was off by 2) |
||||
* fixed escaping when calling a macro inside another one (regression introduced in 1.9.1) |
||||
* optimized variable access on PHP 5.4 |
||||
* fixed a crash of the C extension when an exception was thrown from a macro called without being imported (using _self.XXX) |
||||
|
||||
* 1.11.0 (2012-11-07) |
||||
|
||||
* fixed macro compilation when a variable name is a PHP reserved keyword |
||||
* changed the date filter behavior to always apply the default timezone, except if false is passed as the timezone |
||||
* fixed bitwise operator precedences |
||||
* added the template_from_string function |
||||
* fixed default timezone usage for the date function |
||||
* optimized the way Twig exceptions are managed (to make them faster) |
||||
* added Twig_ExistsLoaderInterface (implementing this interface in your loader make the chain loader much faster) |
||||
|
||||
* 1.10.3 (2012-10-19) |
||||
|
||||
* fixed wrong template location in some error messages |
||||
* reverted a BC break introduced in 1.10.2 |
||||
* added a split filter |
||||
|
||||
* 1.10.2 (2012-10-15) |
||||
|
||||
* fixed macro calls on PHP 5.4 |
||||
|
||||
* 1.10.1 (2012-10-15) |
||||
|
||||
* made a speed optimization to macro calls when imported via the "import" tag |
||||
* fixed C extension compilation on Windows |
||||
* fixed a segfault in the C extension when using DateTime objects |
||||
|
||||
* 1.10.0 (2012-09-28) |
||||
|
||||
* extracted functional tests framework to make it reusable for third-party extensions |
||||
* added namespaced templates support in Twig_Loader_Filesystem |
||||
* added Twig_Loader_Filesystem::prependPath() |
||||
* fixed an error when a token parser pass a closure as a test to the subparse() method |
||||
|
||||
* 1.9.2 (2012-08-25) |
||||
|
||||
* fixed the in operator for objects that contain circular references |
||||
* fixed the C extension when accessing a public property of an object implementing the \ArrayAccess interface |
||||
|
||||
* 1.9.1 (2012-07-22) |
||||
|
||||
* optimized macro calls when auto-escaping is on |
||||
* fixed wrong parent class for Twig_Function_Node |
||||
* made Twig_Loader_Chain more explicit about problems |
||||
|
||||
* 1.9.0 (2012-07-13) |
||||
|
||||
* made the parsing independent of the template loaders |
||||
* fixed exception trace when an error occurs when rendering a child template |
||||
* added escaping strategies for CSS, URL, and HTML attributes |
||||
* fixed nested embed tag calls |
||||
* added the date_modify filter |
||||
|
||||
* 1.8.3 (2012-06-17) |
||||
|
||||
* fixed paths in the filesystem loader when passing a path that ends with a slash or a backslash |
||||
* fixed escaping when a project defines a function named html or js |
||||
* fixed chmod mode to apply the umask correctly |
||||
|
||||
* 1.8.2 (2012-05-30) |
||||
|
||||
* added the abs filter |
||||
* fixed a regression when using a number in template attributes |
||||
* fixed compiler when mbstring.func_overload is set to 2 |
||||
* fixed DateTimeZone support in date filter |
||||
|
||||
* 1.8.1 (2012-05-17) |
||||
|
||||
* fixed a regression when dealing with SimpleXMLElement instances in templates |
||||
* fixed "is_safe" value for the "dump" function when "html_errors" is not defined in php.ini |
||||
* switched to use mbstring whenever possible instead of iconv (you might need to update your encoding as mbstring and iconv encoding names sometimes differ) |
||||
|
||||
* 1.8.0 (2012-05-08) |
||||
|
||||
* enforced interface when adding tests, filters, functions, and node visitors from extensions |
||||
* fixed a side-effect of the date filter where the timezone might be changed |
||||
* simplified usage of the autoescape tag; the only (optional) argument is now the escaping strategy or false (with a BC layer) |
||||
* added a way to dynamically change the auto-escaping strategy according to the template "filename" |
||||
* changed the autoescape option to also accept a supported escaping strategy (for BC, true is equivalent to html) |
||||
* added an embed tag |
||||
|
||||
* 1.7.0 (2012-04-24) |
||||
|
||||
* fixed a PHP warning when using CIFS |
||||
* fixed template line number in some exceptions |
||||
* added an iterable test |
||||
* added an error when defining two blocks with the same name in a template |
||||
* added the preserves_safety option for filters |
||||
* fixed a PHP notice when trying to access a key on a non-object/array variable |
||||
* enhanced error reporting when the template file is an instance of SplFileInfo |
||||
* added Twig_Environment::mergeGlobals() |
||||
* added compilation checks to avoid misuses of the sandbox tag |
||||
* fixed filesystem loader freshness logic for high traffic websites |
||||
* fixed random function when charset is null |
||||
|
||||
* 1.6.5 (2012-04-11) |
||||
|
||||
* fixed a regression when a template only extends another one without defining any blocks |
||||
|
||||
* 1.6.4 (2012-04-02) |
||||
|
||||
* fixed PHP notice in Twig_Error::guessTemplateLine() introduced in 1.6.3 |
||||
* fixed performance when compiling large files |
||||
* optimized parent template creation when the template does not use dynamic inheritance |
||||
|
||||
* 1.6.3 (2012-03-22) |
||||
|
||||
* fixed usage of Z_ADDREF_P for PHP 5.2 in the C extension |
||||
* fixed compilation of numeric values used in templates when using a locale where the decimal separator is not a dot |
||||
* made the strategy used to guess the real template file name and line number in exception messages much faster and more accurate |
||||
|
||||
* 1.6.2 (2012-03-18) |
||||
|
||||
* fixed sandbox mode when used with inheritance |
||||
* added preserveKeys support for the slice filter |
||||
* fixed the date filter when a DateTime instance is passed with a specific timezone |
||||
* added a trim filter |
||||
|
||||
* 1.6.1 (2012-02-29) |
||||
|
||||
* fixed Twig C extension |
||||
* removed the creation of Twig_Markup instances when not needed |
||||
* added a way to set the default global timezone for dates |
||||
* fixed the slice filter on strings when the length is not specified |
||||
* fixed the creation of the cache directory in case of a race condition |
||||
|
||||
* 1.6.0 (2012-02-04) |
||||
|
||||
* fixed raw blocks when used with the whitespace trim option |
||||
* made a speed optimization to macro calls when imported via the "from" tag |
||||
* fixed globals, parsers, visitors, filters, tests, and functions management in Twig_Environment when a new one or new extension is added |
||||
* fixed the attribute function when passing arguments |
||||
* added slice notation support for the [] operator (syntactic sugar for the slice operator) |
||||
* added a slice filter |
||||
* added string support for the reverse filter |
||||
* fixed the empty test and the length filter for Twig_Markup instances |
||||
* added a date function to ease date comparison |
||||
* fixed unary operators precedence |
||||
* added recursive parsing support in the parser |
||||
* added string and integer handling for the random function |
||||
|
||||
* 1.5.1 (2012-01-05) |
||||
|
||||
* fixed a regression when parsing strings |
||||
|
||||
* 1.5.0 (2012-01-04) |
||||
|
||||
* added Traversable objects support for the join filter |
||||
|
||||
* 1.5.0-RC2 (2011-12-30) |
||||
|
||||
* added a way to set the default global date interval format |
||||
* fixed the date filter for DateInterval instances (setTimezone() does not exist for them) |
||||
* refactored Twig_Template::display() to ease its extension |
||||
* added a number_format filter |
||||
|
||||
* 1.5.0-RC1 (2011-12-26) |
||||
|
||||
* removed the need to quote hash keys |
||||
* allowed hash keys to be any expression |
||||
* added a do tag |
||||
* added a flush tag |
||||
* added support for dynamically named filters and functions |
||||
* added a dump function to help debugging templates |
||||
* added a nl2br filter |
||||
* added a random function |
||||
* added a way to change the default format for the date filter |
||||
* fixed the lexer when an operator ending with a letter ends a line |
||||
* added string interpolation support |
||||
* enhanced exceptions for unknown filters, functions, tests, and tags |
||||
|
||||
* 1.4.0 (2011-12-07) |
||||
|
||||
* fixed lexer when using big numbers (> PHP_INT_MAX) |
||||
* added missing preserveKeys argument to the reverse filter |
||||
* fixed macros containing filter tag calls |
||||
|
||||
* 1.4.0-RC2 (2011-11-27) |
||||
|
||||
* removed usage of Reflection in Twig_Template::getAttribute() |
||||
* added a C extension that can optionally replace Twig_Template::getAttribute() |
||||
* added negative timestamp support to the date filter |
||||
|
||||
* 1.4.0-RC1 (2011-11-20) |
||||
|
||||
* optimized variable access when using PHP 5.4 |
||||
* changed the precedence of the .. operator to be more consistent with languages that implements such a feature like Ruby |
||||
* added an Exception to Twig_Loader_Array::isFresh() method when the template does not exist to be consistent with other loaders |
||||
* added Twig_Function_Node to allow more complex functions to have their own Node class |
||||
* added Twig_Filter_Node to allow more complex filters to have their own Node class |
||||
* added Twig_Test_Node to allow more complex tests to have their own Node class |
||||
* added a better error message when a template is empty but contain a BOM |
||||
* fixed "in" operator for empty strings |
||||
* fixed the "defined" test and the "default" filter (now works with more than one call (foo.bar.foo) and for both values of the strict_variables option) |
||||
* changed the way extensions are loaded (addFilter/addFunction/addGlobal/addTest/addNodeVisitor/addTokenParser/addExtension can now be called in any order) |
||||
* added Twig_Environment::display() |
||||
* made the escape filter smarter when the encoding is not supported by PHP |
||||
* added a convert_encoding filter |
||||
* moved all node manipulations outside the compile() Node method |
||||
* made several speed optimizations |
||||
|
||||
* 1.3.0 (2011-10-08) |
||||
|
||||
no changes |
||||
|
||||
* 1.3.0-RC1 (2011-10-04) |
||||
|
||||
* added an optimization for the parent() function |
||||
* added cache reloading when auto_reload is true and an extension has been modified |
||||
* added the possibility to force the escaping of a string already marked as safe (instance of Twig_Markup) |
||||
* allowed empty templates to be used as traits |
||||
* added traits support for the "parent" function |
||||
|
||||
* 1.2.0 (2011-09-13) |
||||
|
||||
no changes |
||||
|
||||
* 1.2.0-RC1 (2011-09-10) |
||||
|
||||
* enhanced the exception when a tag remains unclosed |
||||
* added support for empty Countable objects for the "empty" test |
||||
* fixed algorithm that determines if a template using inheritance is valid (no output between block definitions) |
||||
* added better support for encoding problems when escaping a string (available as of PHP 5.4) |
||||
* added a way to ignore a missing template when using the "include" tag ({% include "foo" ignore missing %}) |
||||
* added support for an array of templates to the "include" and "extends" tags ({% include ['foo', 'bar'] %}) |
||||
* added support for bitwise operators in expressions |
||||
* added the "attribute" function to allow getting dynamic attributes on variables |
||||
* added Twig_Loader_Chain |
||||
* added Twig_Loader_Array::setTemplate() |
||||
* added an optimization for the set tag when used to capture a large chunk of static text |
||||
* changed name regex to match PHP one "[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*" (works for blocks, tags, functions, filters, and macros) |
||||
* removed the possibility to use the "extends" tag from a block |
||||
* added "if" modifier support to "for" loops |
||||
|
||||
* 1.1.2 (2011-07-30) |
||||
|
||||
* fixed json_encode filter on PHP 5.2 |
||||
* fixed regression introduced in 1.1.1 ({{ block(foo|lower) }}) |
||||
* fixed inheritance when using conditional parents |
||||
* fixed compilation of templates when the body of a child template is not empty |
||||
* fixed output when a macro throws an exception |
||||
* fixed a parsing problem when a large chunk of text is enclosed in a comment tag |
||||
* added PHPDoc for all Token parsers and Core extension functions |
||||
|
||||
* 1.1.1 (2011-07-17) |
||||
|
||||
* added a performance optimization in the Optimizer (also helps to lower the number of nested level calls) |
||||
* made some performance improvement for some edge cases |
||||
|
||||
* 1.1.0 (2011-06-28) |
||||
|
||||
* fixed json_encode filter |
||||
|
||||
* 1.1.0-RC3 (2011-06-24) |
||||
|
||||
* fixed method case-sensitivity when using the sandbox mode |
||||
* added timezone support for the date filter |
||||
* fixed possible security problems with NUL bytes |
||||
|
||||
* 1.1.0-RC2 (2011-06-16) |
||||
|
||||
* added an exception when the template passed to "use" is not a string |
||||
* made 'a.b is defined' not throw an exception if a is not defined (in strict mode) |
||||
* added {% line \d+ %} directive |
||||
|
||||
* 1.1.0-RC1 (2011-05-28) |
||||
|
||||
Flush your cache after upgrading. |
||||
|
||||
* fixed date filter when using a timestamp |
||||
* fixed the defined test for some cases |
||||
* fixed a parsing problem when a large chunk of text is enclosed in a raw tag |
||||
* added support for horizontal reuse of template blocks (see docs for more information) |
||||
* added whitespace control modifier to all tags (see docs for more information) |
||||
* added null as an alias for none (the null test is also an alias for the none test now) |
||||
* made TRUE, FALSE, NONE equivalent to their lowercase counterparts |
||||
* wrapped all compilation and runtime exceptions with Twig_Error_Runtime and added logic to guess the template name and line |
||||
* moved display() method to Twig_Template (generated templates should now use doDisplay() instead) |
||||
|
||||
* 1.0.0 (2011-03-27) |
||||
|
||||
* fixed output when using mbstring |
||||
* fixed duplicate call of methods when using the sandbox |
||||
* made the charset configurable for the escape filter |
||||
|
||||
* 1.0.0-RC2 (2011-02-21) |
||||
|
||||
* changed the way {% set %} works when capturing (the content is now marked as safe) |
||||
* added support for macro name in the endmacro tag |
||||
* make Twig_Error compatible with PHP 5.3.0 > |
||||
* fixed an infinite loop on some Windows configurations |
||||
* fixed the "length" filter for numbers |
||||
* fixed Template::getAttribute() as properties in PHP are case sensitive |
||||
* removed coupling between Twig_Node and Twig_Template |
||||
* fixed the ternary operator precedence rule |
||||
|
||||
* 1.0.0-RC1 (2011-01-09) |
||||
|
||||
Backward incompatibilities: |
||||
|
||||
* the "items" filter, which has been deprecated for quite a long time now, has been removed |
||||
* the "range" filter has been converted to a function: 0|range(10) -> range(0, 10) |
||||
* the "constant" filter has been converted to a function: {{ some_date|date('DATE_W3C'|constant) }} -> {{ some_date|date(constant('DATE_W3C')) }} |
||||
* the "cycle" filter has been converted to a function: {{ ['odd', 'even']|cycle(i) }} -> {{ cycle(['odd', 'even'], i) }} |
||||
* the "for" tag does not support "joined by" anymore |
||||
* the "autoescape" first argument is now "true"/"false" (instead of "on"/"off") |
||||
* the "parent" tag has been replaced by a "parent" function ({{ parent() }} instead of {% parent %}) |
||||
* the "display" tag has been replaced by a "block" function ({{ block('title') }} instead of {% display title %}) |
||||
* removed the grammar and simple token parser (moved to the Twig Extensions repository) |
||||
|
||||
Changes: |
||||
|
||||
* added "needs_context" option for filters and functions (the context is then passed as a first argument) |
||||
* added global variables support |
||||
* made macros return their value instead of echoing directly (fixes calling a macro in sandbox mode) |
||||
* added the "from" tag to import macros as functions |
||||
* added support for functions (a function is just syntactic sugar for a getAttribute() call) |
||||
* made macros callable when sandbox mode is enabled |
||||
* added an exception when a macro uses a reserved name |
||||
* the "default" filter now uses the "empty" test instead of just checking for null |
||||
* added the "empty" test |
||||
|
||||
* 0.9.10 (2010-12-16) |
||||
|
||||
Backward incompatibilities: |
||||
|
||||
* The Escaper extension is enabled by default, which means that all displayed |
||||
variables are now automatically escaped. You can revert to the previous |
||||
behavior by removing the extension via $env->removeExtension('escaper') |
||||
or just set the 'autoescape' option to 'false'. |
||||
* removed the "without loop" attribute for the "for" tag (not needed anymore |
||||
as the Optimizer take care of that for most cases) |
||||
* arrays and hashes have now a different syntax |
||||
* arrays keep the same syntax with square brackets: [1, 2] |
||||
* hashes now use curly braces (["a": "b"] should now be written as {"a": "b"}) |
||||
* support for "arrays with keys" and "hashes without keys" is not supported anymore ([1, "foo": "bar"] or {"foo": "bar", 1}) |
||||
* the i18n extension is now part of the Twig Extensions repository |
||||
|
||||
Changes: |
||||
|
||||
* added the merge filter |
||||
* removed 'is_escaper' option for filters (a left over from the previous version) -- you must use 'is_safe' now instead |
||||
* fixed usage of operators as method names (like is, in, and not) |
||||
* changed the order of execution for node visitors |
||||
* fixed default() filter behavior when used with strict_variables set to on |
||||
* fixed filesystem loader compatibility with PHAR files |
||||
* enhanced error messages when an unexpected token is parsed in an expression |
||||
* fixed filename not being added to syntax error messages |
||||
* added the autoescape option to enable/disable autoescaping |
||||
* removed the newline after a comment (mimics PHP behavior) |
||||
* added a syntax error exception when parent block is used on a template that does not extend another one |
||||
* made the Escaper extension enabled by default |
||||
* fixed sandbox extension when used with auto output escaping |
||||
* fixed escaper when wrapping a Twig_Node_Print (the original class must be preserved) |
||||
* added an Optimizer extension (enabled by default; optimizes "for" loops and "raw" filters) |
||||
* added priority to node visitors |
||||
|
||||
* 0.9.9 (2010-11-28) |
||||
|
||||
Backward incompatibilities: |
||||
* the self special variable has been renamed to _self |
||||
* the odd and even filters are now tests: |
||||
{{ foo|odd }} must now be written {{ foo is odd }} |
||||
* the "safe" filter has been renamed to "raw" |
||||
* in Node classes, |
||||
sub-nodes are now accessed via getNode() (instead of property access) |
||||
attributes via getAttribute() (instead of array access) |
||||
* the urlencode filter had been renamed to url_encode |
||||
* the include tag now merges the passed variables with the current context by default |
||||
(the old behavior is still possible by adding the "only" keyword) |
||||
* moved Exceptions to Twig_Error_* (Twig_SyntaxError/Twig_RuntimeError are now Twig_Error_Syntax/Twig_Error_Runtime) |
||||
* removed support for {{ 1 < i < 3 }} (use {{ i > 1 and i < 3 }} instead) |
||||
* the "in" filter has been removed ({{ a|in(b) }} should now be written {{ a in b }}) |
||||
|
||||
Changes: |
||||
* added file and line to Twig_Error_Runtime exceptions thrown from Twig_Template |
||||
* changed trans tag to accept any variable for the plural count |
||||
* fixed sandbox mode (__toString() method check was not enforced if called implicitly from complex statements) |
||||
* added the ** (power) operator |
||||
* changed the algorithm used for parsing expressions |
||||
* added the spaceless tag |
||||
* removed trim_blocks option |
||||
* added support for is*() methods for attributes (foo.bar now looks for foo->getBar() or foo->isBar()) |
||||
* changed all exceptions to extend Twig_Error |
||||
* fixed unary expressions ({{ not(1 or 0) }}) |
||||
* fixed child templates (with an extend tag) that uses one or more imports |
||||
* added support for {{ 1 not in [2, 3] }} (more readable than the current {{ not (1 in [2, 3]) }}) |
||||
* escaping has been rewritten |
||||
* the implementation of template inheritance has been rewritten |
||||
(blocks can now be called individually and still work with inheritance) |
||||
* fixed error handling for if tag when a syntax error occurs within a subparse process |
||||
* added a way to implement custom logic for resolving token parsers given a tag name |
||||
* fixed js escaper to be stricter (now uses a whilelist-based js escaper) |
||||
* added the following filers: "constant", "trans", "replace", "json_encode" |
||||
* added a "constant" test |
||||
* fixed objects with __toString() not being autoescaped |
||||
* fixed subscript expressions when calling __call() (methods now keep the case) |
||||
* added "test" feature (accessible via the "is" operator) |
||||
* removed the debug tag (should be done in an extension) |
||||
* fixed trans tag when no vars are used in plural form |
||||
* fixed race condition when writing template cache |
||||
* added the special _charset variable to reference the current charset |
||||
* added the special _context variable to reference the current context |
||||
* renamed self to _self (to avoid conflict) |
||||
* fixed Twig_Template::getAttribute() for protected properties |
||||
|
||||
* 0.9.8 (2010-06-28) |
||||
|
||||
Backward incompatibilities: |
||||
* the trans tag plural count is now attached to the plural tag: |
||||
old: `{% trans count %}...{% plural %}...{% endtrans %}` |
||||
new: `{% trans %}...{% plural count %}...{% endtrans %}` |
||||
|
||||
* added a way to translate strings coming from a variable ({% trans var %}) |
||||
* fixed trans tag when used with the Escaper extension |
||||
* fixed default cache umask |
||||
* removed Twig_Template instances from the debug tag output |
||||
* fixed objects with __isset() defined |
||||
* fixed set tag when used with a capture |
||||
* fixed type hinting for Twig_Environment::addFilter() method |
||||
|
||||
* 0.9.7 (2010-06-12) |
||||
|
||||
Backward incompatibilities: |
||||
* changed 'as' to '=' for the set tag ({% set title as "Title" %} must now be {% set title = "Title" %}) |
||||
* removed the sandboxed attribute of the include tag (use the new sandbox tag instead) |
||||
* refactored the Node system (if you have custom nodes, you will have to update them to use the new API) |
||||
|
||||
* added self as a special variable that refers to the current template (useful for importing macros from the current template) |
||||
* added Twig_Template instance support to the include tag |
||||
* added support for dynamic and conditional inheritance ({% extends some_var %} and {% extends standalone ? "minimum" : "base" %}) |
||||
* added a grammar sub-framework to ease the creation of custom tags |
||||
* fixed the for tag for large arrays (some loop variables are now only available for arrays and objects that implement the Countable interface) |
||||
* removed the Twig_Resource::resolveMissingFilter() method |
||||
* fixed the filter tag which did not apply filtering to included files |
||||
* added a bunch of unit tests |
||||
* added a bunch of phpdoc |
||||
* added a sandbox tag in the sandbox extension |
||||
* changed the date filter to support any date format supported by DateTime |
||||
* added strict_variable setting to throw an exception when an invalid variable is used in a template (disabled by default) |
||||
* added the lexer, parser, and compiler as arguments to the Twig_Environment constructor |
||||
* changed the cache option to only accepts an explicit path to a cache directory or false |
||||
* added a way to add token parsers, filters, and visitors without creating an extension |
||||
* added three interfaces: Twig_NodeInterface, Twig_TokenParserInterface, and Twig_FilterInterface |
||||
* changed the generated code to match the new coding standards |
||||
* fixed sandbox mode (__toString() method check was not enforced if called implicitly from a simple statement like {{ article }}) |
||||
* added an exception when a child template has a non-empty body (as it is always ignored when rendering) |
||||
|
||||
* 0.9.6 (2010-05-12) |
||||
|
||||
* fixed variables defined outside a loop and for which the value changes in a for loop |
||||
* fixed the test suite for PHP 5.2 and older versions of PHPUnit |
||||
* added support for __call() in expression resolution |
||||
* fixed node visiting for macros (macros are now visited by visitors as any other node) |
||||
* fixed nested block definitions with a parent call (rarely useful but nonetheless supported now) |
||||
* added the cycle filter |
||||
* fixed the Lexer when mbstring.func_overload is used with an mbstring.internal_encoding different from ASCII |
||||
* added a long-syntax for the set tag ({% set foo %}...{% endset %}) |
||||
* unit tests are now powered by PHPUnit |
||||
* added support for gettext via the `i18n` extension |
||||
* fixed twig_capitalize_string_filter() and fixed twig_length_filter() when used with UTF-8 values |
||||
* added a more useful exception if an if tag is not closed properly |
||||
* added support for escaping strategy in the autoescape tag |
||||
* fixed lexer when a template has a big chunk of text between/in a block |
||||
|
||||
* 0.9.5 (2010-01-20) |
||||
|
||||
As for any new release, don't forget to remove all cached templates after |
||||
upgrading. |
||||
|
||||
If you have defined custom filters, you MUST upgrade them for this release. To |
||||
upgrade, replace "array" with "new Twig_Filter_Function", and replace the |
||||
environment constant by the "needs_environment" option: |
||||
|
||||
// before |
||||
'even' => array('twig_is_even_filter', false), |
||||
'escape' => array('twig_escape_filter', true), |
||||
|
||||
// after |
||||
'even' => new Twig_Filter_Function('twig_is_even_filter'), |
||||
'escape' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true)), |
||||
|
||||
If you have created NodeTransformer classes, you will need to upgrade them to |
||||
the new interface (please note that the interface is not yet considered |
||||
stable). |
||||
|
||||
* fixed list nodes that did not extend the Twig_NodeListInterface |
||||
* added the "without loop" option to the for tag (it disables the generation of the loop variable) |
||||
* refactored node transformers to node visitors |
||||
* fixed automatic-escaping for blocks |
||||
* added a way to specify variables to pass to an included template |
||||
* changed the automatic-escaping rules to be more sensible and more configurable in custom filters (the documentation lists all the rules) |
||||
* improved the filter system to allow object methods to be used as filters |
||||
* changed the Array and String loaders to actually make use of the cache mechanism |
||||
* included the default filter function definitions in the extension class files directly (Core, Escaper) |
||||
* added the // operator (like the floor() PHP function) |
||||
* added the .. operator (as a syntactic sugar for the range filter when the step is 1) |
||||
* added the in operator (as a syntactic sugar for the in filter) |
||||
* added the following filters in the Core extension: in, range |
||||
* added support for arrays (same behavior as in PHP, a mix between lists and dictionaries, arrays and hashes) |
||||
* enhanced some error messages to provide better feedback in case of parsing errors |
||||
|
||||
* 0.9.4 (2009-12-02) |
||||
|
||||
If you have custom loaders, you MUST upgrade them for this release: The |
||||
Twig_Loader base class has been removed, and the Twig_LoaderInterface has also |
||||
been changed (see the source code for more information or the documentation). |
||||
|
||||
* added support for DateTime instances for the date filter |
||||
* fixed loop.last when the array only has one item |
||||
* made it possible to insert newlines in tag and variable blocks |
||||
* fixed a bug when a literal '\n' were present in a template text |
||||
* fixed bug when the filename of a template contains */ |
||||
* refactored loaders |
||||
|
||||
* 0.9.3 (2009-11-11) |
||||
|
||||
This release is NOT backward compatible with the previous releases. |
||||
|
||||
The loaders do not take the cache and autoReload arguments anymore. Instead, |
||||
the Twig_Environment class has two new options: cache and auto_reload. |
||||
Upgrading your code means changing this kind of code: |
||||
|
||||
$loader = new Twig_Loader_Filesystem('/path/to/templates', '/path/to/compilation_cache', true); |
||||
$twig = new Twig_Environment($loader); |
||||
|
||||
to something like this: |
||||
|
||||
$loader = new Twig_Loader_Filesystem('/path/to/templates'); |
||||
$twig = new Twig_Environment($loader, array( |
||||
'cache' => '/path/to/compilation_cache', |
||||
'auto_reload' => true, |
||||
)); |
||||
|
||||
* deprecated the "items" filter as it is not needed anymore |
||||
* made cache and auto_reload options of Twig_Environment instead of arguments of Twig_Loader |
||||
* optimized template loading speed |
||||
* removed output when an error occurs in a template and render() is used |
||||
* made major speed improvements for loops (up to 300% on even the smallest loops) |
||||
* added properties as part of the sandbox mode |
||||
* added public properties support (obj.item can now be the item property on the obj object) |
||||
* extended set tag to support expression as value ({% set foo as 'foo' ~ 'bar' %} ) |
||||
* fixed bug when \ was used in HTML |
||||
|
||||
* 0.9.2 (2009-10-29) |
||||
|
||||
* made some speed optimizations |
||||
* changed the cache extension to .php |
||||
* added a js escaping strategy |
||||
* added support for short block tag |
||||
* changed the filter tag to allow chained filters |
||||
* made lexer more flexible as you can now change the default delimiters |
||||
* added set tag |
||||
* changed default directory permission when cache dir does not exist (more secure) |
||||
* added macro support |
||||
* changed filters first optional argument to be a Twig_Environment instance instead of a Twig_Template instance |
||||
* made Twig_Autoloader::autoload() a static method |
||||
* avoid writing template file if an error occurs |
||||
* added $ escaping when outputting raw strings |
||||
* enhanced some error messages to ease debugging |
||||
* fixed empty cache files when the template contains an error |
||||
|
||||
* 0.9.1 (2009-10-14) |
||||
|
||||
* fixed a bug in PHP 5.2.6 |
||||
* fixed numbers with one than one decimal |
||||
* added support for method calls with arguments ({{ foo.bar('a', 43) }}) |
||||
* made small speed optimizations |
||||
* made minor tweaks to allow better extensibility and flexibility |
||||
|
||||
* 0.9.0 (2009-10-12) |
||||
|
||||
* Initial release |
||||
@ -0,0 +1,31 @@ |
||||
Copyright (c) 2009-2014 by the Twig Team. |
||||
|
||||
Some rights reserved. |
||||
|
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are |
||||
met: |
||||
|
||||
* Redistributions of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
|
||||
* Redistributions in binary form must reproduce the above |
||||
copyright notice, this list of conditions and the following |
||||
disclaimer in the documentation and/or other materials provided |
||||
with the distribution. |
||||
|
||||
* The names of the contributors may not be used to endorse or |
||||
promote products derived from this software without specific |
||||
prior written permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
@ -0,0 +1,15 @@ |
||||
Twig, the flexible, fast, and secure template language for PHP |
||||
============================================================== |
||||
|
||||
Twig is a template language for PHP, released under the new BSD license (code |
||||
and documentation). |
||||
|
||||
Twig uses a syntax similar to the Django and Jinja template languages which |
||||
inspired the Twig runtime environment. |
||||
|
||||
More Information |
||||
---------------- |
||||
|
||||
Read the `documentation`_ for more information. |
||||
|
||||
.. _documentation: http://twig.sensiolabs.org/documentation |
||||
@ -0,0 +1,42 @@ |
||||
{ |
||||
"name": "twig/twig", |
||||
"type": "library", |
||||
"description": "Twig, the flexible, fast, and secure template language for PHP", |
||||
"keywords": ["templating"], |
||||
"homepage": "http://twig.sensiolabs.org", |
||||
"license": "BSD-3-Clause", |
||||
"authors": [ |
||||
{ |
||||
"name": "Fabien Potencier", |
||||
"email": "fabien@symfony.com", |
||||
"homepage": "http://fabien.potencier.org", |
||||
"role": "Lead Developer" |
||||
}, |
||||
{ |
||||
"name": "Twig Team", |
||||
"homepage": "https://github.com/fabpot/Twig/graphs/contributors", |
||||
"role": "Contributors" |
||||
}, |
||||
{ |
||||
"name": "Armin Ronacher", |
||||
"email": "armin.ronacher@active-4.com", |
||||
"role": "Project Founder" |
||||
} |
||||
], |
||||
"support": { |
||||
"forum": "https://groups.google.com/forum/#!forum/twig-users" |
||||
}, |
||||
"require": { |
||||
"php": ">=5.2.4" |
||||
}, |
||||
"autoload": { |
||||
"psr-0" : { |
||||
"Twig_" : "lib/" |
||||
} |
||||
}, |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "1.16-dev" |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,30 @@ |
||||
*.sw* |
||||
.deps |
||||
Makefile |
||||
Makefile.fragments |
||||
Makefile.global |
||||
Makefile.objects |
||||
acinclude.m4 |
||||
aclocal.m4 |
||||
build/ |
||||
config.cache |
||||
config.guess |
||||
config.h |
||||
config.h.in |
||||
config.log |
||||
config.nice |
||||
config.status |
||||
config.sub |
||||
configure |
||||
configure.in |
||||
install-sh |
||||
libtool |
||||
ltmain.sh |
||||
missing |
||||
mkinstalldirs |
||||
run-tests.php |
||||
twig.loT |
||||
.libs/ |
||||
modules/ |
||||
twig.la |
||||
twig.lo |
||||
@ -0,0 +1,31 @@ |
||||
Copyright (c) 2009-2013 by the Twig Team, see AUTHORS for more details. |
||||
|
||||
Some rights reserved. |
||||
|
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are |
||||
met: |
||||
|
||||
* Redistributions of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
|
||||
* Redistributions in binary form must reproduce the above |
||||
copyright notice, this list of conditions and the following |
||||
disclaimer in the documentation and/or other materials provided |
||||
with the distribution. |
||||
|
||||
* The names of the contributors may not be used to endorse or |
||||
promote products derived from this software without specific |
||||
prior written permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
@ -0,0 +1,8 @@ |
||||
dnl config.m4 for extension twig |
||||
|
||||
PHP_ARG_ENABLE(twig, whether to enable twig support, |
||||
[ --enable-twig Enable twig support]) |
||||
|
||||
if test "$PHP_TWIG" != "no"; then |
||||
PHP_NEW_EXTENSION(twig, twig.c, $ext_shared) |
||||
fi |
||||
@ -0,0 +1,8 @@ |
||||
// vim:ft=javascript |
||||
|
||||
ARG_ENABLE("twig", "Twig support", "no"); |
||||
|
||||
if (PHP_TWIG != "no") { |
||||
AC_DEFINE('HAVE_TWIG', 1); |
||||
EXTENSION('twig', 'twig.c'); |
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
/*
|
||||
+----------------------------------------------------------------------+ |
||||
| Twig Extension | |
||||
+----------------------------------------------------------------------+ |
||||
| Copyright (c) 2011 Derick Rethans | |
||||
+----------------------------------------------------------------------+ |
||||
| Redistribution and use in source and binary forms, with or without | |
||||
| modification, are permitted provided that the conditions mentioned | |
||||
| in the accompanying LICENSE file are met (BSD-3-Clause). | |
||||
+----------------------------------------------------------------------+ |
||||
| Author: Derick Rethans <derick@derickrethans.nl> | |
||||
+----------------------------------------------------------------------+ |
||||
*/ |
||||
|
||||
#ifndef PHP_TWIG_H |
||||
#define PHP_TWIG_H |
||||
|
||||
#define PHP_TWIG_VERSION "1.16.0" |
||||
|
||||
#include "php.h" |
||||
|
||||
extern zend_module_entry twig_module_entry; |
||||
#define phpext_twig_ptr &twig_module_entry |
||||
|
||||
#ifdef ZTS |
||||
#include "TSRM.h" |
||||
#endif |
||||
|
||||
PHP_FUNCTION(twig_template_get_attributes); |
||||
|
||||
#endif |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,248 @@ |
||||
<?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. |
||||
*/ |
||||
|
||||
/** |
||||
* Twig base exception. |
||||
* |
||||
* This exception class and its children must only be used when |
||||
* an error occurs during the loading of a template, when a syntax error |
||||
* is detected in a template, or when rendering a template. Other |
||||
* errors must use regular PHP exception classes (like when the template |
||||
* cache directory is not writable for instance). |
||||
* |
||||
* To help debugging template issues, this class tracks the original template |
||||
* name and line where the error occurred. |
||||
* |
||||
* Whenever possible, you must set these information (original template name |
||||
* and line number) yourself by passing them to the constructor. If some or all |
||||
* these information are not available from where you throw the exception, then |
||||
* this class will guess them automatically (when the line number is set to -1 |
||||
* and/or the filename is set to null). As this is a costly operation, this |
||||
* can be disabled by passing false for both the filename and the line number |
||||
* when creating a new instance of this class. |
||||
* |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
class Twig_Error extends Exception |
||||
{ |
||||
protected $lineno; |
||||
protected $filename; |
||||
protected $rawMessage; |
||||
protected $previous; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* Set both the line number and the filename to false to |
||||
* disable automatic guessing of the original template name |
||||
* and line number. |
||||
* |
||||
* Set the line number to -1 to enable its automatic guessing. |
||||
* Set the filename to null to enable its automatic guessing. |
||||
* |
||||
* By default, automatic guessing is enabled. |
||||
* |
||||
* @param string $message The error message |
||||
* @param int $lineno The template line where the error occurred |
||||
* @param string $filename The template file name where the error occurred |
||||
* @param Exception $previous The previous exception |
||||
*/ |
||||
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null) |
||||
{ |
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) { |
||||
$this->previous = $previous; |
||||
parent::__construct(''); |
||||
} else { |
||||
parent::__construct('', 0, $previous); |
||||
} |
||||
|
||||
$this->lineno = $lineno; |
||||
$this->filename = $filename; |
||||
|
||||
if (-1 === $this->lineno || null === $this->filename) { |
||||
$this->guessTemplateInfo(); |
||||
} |
||||
|
||||
$this->rawMessage = $message; |
||||
|
||||
$this->updateRepr(); |
||||
} |
||||
|
||||
/** |
||||
* Gets the raw message. |
||||
* |
||||
* @return string The raw message |
||||
*/ |
||||
public function getRawMessage() |
||||
{ |
||||
return $this->rawMessage; |
||||
} |
||||
|
||||
/** |
||||
* Gets the filename where the error occurred. |
||||
* |
||||
* @return string The filename |
||||
*/ |
||||
public function getTemplateFile() |
||||
{ |
||||
return $this->filename; |
||||
} |
||||
|
||||
/** |
||||
* Sets the filename where the error occurred. |
||||
* |
||||
* @param string $filename The filename |
||||
*/ |
||||
public function setTemplateFile($filename) |
||||
{ |
||||
$this->filename = $filename; |
||||
|
||||
$this->updateRepr(); |
||||
} |
||||
|
||||
/** |
||||
* Gets the template line where the error occurred. |
||||
* |
||||
* @return int The template line |
||||
*/ |
||||
public function getTemplateLine() |
||||
{ |
||||
return $this->lineno; |
||||
} |
||||
|
||||
/** |
||||
* Sets the template line where the error occurred. |
||||
* |
||||
* @param int $lineno The template line |
||||
*/ |
||||
public function setTemplateLine($lineno) |
||||
{ |
||||
$this->lineno = $lineno; |
||||
|
||||
$this->updateRepr(); |
||||
} |
||||
|
||||
public function guess() |
||||
{ |
||||
$this->guessTemplateInfo(); |
||||
$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)); |
||||
} |
||||
|
||||
protected function updateRepr() |
||||
{ |
||||
$this->message = $this->rawMessage; |
||||
|
||||
$dot = false; |
||||
if ('.' === substr($this->message, -1)) { |
||||
$this->message = substr($this->message, 0, -1); |
||||
$dot = true; |
||||
} |
||||
|
||||
if ($this->filename) { |
||||
if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) { |
||||
$filename = sprintf('"%s"', $this->filename); |
||||
} else { |
||||
$filename = json_encode($this->filename); |
||||
} |
||||
$this->message .= sprintf(' in %s', $filename); |
||||
} |
||||
|
||||
if ($this->lineno && $this->lineno >= 0) { |
||||
$this->message .= sprintf(' at line %d', $this->lineno); |
||||
} |
||||
|
||||
if ($dot) { |
||||
$this->message .= '.'; |
||||
} |
||||
} |
||||
|
||||
protected function guessTemplateInfo() |
||||
{ |
||||
$template = null; |
||||
$templateClass = null; |
||||
|
||||
if (version_compare(phpversion(), '5.3.6', '>=')) { |
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT); |
||||
} else { |
||||
$backtrace = debug_backtrace(); |
||||
} |
||||
|
||||
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)) { |
||||
$template = $trace['object']; |
||||
$templateClass = get_class($trace['object']); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// update template filename |
||||
if (null !== $template && null === $this->filename) { |
||||
$this->filename = $template->getTemplateName(); |
||||
} |
||||
|
||||
if (null === $template || $this->lineno > -1) { |
||||
return; |
||||
} |
||||
|
||||
$r = new ReflectionObject($template); |
||||
$file = $r->getFileName(); |
||||
|
||||
// hhvm has a bug where eval'ed files comes out as the current directory |
||||
if (is_dir($file)) { |
||||
$file = ''; |
||||
} |
||||
|
||||
$exceptions = array($e = $this); |
||||
while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) { |
||||
$exceptions[] = $e; |
||||
} |
||||
|
||||
while ($e = array_pop($exceptions)) { |
||||
$traces = $e->getTrace(); |
||||
while ($trace = array_shift($traces)) { |
||||
if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) { |
||||
continue; |
||||
} |
||||
|
||||
foreach ($template->getDebugInfo() as $codeLine => $templateLine) { |
||||
if ($codeLine <= $trace['line']) { |
||||
// update template line |
||||
$this->lineno = $templateLine; |
||||
|
||||
return; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2010 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Exception thrown when an error occurs during template loading. |
||||
* |
||||
* Automatic template information guessing is always turned off as |
||||
* if a template cannot be loaded, there is nothing to guess. |
||||
* However, when a template is loaded from another one, then, we need |
||||
* to find the current context and this is automatically done by |
||||
* Twig_Template::displayWithErrorHandling(). |
||||
* |
||||
* This strategy makes Twig_Environment::resolveTemplate() much faster. |
||||
* |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
class Twig_Error_Loader extends Twig_Error |
||||
{ |
||||
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null) |
||||
{ |
||||
parent::__construct($message, false, false, $previous); |
||||
} |
||||
} |
||||
@ -0,0 +1,29 @@ |
||||
<?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. |
||||
*/ |
||||
|
||||
/** |
||||
* Adds an exists() method for loaders. |
||||
* |
||||
* @author Florin Patan <florinpatan@gmail.com> |
||||
* |
||||
* @deprecated since 1.12 (to be removed in 3.0) |
||||
*/ |
||||
interface Twig_ExistsLoaderInterface |
||||
{ |
||||
/** |
||||
* 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); |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,107 @@ |
||||
<?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. |
||||
*/ |
||||
class Twig_Extension_Escaper extends Twig_Extension |
||||
{ |
||||
protected $defaultStrategy; |
||||
|
||||
public function __construct($defaultStrategy = 'html') |
||||
{ |
||||
$this->setDefaultStrategy($defaultStrategy); |
||||
} |
||||
|
||||
/** |
||||
* Returns the token parser instances to add to the existing list. |
||||
* |
||||
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances |
||||
*/ |
||||
public function getTokenParsers() |
||||
{ |
||||
return array(new Twig_TokenParser_AutoEscape()); |
||||
} |
||||
|
||||
/** |
||||
* Returns the node visitor instances to add to the existing list. |
||||
* |
||||
* @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances |
||||
*/ |
||||
public function getNodeVisitors() |
||||
{ |
||||
return array(new Twig_NodeVisitor_Escaper()); |
||||
} |
||||
|
||||
/** |
||||
* Returns a list of filters to add to the existing list. |
||||
* |
||||
* @return array An array of filters |
||||
*/ |
||||
public function getFilters() |
||||
{ |
||||
return array( |
||||
new Twig_SimpleFilter('raw', 'twig_raw_filter', array('is_safe' => array('all'))), |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Sets the default strategy to use when not defined by the user. |
||||
* |
||||
* The strategy can be a valid PHP callback that takes the template |
||||
* "filename" as an argument and returns the strategy to use. |
||||
* |
||||
* @param mixed $defaultStrategy An escaping strategy |
||||
*/ |
||||
public function setDefaultStrategy($defaultStrategy) |
||||
{ |
||||
// for BC |
||||
if (true === $defaultStrategy) { |
||||
$defaultStrategy = 'html'; |
||||
} |
||||
|
||||
$this->defaultStrategy = $defaultStrategy; |
||||
} |
||||
|
||||
/** |
||||
* Gets the default strategy to use when not defined by the user. |
||||
* |
||||
* @param string $filename The template "filename" |
||||
* |
||||
* @return string The default strategy to use for the template |
||||
*/ |
||||
public function getDefaultStrategy($filename) |
||||
{ |
||||
// disable string callables to avoid calling a function named html or js, |
||||
// or any other upcoming escaping strategy |
||||
if (!is_string($this->defaultStrategy) && is_callable($this->defaultStrategy)) { |
||||
return call_user_func($this->defaultStrategy, $filename); |
||||
} |
||||
|
||||
return $this->defaultStrategy; |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of the extension. |
||||
* |
||||
* @return string The extension name |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'escaper'; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Marks a variable as being safe. |
||||
* |
||||
* @param string $string A PHP variable |
||||
*/ |
||||
function twig_raw_filter($string) |
||||
{ |
||||
return $string; |
||||
} |
||||
@ -0,0 +1,113 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2012 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Internal class. |
||||
* |
||||
* This class is used by Twig_Environment as a staging area and must not be used directly. |
||||
* |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
class Twig_Extension_Staging extends Twig_Extension |
||||
{ |
||||
protected $functions = array(); |
||||
protected $filters = array(); |
||||
protected $visitors = array(); |
||||
protected $tokenParsers = array(); |
||||
protected $globals = array(); |
||||
protected $tests = array(); |
||||
|
||||
public function addFunction($name, $function) |
||||
{ |
||||
$this->functions[$name] = $function; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getFunctions() |
||||
{ |
||||
return $this->functions; |
||||
} |
||||
|
||||
public function addFilter($name, $filter) |
||||
{ |
||||
$this->filters[$name] = $filter; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getFilters() |
||||
{ |
||||
return $this->filters; |
||||
} |
||||
|
||||
public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) |
||||
{ |
||||
$this->visitors[] = $visitor; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getNodeVisitors() |
||||
{ |
||||
return $this->visitors; |
||||
} |
||||
|
||||
public function addTokenParser(Twig_TokenParserInterface $parser) |
||||
{ |
||||
$this->tokenParsers[] = $parser; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getTokenParsers() |
||||
{ |
||||
return $this->tokenParsers; |
||||
} |
||||
|
||||
public function addGlobal($name, $value) |
||||
{ |
||||
$this->globals[$name] = $value; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getGlobals() |
||||
{ |
||||
return $this->globals; |
||||
} |
||||
|
||||
public function addTest($name, $test) |
||||
{ |
||||
$this->tests[$name] = $test; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getTests() |
||||
{ |
||||
return $this->tests; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'staging'; |
||||
} |
||||
} |
||||
@ -0,0 +1,64 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2012 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
class Twig_Extension_StringLoader extends Twig_Extension |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getFunctions() |
||||
{ |
||||
return array( |
||||
new Twig_SimpleFunction('template_from_string', 'twig_template_from_string', array('needs_environment' => true)), |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'string_loader'; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Loads a template from a string. |
||||
* |
||||
* <pre> |
||||
* {{ include(template_from_string("Hello {{ name }}")) }} |
||||
* </pre> |
||||
* |
||||
* @param Twig_Environment $env A Twig_Environment instance |
||||
* @param string $template A template as a string |
||||
* |
||||
* @return Twig_Template A Twig_Template instance |
||||
*/ |
||||
function twig_template_from_string(Twig_Environment $env, $template) |
||||
{ |
||||
$name = sprintf('__string_template__%s', hash('sha256', uniqid(mt_rand(), true), false)); |
||||
|
||||
$loader = new Twig_Loader_Chain(array( |
||||
new Twig_Loader_Array(array($name => $template)), |
||||
$current = $env->getLoader(), |
||||
)); |
||||
|
||||
$env->setLoader($loader); |
||||
try { |
||||
$template = $env->loadTemplate($name); |
||||
} catch (Exception $e) { |
||||
$env->setLoader($current); |
||||
|
||||
throw $e; |
||||
} |
||||
$env->setLoader($current); |
||||
|
||||
return $template; |
||||
} |
||||
@ -0,0 +1,23 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2012 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Represents a callable template filter. |
||||
* |
||||
* Use Twig_SimpleFilter instead. |
||||
* |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
* @deprecated since 1.12 (to be removed in 2.0) |
||||
*/ |
||||
interface Twig_FilterCallableInterface |
||||
{ |
||||
public function getCallable(); |
||||
} |
||||
@ -0,0 +1,42 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2010 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Represents a template filter. |
||||
* |
||||
* Use Twig_SimpleFilter instead. |
||||
* |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
* @deprecated since 1.12 (to be removed in 2.0) |
||||
*/ |
||||
interface Twig_FilterInterface |
||||
{ |
||||
/** |
||||
* Compiles a filter. |
||||
* |
||||
* @return string The PHP code for the filter |
||||
*/ |
||||
public function compile(); |
||||
|
||||
public function needsEnvironment(); |
||||
|
||||
public function needsContext(); |
||||
|
||||
public function getSafe(Twig_Node $filterArgs); |
||||
|
||||
public function getPreservesSafety(); |
||||
|
||||
public function getPreEscape(); |
||||
|
||||
public function setArguments($arguments); |
||||
|
||||
public function getArguments(); |
||||
} |
||||
@ -0,0 +1,23 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2012 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Represents a callable template function. |
||||
* |
||||
* Use Twig_SimpleFunction instead. |
||||
* |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
* @deprecated since 1.12 (to be removed in 2.0) |
||||
*/ |
||||
interface Twig_FunctionCallableInterface |
||||
{ |
||||
public function getCallable(); |
||||
} |
||||
@ -0,0 +1,138 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2011 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Loads templates from other loaders. |
||||
* |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface |
||||
{ |
||||
private $hasSourceCache = array(); |
||||
protected $loaders = array(); |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param Twig_LoaderInterface[] $loaders An array of loader instances |
||||
*/ |
||||
public function __construct(array $loaders = array()) |
||||
{ |
||||
foreach ($loaders as $loader) { |
||||
$this->addLoader($loader); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Adds a loader instance. |
||||
* |
||||
* @param Twig_LoaderInterface $loader A Loader instance |
||||
*/ |
||||
public function addLoader(Twig_LoaderInterface $loader) |
||||
{ |
||||
$this->loaders[] = $loader; |
||||
$this->hasSourceCache = array(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getSource($name) |
||||
{ |
||||
$exceptions = array(); |
||||
foreach ($this->loaders as $loader) { |
||||
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { |
||||
continue; |
||||
} |
||||
|
||||
try { |
||||
return $loader->getSource($name); |
||||
} catch (Twig_Error_Loader $e) { |
||||
$exceptions[] = $e->getMessage(); |
||||
} |
||||
} |
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(', ', $exceptions))); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function exists($name) |
||||
{ |
||||
$name = (string) $name; |
||||
|
||||
if (isset($this->hasSourceCache[$name])) { |
||||
return $this->hasSourceCache[$name]; |
||||
} |
||||
|
||||
foreach ($this->loaders as $loader) { |
||||
if ($loader instanceof Twig_ExistsLoaderInterface) { |
||||
if ($loader->exists($name)) { |
||||
return $this->hasSourceCache[$name] = true; |
||||
} |
||||
|
||||
continue; |
||||
} |
||||
|
||||
try { |
||||
$loader->getSource($name); |
||||
|
||||
return $this->hasSourceCache[$name] = true; |
||||
} catch (Twig_Error_Loader $e) { |
||||
} |
||||
} |
||||
|
||||
return $this->hasSourceCache[$name] = false; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getCacheKey($name) |
||||
{ |
||||
$exceptions = array(); |
||||
foreach ($this->loaders as $loader) { |
||||
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { |
||||
continue; |
||||
} |
||||
|
||||
try { |
||||
return $loader->getCacheKey($name); |
||||
} catch (Twig_Error_Loader $e) { |
||||
$exceptions[] = get_class($loader).': '.$e->getMessage(); |
||||
} |
||||
} |
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions))); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function isFresh($name, $time) |
||||
{ |
||||
$exceptions = array(); |
||||
foreach ($this->loaders as $loader) { |
||||
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { |
||||
continue; |
||||
} |
||||
|
||||
try { |
||||
return $loader->isFresh($name, $time); |
||||
} catch (Twig_Error_Loader $e) { |
||||
$exceptions[] = get_class($loader).': '.$e->getMessage(); |
||||
} |
||||
} |
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions))); |
||||
} |
||||
} |
||||
@ -0,0 +1,236 @@ |
||||
<?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. |
||||
*/ |
||||
|
||||
/** |
||||
* Loads template from the filesystem. |
||||
* |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface |
||||
{ |
||||
/** Identifier of the main namespace. */ |
||||
const MAIN_NAMESPACE = '__main__'; |
||||
|
||||
protected $paths = array(); |
||||
protected $cache = array(); |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param string|array $paths A path or an array of paths where to look for templates |
||||
*/ |
||||
public function __construct($paths = array()) |
||||
{ |
||||
if ($paths) { |
||||
$this->setPaths($paths); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the paths to the templates. |
||||
* |
||||
* @param string $namespace A path namespace |
||||
* |
||||
* @return array The array of paths where to look for templates |
||||
*/ |
||||
public function getPaths($namespace = self::MAIN_NAMESPACE) |
||||
{ |
||||
return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the path namespaces. |
||||
* |
||||
* The main namespace is always defined. |
||||
* |
||||
* @return array The array of defined namespaces |
||||
*/ |
||||
public function getNamespaces() |
||||
{ |
||||
return array_keys($this->paths); |
||||
} |
||||
|
||||
/** |
||||
* Sets the paths where templates are stored. |
||||
* |
||||
* @param string|array $paths A path or an array of paths where to look for templates |
||||
* @param string $namespace A path namespace |
||||
*/ |
||||
public function setPaths($paths, $namespace = self::MAIN_NAMESPACE) |
||||
{ |
||||
if (!is_array($paths)) { |
||||
$paths = array($paths); |
||||
} |
||||
|
||||
$this->paths[$namespace] = array(); |
||||
foreach ($paths as $path) { |
||||
$this->addPath($path, $namespace); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Adds a path where templates are stored. |
||||
* |
||||
* @param string $path A path where to look for templates |
||||
* @param string $namespace A path name |
||||
* |
||||
* @throws Twig_Error_Loader |
||||
*/ |
||||
public function addPath($path, $namespace = self::MAIN_NAMESPACE) |
||||
{ |
||||
// invalidate the cache |
||||
$this->cache = array(); |
||||
|
||||
if (!is_dir($path)) { |
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path)); |
||||
} |
||||
|
||||
$this->paths[$namespace][] = rtrim($path, '/\\'); |
||||
} |
||||
|
||||
/** |
||||
* Prepends a path where templates are stored. |
||||
* |
||||
* @param string $path A path where to look for templates |
||||
* @param string $namespace A path name |
||||
* |
||||
* @throws Twig_Error_Loader |
||||
*/ |
||||
public function prependPath($path, $namespace = self::MAIN_NAMESPACE) |
||||
{ |
||||
// invalidate the cache |
||||
$this->cache = array(); |
||||
|
||||
if (!is_dir($path)) { |
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path)); |
||||
} |
||||
|
||||
$path = rtrim($path, '/\\'); |
||||
|
||||
if (!isset($this->paths[$namespace])) { |
||||
$this->paths[$namespace][] = $path; |
||||
} else { |
||||
array_unshift($this->paths[$namespace], $path); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getSource($name) |
||||
{ |
||||
return file_get_contents($this->findTemplate($name)); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getCacheKey($name) |
||||
{ |
||||
return $this->findTemplate($name); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function exists($name) |
||||
{ |
||||
$name = $this->normalizeName($name); |
||||
|
||||
if (isset($this->cache[$name])) { |
||||
return true; |
||||
} |
||||
|
||||
try { |
||||
$this->findTemplate($name); |
||||
|
||||
return true; |
||||
} catch (Twig_Error_Loader $exception) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function isFresh($name, $time) |
||||
{ |
||||
return filemtime($this->findTemplate($name)) <= $time; |
||||
} |
||||
|
||||
protected function findTemplate($name) |
||||
{ |
||||
$name = $this->normalizeName($name); |
||||
|
||||
if (isset($this->cache[$name])) { |
||||
return $this->cache[$name]; |
||||
} |
||||
|
||||
$this->validateName($name); |
||||
|
||||
list($namespace, $shortname) = $this->parseName($name); |
||||
|
||||
if (!isset($this->paths[$namespace])) { |
||||
throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace)); |
||||
} |
||||
|
||||
foreach ($this->paths[$namespace] as $path) { |
||||
if (is_file($path.'/'.$shortname)) { |
||||
return $this->cache[$name] = $path.'/'.$shortname; |
||||
} |
||||
} |
||||
|
||||
throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace]))); |
||||
} |
||||
|
||||
protected function parseName($name, $default = self::MAIN_NAMESPACE) |
||||
{ |
||||
if (isset($name[0]) && '@' == $name[0]) { |
||||
if (false === $pos = strpos($name, '/')) { |
||||
throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); |
||||
} |
||||
|
||||
$namespace = substr($name, 1, $pos - 1); |
||||
$shortname = substr($name, $pos + 1); |
||||
|
||||
return array($namespace, $shortname); |
||||
} |
||||
|
||||
return array($default, $name); |
||||
} |
||||
|
||||
protected function normalizeName($name) |
||||
{ |
||||
return preg_replace('#/{2,}#', '/', strtr((string) $name, '\\', '/')); |
||||
} |
||||
|
||||
protected function validateName($name) |
||||
{ |
||||
if (false !== strpos($name, "\0")) { |
||||
throw new Twig_Error_Loader('A template name cannot contain NUL bytes.'); |
||||
} |
||||
|
||||
$name = ltrim($name, '/'); |
||||
$parts = explode('/', $name); |
||||
$level = 0; |
||||
foreach ($parts as $part) { |
||||
if ('..' === $part) { |
||||
--$level; |
||||
} elseif ('.' !== $part) { |
||||
++$level; |
||||
} |
||||
|
||||
if ($level < 0) { |
||||
throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,38 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2012 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
/** |
||||
* Represents an embed node. |
||||
* |
||||
* @author Fabien Potencier <fabien@symfony.com> |
||||
*/ |
||||
class Twig_Node_Embed extends Twig_Node_Include |
||||
{ |
||||
// we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module) |
||||
public function __construct($filename, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) |
||||
{ |
||||
parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag); |
||||
|
||||
$this->setAttribute('filename', $filename); |
||||
$this->setAttribute('index', $index); |
||||
} |
||||
|
||||
protected function addGetTemplate(Twig_Compiler $compiler) |
||||
{ |
||||
$compiler |
||||
->write("\$this->env->loadTemplate(") |
||||
->string($this->getAttribute('filename')) |
||||
->raw(', ') |
||||
->string($this->getAttribute('index')) |
||||
->raw(")") |
||||
; |
||||
} |
||||
} |
||||
@ -0,0 +1,30 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2013 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary |
||||
{ |
||||
public function compile(Twig_Compiler $compiler) |
||||
{ |
||||
$compiler |
||||
->raw('(0 === substr_compare(') |
||||
->subcompile($this->getNode('left')) |
||||
->raw(', ') |
||||
->subcompile($this->getNode('right')) |
||||
->raw(', -strlen(') |
||||
->subcompile($this->getNode('right')) |
||||
->raw(')))') |
||||
; |
||||
} |
||||
|
||||
public function operator(Twig_Compiler $compiler) |
||||
{ |
||||
return $compiler->raw(''); |
||||
} |
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of Twig. |
||||
* |
||||
* (c) 2013 Fabien Potencier |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary |
||||
{ |
||||
public function compile(Twig_Compiler $compiler) |
||||
{ |
||||
$compiler |
||||
->raw('preg_match(') |
||||
->subcompile($this->getNode('right')) |
||||
->raw(', ') |
||||
->subcompile($this->getNode('left')) |
||||
->raw(')') |
||||
; |
||||
} |
||||
|
||||
public function operator(Twig_Compiler $compiler) |
||||
{ |
||||
return $compiler->raw(''); |
||||
} |
||||
} |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue