mirror of
https://github.com/vichan-devel/vichan.git
synced 2024-11-12 01:50:48 +01:00
Update Twig. This closes #295
This commit is contained in:
parent
b078ffb1e4
commit
0aa4e3badc
@ -3,37 +3,43 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Autoloader class is deprecated since version 1.21 and will be removed in 2.0. Use Composer instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Autoloads Twig classes.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.21 and will be removed in 2.0. Use Composer instead. 2.0.
|
||||
*/
|
||||
class Twig_Autoloader
|
||||
{
|
||||
/**
|
||||
* Registers Twig_Autoloader as an SPL autoloader.
|
||||
*
|
||||
* @param Boolean $prepend Whether to prepend the autoloader or not.
|
||||
* @param bool $prepend whether to prepend the autoloader or not
|
||||
*/
|
||||
public static function register($prepend = false)
|
||||
{
|
||||
if (version_compare(phpversion(), '5.3.0', '>=')) {
|
||||
spl_autoload_register(array(new self, 'autoload'), true, $prepend);
|
||||
@trigger_error('Using Twig_Autoloader is deprecated since version 1.21. Use Composer instead.', E_USER_DEPRECATED);
|
||||
|
||||
if (PHP_VERSION_ID < 50300) {
|
||||
spl_autoload_register(array(__CLASS__, 'autoload'));
|
||||
} else {
|
||||
spl_autoload_register(array(new self, 'autoload'));
|
||||
spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles autoloading of classes.
|
||||
*
|
||||
* @param string $class A class name.
|
||||
* @param string $class a class name
|
||||
*/
|
||||
public static function autoload($class)
|
||||
{
|
||||
|
54
inc/lib/Twig/BaseNodeVisitor.php
Normal file
54
inc/lib/Twig/BaseNodeVisitor.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Twig_BaseNodeVisitor can be used to make node visitors compatible with Twig 1.x and 2.x.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface
|
||||
{
|
||||
final public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
if (!$node instanceof Twig_Node) {
|
||||
throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.');
|
||||
}
|
||||
|
||||
return $this->doEnterNode($node, $env);
|
||||
}
|
||||
|
||||
final public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
if (!$node instanceof Twig_Node) {
|
||||
throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.');
|
||||
}
|
||||
|
||||
return $this->doLeaveNode($node, $env);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before child nodes are visited.
|
||||
*
|
||||
* @return Twig_Node The modified node
|
||||
*/
|
||||
abstract protected function doEnterNode(Twig_Node $node, Twig_Environment $env);
|
||||
|
||||
/**
|
||||
* Called after child nodes are visited.
|
||||
*
|
||||
* @return Twig_Node|false The modified node or false if the node must be removed
|
||||
*/
|
||||
abstract protected function doLeaveNode(Twig_Node $node, Twig_Environment $env);
|
||||
}
|
||||
|
||||
class_alias('Twig_BaseNodeVisitor', 'Twig\NodeVisitor\AbstractNodeVisitor', false);
|
||||
class_exists('Twig_Environment');
|
||||
class_exists('Twig_Node');
|
93
inc/lib/Twig/Cache/Filesystem.php
Normal file
93
inc/lib/Twig/Cache/Filesystem.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements a cache on the filesystem.
|
||||
*
|
||||
* @author Andrew Tch <andrew@noop.lv>
|
||||
*/
|
||||
class Twig_Cache_Filesystem implements Twig_CacheInterface
|
||||
{
|
||||
const FORCE_BYTECODE_INVALIDATION = 1;
|
||||
|
||||
private $directory;
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @param $directory string The root cache directory
|
||||
* @param $options int A set of options
|
||||
*/
|
||||
public function __construct($directory, $options = 0)
|
||||
{
|
||||
$this->directory = rtrim($directory, '\/').'/';
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
public function generateKey($name, $className)
|
||||
{
|
||||
$hash = hash('sha256', $className);
|
||||
|
||||
return $this->directory.$hash[0].$hash[1].'/'.$hash.'.php';
|
||||
}
|
||||
|
||||
public function load($key)
|
||||
{
|
||||
if (file_exists($key)) {
|
||||
@include_once $key;
|
||||
}
|
||||
}
|
||||
|
||||
public function write($key, $content)
|
||||
{
|
||||
$dir = dirname($key);
|
||||
if (!is_dir($dir)) {
|
||||
if (false === @mkdir($dir, 0777, true)) {
|
||||
if (PHP_VERSION_ID >= 50300) {
|
||||
clearstatcache(true, $dir);
|
||||
}
|
||||
if (!is_dir($dir)) {
|
||||
throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
|
||||
}
|
||||
}
|
||||
} elseif (!is_writable($dir)) {
|
||||
throw new RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir));
|
||||
}
|
||||
|
||||
$tmpFile = tempnam($dir, basename($key));
|
||||
if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $key)) {
|
||||
@chmod($key, 0666 & ~umask());
|
||||
|
||||
if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) {
|
||||
// Compile cached file into bytecode cache
|
||||
if (function_exists('opcache_invalidate')) {
|
||||
opcache_invalidate($key, true);
|
||||
} elseif (function_exists('apc_compile_file')) {
|
||||
apc_compile_file($key);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('Failed to write cache file "%s".', $key));
|
||||
}
|
||||
|
||||
public function getTimestamp($key)
|
||||
{
|
||||
if (!file_exists($key)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) @filemtime($key);
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Cache_Filesystem', 'Twig\Cache\FilesystemCache', false);
|
40
inc/lib/Twig/Cache/Null.php
Normal file
40
inc/lib/Twig/Cache/Null.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements a no-cache strategy.
|
||||
*
|
||||
* @final
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Cache_Null implements Twig_CacheInterface
|
||||
{
|
||||
public function generateKey($name, $className)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function write($key, $content)
|
||||
{
|
||||
}
|
||||
|
||||
public function load($key)
|
||||
{
|
||||
}
|
||||
|
||||
public function getTimestamp($key)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Cache_Null', 'Twig\Cache\NullCache', false);
|
58
inc/lib/Twig/CacheInterface.php
Normal file
58
inc/lib/Twig/CacheInterface.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface implemented by cache classes.
|
||||
*
|
||||
* It is highly recommended to always store templates on the filesystem to
|
||||
* benefit from the PHP opcode cache. This interface is mostly useful if you
|
||||
* need to implement a custom strategy for storing templates on the filesystem.
|
||||
*
|
||||
* @author Andrew Tch <andrew@noop.lv>
|
||||
*/
|
||||
interface Twig_CacheInterface
|
||||
{
|
||||
/**
|
||||
* Generates a cache key for the given template class name.
|
||||
*
|
||||
* @param string $name The template name
|
||||
* @param string $className The template class name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateKey($name, $className);
|
||||
|
||||
/**
|
||||
* Writes the compiled template to cache.
|
||||
*
|
||||
* @param string $key The cache key
|
||||
* @param string $content The template representation as a PHP class
|
||||
*/
|
||||
public function write($key, $content);
|
||||
|
||||
/**
|
||||
* Loads a template from the cache.
|
||||
*
|
||||
* @param string $key The cache key
|
||||
*/
|
||||
public function load($key);
|
||||
|
||||
/**
|
||||
* Returns the modification timestamp of a key.
|
||||
*
|
||||
* @param string $key The cache key
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTimestamp($key);
|
||||
}
|
||||
|
||||
class_alias('Twig_CacheInterface', 'Twig\Cache\CacheInterface', false);
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -21,31 +21,31 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
protected $source;
|
||||
protected $indentation;
|
||||
protected $env;
|
||||
protected $debugInfo;
|
||||
protected $debugInfo = array();
|
||||
protected $sourceOffset;
|
||||
protected $sourceLine;
|
||||
protected $filename;
|
||||
private $varNameSalt = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Twig_Environment $env The twig environment instance
|
||||
*/
|
||||
public function __construct(Twig_Environment $env)
|
||||
{
|
||||
$this->env = $env;
|
||||
$this->debugInfo = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.25 (to be removed in 2.0)
|
||||
*/
|
||||
public function getFilename()
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
|
||||
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the environment instance related to this compiler.
|
||||
*
|
||||
* @return Twig_Environment The environment instance
|
||||
* @return Twig_Environment
|
||||
*/
|
||||
public function getEnvironment()
|
||||
{
|
||||
@ -66,21 +66,24 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
* Compiles a node.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to compile
|
||||
* @param integer $indentation The current indentation
|
||||
* @param int $indentation The current indentation
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
* @return $this
|
||||
*/
|
||||
public function compile(Twig_NodeInterface $node, $indentation = 0)
|
||||
{
|
||||
$this->lastLine = null;
|
||||
$this->source = '';
|
||||
$this->debugInfo = array();
|
||||
$this->sourceOffset = 0;
|
||||
// source code starts at 1 (as we then increment it when we encounter new lines)
|
||||
$this->sourceLine = 1;
|
||||
$this->indentation = $indentation;
|
||||
$this->varNameSalt = 0;
|
||||
|
||||
if ($node instanceof Twig_Node_Module) {
|
||||
$this->filename = $node->getAttribute('filename');
|
||||
// to be removed in 2.0
|
||||
$this->filename = $node->getTemplateName();
|
||||
}
|
||||
|
||||
$node->compile($this);
|
||||
@ -91,7 +94,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
public function subcompile(Twig_NodeInterface $node, $raw = true)
|
||||
{
|
||||
if (false === $raw) {
|
||||
$this->addIndentation();
|
||||
$this->source .= str_repeat(' ', $this->indentation * 4);
|
||||
}
|
||||
|
||||
$node->compile($this);
|
||||
@ -104,7 +107,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
*
|
||||
* @param string $string The string
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
* @return $this
|
||||
*/
|
||||
public function raw($string)
|
||||
{
|
||||
@ -116,14 +119,13 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
/**
|
||||
* Writes a string to the compiled code by adding indentation.
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
* @return $this
|
||||
*/
|
||||
public function write()
|
||||
{
|
||||
$strings = func_get_args();
|
||||
foreach ($strings as $string) {
|
||||
$this->addIndentation();
|
||||
$this->source .= $string;
|
||||
$this->source .= str_repeat(' ', $this->indentation * 4).$string;
|
||||
}
|
||||
|
||||
return $this;
|
||||
@ -132,10 +134,14 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
/**
|
||||
* Appends an indentation to the current PHP code after compilation.
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated since 1.27 (to be removed in 2.0).
|
||||
*/
|
||||
public function addIndentation()
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use write(\'\') instead.', E_USER_DEPRECATED);
|
||||
|
||||
$this->source .= str_repeat(' ', $this->indentation * 4);
|
||||
|
||||
return $this;
|
||||
@ -146,7 +152,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
*
|
||||
* @param string $value The string
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
* @return $this
|
||||
*/
|
||||
public function string($value)
|
||||
{
|
||||
@ -160,12 +166,12 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
*
|
||||
* @param mixed $value The value to convert
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
* @return $this
|
||||
*/
|
||||
public function repr($value)
|
||||
{
|
||||
if (is_int($value) || is_float($value)) {
|
||||
if (false !== $locale = setlocale(LC_NUMERIC, 0)) {
|
||||
if (false !== $locale = setlocale(LC_NUMERIC, '0')) {
|
||||
setlocale(LC_NUMERIC, 'C');
|
||||
}
|
||||
|
||||
@ -181,14 +187,14 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
} elseif (is_array($value)) {
|
||||
$this->raw('array(');
|
||||
$first = true;
|
||||
foreach ($value as $key => $value) {
|
||||
foreach ($value as $key => $v) {
|
||||
if (!$first) {
|
||||
$this->raw(', ');
|
||||
}
|
||||
$first = false;
|
||||
$this->repr($key);
|
||||
$this->raw(' => ');
|
||||
$this->repr($value);
|
||||
$this->repr($v);
|
||||
}
|
||||
$this->raw(')');
|
||||
} else {
|
||||
@ -201,28 +207,28 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
/**
|
||||
* Adds debugging information.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The related twig node
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
* @return $this
|
||||
*/
|
||||
public function addDebugInfo(Twig_NodeInterface $node)
|
||||
{
|
||||
if ($node->getLine() != $this->lastLine) {
|
||||
$this->write("// line {$node->getLine()}\n");
|
||||
if ($node->getTemplateLine() != $this->lastLine) {
|
||||
$this->write(sprintf("// line %d\n", $node->getTemplateLine()));
|
||||
|
||||
// when mbstring.func_overload is set to 2
|
||||
// mb_substr_count() replaces substr_count()
|
||||
// but they have different signatures!
|
||||
if (((int) ini_get('mbstring.func_overload')) & 2) {
|
||||
@trigger_error('Support for having "mbstring.func_overload" different from 0 is deprecated version 1.29 and will be removed in 2.0.', E_USER_DEPRECATED);
|
||||
|
||||
// this is much slower than the "right" version
|
||||
$this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n");
|
||||
} else {
|
||||
$this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
|
||||
}
|
||||
$this->sourceOffset = strlen($this->source);
|
||||
$this->debugInfo[$this->sourceLine] = $node->getLine();
|
||||
$this->debugInfo[$this->sourceLine] = $node->getTemplateLine();
|
||||
|
||||
$this->lastLine = $node->getLine();
|
||||
$this->lastLine = $node->getTemplateLine();
|
||||
}
|
||||
|
||||
return $this;
|
||||
@ -230,15 +236,17 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
|
||||
public function getDebugInfo()
|
||||
{
|
||||
ksort($this->debugInfo);
|
||||
|
||||
return $this->debugInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indents the generated code.
|
||||
*
|
||||
* @param integer $step The number of indentation to add
|
||||
* @param int $step The number of indentation to add
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
* @return $this
|
||||
*/
|
||||
public function indent($step = 1)
|
||||
{
|
||||
@ -250,19 +258,29 @@ class Twig_Compiler implements Twig_CompilerInterface
|
||||
/**
|
||||
* Outdents the generated code.
|
||||
*
|
||||
* @param integer $step The number of indentation to remove
|
||||
* @param int $step The number of indentation to remove
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws LogicException When trying to outdent too much so the indentation would become negative
|
||||
*/
|
||||
public function outdent($step = 1)
|
||||
{
|
||||
// can't outdent by more steps than the current indentation level
|
||||
if ($this->indentation < $step) {
|
||||
throw new LogicException('Unable to call outdent() as the indentation would become negative');
|
||||
throw new LogicException('Unable to call outdent() as the indentation would become negative.');
|
||||
}
|
||||
|
||||
$this->indentation -= $step;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVarName()
|
||||
{
|
||||
return sprintf('__internal_%s', hash('sha256', __METHOD__.$this->varNameSalt++));
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Compiler', 'Twig\Compiler', false);
|
||||
class_exists('Twig_Node');
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -13,16 +13,15 @@
|
||||
* Interface implemented by compiler classes.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 3.0)
|
||||
*/
|
||||
interface Twig_CompilerInterface
|
||||
{
|
||||
/**
|
||||
* Compiles a node.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to compile
|
||||
*
|
||||
* @return Twig_CompilerInterface The current compiler instance
|
||||
* @return $this
|
||||
*/
|
||||
public function compile(Twig_NodeInterface $node);
|
||||
|
||||
|
39
inc/lib/Twig/ContainerRuntimeLoader.php
Normal file
39
inc/lib/Twig/ContainerRuntimeLoader.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Lazily loads Twig runtime implementations from a PSR-11 container.
|
||||
*
|
||||
* Note that the runtime services MUST use their class names as identifiers.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
*/
|
||||
class Twig_ContainerRuntimeLoader implements Twig_RuntimeLoaderInterface
|
||||
{
|
||||
private $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function load($class)
|
||||
{
|
||||
if ($this->container->has($class)) {
|
||||
return $this->container->get($class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_ContainerRuntimeLoader', 'Twig\RuntimeLoader\ContainerRuntimeLoader', false);
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -25,8 +25,8 @@
|
||||
* 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
|
||||
* and/or the name is set to null). As this is a costly operation, this
|
||||
* can be disabled by passing false for both the name and the line number
|
||||
* when creating a new instance of this class.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
@ -34,30 +34,44 @@
|
||||
class Twig_Error extends Exception
|
||||
{
|
||||
protected $lineno;
|
||||
// to be renamed to name in 2.0
|
||||
protected $filename;
|
||||
protected $rawMessage;
|
||||
protected $previous;
|
||||
|
||||
private $sourcePath;
|
||||
private $sourceCode;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Set both the line number and the filename to false to
|
||||
* Set both the line number and the name 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.
|
||||
* Set the name to null to enable its automatic guessing.
|
||||
*
|
||||
* By default, automatic guessing is enabled.
|
||||
*
|
||||
* @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
|
||||
* @param string $message The error message
|
||||
* @param int $lineno The template line where the error occurred
|
||||
* @param Twig_Source|string|null $source The source context where the error occurred
|
||||
* @param Exception $previous The previous exception
|
||||
*/
|
||||
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
|
||||
public function __construct($message, $lineno = -1, $source = null, Exception $previous = null)
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
if (null === $source) {
|
||||
$name = null;
|
||||
} elseif (!$source instanceof Twig_Source) {
|
||||
// for compat with the Twig C ext., passing the template name as string is accepted
|
||||
$name = $source;
|
||||
} else {
|
||||
$name = $source->getName();
|
||||
$this->sourceCode = $source->getCode();
|
||||
$this->sourcePath = $source->getPath();
|
||||
}
|
||||
if (PHP_VERSION_ID < 50300) {
|
||||
$this->previous = $previous;
|
||||
parent::__construct('');
|
||||
} else {
|
||||
@ -65,9 +79,9 @@ class Twig_Error extends Exception
|
||||
}
|
||||
|
||||
$this->lineno = $lineno;
|
||||
$this->filename = $filename;
|
||||
$this->filename = $name;
|
||||
|
||||
if (-1 === $this->lineno || null === $this->filename) {
|
||||
if (-1 === $lineno || null === $name || null === $this->sourcePath) {
|
||||
$this->guessTemplateInfo();
|
||||
}
|
||||
|
||||
@ -87,23 +101,62 @@ class Twig_Error extends Exception
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filename where the error occurred.
|
||||
* Gets the logical name where the error occurred.
|
||||
*
|
||||
* @return string The filename
|
||||
* @return string The name
|
||||
*
|
||||
* @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead.
|
||||
*/
|
||||
public function getTemplateFile()
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filename where the error occurred.
|
||||
* Sets the logical name where the error occurred.
|
||||
*
|
||||
* @param string $filename The filename
|
||||
* @param string $name The name
|
||||
*
|
||||
* @deprecated since 1.27 (to be removed in 2.0). Use setSourceContext() instead.
|
||||
*/
|
||||
public function setTemplateFile($filename)
|
||||
public function setTemplateFile($name)
|
||||
{
|
||||
$this->filename = $filename;
|
||||
@trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->filename = $name;
|
||||
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the logical name where the error occurred.
|
||||
*
|
||||
* @return string The name
|
||||
*
|
||||
* @deprecated since 1.29 (to be removed in 2.0). Use getSourceContext() instead.
|
||||
*/
|
||||
public function getTemplateName()
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logical name where the error occurred.
|
||||
*
|
||||
* @param string $name The name
|
||||
*
|
||||
* @deprecated since 1.29 (to be removed in 2.0). Use setSourceContext() instead.
|
||||
*/
|
||||
public function setTemplateName($name)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->filename = $name;
|
||||
$this->sourceCode = $this->sourcePath = null;
|
||||
|
||||
$this->updateRepr();
|
||||
}
|
||||
@ -111,7 +164,7 @@ class Twig_Error extends Exception
|
||||
/**
|
||||
* Gets the template line where the error occurred.
|
||||
*
|
||||
* @return integer The template line
|
||||
* @return int The template line
|
||||
*/
|
||||
public function getTemplateLine()
|
||||
{
|
||||
@ -121,7 +174,7 @@ class Twig_Error extends Exception
|
||||
/**
|
||||
* Sets the template line where the error occurred.
|
||||
*
|
||||
* @param integer $lineno The template line
|
||||
* @param int $lineno The template line
|
||||
*/
|
||||
public function setTemplateLine($lineno)
|
||||
{
|
||||
@ -130,6 +183,32 @@ class Twig_Error extends Exception
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source context of the Twig template where the error occurred.
|
||||
*
|
||||
* @return Twig_Source|null
|
||||
*/
|
||||
public function getSourceContext()
|
||||
{
|
||||
return $this->filename ? new Twig_Source($this->sourceCode, $this->filename, $this->sourcePath) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source context of the Twig template where the error occurred.
|
||||
*/
|
||||
public function setSourceContext(Twig_Source $source = null)
|
||||
{
|
||||
if (null === $source) {
|
||||
$this->sourceCode = $this->filename = $this->sourcePath = null;
|
||||
} else {
|
||||
$this->sourceCode = $source->getCode();
|
||||
$this->filename = $source->getName();
|
||||
$this->sourcePath = $source->getPath();
|
||||
}
|
||||
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
public function guess()
|
||||
{
|
||||
$this->guessTemplateInfo();
|
||||
@ -155,23 +234,45 @@ class Twig_Error extends Exception
|
||||
throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method));
|
||||
}
|
||||
|
||||
public function appendMessage($rawMessage)
|
||||
{
|
||||
$this->rawMessage .= $rawMessage;
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function updateRepr()
|
||||
{
|
||||
$this->message = $this->rawMessage;
|
||||
|
||||
if ($this->sourcePath && $this->lineno > 0) {
|
||||
$this->file = $this->sourcePath;
|
||||
$this->line = $this->lineno;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$dot = false;
|
||||
if ('.' === substr($this->message, -1)) {
|
||||
$this->message = substr($this->message, 0, -1);
|
||||
$dot = true;
|
||||
}
|
||||
|
||||
$questionMark = false;
|
||||
if ('?' === substr($this->message, -1)) {
|
||||
$this->message = substr($this->message, 0, -1);
|
||||
$questionMark = true;
|
||||
}
|
||||
|
||||
if ($this->filename) {
|
||||
if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
|
||||
$filename = sprintf('"%s"', $this->filename);
|
||||
$name = sprintf('"%s"', $this->filename);
|
||||
} else {
|
||||
$filename = json_encode($this->filename);
|
||||
$name = json_encode($this->filename);
|
||||
}
|
||||
$this->message .= sprintf(' in %s', $filename);
|
||||
$this->message .= sprintf(' in %s', $name);
|
||||
}
|
||||
|
||||
if ($this->lineno && $this->lineno >= 0) {
|
||||
@ -181,14 +282,21 @@ class Twig_Error extends Exception
|
||||
if ($dot) {
|
||||
$this->message .= '.';
|
||||
}
|
||||
|
||||
if ($questionMark) {
|
||||
$this->message .= '?';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function guessTemplateInfo()
|
||||
{
|
||||
$template = null;
|
||||
$templateClass = null;
|
||||
|
||||
if (version_compare(phpversion(), '5.3.6', '>=')) {
|
||||
if (PHP_VERSION_ID >= 50306) {
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
|
||||
} else {
|
||||
$backtrace = debug_backtrace();
|
||||
@ -205,11 +313,18 @@ class Twig_Error extends Exception
|
||||
}
|
||||
}
|
||||
|
||||
// update template filename
|
||||
// update template name
|
||||
if (null !== $template && null === $this->filename) {
|
||||
$this->filename = $template->getTemplateName();
|
||||
}
|
||||
|
||||
// update template path if any
|
||||
if (null !== $template && null === $this->sourcePath) {
|
||||
$src = $template->getSourceContext();
|
||||
$this->sourceCode = $src->getCode();
|
||||
$this->sourcePath = $src->getPath();
|
||||
}
|
||||
|
||||
if (null === $template || $this->lineno > -1) {
|
||||
return;
|
||||
}
|
||||
@ -224,6 +339,8 @@ class Twig_Error extends Exception
|
||||
|
||||
while ($e = array_pop($exceptions)) {
|
||||
$traces = $e->getTrace();
|
||||
array_unshift($traces, array('file' => $e->getFile(), 'line' => $e->getLine()));
|
||||
|
||||
while ($trace = array_shift($traces)) {
|
||||
if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
|
||||
continue;
|
||||
@ -241,3 +358,6 @@ class Twig_Error extends Exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Error', 'Twig\Error\Error', false);
|
||||
class_exists('Twig_Source');
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -24,8 +24,17 @@
|
||||
*/
|
||||
class Twig_Error_Loader extends Twig_Error
|
||||
{
|
||||
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
|
||||
public function __construct($message, $lineno = -1, $source = null, Exception $previous = null)
|
||||
{
|
||||
parent::__construct($message, false, false, $previous);
|
||||
if (PHP_VERSION_ID < 50300) {
|
||||
$this->previous = $previous;
|
||||
Exception::__construct('');
|
||||
} else {
|
||||
Exception::__construct('', 0, $previous);
|
||||
}
|
||||
$this->appendMessage($message);
|
||||
$this->setTemplateLine(false);
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Error_Loader', 'Twig\Error\LoaderError', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -18,3 +18,5 @@
|
||||
class Twig_Error_Runtime extends Twig_Error
|
||||
{
|
||||
}
|
||||
|
||||
class_alias('Twig_Error_Runtime', 'Twig\Error\RuntimeError', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -17,4 +17,39 @@
|
||||
*/
|
||||
class Twig_Error_Syntax extends Twig_Error
|
||||
{
|
||||
/**
|
||||
* Tweaks the error message to include suggestions.
|
||||
*
|
||||
* @param string $name The original name of the item that does not exist
|
||||
* @param array $items An array of possible items
|
||||
*/
|
||||
public function addSuggestions($name, array $items)
|
||||
{
|
||||
if (!$alternatives = self::computeAlternatives($name, $items)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->appendMessage(sprintf(' Did you mean "%s"?', implode('", "', $alternatives)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* To be merged with the addSuggestions() method in 2.0.
|
||||
*/
|
||||
public static function computeAlternatives($name, $items)
|
||||
{
|
||||
$alternatives = array();
|
||||
foreach ($items as $item) {
|
||||
$lev = levenshtein($name, $item);
|
||||
if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
|
||||
$alternatives[$item] = $lev;
|
||||
}
|
||||
}
|
||||
asort($alternatives);
|
||||
|
||||
return array_keys($alternatives);
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Error_Syntax', 'Twig\Error\SyntaxError', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -13,7 +13,8 @@
|
||||
* Adds an exists() method for loaders.
|
||||
*
|
||||
* @author Florin Patan <florinpatan@gmail.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 3.0)
|
||||
*/
|
||||
interface Twig_ExistsLoaderInterface
|
||||
{
|
||||
@ -22,7 +23,9 @@ interface Twig_ExistsLoaderInterface
|
||||
*
|
||||
* @param string $name The name of the template to check if we can load
|
||||
*
|
||||
* @return boolean If the template source code is handled by this loader or not
|
||||
* @return bool If the template source code is handled by this loader or not
|
||||
*/
|
||||
public function exists($name);
|
||||
}
|
||||
|
||||
class_alias('Twig_ExistsLoaderInterface', 'Twig\Loader\ExistsLoaderInterface', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,10 +15,12 @@
|
||||
*
|
||||
* This parser implements a "Precedence climbing" algorithm.
|
||||
*
|
||||
* @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
|
||||
* @see http://en.wikipedia.org/wiki/Operator-precedence_parser
|
||||
* @see https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
|
||||
* @see https://en.wikipedia.org/wiki/Operator-precedence_parser
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class Twig_ExpressionParser
|
||||
{
|
||||
@ -29,11 +31,23 @@ class Twig_ExpressionParser
|
||||
protected $unaryOperators;
|
||||
protected $binaryOperators;
|
||||
|
||||
public function __construct(Twig_Parser $parser, array $unaryOperators, array $binaryOperators)
|
||||
private $env;
|
||||
|
||||
public function __construct(Twig_Parser $parser, $env = null)
|
||||
{
|
||||
$this->parser = $parser;
|
||||
$this->unaryOperators = $unaryOperators;
|
||||
$this->binaryOperators = $binaryOperators;
|
||||
|
||||
if ($env instanceof Twig_Environment) {
|
||||
$this->env = $env;
|
||||
$this->unaryOperators = $env->getUnaryOperators();
|
||||
$this->binaryOperators = $env->getBinaryOperators();
|
||||
} else {
|
||||
@trigger_error('Passing the operators as constructor arguments to '.__METHOD__.' is deprecated since version 1.27. Pass the environment instead.', E_USER_DEPRECATED);
|
||||
|
||||
$this->env = $parser->getEnvironment();
|
||||
$this->unaryOperators = func_get_arg(1);
|
||||
$this->binaryOperators = func_get_arg(2);
|
||||
}
|
||||
}
|
||||
|
||||
public function parseExpression($precedence = 0)
|
||||
@ -44,7 +58,11 @@ class Twig_ExpressionParser
|
||||
$op = $this->binaryOperators[$token->getValue()];
|
||||
$this->parser->getStream()->next();
|
||||
|
||||
if (isset($op['callable'])) {
|
||||
if ('is not' === $token->getValue()) {
|
||||
$expr = $this->parseNotTestExpression($expr);
|
||||
} elseif ('is' === $token->getValue()) {
|
||||
$expr = $this->parseTestExpression($expr);
|
||||
} elseif (isset($op['callable'])) {
|
||||
$expr = call_user_func($op['callable'], $this->parser, $expr);
|
||||
} else {
|
||||
$expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
|
||||
@ -86,18 +104,15 @@ class Twig_ExpressionParser
|
||||
|
||||
protected function parseConditionalExpression($expr)
|
||||
{
|
||||
while ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '?')) {
|
||||
$this->parser->getStream()->next();
|
||||
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||
while ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, '?')) {
|
||||
if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||
$expr2 = $this->parseExpression();
|
||||
if ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||
$this->parser->getStream()->next();
|
||||
if ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||
$expr3 = $this->parseExpression();
|
||||
} else {
|
||||
$expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
} else {
|
||||
$this->parser->getStream()->next();
|
||||
$expr2 = $expr;
|
||||
$expr3 = $this->parseExpression();
|
||||
}
|
||||
@ -161,13 +176,39 @@ class Twig_ExpressionParser
|
||||
$node = $this->parseStringExpression();
|
||||
break;
|
||||
|
||||
case Twig_Token::OPERATOR_TYPE:
|
||||
if (preg_match(Twig_Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) {
|
||||
// in this context, string operators are variable names
|
||||
$this->parser->getStream()->next();
|
||||
$node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
|
||||
break;
|
||||
} elseif (isset($this->unaryOperators[$token->getValue()])) {
|
||||
$class = $this->unaryOperators[$token->getValue()]['class'];
|
||||
|
||||
$ref = new ReflectionClass($class);
|
||||
$negClass = 'Twig_Node_Expression_Unary_Neg';
|
||||
$posClass = 'Twig_Node_Expression_Unary_Pos';
|
||||
if (!(in_array($ref->getName(), array($negClass, $posClass)) || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass))) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
|
||||
}
|
||||
|
||||
$this->parser->getStream()->next();
|
||||
$expr = $this->parsePrimaryExpression();
|
||||
|
||||
$node = new $class($expr, $token->getLine());
|
||||
break;
|
||||
}
|
||||
|
||||
// no break
|
||||
default:
|
||||
if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) {
|
||||
$node = $this->parseArrayExpression();
|
||||
} elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
|
||||
$node = $this->parseHashExpression();
|
||||
} elseif ($token->test(Twig_Token::OPERATOR_TYPE, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
|
||||
} else {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType(), $token->getLine()), $token->getValue()), $token->getLine(), $this->parser->getFilename());
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,12 +223,10 @@ class Twig_ExpressionParser
|
||||
// a string cannot be followed by another string in a single expression
|
||||
$nextCanBeString = true;
|
||||
while (true) {
|
||||
if ($stream->test(Twig_Token::STRING_TYPE) && $nextCanBeString) {
|
||||
$token = $stream->next();
|
||||
if ($nextCanBeString && $token = $stream->nextIf(Twig_Token::STRING_TYPE)) {
|
||||
$nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
|
||||
$nextCanBeString = false;
|
||||
} elseif ($stream->test(Twig_Token::INTERPOLATION_START_TYPE)) {
|
||||
$stream->next();
|
||||
} elseif ($stream->nextIf(Twig_Token::INTERPOLATION_START_TYPE)) {
|
||||
$nodes[] = $this->parseExpression();
|
||||
$stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
|
||||
$nextCanBeString = true;
|
||||
@ -198,7 +237,7 @@ class Twig_ExpressionParser
|
||||
|
||||
$expr = array_shift($nodes);
|
||||
foreach ($nodes as $node) {
|
||||
$expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getLine());
|
||||
$expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getTemplateLine());
|
||||
}
|
||||
|
||||
return $expr;
|
||||
@ -253,15 +292,14 @@ class Twig_ExpressionParser
|
||||
// * a string -- 'a'
|
||||
// * a name, which is equivalent to a string -- a
|
||||
// * an expression, which must be enclosed in parentheses -- (1 + 2)
|
||||
if ($stream->test(Twig_Token::STRING_TYPE) || $stream->test(Twig_Token::NAME_TYPE) || $stream->test(Twig_Token::NUMBER_TYPE)) {
|
||||
$token = $stream->next();
|
||||
if (($token = $stream->nextIf(Twig_Token::STRING_TYPE)) || ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) || $token = $stream->nextIf(Twig_Token::NUMBER_TYPE)) {
|
||||
$key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
|
||||
} elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||
$key = $this->parseExpression();
|
||||
} else {
|
||||
$current = $stream->getCurrent();
|
||||
|
||||
throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType(), $current->getLine()), $current->getValue()), $current->getLine(), $this->parser->getFilename());
|
||||
throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext());
|
||||
}
|
||||
|
||||
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
|
||||
@ -278,7 +316,7 @@ class Twig_ExpressionParser
|
||||
{
|
||||
while (true) {
|
||||
$token = $this->parser->getCurrentToken();
|
||||
if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) {
|
||||
if (Twig_Token::PUNCTUATION_TYPE == $token->getType()) {
|
||||
if ('.' == $token->getValue() || '[' == $token->getValue()) {
|
||||
$node = $this->parseSubscriptExpression($node);
|
||||
} elseif ('|' == $token->getValue()) {
|
||||
@ -298,41 +336,46 @@ class Twig_ExpressionParser
|
||||
{
|
||||
switch ($name) {
|
||||
case 'parent':
|
||||
$args = $this->parseArguments();
|
||||
$this->parseArguments();
|
||||
if (!count($this->parser->getBlockStack())) {
|
||||
throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename());
|
||||
throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext());
|
||||
}
|
||||
|
||||
if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
|
||||
throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line, $this->parser->getFilename());
|
||||
throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext());
|
||||
}
|
||||
|
||||
return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
|
||||
case 'block':
|
||||
return new Twig_Node_Expression_BlockReference($this->parseArguments()->getNode(0), false, $line);
|
||||
$args = $this->parseArguments();
|
||||
if (count($args) < 1) {
|
||||
throw new Twig_Error_Syntax('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext());
|
||||
}
|
||||
|
||||
return new Twig_Node_Expression_BlockReference($args->getNode(0), count($args) > 1 ? $args->getNode(1) : null, $line);
|
||||
case 'attribute':
|
||||
$args = $this->parseArguments();
|
||||
if (count($args) < 2) {
|
||||
throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line, $this->parser->getFilename());
|
||||
throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext());
|
||||
}
|
||||
|
||||
return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_Template::ANY_CALL, $line);
|
||||
return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line);
|
||||
default:
|
||||
$args = $this->parseArguments(true);
|
||||
if (null !== $alias = $this->parser->getImportedSymbol('macro', $name)) {
|
||||
return new Twig_Node_Expression_MacroCall($alias['node'], $alias['name'], $this->createArrayFromArguments($args), $line);
|
||||
}
|
||||
|
||||
try {
|
||||
$class = $this->getFunctionNodeClass($name, $line);
|
||||
} catch (Twig_Error_Syntax $e) {
|
||||
if (!$this->parser->hasMacro($name)) {
|
||||
throw $e;
|
||||
if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
|
||||
$arguments = new Twig_Node_Expression_Array(array(), $line);
|
||||
foreach ($this->parseArguments() as $n) {
|
||||
$arguments->addElement($n);
|
||||
}
|
||||
|
||||
return new Twig_Node_Expression_MacroCall(new Twig_Node_Expression_Name('_self', $line), $name, $this->createArrayFromArguments($args), $line);
|
||||
$node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line);
|
||||
$node->setAttribute('safe', true);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
$args = $this->parseArguments(true);
|
||||
$class = $this->getFunctionNodeClass($name, $line);
|
||||
|
||||
return new $class($name, $args, $line);
|
||||
}
|
||||
}
|
||||
@ -344,33 +387,42 @@ class Twig_ExpressionParser
|
||||
$lineno = $token->getLine();
|
||||
$arguments = new Twig_Node_Expression_Array(array(), $lineno);
|
||||
$type = Twig_Template::ANY_CALL;
|
||||
if ($token->getValue() == '.') {
|
||||
if ('.' == $token->getValue()) {
|
||||
$token = $stream->next();
|
||||
if (
|
||||
$token->getType() == Twig_Token::NAME_TYPE
|
||||
Twig_Token::NAME_TYPE == $token->getType()
|
||||
||
|
||||
$token->getType() == Twig_Token::NUMBER_TYPE
|
||||
Twig_Token::NUMBER_TYPE == $token->getType()
|
||||
||
|
||||
($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
|
||||
(Twig_Token::OPERATOR_TYPE == $token->getType() && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
|
||||
) {
|
||||
$arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);
|
||||
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||
$type = Twig_Template::METHOD_CALL;
|
||||
foreach ($this->parseArguments() as $n) {
|
||||
$arguments->addElement($n);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
|
||||
throw new Twig_Error_Syntax('Expected name or number.', $lineno, $stream->getSourceContext());
|
||||
}
|
||||
|
||||
if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
|
||||
if (!$arg instanceof Twig_Node_Expression_Constant) {
|
||||
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
|
||||
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext());
|
||||
}
|
||||
|
||||
$arguments = $this->createArrayFromArguments($this->parseArguments(true));
|
||||
$name = $arg->getAttribute('value');
|
||||
|
||||
return new Twig_Node_Expression_MacroCall($node, $arg->getAttribute('value'), $arguments, $lineno);
|
||||
}
|
||||
if ($this->parser->isReservedMacroName($name)) {
|
||||
throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext());
|
||||
}
|
||||
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||
$type = Twig_Template::METHOD_CALL;
|
||||
$arguments = $this->createArrayFromArguments($this->parseArguments());
|
||||
$node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno);
|
||||
$node->setAttribute('safe', true);
|
||||
|
||||
return $node;
|
||||
}
|
||||
} else {
|
||||
$type = Twig_Template::ARRAY_CALL;
|
||||
@ -384,9 +436,8 @@ class Twig_ExpressionParser
|
||||
$arg = $this->parseExpression();
|
||||
}
|
||||
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||
if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||
$slice = true;
|
||||
$stream->next();
|
||||
}
|
||||
|
||||
if ($slice) {
|
||||
@ -447,10 +498,12 @@ class Twig_ExpressionParser
|
||||
/**
|
||||
* Parses arguments.
|
||||
*
|
||||
* @param Boolean $namedArguments Whether to allow named arguments or not
|
||||
* @param Boolean $definition Whether we are parsing arguments for a function definition
|
||||
* @param bool $namedArguments Whether to allow named arguments or not
|
||||
* @param bool $definition Whether we are parsing arguments for a function definition
|
||||
*
|
||||
* @return Twig_Node
|
||||
*
|
||||
* @throws Twig_Error_Syntax
|
||||
*/
|
||||
public function parseArguments($namedArguments = false, $definition = false)
|
||||
{
|
||||
@ -471,10 +524,9 @@ class Twig_ExpressionParser
|
||||
}
|
||||
|
||||
$name = null;
|
||||
if ($namedArguments && $stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
|
||||
$token = $stream->next();
|
||||
if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) {
|
||||
if (!$value instanceof Twig_Node_Expression_Name) {
|
||||
throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given', get_class($value)), $token->getLine(), $this->parser->getFilename());
|
||||
throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given.', get_class($value)), $token->getLine(), $stream->getSourceContext());
|
||||
}
|
||||
$name = $value->getAttribute('name');
|
||||
|
||||
@ -482,26 +534,25 @@ class Twig_ExpressionParser
|
||||
$value = $this->parsePrimaryExpression();
|
||||
|
||||
if (!$this->checkConstantExpression($value)) {
|
||||
throw new Twig_Error_Syntax('A default value for an argument must be a constant (a boolean, a string, a number, or an array).', $token->getLine(), $this->parser->getFilename());
|
||||
throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $stream->getSourceContext());
|
||||
}
|
||||
} else {
|
||||
$value = $this->parseExpression();
|
||||
}
|
||||
}
|
||||
|
||||
if ($definition && null === $name) {
|
||||
$name = $value->getAttribute('name');
|
||||
$value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
|
||||
if (null === $name) {
|
||||
$args[] = $value;
|
||||
} else {
|
||||
if ($definition && isset($args[$name])) {
|
||||
throw new Twig_Error_Syntax(sprintf('Arguments cannot contain the same argument name more than once ("%s" is defined twice).', $name), $token->getLine(), $this->parser->getFilename());
|
||||
if ($definition) {
|
||||
if (null === $name) {
|
||||
$name = $value->getAttribute('name');
|
||||
$value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
|
||||
$args[$name] = $value;
|
||||
} else {
|
||||
if (null === $name) {
|
||||
$args[] = $value;
|
||||
} else {
|
||||
$args[$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
|
||||
@ -511,18 +562,19 @@ class Twig_ExpressionParser
|
||||
|
||||
public function parseAssignmentExpression()
|
||||
{
|
||||
$stream = $this->parser->getStream();
|
||||
$targets = array();
|
||||
while (true) {
|
||||
$token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to');
|
||||
if (in_array($token->getValue(), array('true', 'false', 'none'))) {
|
||||
throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine(), $this->parser->getFilename());
|
||||
$token = $stream->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to');
|
||||
$value = $token->getValue();
|
||||
if (in_array(strtolower($value), array('true', 'false', 'none', 'null'))) {
|
||||
throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext());
|
||||
}
|
||||
$targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine());
|
||||
$targets[] = new Twig_Node_Expression_AssignName($value, $token->getLine());
|
||||
|
||||
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
|
||||
if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
|
||||
break;
|
||||
}
|
||||
$this->parser->getStream()->next();
|
||||
}
|
||||
|
||||
return new Twig_Node($targets);
|
||||
@ -533,26 +585,104 @@ class Twig_ExpressionParser
|
||||
$targets = array();
|
||||
while (true) {
|
||||
$targets[] = $this->parseExpression();
|
||||
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
|
||||
if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
|
||||
break;
|
||||
}
|
||||
$this->parser->getStream()->next();
|
||||
}
|
||||
|
||||
return new Twig_Node($targets);
|
||||
}
|
||||
|
||||
private function parseNotTestExpression(Twig_NodeInterface $node)
|
||||
{
|
||||
return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
|
||||
private function parseTestExpression(Twig_NodeInterface $node)
|
||||
{
|
||||
$stream = $this->parser->getStream();
|
||||
list($name, $test) = $this->getTest($node->getTemplateLine());
|
||||
|
||||
$class = $this->getTestNodeClass($test);
|
||||
$arguments = null;
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||
$arguments = $this->parser->getExpressionParser()->parseArguments(true);
|
||||
}
|
||||
|
||||
return new $class($node, $name, $arguments, $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
|
||||
private function getTest($line)
|
||||
{
|
||||
$stream = $this->parser->getStream();
|
||||
$name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
|
||||
|
||||
if ($test = $this->env->getTest($name)) {
|
||||
return array($name, $test);
|
||||
}
|
||||
|
||||
if ($stream->test(Twig_Token::NAME_TYPE)) {
|
||||
// try 2-words tests
|
||||
$name = $name.' '.$this->parser->getCurrentToken()->getValue();
|
||||
|
||||
if ($test = $this->env->getTest($name)) {
|
||||
$stream->next();
|
||||
|
||||
return array($name, $test);
|
||||
}
|
||||
}
|
||||
|
||||
$e = new Twig_Error_Syntax(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext());
|
||||
$e->addSuggestions($name, array_keys($this->env->getTests()));
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
private function getTestNodeClass($test)
|
||||
{
|
||||
if ($test instanceof Twig_SimpleTest && $test->isDeprecated()) {
|
||||
$stream = $this->parser->getStream();
|
||||
$message = sprintf('Twig Test "%s" is deprecated', $test->getName());
|
||||
if (!is_bool($test->getDeprecatedVersion())) {
|
||||
$message .= sprintf(' since version %s', $test->getDeprecatedVersion());
|
||||
}
|
||||
if ($test->getAlternative()) {
|
||||
$message .= sprintf('. Use "%s" instead', $test->getAlternative());
|
||||
}
|
||||
$src = $stream->getSourceContext();
|
||||
$message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $stream->getCurrent()->getLine());
|
||||
|
||||
@trigger_error($message, E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ($test instanceof Twig_SimpleTest) {
|
||||
return $test->getNodeClass();
|
||||
}
|
||||
|
||||
return $test instanceof Twig_Test_Node ? $test->getClass() : 'Twig_Node_Expression_Test';
|
||||
}
|
||||
|
||||
protected function getFunctionNodeClass($name, $line)
|
||||
{
|
||||
$env = $this->parser->getEnvironment();
|
||||
if (false === $function = $this->env->getFunction($name)) {
|
||||
$e = new Twig_Error_Syntax(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext());
|
||||
$e->addSuggestions($name, array_keys($this->env->getFunctions()));
|
||||
|
||||
if (false === $function = $env->getFunction($name)) {
|
||||
$message = sprintf('The function "%s" does not exist', $name);
|
||||
if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFunctions()))) {
|
||||
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) {
|
||||
$message = sprintf('Twig Function "%s" is deprecated', $function->getName());
|
||||
if (!is_bool($function->getDeprecatedVersion())) {
|
||||
$message .= sprintf(' since version %s', $function->getDeprecatedVersion());
|
||||
}
|
||||
if ($function->getAlternative()) {
|
||||
$message .= sprintf('. Use "%s" instead', $function->getAlternative());
|
||||
}
|
||||
$src = $this->parser->getStream()->getSourceContext();
|
||||
$message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $line);
|
||||
|
||||
throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
|
||||
@trigger_error($message, E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ($function instanceof Twig_SimpleFunction) {
|
||||
@ -564,15 +694,25 @@ class Twig_ExpressionParser
|
||||
|
||||
protected function getFilterNodeClass($name, $line)
|
||||
{
|
||||
$env = $this->parser->getEnvironment();
|
||||
if (false === $filter = $this->env->getFilter($name)) {
|
||||
$e = new Twig_Error_Syntax(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext());
|
||||
$e->addSuggestions($name, array_keys($this->env->getFilters()));
|
||||
|
||||
if (false === $filter = $env->getFilter($name)) {
|
||||
$message = sprintf('The filter "%s" does not exist', $name);
|
||||
if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFilters()))) {
|
||||
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) {
|
||||
$message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
|
||||
if (!is_bool($filter->getDeprecatedVersion())) {
|
||||
$message .= sprintf(' since version %s', $filter->getDeprecatedVersion());
|
||||
}
|
||||
if ($filter->getAlternative()) {
|
||||
$message .= sprintf('. Use "%s" instead', $filter->getAlternative());
|
||||
}
|
||||
$src = $this->parser->getStream()->getSourceContext();
|
||||
$message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $line);
|
||||
|
||||
throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
|
||||
@trigger_error($message, E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ($filter instanceof Twig_SimpleFilter) {
|
||||
@ -585,7 +725,9 @@ class Twig_ExpressionParser
|
||||
// checks that the node only contains "constant" elements
|
||||
protected function checkConstantExpression(Twig_NodeInterface $node)
|
||||
{
|
||||
if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array)) {
|
||||
if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array
|
||||
|| $node instanceof Twig_Node_Expression_Unary_Neg || $node instanceof Twig_Node_Expression_Unary_Pos
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -597,15 +739,6 @@ class Twig_ExpressionParser
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function createArrayFromArguments(Twig_Node $arguments, $line = null)
|
||||
{
|
||||
$line = null === $line ? $arguments->getLine() : $line;
|
||||
$array = new Twig_Node_Expression_Array(array(), $line);
|
||||
foreach ($arguments as $key => $value) {
|
||||
$array->addElement($value, new Twig_Node_Expression_Constant($key, $value->getLine()));
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_ExpressionParser', 'Twig\ExpressionParser', false);
|
||||
|
@ -3,91 +3,67 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
abstract class Twig_Extension implements Twig_ExtensionInterface
|
||||
{
|
||||
/**
|
||||
* Initializes the runtime environment.
|
||||
*
|
||||
* This is where you can load some file that contains filter functions for instance.
|
||||
*
|
||||
* @param Twig_Environment $environment The current Twig_Environment instance
|
||||
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
||||
*/
|
||||
public function initRuntime(Twig_Environment $environment)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node visitor instances to add to the existing list.
|
||||
*
|
||||
* @return array An array of Twig_NodeVisitorInterface instances
|
||||
*/
|
||||
public function getNodeVisitors()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of filters to add to the existing list.
|
||||
*
|
||||
* @return array An array of filters
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of tests to add to the existing list.
|
||||
*
|
||||
* @return array An array of tests
|
||||
*/
|
||||
public function getTests()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of functions to add to the existing list.
|
||||
*
|
||||
* @return array An array of functions
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of operators to add to the existing list.
|
||||
*
|
||||
* @return array An array of operators
|
||||
*/
|
||||
public function getOperators()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of global variables to add to the existing list.
|
||||
*
|
||||
* @return array An array of global variables
|
||||
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_GlobalsInterface instead
|
||||
*/
|
||||
public function getGlobals()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.26 (to be removed in 2.0), not used anymore internally
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return get_class($this);
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Extension', 'Twig\Extension\AbstractExtension', false);
|
||||
class_exists('Twig_Environment');
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,18 +3,17 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2011 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class Twig_Extension_Debug extends Twig_Extension
|
||||
{
|
||||
/**
|
||||
* Returns a list of global functions to add to the existing list.
|
||||
*
|
||||
* @return array An array of global functions
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
// dump is safe if var_dump is overridden by xdebug
|
||||
@ -24,7 +23,7 @@ class Twig_Extension_Debug extends Twig_Extension
|
||||
// false means that it was not set (and the default is on) or it explicitly enabled
|
||||
// xdebug.overload_var_dump produces HTML only when html_errors is also enabled
|
||||
&& (false === ini_get('html_errors') || ini_get('html_errors'))
|
||||
|| 'cli' === php_sapi_name()
|
||||
|| 'cli' === PHP_SAPI
|
||||
;
|
||||
|
||||
return array(
|
||||
@ -32,11 +31,6 @@ class Twig_Extension_Debug extends Twig_Extension
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the extension.
|
||||
*
|
||||
* @return string The extension name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'debug';
|
||||
@ -62,10 +56,12 @@ function twig_var_dump(Twig_Environment $env, $context)
|
||||
|
||||
var_dump($vars);
|
||||
} else {
|
||||
for ($i = 2; $i < $count; $i++) {
|
||||
for ($i = 2; $i < $count; ++$i) {
|
||||
var_dump(func_get_arg($i));
|
||||
}
|
||||
}
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
class_alias('Twig_Extension_Debug', 'Twig\Extension\DebugExtension', false);
|
||||
|
@ -3,45 +3,39 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class Twig_Extension_Escaper extends Twig_Extension
|
||||
{
|
||||
protected $defaultStrategy;
|
||||
|
||||
/**
|
||||
* @param string|false|callable $defaultStrategy An escaping strategy
|
||||
*
|
||||
* @see setDefaultStrategy()
|
||||
*/
|
||||
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 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(
|
||||
@ -53,43 +47,50 @@ class Twig_Extension_Escaper extends Twig_Extension
|
||||
* 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.
|
||||
* name as an argument and returns the strategy to use.
|
||||
*
|
||||
* @param mixed $defaultStrategy An escaping strategy
|
||||
* @param string|false|callable $defaultStrategy An escaping strategy
|
||||
*/
|
||||
public function setDefaultStrategy($defaultStrategy)
|
||||
{
|
||||
// for BC
|
||||
if (true === $defaultStrategy) {
|
||||
@trigger_error('Using "true" as the default strategy is deprecated since version 1.21. Use "html" instead.', E_USER_DEPRECATED);
|
||||
|
||||
$defaultStrategy = 'html';
|
||||
}
|
||||
|
||||
if ('filename' === $defaultStrategy) {
|
||||
@trigger_error('Using "filename" as the default strategy is deprecated since version 1.27. Use "name" instead.', E_USER_DEPRECATED);
|
||||
|
||||
$defaultStrategy = 'name';
|
||||
}
|
||||
|
||||
if ('name' === $defaultStrategy) {
|
||||
$defaultStrategy = array('Twig_FileExtensionEscapingStrategy', 'guess');
|
||||
}
|
||||
|
||||
$this->defaultStrategy = $defaultStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default strategy to use when not defined by the user.
|
||||
*
|
||||
* @param string $filename The template "filename"
|
||||
* @param string $name The template name
|
||||
*
|
||||
* @return string The default strategy to use for the template
|
||||
* @return string|false The default strategy to use for the template
|
||||
*/
|
||||
public function getDefaultStrategy($filename)
|
||||
public function getDefaultStrategy($name)
|
||||
{
|
||||
// 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);
|
||||
if (!is_string($this->defaultStrategy) && false !== $this->defaultStrategy) {
|
||||
return call_user_func($this->defaultStrategy, $name);
|
||||
}
|
||||
|
||||
return $this->defaultStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the extension.
|
||||
*
|
||||
* @return string The extension name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'escaper';
|
||||
@ -100,8 +101,12 @@ class Twig_Extension_Escaper extends Twig_Extension
|
||||
* Marks a variable as being safe.
|
||||
*
|
||||
* @param string $string A PHP variable
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function twig_raw_filter($string)
|
||||
{
|
||||
return $string;
|
||||
}
|
||||
|
||||
class_alias('Twig_Extension_Escaper', 'Twig\Extension\EscaperExtension', false);
|
||||
|
24
inc/lib/Twig/Extension/GlobalsInterface.php
Normal file
24
inc/lib/Twig/Extension/GlobalsInterface.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enables usage of the deprecated Twig_Extension::getGlobals() method.
|
||||
*
|
||||
* Explicitly implement this interface if you really need to implement the
|
||||
* deprecated getGlobals() method in your extensions.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface Twig_Extension_GlobalsInterface
|
||||
{
|
||||
}
|
||||
|
||||
class_alias('Twig_Extension_GlobalsInterface', 'Twig\Extension\GlobalsInterface', false);
|
24
inc/lib/Twig/Extension/InitRuntimeInterface.php
Normal file
24
inc/lib/Twig/Extension/InitRuntimeInterface.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enables usage of the deprecated Twig_Extension::initRuntime() method.
|
||||
*
|
||||
* Explicitly implement this interface if you really need to implement the
|
||||
* deprecated initRuntime() method in your extensions.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface Twig_Extension_InitRuntimeInterface
|
||||
{
|
||||
}
|
||||
|
||||
class_alias('Twig_Extension_InitRuntimeInterface', 'Twig\Extension\InitRuntimeInterface', false);
|
@ -3,11 +3,15 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class Twig_Extension_Optimizer extends Twig_Extension
|
||||
{
|
||||
protected $optimizers;
|
||||
@ -17,19 +21,15 @@ class Twig_Extension_Optimizer extends Twig_Extension
|
||||
$this->optimizers = $optimizers;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNodeVisitors()
|
||||
{
|
||||
return array(new Twig_NodeVisitor_Optimizer($this->optimizers));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'optimizer';
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Extension_Optimizer', 'Twig\Extension\OptimizerExtension', false);
|
||||
|
49
inc/lib/Twig/Extension/Profiler.php
Normal file
49
inc/lib/Twig/Extension/Profiler.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Twig_Extension_Profiler extends Twig_Extension
|
||||
{
|
||||
private $actives = array();
|
||||
|
||||
public function __construct(Twig_Profiler_Profile $profile)
|
||||
{
|
||||
$this->actives[] = $profile;
|
||||
}
|
||||
|
||||
public function enter(Twig_Profiler_Profile $profile)
|
||||
{
|
||||
$this->actives[0]->addProfile($profile);
|
||||
array_unshift($this->actives, $profile);
|
||||
}
|
||||
|
||||
public function leave(Twig_Profiler_Profile $profile)
|
||||
{
|
||||
$profile->leave();
|
||||
array_shift($this->actives);
|
||||
|
||||
if (1 === count($this->actives)) {
|
||||
$this->actives[0]->leave();
|
||||
}
|
||||
}
|
||||
|
||||
public function getNodeVisitors()
|
||||
{
|
||||
return array(new Twig_Profiler_NodeVisitor_Profiler(get_class($this)));
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'profiler';
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Extension_Profiler', 'Twig\Extension\ProfilerExtension', false);
|
||||
class_exists('Twig_Profiler_Profile');
|
@ -3,11 +3,15 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class Twig_Extension_Sandbox extends Twig_Extension
|
||||
{
|
||||
protected $sandboxedGlobally;
|
||||
@ -16,25 +20,15 @@ class Twig_Extension_Sandbox extends Twig_Extension
|
||||
|
||||
public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false)
|
||||
{
|
||||
$this->policy = $policy;
|
||||
$this->policy = $policy;
|
||||
$this->sandboxedGlobally = $sandboxed;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_Sandbox());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_Sandbox());
|
||||
@ -93,20 +87,17 @@ class Twig_Extension_Sandbox extends Twig_Extension
|
||||
|
||||
public function ensureToStringAllowed($obj)
|
||||
{
|
||||
if (is_object($obj)) {
|
||||
if ($this->isSandboxed() && is_object($obj)) {
|
||||
$this->policy->checkMethodAllowed($obj, '__toString');
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the extension.
|
||||
*
|
||||
* @return string The extension name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'sandbox';
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Extension_Sandbox', 'Twig\Extension\SandboxExtension', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,6 +15,8 @@
|
||||
* This class is used by Twig_Environment as a staging area and must not be used directly.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class Twig_Extension_Staging extends Twig_Extension
|
||||
{
|
||||
@ -27,12 +29,13 @@ class Twig_Extension_Staging extends Twig_Extension
|
||||
|
||||
public function addFunction($name, $function)
|
||||
{
|
||||
if (isset($this->functions[$name])) {
|
||||
@trigger_error(sprintf('Overriding function "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->functions[$name] = $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return $this->functions;
|
||||
@ -40,12 +43,13 @@ class Twig_Extension_Staging extends Twig_Extension
|
||||
|
||||
public function addFilter($name, $filter)
|
||||
{
|
||||
if (isset($this->filters[$name])) {
|
||||
@trigger_error(sprintf('Overriding filter "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->filters[$name] = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return $this->filters;
|
||||
@ -56,9 +60,6 @@ class Twig_Extension_Staging extends Twig_Extension
|
||||
$this->visitors[] = $visitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNodeVisitors()
|
||||
{
|
||||
return $this->visitors;
|
||||
@ -66,12 +67,13 @@ class Twig_Extension_Staging extends Twig_Extension
|
||||
|
||||
public function addTokenParser(Twig_TokenParserInterface $parser)
|
||||
{
|
||||
$this->tokenParsers[] = $parser;
|
||||
if (isset($this->tokenParsers[$parser->getTag()])) {
|
||||
@trigger_error(sprintf('Overriding tag "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $parser->getTag()), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->tokenParsers[$parser->getTag()] = $parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTokenParsers()
|
||||
{
|
||||
return $this->tokenParsers;
|
||||
@ -82,9 +84,6 @@ class Twig_Extension_Staging extends Twig_Extension
|
||||
$this->globals[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getGlobals()
|
||||
{
|
||||
return $this->globals;
|
||||
@ -92,22 +91,22 @@ class Twig_Extension_Staging extends Twig_Extension
|
||||
|
||||
public function addTest($name, $test)
|
||||
{
|
||||
if (isset($this->tests[$name])) {
|
||||
@trigger_error(sprintf('Overriding test "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->tests[$name] = $test;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTests()
|
||||
{
|
||||
return $this->tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'staging';
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Extension_Staging', 'Twig\Extension\StagingExtension', false);
|
||||
|
@ -3,16 +3,17 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class Twig_Extension_StringLoader extends Twig_Extension
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return array(
|
||||
@ -20,9 +21,6 @@ class Twig_Extension_StringLoader extends Twig_Extension
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'string_loader';
|
||||
@ -37,28 +35,13 @@ class Twig_Extension_StringLoader extends Twig_Extension
|
||||
* </pre>
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param string $template A template as a string
|
||||
* @param string $template A template as a string or object implementing __toString()
|
||||
*
|
||||
* @return Twig_Template A Twig_Template instance
|
||||
* @return Twig_Template
|
||||
*/
|
||||
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;
|
||||
return $env->createTemplate((string) $template);
|
||||
}
|
||||
|
||||
class_alias('Twig_Extension_StringLoader', 'Twig\Extension\StringLoaderExtension', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -21,49 +21,49 @@ interface Twig_ExtensionInterface
|
||||
*
|
||||
* This is where you can load some file that contains filter functions for instance.
|
||||
*
|
||||
* @param Twig_Environment $environment The current Twig_Environment instance
|
||||
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
||||
*/
|
||||
public function initRuntime(Twig_Environment $environment);
|
||||
|
||||
/**
|
||||
* Returns the token parser instances to add to the existing list.
|
||||
*
|
||||
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
|
||||
* @return Twig_TokenParserInterface[]
|
||||
*/
|
||||
public function getTokenParsers();
|
||||
|
||||
/**
|
||||
* Returns the node visitor instances to add to the existing list.
|
||||
*
|
||||
* @return array An array of Twig_NodeVisitorInterface instances
|
||||
* @return Twig_NodeVisitorInterface[]
|
||||
*/
|
||||
public function getNodeVisitors();
|
||||
|
||||
/**
|
||||
* Returns a list of filters to add to the existing list.
|
||||
*
|
||||
* @return array An array of filters
|
||||
* @return Twig_SimpleFilter[]
|
||||
*/
|
||||
public function getFilters();
|
||||
|
||||
/**
|
||||
* Returns a list of tests to add to the existing list.
|
||||
*
|
||||
* @return array An array of tests
|
||||
* @return Twig_SimpleTest[]
|
||||
*/
|
||||
public function getTests();
|
||||
|
||||
/**
|
||||
* Returns a list of functions to add to the existing list.
|
||||
*
|
||||
* @return array An array of functions
|
||||
* @return Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFunctions();
|
||||
|
||||
/**
|
||||
* Returns a list of operators to add to the existing list.
|
||||
*
|
||||
* @return array An array of operators
|
||||
* @return array<array> First array of unary operators, second array of binary operators
|
||||
*/
|
||||
public function getOperators();
|
||||
|
||||
@ -71,6 +71,8 @@ interface Twig_ExtensionInterface
|
||||
* Returns a list of global variables to add to the existing list.
|
||||
*
|
||||
* @return array An array of global variables
|
||||
*
|
||||
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_GlobalsInterface instead
|
||||
*/
|
||||
public function getGlobals();
|
||||
|
||||
@ -78,6 +80,11 @@ interface Twig_ExtensionInterface
|
||||
* Returns the name of the extension.
|
||||
*
|
||||
* @return string The extension name
|
||||
*
|
||||
* @deprecated since 1.26 (to be removed in 2.0), not used anymore internally
|
||||
*/
|
||||
public function getName();
|
||||
}
|
||||
|
||||
class_alias('Twig_ExtensionInterface', 'Twig\Extension\ExtensionInterface', false);
|
||||
class_exists('Twig_Environment');
|
||||
|
39
inc/lib/Twig/FactoryRuntimeLoader.php
Normal file
39
inc/lib/Twig/FactoryRuntimeLoader.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Lazy loads the runtime implementations for a Twig element.
|
||||
*
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
*/
|
||||
class Twig_FactoryRuntimeLoader implements Twig_RuntimeLoaderInterface
|
||||
{
|
||||
private $map;
|
||||
|
||||
/**
|
||||
* @param array $map An array where keys are class names and values factory callables
|
||||
*/
|
||||
public function __construct($map = array())
|
||||
{
|
||||
$this->map = $map;
|
||||
}
|
||||
|
||||
public function load($class)
|
||||
{
|
||||
if (isset($this->map[$class])) {
|
||||
$runtimeFactory = $this->map[$class];
|
||||
|
||||
return $runtimeFactory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_FactoryRuntimeLoader', 'Twig\RuntimeLoader\FactoryRuntimeLoader', false);
|
60
inc/lib/Twig/FileExtensionEscapingStrategy.php
Normal file
60
inc/lib/Twig/FileExtensionEscapingStrategy.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default autoescaping strategy based on file names.
|
||||
*
|
||||
* This strategy sets the HTML as the default autoescaping strategy,
|
||||
* but changes it based on the template name.
|
||||
*
|
||||
* Note that there is no runtime performance impact as the
|
||||
* default autoescaping strategy is set at compilation time.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_FileExtensionEscapingStrategy
|
||||
{
|
||||
/**
|
||||
* Guesses the best autoescaping strategy based on the file name.
|
||||
*
|
||||
* @param string $name The template name
|
||||
*
|
||||
* @return string|false The escaping strategy name to use or false to disable
|
||||
*/
|
||||
public static function guess($name)
|
||||
{
|
||||
if (in_array(substr($name, -1), array('/', '\\'))) {
|
||||
return 'html'; // return html for directories
|
||||
}
|
||||
|
||||
if ('.twig' === substr($name, -5)) {
|
||||
$name = substr($name, 0, -5);
|
||||
}
|
||||
|
||||
$extension = pathinfo($name, PATHINFO_EXTENSION);
|
||||
|
||||
switch ($extension) {
|
||||
case 'js':
|
||||
return 'js';
|
||||
|
||||
case 'css':
|
||||
return 'css';
|
||||
|
||||
case 'txt':
|
||||
return false;
|
||||
|
||||
default:
|
||||
return 'html';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_FileExtensionEscapingStrategy', 'Twig\FileExtensionEscapingStrategy', false);
|
@ -3,18 +3,21 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Filter class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a template filter.
|
||||
*
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
|
||||
@ -26,10 +29,10 @@ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableI
|
||||
{
|
||||
$this->options = array_merge(array(
|
||||
'needs_environment' => false,
|
||||
'needs_context' => false,
|
||||
'pre_escape' => null,
|
||||
'preserves_safety' => null,
|
||||
'callable' => null,
|
||||
'needs_context' => false,
|
||||
'pre_escape' => null,
|
||||
'preserves_safety' => null,
|
||||
'callable' => null,
|
||||
), $options);
|
||||
}
|
||||
|
||||
|
@ -3,18 +3,21 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Filter_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a function template filter.
|
||||
*
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Filter_Function extends Twig_Filter
|
||||
|
@ -3,18 +3,21 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Filter_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a method template filter.
|
||||
*
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Filter_Method extends Twig_Filter
|
||||
@ -34,6 +37,6 @@ class Twig_Filter_Method extends Twig_Filter
|
||||
|
||||
public function compile()
|
||||
{
|
||||
return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
|
||||
return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method);
|
||||
}
|
||||
}
|
||||
|
@ -3,18 +3,21 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2011 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Filter_Node class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a template filter as a node.
|
||||
*
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Filter_Node extends Twig_Filter
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,6 +15,7 @@
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FilterCallableInterface
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,6 +15,7 @@
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FilterInterface
|
||||
|
@ -3,18 +3,21 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a template function.
|
||||
*
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
|
||||
@ -26,8 +29,8 @@ abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCal
|
||||
{
|
||||
$this->options = array_merge(array(
|
||||
'needs_environment' => false,
|
||||
'needs_context' => false,
|
||||
'callable' => null,
|
||||
'needs_context' => false,
|
||||
'callable' => null,
|
||||
), $options);
|
||||
}
|
||||
|
||||
|
@ -3,19 +3,22 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2010 Arnaud Le Blanc
|
||||
* (c) Fabien Potencier
|
||||
* (c) Arnaud Le Blanc
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Function_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a function template function.
|
||||
*
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Function_Function extends Twig_Function
|
||||
|
@ -3,19 +3,22 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2010 Arnaud Le Blanc
|
||||
* (c) Fabien Potencier
|
||||
* (c) Arnaud Le Blanc
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Function_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a method template function.
|
||||
*
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Function_Method extends Twig_Function
|
||||
@ -35,6 +38,6 @@ class Twig_Function_Method extends Twig_Function
|
||||
|
||||
public function compile()
|
||||
{
|
||||
return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
|
||||
return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method);
|
||||
}
|
||||
}
|
||||
|
@ -3,18 +3,21 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2011 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Function_Node class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a template function as a node.
|
||||
*
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Function_Node extends Twig_Function
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,6 +15,7 @@
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FunctionCallableInterface
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) 2010 Arnaud Le Blanc
|
||||
* (c) Fabien Potencier
|
||||
* (c) Arnaud Le Blanc
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,6 +16,7 @@
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FunctionInterface
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -26,6 +26,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
||||
protected $states;
|
||||
protected $brackets;
|
||||
protected $env;
|
||||
// to be renamed to $name in 2.0 (where it is private)
|
||||
protected $filename;
|
||||
protected $options;
|
||||
protected $regexes;
|
||||
@ -33,62 +34,69 @@ class Twig_Lexer implements Twig_LexerInterface
|
||||
protected $positions;
|
||||
protected $currentVarBlockLine;
|
||||
|
||||
const STATE_DATA = 0;
|
||||
const STATE_BLOCK = 1;
|
||||
const STATE_VAR = 2;
|
||||
const STATE_STRING = 3;
|
||||
const STATE_INTERPOLATION = 4;
|
||||
private $source;
|
||||
|
||||
const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A';
|
||||
const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A';
|
||||
const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As';
|
||||
const STATE_DATA = 0;
|
||||
const STATE_BLOCK = 1;
|
||||
const STATE_VAR = 2;
|
||||
const STATE_STRING = 3;
|
||||
const STATE_INTERPOLATION = 4;
|
||||
|
||||
const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A';
|
||||
const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A';
|
||||
const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As';
|
||||
const REGEX_DQ_STRING_DELIM = '/"/A';
|
||||
const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
|
||||
const PUNCTUATION = '()[]{}?:.,|';
|
||||
const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
|
||||
const PUNCTUATION = '()[]{}?:.,|';
|
||||
|
||||
public function __construct(Twig_Environment $env, array $options = array())
|
||||
{
|
||||
$this->env = $env;
|
||||
|
||||
$this->options = array_merge(array(
|
||||
'tag_comment' => array('{#', '#}'),
|
||||
'tag_block' => array('{%', '%}'),
|
||||
'tag_variable' => array('{{', '}}'),
|
||||
'tag_comment' => array('{#', '#}'),
|
||||
'tag_block' => array('{%', '%}'),
|
||||
'tag_variable' => array('{{', '}}'),
|
||||
'whitespace_trim' => '-',
|
||||
'interpolation' => array('#{', '}'),
|
||||
'interpolation' => array('#{', '}'),
|
||||
), $options);
|
||||
|
||||
$this->regexes = array(
|
||||
'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
|
||||
'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
|
||||
'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
|
||||
'operator' => $this->getOperatorRegex(),
|
||||
'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
|
||||
'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
|
||||
'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
|
||||
'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
|
||||
'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
|
||||
'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
|
||||
'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
|
||||
'operator' => $this->getOperatorRegex(),
|
||||
'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
|
||||
'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
|
||||
'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
|
||||
'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
|
||||
'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A',
|
||||
'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A',
|
||||
'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tokenizes a source code.
|
||||
*
|
||||
* @param string $code The source code
|
||||
* @param string $filename A unique identifier for the source code
|
||||
*
|
||||
* @return Twig_TokenStream A token stream instance
|
||||
*/
|
||||
public function tokenize($code, $filename = null)
|
||||
public function tokenize($code, $name = null)
|
||||
{
|
||||
if (!$code instanceof Twig_Source) {
|
||||
@trigger_error(sprintf('Passing a string as the $code argument of %s() is deprecated since version 1.27 and will be removed in 2.0. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
$this->source = new Twig_Source($code, $name);
|
||||
} else {
|
||||
$this->source = $code;
|
||||
}
|
||||
|
||||
if (((int) ini_get('mbstring.func_overload')) & 2) {
|
||||
@trigger_error('Support for having "mbstring.func_overload" different from 0 is deprecated version 1.29 and will be removed in 2.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
|
||||
$mbEncoding = mb_internal_encoding();
|
||||
mb_internal_encoding('ASCII');
|
||||
} else {
|
||||
$mbEncoding = null;
|
||||
}
|
||||
|
||||
$this->code = str_replace(array("\r\n", "\r"), "\n", $code);
|
||||
$this->filename = $filename;
|
||||
$this->code = str_replace(array("\r\n", "\r"), "\n", $this->source->getCode());
|
||||
$this->filename = $this->source->getName();
|
||||
$this->cursor = 0;
|
||||
$this->lineno = 1;
|
||||
$this->end = strlen($this->code);
|
||||
@ -132,14 +140,14 @@ class Twig_Lexer implements Twig_LexerInterface
|
||||
|
||||
if (!empty($this->brackets)) {
|
||||
list($expect, $lineno) = array_pop($this->brackets);
|
||||
throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
|
||||
throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source);
|
||||
}
|
||||
|
||||
if (isset($mbEncoding)) {
|
||||
if ($mbEncoding) {
|
||||
mb_internal_encoding($mbEncoding);
|
||||
}
|
||||
|
||||
return new Twig_TokenStream($this->tokens, $this->filename);
|
||||
return new Twig_TokenStream($this->tokens, $this->source);
|
||||
}
|
||||
|
||||
protected function lexData()
|
||||
@ -227,13 +235,13 @@ class Twig_Lexer implements Twig_LexerInterface
|
||||
$this->moveCursor($match[0]);
|
||||
|
||||
if ($this->cursor >= $this->end) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $this->state === self::STATE_BLOCK ? 'block' : 'variable'), $this->currentVarBlockLine, $this->filename);
|
||||
throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', self::STATE_BLOCK === $this->state ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source);
|
||||
}
|
||||
}
|
||||
|
||||
// operators
|
||||
if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) {
|
||||
$this->pushToken(Twig_Token::OPERATOR_TYPE, $match[0]);
|
||||
$this->pushToken(Twig_Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0]));
|
||||
$this->moveCursor($match[0]);
|
||||
}
|
||||
// names
|
||||
@ -259,12 +267,12 @@ class Twig_Lexer implements Twig_LexerInterface
|
||||
// closing bracket
|
||||
elseif (false !== strpos(')]}', $this->code[$this->cursor])) {
|
||||
if (empty($this->brackets)) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected "%s"', $this->code[$this->cursor]), $this->lineno, $this->filename);
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source);
|
||||
}
|
||||
|
||||
list($expect, $lineno) = array_pop($this->brackets);
|
||||
if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
|
||||
throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,14 +292,18 @@ class Twig_Lexer implements Twig_LexerInterface
|
||||
}
|
||||
// unlexable
|
||||
else {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected character "%s"', $this->code[$this->cursor]), $this->lineno, $this->filename);
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source);
|
||||
}
|
||||
}
|
||||
|
||||
protected function lexRawData($tag)
|
||||
{
|
||||
if ('raw' === $tag) {
|
||||
@trigger_error(sprintf('Twig Tag "raw" is deprecated since version 1.21. Use "verbatim" instead in %s at line %d.', $this->filename, $this->lineno), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block', $tag), $this->lineno, $this->filename);
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block.', $tag), $this->lineno, $this->source);
|
||||
}
|
||||
|
||||
$text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
|
||||
@ -307,7 +319,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
||||
protected function lexComment()
|
||||
{
|
||||
if (!preg_match($this->regexes['lex_comment'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
||||
throw new Twig_Error_Syntax('Unclosed comment', $this->lineno, $this->filename);
|
||||
throw new Twig_Error_Syntax('Unclosed comment.', $this->lineno, $this->source);
|
||||
}
|
||||
|
||||
$this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]);
|
||||
@ -320,20 +332,20 @@ class Twig_Lexer implements Twig_LexerInterface
|
||||
$this->pushToken(Twig_Token::INTERPOLATION_START_TYPE);
|
||||
$this->moveCursor($match[0]);
|
||||
$this->pushState(self::STATE_INTERPOLATION);
|
||||
|
||||
} elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, null, $this->cursor) && strlen($match[0]) > 0) {
|
||||
$this->pushToken(Twig_Token::STRING_TYPE, stripcslashes($match[0]));
|
||||
$this->moveCursor($match[0]);
|
||||
|
||||
} elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
|
||||
|
||||
list($expect, $lineno) = array_pop($this->brackets);
|
||||
if ($this->code[$this->cursor] != '"') {
|
||||
throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
|
||||
if ('"' != $this->code[$this->cursor]) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source);
|
||||
}
|
||||
|
||||
$this->popState();
|
||||
++$this->cursor;
|
||||
} else {
|
||||
// unlexable
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source);
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,10 +394,15 @@ class Twig_Lexer implements Twig_LexerInterface
|
||||
// an operator that ends with a character must be followed by
|
||||
// a whitespace or a parenthesis
|
||||
if (ctype_alpha($operator[$length - 1])) {
|
||||
$regex[] = preg_quote($operator, '/').'(?=[\s()])';
|
||||
$r = preg_quote($operator, '/').'(?=[\s()])';
|
||||
} else {
|
||||
$regex[] = preg_quote($operator, '/');
|
||||
$r = preg_quote($operator, '/');
|
||||
}
|
||||
|
||||
// an operator with a space can be any amount of whitespaces
|
||||
$r = preg_replace('/\s+/', '\s+', $r);
|
||||
|
||||
$regex[] = $r;
|
||||
}
|
||||
|
||||
return '/'.implode('|', $regex).'/A';
|
||||
@ -400,9 +417,11 @@ class Twig_Lexer implements Twig_LexerInterface
|
||||
protected function popState()
|
||||
{
|
||||
if (0 === count($this->states)) {
|
||||
throw new Exception('Cannot pop state without a previous state');
|
||||
throw new Exception('Cannot pop state without a previous state.');
|
||||
}
|
||||
|
||||
$this->state = array_pop($this->states);
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Lexer', 'Twig\Lexer', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -13,17 +13,20 @@
|
||||
* Interface implemented by lexer classes.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 3.0)
|
||||
*/
|
||||
interface Twig_LexerInterface
|
||||
{
|
||||
/**
|
||||
* Tokenizes a source code.
|
||||
*
|
||||
* @param string $code The source code
|
||||
* @param string $filename A unique identifier for the source code
|
||||
* @param string|Twig_Source $code The source code
|
||||
* @param string $name A unique identifier for the source code
|
||||
*
|
||||
* @return Twig_TokenStream A token stream instance
|
||||
* @return Twig_TokenStream
|
||||
*
|
||||
* @throws Twig_Error_Syntax When the code is syntactically wrong
|
||||
*/
|
||||
public function tokenize($code, $filename = null);
|
||||
public function tokenize($code, $name = null);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -17,20 +17,20 @@
|
||||
* source code of the template). If you don't want to see your cache grows out of
|
||||
* control, you need to take care of clearing the old cache file by yourself.
|
||||
*
|
||||
* This loader should only be used for unit testing.
|
||||
*
|
||||
* @final
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
||||
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
||||
{
|
||||
protected $templates = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $templates An array of templates (keys are the names, and values are the source code)
|
||||
*
|
||||
* @see Twig_Loader
|
||||
*/
|
||||
public function __construct(array $templates)
|
||||
public function __construct(array $templates = array())
|
||||
{
|
||||
$this->templates = $templates;
|
||||
}
|
||||
@ -46,11 +46,10 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
||||
$this->templates[(string) $name] = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSource($name)
|
||||
{
|
||||
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
|
||||
|
||||
$name = (string) $name;
|
||||
if (!isset($this->templates[$name])) {
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
||||
@ -59,17 +58,21 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
||||
return $this->templates[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSourceContext($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
if (!isset($this->templates[$name])) {
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
||||
}
|
||||
|
||||
return new Twig_Source($this->templates[$name], $name);
|
||||
}
|
||||
|
||||
public function exists($name)
|
||||
{
|
||||
return isset($this->templates[(string) $name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheKey($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
@ -77,12 +80,9 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
||||
}
|
||||
|
||||
return $this->templates[$name];
|
||||
return $name.':'.$this->templates[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isFresh($name, $time)
|
||||
{
|
||||
$name = (string) $name;
|
||||
@ -93,3 +93,5 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Loader_Array', 'Twig\Loader\ArrayLoader', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2011 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -12,17 +12,17 @@
|
||||
/**
|
||||
* Loads templates from other loaders.
|
||||
*
|
||||
* @final
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
||||
class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
||||
{
|
||||
private $hasSourceCache = array();
|
||||
protected $loaders = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Twig_LoaderInterface[] $loaders An array of loader instances
|
||||
* @param Twig_LoaderInterface[] $loaders
|
||||
*/
|
||||
public function __construct(array $loaders = array())
|
||||
{
|
||||
@ -31,22 +31,16 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
|
||||
|
||||
$exceptions = array();
|
||||
foreach ($this->loaders as $loader) {
|
||||
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
|
||||
@ -60,12 +54,31 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(', ', $exceptions)));
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
||||
}
|
||||
|
||||
public function getSourceContext($name)
|
||||
{
|
||||
$exceptions = array();
|
||||
foreach ($this->loaders as $loader) {
|
||||
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if ($loader instanceof Twig_SourceContextLoaderInterface) {
|
||||
return $loader->getSourceContext($name);
|
||||
}
|
||||
|
||||
return new Twig_Source($loader->getSource($name), $name);
|
||||
} catch (Twig_Error_Loader $e) {
|
||||
$exceptions[] = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
@ -84,7 +97,11 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
||||
}
|
||||
|
||||
try {
|
||||
$loader->getSource($name);
|
||||
if ($loader instanceof Twig_SourceContextLoaderInterface) {
|
||||
$loader->getSourceContext($name);
|
||||
} else {
|
||||
$loader->getSource($name);
|
||||
}
|
||||
|
||||
return $this->hasSourceCache[$name] = true;
|
||||
} catch (Twig_Error_Loader $e) {
|
||||
@ -94,9 +111,6 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
||||
return $this->hasSourceCache[$name] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheKey($name)
|
||||
{
|
||||
$exceptions = array();
|
||||
@ -112,12 +126,9 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isFresh($name, $time)
|
||||
{
|
||||
$exceptions = array();
|
||||
@ -133,6 +144,8 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Loader_Chain', 'Twig\Loader\ChainLoader', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -14,21 +14,28 @@
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
||||
class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
||||
{
|
||||
/** Identifier of the main namespace. */
|
||||
const MAIN_NAMESPACE = '__main__';
|
||||
|
||||
protected $paths = array();
|
||||
protected $cache = array();
|
||||
protected $errorCache = array();
|
||||
|
||||
private $rootPath;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|array $paths A path or an array of paths where to look for templates
|
||||
* @param string|array $paths A path or an array of paths where to look for templates
|
||||
* @param string|null $rootPath The root path common to all relative paths (null for getcwd())
|
||||
*/
|
||||
public function __construct($paths = array())
|
||||
public function __construct($paths = array(), $rootPath = null)
|
||||
{
|
||||
$this->rootPath = (null === $rootPath ? getcwd() : $rootPath).DIRECTORY_SEPARATOR;
|
||||
if (false !== $realPath = realpath($rootPath)) {
|
||||
$this->rootPath = $realPath.DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
if ($paths) {
|
||||
$this->setPaths($paths);
|
||||
}
|
||||
@ -80,17 +87,18 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
||||
* Adds a path where templates are stored.
|
||||
*
|
||||
* @param string $path A path where to look for templates
|
||||
* @param string $namespace A path name
|
||||
* @param string $namespace A path namespace
|
||||
*
|
||||
* @throws Twig_Error_Loader
|
||||
*/
|
||||
public function addPath($path, $namespace = self::MAIN_NAMESPACE)
|
||||
{
|
||||
// invalidate the cache
|
||||
$this->cache = array();
|
||||
$this->cache = $this->errorCache = array();
|
||||
|
||||
if (!is_dir($path)) {
|
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
|
||||
$checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
|
||||
if (!is_dir($checkPath)) {
|
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
|
||||
}
|
||||
|
||||
$this->paths[$namespace][] = rtrim($path, '/\\');
|
||||
@ -100,17 +108,18 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
||||
* Prepends a path where templates are stored.
|
||||
*
|
||||
* @param string $path A path where to look for templates
|
||||
* @param string $namespace A path name
|
||||
* @param string $namespace A path namespace
|
||||
*
|
||||
* @throws Twig_Error_Loader
|
||||
*/
|
||||
public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
|
||||
{
|
||||
// invalidate the cache
|
||||
$this->cache = array();
|
||||
$this->cache = $this->errorCache = array();
|
||||
|
||||
if (!is_dir($path)) {
|
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
|
||||
$checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
|
||||
if (!is_dir($checkPath)) {
|
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
|
||||
}
|
||||
|
||||
$path = rtrim($path, '/\\');
|
||||
@ -122,64 +131,109 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSource($name)
|
||||
{
|
||||
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
|
||||
|
||||
return file_get_contents($this->findTemplate($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheKey($name)
|
||||
public function getSourceContext($name)
|
||||
{
|
||||
return $this->findTemplate($name);
|
||||
$path = $this->findTemplate($name);
|
||||
|
||||
return new Twig_Source(file_get_contents($path), $name, $path);
|
||||
}
|
||||
|
||||
public function getCacheKey($name)
|
||||
{
|
||||
$path = $this->findTemplate($name);
|
||||
$len = strlen($this->rootPath);
|
||||
if (0 === strncmp($this->rootPath, $path, $len)) {
|
||||
return substr($path, $len);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
$name = $this->normalizeName($name);
|
||||
|
||||
if (isset($this->cache[$name])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->findTemplate($name);
|
||||
|
||||
return true;
|
||||
return false !== $this->findTemplate($name, false);
|
||||
} catch (Twig_Error_Loader $exception) {
|
||||
@trigger_error(sprintf('In %s::findTemplate(), you must accept a second argument that when set to "false" returns "false" instead of throwing an exception. Not supporting this argument is deprecated since version 1.27.', get_class($this)), E_USER_DEPRECATED);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isFresh($name, $time)
|
||||
{
|
||||
return filemtime($this->findTemplate($name)) <= $time;
|
||||
return filemtime($this->findTemplate($name)) < $time;
|
||||
}
|
||||
|
||||
protected function findTemplate($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
|
||||
// normalize name
|
||||
$name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/'));
|
||||
$throw = func_num_args() > 1 ? func_get_arg(1) : true;
|
||||
$name = $this->normalizeName($name);
|
||||
|
||||
if (isset($this->cache[$name])) {
|
||||
return $this->cache[$name];
|
||||
}
|
||||
|
||||
if (isset($this->errorCache[$name])) {
|
||||
if (!$throw) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader($this->errorCache[$name]);
|
||||
}
|
||||
|
||||
$this->validateName($name);
|
||||
|
||||
$namespace = self::MAIN_NAMESPACE;
|
||||
$shortname = $name;
|
||||
list($namespace, $shortname) = $this->parseName($name);
|
||||
|
||||
if (!isset($this->paths[$namespace])) {
|
||||
$this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace);
|
||||
|
||||
if (!$throw) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader($this->errorCache[$name]);
|
||||
}
|
||||
|
||||
foreach ($this->paths[$namespace] as $path) {
|
||||
if (!$this->isAbsolutePath($path)) {
|
||||
$path = $this->rootPath.'/'.$path;
|
||||
}
|
||||
|
||||
if (is_file($path.'/'.$shortname)) {
|
||||
if (false !== $realpath = realpath($path.'/'.$shortname)) {
|
||||
return $this->cache[$name] = $realpath;
|
||||
}
|
||||
|
||||
return $this->cache[$name] = $path.'/'.$shortname;
|
||||
}
|
||||
}
|
||||
|
||||
$this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace]));
|
||||
|
||||
if (!$throw) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader($this->errorCache[$name]);
|
||||
}
|
||||
|
||||
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));
|
||||
@ -187,19 +241,16 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
||||
|
||||
$namespace = substr($name, 1, $pos - 1);
|
||||
$shortname = substr($name, $pos + 1);
|
||||
|
||||
return array($namespace, $shortname);
|
||||
}
|
||||
|
||||
if (!isset($this->paths[$namespace])) {
|
||||
throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace));
|
||||
}
|
||||
return array($default, $name);
|
||||
}
|
||||
|
||||
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 normalizeName($name)
|
||||
{
|
||||
return preg_replace('#/{2,}#', '/', str_replace('\\', '/', (string) $name));
|
||||
}
|
||||
|
||||
protected function validateName($name)
|
||||
@ -223,4 +274,17 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isAbsolutePath($file)
|
||||
{
|
||||
return strspn($file, '/\\', 0, 1)
|
||||
|| (strlen($file) > 3 && ctype_alpha($file[0])
|
||||
&& ':' === substr($file, 1, 1)
|
||||
&& strspn($file, '/\\', 2, 1)
|
||||
)
|
||||
|| null !== parse_url($file, PHP_URL_SCHEME)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Loader_Filesystem', 'Twig\Loader\FilesystemLoader', false);
|
||||
|
@ -3,55 +3,54 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Loader_String class is deprecated since version 1.18.1 and will be removed in 2.0. Use Twig_Loader_Array instead or Twig_Environment::createTemplate().', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Loads a template from a string.
|
||||
*
|
||||
* This loader should only be used for unit testing as it has many limitations
|
||||
* (for instance, the include or extends tag does not make any sense for a string
|
||||
* loader).
|
||||
* This loader should NEVER be used. It only exists for Twig internal purposes.
|
||||
*
|
||||
* When using this loader with a cache mechanism, you should know that a new cache
|
||||
* key is generated each time a template content "changes" (the cache key being the
|
||||
* source code of the template). If you don't want to see your cache grows out of
|
||||
* control, you need to take care of clearing the old cache file by yourself.
|
||||
*
|
||||
* @deprecated since 1.18.1 (to be removed in 2.0)
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
||||
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSource($name)
|
||||
{
|
||||
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSourceContext($name)
|
||||
{
|
||||
return new Twig_Source($name, $name);
|
||||
}
|
||||
|
||||
public function exists($name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheKey($name)
|
||||
{
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isFresh($name, $time)
|
||||
{
|
||||
return true;
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -24,6 +24,8 @@ interface Twig_LoaderInterface
|
||||
* @return string The template source code
|
||||
*
|
||||
* @throws Twig_Error_Loader When $name is not found
|
||||
*
|
||||
* @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface
|
||||
*/
|
||||
public function getSource($name);
|
||||
|
||||
@ -41,12 +43,15 @@ interface Twig_LoaderInterface
|
||||
/**
|
||||
* 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
|
||||
* @param string $name The template name
|
||||
* @param int $time Timestamp of the last modification time of the
|
||||
* cached template
|
||||
*
|
||||
* @return Boolean true if the template is fresh, false otherwise
|
||||
* @return bool true if the template is fresh, false otherwise
|
||||
*
|
||||
* @throws Twig_Error_Loader When $name is not found
|
||||
*/
|
||||
public function isFresh($name, $time);
|
||||
}
|
||||
|
||||
class_alias('Twig_LoaderInterface', 'Twig\Loader\LoaderInterface', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -35,3 +35,5 @@ class Twig_Markup implements Countable
|
||||
return function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : strlen($this->content);
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Markup', 'Twig\Markup', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -22,19 +22,26 @@ class Twig_Node implements Twig_NodeInterface
|
||||
protected $lineno;
|
||||
protected $tag;
|
||||
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* The nodes are automatically made available as properties ($this->node).
|
||||
* The attributes are automatically made available as array items ($this['name']).
|
||||
*
|
||||
* @param array $nodes An array of named nodes
|
||||
* @param array $attributes An array of attributes (should not be nodes)
|
||||
* @param integer $lineno The line number
|
||||
* @param string $tag The tag name associated with the Node
|
||||
* @param array $nodes An array of named nodes
|
||||
* @param array $attributes An array of attributes (should not be nodes)
|
||||
* @param int $lineno The line number
|
||||
* @param string $tag The tag name associated with the Node
|
||||
*/
|
||||
public function __construct(array $nodes = array(), array $attributes = array(), $lineno = 0, $tag = null)
|
||||
{
|
||||
foreach ($nodes as $name => $node) {
|
||||
if (!$node instanceof Twig_NodeInterface) {
|
||||
@trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', is_object($node) ? get_class($node) : null === $node ? 'null' : gettype($node), $name, get_class($this)), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
$this->nodes = $nodes;
|
||||
$this->attributes = $attributes;
|
||||
$this->lineno = $lineno;
|
||||
@ -69,8 +76,13 @@ class Twig_Node implements Twig_NodeInterface
|
||||
return implode("\n", $repr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.16.1 (to be removed in 2.0)
|
||||
*/
|
||||
public function toXml($asDom = false)
|
||||
{
|
||||
@trigger_error(sprintf('%s is deprecated since version 1.16.1 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$dom = new DOMDocument('1.0', 'UTF-8');
|
||||
$dom->formatOutput = true;
|
||||
$dom->appendChild($xml = $dom->createElement('twig'));
|
||||
@ -96,7 +108,7 @@ class Twig_Node implements Twig_NodeInterface
|
||||
$node->appendChild($child);
|
||||
}
|
||||
|
||||
return $asDom ? $dom : $dom->saveXml();
|
||||
return $asDom ? $dom : $dom->saveXML();
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
@ -106,8 +118,18 @@ class Twig_Node implements Twig_NodeInterface
|
||||
}
|
||||
}
|
||||
|
||||
public function getTemplateLine()
|
||||
{
|
||||
return $this->lineno;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.27 (to be removed in 2.0)
|
||||
*/
|
||||
public function getLine()
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateLine() instead.', E_USER_DEPRECATED);
|
||||
|
||||
return $this->lineno;
|
||||
}
|
||||
|
||||
@ -117,11 +139,7 @@ class Twig_Node implements Twig_NodeInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the attribute is defined.
|
||||
*
|
||||
* @param string The attribute name
|
||||
*
|
||||
* @return Boolean true if the attribute is defined, false otherwise
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAttribute($name)
|
||||
{
|
||||
@ -129,11 +147,7 @@ class Twig_Node implements Twig_NodeInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an attribute.
|
||||
*
|
||||
* @param string The attribute name
|
||||
*
|
||||
* @return mixed The attribute value
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttribute($name)
|
||||
{
|
||||
@ -145,32 +159,21 @@ class Twig_Node implements Twig_NodeInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an attribute.
|
||||
*
|
||||
* @param string The attribute name
|
||||
* @param mixed The attribute value
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setAttribute($name, $value)
|
||||
{
|
||||
$this->attributes[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an attribute.
|
||||
*
|
||||
* @param string The attribute name
|
||||
*/
|
||||
public function removeAttribute($name)
|
||||
{
|
||||
unset($this->attributes[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the node with the given identifier exists.
|
||||
*
|
||||
* @param string The node name
|
||||
*
|
||||
* @return Boolean true if the node with the given name exists, false otherwise
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNode($name)
|
||||
{
|
||||
@ -178,11 +181,7 @@ class Twig_Node implements Twig_NodeInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node by name.
|
||||
*
|
||||
* @param string The node name
|
||||
*
|
||||
* @return Twig_Node A Twig_Node instance
|
||||
* @return Twig_Node
|
||||
*/
|
||||
public function getNode($name)
|
||||
{
|
||||
@ -193,22 +192,15 @@ class Twig_Node implements Twig_NodeInterface
|
||||
return $this->nodes[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a node.
|
||||
*
|
||||
* @param string The node name
|
||||
* @param Twig_Node A Twig_Node instance
|
||||
*/
|
||||
public function setNode($name, $node = null)
|
||||
{
|
||||
if (!$node instanceof Twig_NodeInterface) {
|
||||
@trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', is_object($node) ? get_class($node) : null === $node ? 'null' : gettype($node), $name, get_class($this)), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->nodes[$name] = $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a node by name.
|
||||
*
|
||||
* @param string The node name
|
||||
*/
|
||||
public function removeNode($name)
|
||||
{
|
||||
unset($this->nodes[$name]);
|
||||
@ -223,4 +215,42 @@ class Twig_Node implements Twig_NodeInterface
|
||||
{
|
||||
return new ArrayIterator($this->nodes);
|
||||
}
|
||||
|
||||
public function setTemplateName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
foreach ($this->nodes as $node) {
|
||||
if (null !== $node) {
|
||||
$node->setTemplateName($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getTemplateName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.27 (to be removed in 2.0)
|
||||
*/
|
||||
public function setFilename($name)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use setTemplateName() instead.', E_USER_DEPRECATED);
|
||||
|
||||
$this->setTemplateName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.27 (to be removed in 2.0)
|
||||
*/
|
||||
public function getFilename()
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateName() instead.', E_USER_DEPRECATED);
|
||||
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node', 'Twig\Node\Node', false);
|
||||
class_exists('Twig_Compiler');
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -27,13 +27,10 @@ class Twig_Node_AutoEscape extends Twig_Node
|
||||
parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->subcompile($this->getNode('body'));
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_AutoEscape', 'Twig\Node\AutoEscapeNode', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -22,11 +22,6 @@ class Twig_Node_Block extends Twig_Node
|
||||
parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
@ -42,3 +37,5 @@ class Twig_Node_Block extends Twig_Node
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Block', 'Twig\Node\BlockNode', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -22,11 +22,6 @@ class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInter
|
||||
parent::__construct(array(), array('name' => $name), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
@ -35,3 +30,5 @@ class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInter
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_BlockReference', 'Twig\Node\BlockReferenceNode', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2011 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -17,3 +17,5 @@
|
||||
class Twig_Node_Body extends Twig_Node
|
||||
{
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Body', 'Twig\Node\BodyNode', false);
|
||||
|
80
inc/lib/Twig/Node/CheckSecurity.php
Normal file
80
inc/lib/Twig/Node/CheckSecurity.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_CheckSecurity extends Twig_Node
|
||||
{
|
||||
protected $usedFilters;
|
||||
protected $usedTags;
|
||||
protected $usedFunctions;
|
||||
|
||||
public function __construct(array $usedFilters, array $usedTags, array $usedFunctions)
|
||||
{
|
||||
$this->usedFilters = $usedFilters;
|
||||
$this->usedTags = $usedTags;
|
||||
$this->usedFunctions = $usedFunctions;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$tags = $filters = $functions = array();
|
||||
foreach (array('tags', 'filters', 'functions') as $type) {
|
||||
foreach ($this->{'used'.ucfirst($type)} as $name => $node) {
|
||||
if ($node instanceof Twig_Node) {
|
||||
${$type}[$name] = $node->getTemplateLine();
|
||||
} else {
|
||||
${$type}[$node] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$compiler
|
||||
->write('$tags = ')->repr(array_filter($tags))->raw(";\n")
|
||||
->write('$filters = ')->repr(array_filter($filters))->raw(";\n")
|
||||
->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n")
|
||||
->write("try {\n")
|
||||
->indent()
|
||||
->write("\$this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity(\n")
|
||||
->indent()
|
||||
->write(!$tags ? "array(),\n" : "array('".implode("', '", array_keys($tags))."'),\n")
|
||||
->write(!$filters ? "array(),\n" : "array('".implode("', '", array_keys($filters))."'),\n")
|
||||
->write(!$functions ? "array()\n" : "array('".implode("', '", array_keys($functions))."')\n")
|
||||
->outdent()
|
||||
->write(");\n")
|
||||
->outdent()
|
||||
->write("} catch (Twig_Sandbox_SecurityError \$e) {\n")
|
||||
->indent()
|
||||
->write("\$e->setSourceContext(\$this->getSourceContext());\n\n")
|
||||
->write("if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n")
|
||||
->indent()
|
||||
->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n")
|
||||
->outdent()
|
||||
->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset(\$filters[\$e->getFilterName()])) {\n")
|
||||
->indent()
|
||||
->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n")
|
||||
->outdent()
|
||||
->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n")
|
||||
->indent()
|
||||
->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n")
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
->write("throw \$e;\n")
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_CheckSecurity', 'Twig\Node\CheckSecurityNode', false);
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2011 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -21,11 +21,6 @@ class Twig_Node_Do extends Twig_Node
|
||||
parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
@ -36,3 +31,5 @@ class Twig_Node_Do extends Twig_Node
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Do', 'Twig\Node\DoNode', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -17,22 +17,30 @@
|
||||
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)
|
||||
public function __construct($name, $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('name', $name);
|
||||
// to be removed in 2.0, used name instead
|
||||
$this->setAttribute('filename', $name);
|
||||
$this->setAttribute('index', $index);
|
||||
}
|
||||
|
||||
protected function addGetTemplate(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->write("\$this->env->loadTemplate(")
|
||||
->string($this->getAttribute('filename'))
|
||||
->write('$this->loadTemplate(')
|
||||
->string($this->getAttribute('name'))
|
||||
->raw(', ')
|
||||
->repr($this->getTemplateName())
|
||||
->raw(', ')
|
||||
->repr($this->getTemplateLine())
|
||||
->raw(', ')
|
||||
->string($this->getAttribute('index'))
|
||||
->raw(")")
|
||||
->raw(')')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Embed', 'Twig\Node\EmbedNode', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -18,3 +18,5 @@
|
||||
abstract class Twig_Node_Expression extends Twig_Node
|
||||
{
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression', 'Twig\Node\Expression\AbstractExpression', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -43,7 +43,7 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
|
||||
foreach ($this->getKeyValuePairs() as $pair) {
|
||||
// we compare the string representation of the keys
|
||||
// to avoid comparing the line numbers which are not relevant here.
|
||||
if ((string) $key == (string) $pair['key']) {
|
||||
if ((string) $key === (string) $pair['key']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -54,17 +54,12 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
|
||||
public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null)
|
||||
{
|
||||
if (null === $key) {
|
||||
$key = new Twig_Node_Expression_Constant(++$this->index, $value->getLine());
|
||||
$key = new Twig_Node_Expression_Constant(++$this->index, $value->getTemplateLine());
|
||||
}
|
||||
|
||||
array_push($this->nodes, $key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->raw('array(');
|
||||
@ -84,3 +79,5 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
|
||||
$compiler->raw(')');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Array', 'Twig\Node\Expression\ArrayExpression', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -12,11 +12,6 @@
|
||||
|
||||
class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
|
||||
{
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
@ -26,3 +21,5 @@ class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_AssignName', 'Twig\Node\Expression\AssignNameExpression', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,11 +16,6 @@ abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
|
||||
parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
@ -38,3 +33,5 @@ abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
|
||||
|
||||
abstract public function operator(Twig_Compiler $compiler);
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary', 'Twig\Node\Expression\Binary\AbstractBinary', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('+');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Add', 'Twig\Node\Expression\Binary\AddBinary', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('&&');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_And', 'Twig\Node\Expression\Binary\AndBinary', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('&');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_BitwiseAnd', 'Twig\Node\Expression\Binary\BitwiseAndBinary', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('|');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_BitwiseOr', 'Twig\Node\Expression\Binary\BitwiseOrBinary', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('^');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_BitwiseXor', 'Twig\Node\Expression\Binary\BitwiseXorBinary', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('.');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Concat', 'Twig\Node\Expression\Binary\ConcatBinary', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('/');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Div', 'Twig\Node\Expression\Binary\DivBinary', false);
|
||||
|
32
inc/lib/Twig/Node/Expression/Binary/EndsWith.php
Normal file
32
inc/lib/Twig/Node/Expression/Binary/EndsWith.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 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)
|
||||
{
|
||||
$left = $compiler->getVarName();
|
||||
$right = $compiler->getVarName();
|
||||
$compiler
|
||||
->raw(sprintf('(is_string($%s = ', $left))
|
||||
->subcompile($this->getNode('left'))
|
||||
->raw(sprintf(') && is_string($%s = ', $right))
|
||||
->subcompile($this->getNode('right'))
|
||||
->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s, -strlen($%2$s))))', $left, $right))
|
||||
;
|
||||
}
|
||||
|
||||
public function operator(Twig_Compiler $compiler)
|
||||
{
|
||||
return $compiler->raw('');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_EndsWith', 'Twig\Node\Expression\Binary\EndsWithBinary', false);
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('==');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Equal', 'Twig\Node\Expression\Binary\EqualBinary', false);
|
||||
|
@ -3,23 +3,18 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 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_FloorDiv extends Twig_Node_Expression_Binary
|
||||
{
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->raw('intval(floor(');
|
||||
$compiler->raw('(int) floor(');
|
||||
parent::compile($compiler);
|
||||
$compiler->raw('))');
|
||||
$compiler->raw(')');
|
||||
}
|
||||
|
||||
public function operator(Twig_Compiler $compiler)
|
||||
@ -27,3 +22,5 @@ class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('/');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_FloorDiv', 'Twig\Node\Expression\Binary\FloorDivBinary', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('>');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Greater', 'Twig\Node\Expression\Binary\GreaterBinary', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_GreaterEqual extends Twig_Node_Expression_Bina
|
||||
return $compiler->raw('>=');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_GreaterEqual', 'Twig\Node\Expression\Binary\GreaterEqualBinary', false);
|
||||
|
@ -3,18 +3,13 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) 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_In extends Twig_Node_Expression_Binary
|
||||
{
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
@ -31,3 +26,5 @@ class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('in');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_In', 'Twig\Node\Expression\Binary\InBinary', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('<');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Less', 'Twig\Node\Expression\Binary\LessBinary', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_LessEqual extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('<=');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_LessEqual', 'Twig\Node\Expression\Binary\LessEqualBinary', false);
|
||||
|
30
inc/lib/Twig/Node/Expression/Binary/Matches.php
Normal file
30
inc/lib/Twig/Node/Expression/Binary/Matches.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 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('');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Matches', 'Twig\Node\Expression\Binary\MatchesBinary', false);
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('%');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Mod', 'Twig\Node\Expression\Binary\ModBinary', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('*');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Mul', 'Twig\Node\Expression\Binary\MulBinary', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('!=');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_NotEqual', 'Twig\Node\Expression\Binary\NotEqualBinary', false);
|
||||
|
@ -3,18 +3,13 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) 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_NotIn extends Twig_Node_Expression_Binary
|
||||
{
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
@ -31,3 +26,5 @@ class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('not in');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_NotIn', 'Twig\Node\Expression\Binary\NotInBinary', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('||');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Or', 'Twig\Node\Expression\Binary\OrBinary', false);
|
||||
|
@ -3,20 +3,19 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) 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_Power extends Twig_Node_Expression_Binary
|
||||
{
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
if (PHP_VERSION_ID >= 50600) {
|
||||
return parent::compile($compiler);
|
||||
}
|
||||
|
||||
$compiler
|
||||
->raw('pow(')
|
||||
->subcompile($this->getNode('left'))
|
||||
@ -31,3 +30,5 @@ class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('**');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Power', 'Twig\Node\Expression\Binary\PowerBinary', false);
|
||||
|
@ -3,18 +3,13 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) 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_Range extends Twig_Node_Expression_Binary
|
||||
{
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
@ -31,3 +26,5 @@ class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('..');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Range', 'Twig\Node\Expression\Binary\RangeBinary', false);
|
||||
|
32
inc/lib/Twig/Node/Expression/Binary/StartsWith.php
Normal file
32
inc/lib/Twig/Node/Expression/Binary/StartsWith.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 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_StartsWith extends Twig_Node_Expression_Binary
|
||||
{
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$left = $compiler->getVarName();
|
||||
$right = $compiler->getVarName();
|
||||
$compiler
|
||||
->raw(sprintf('(is_string($%s = ', $left))
|
||||
->subcompile($this->getNode('left'))
|
||||
->raw(sprintf(') && is_string($%s = ', $right))
|
||||
->subcompile($this->getNode('right'))
|
||||
->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s, $%2$s)))', $left, $right))
|
||||
;
|
||||
}
|
||||
|
||||
public function operator(Twig_Compiler $compiler)
|
||||
{
|
||||
return $compiler->raw('');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_StartsWith', 'Twig\Node\Expression\Binary\StartsWithBinary', false);
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary
|
||||
return $compiler->raw('-');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Binary_Sub', 'Twig\Node\Expression\Binary\SubBinary', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -17,35 +17,77 @@
|
||||
*/
|
||||
class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
||||
{
|
||||
public function __construct(Twig_NodeInterface $name, $asString = false, $lineno, $tag = null)
|
||||
/**
|
||||
* @param Twig_Node|null $template
|
||||
*/
|
||||
public function __construct(Twig_NodeInterface $name, $template = null, $lineno, $tag = null)
|
||||
{
|
||||
parent::__construct(array('name' => $name), array('as_string' => $asString, 'output' => false), $lineno, $tag);
|
||||
if (is_bool($template)) {
|
||||
@trigger_error(sprintf('The %s method "$asString" argument is deprecated since version 1.28 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$template = null;
|
||||
}
|
||||
|
||||
$nodes = array('name' => $name);
|
||||
if (null !== $template) {
|
||||
$nodes['template'] = $template;
|
||||
}
|
||||
|
||||
parent::__construct($nodes, array('is_defined_test' => false, 'output' => false), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
if ($this->getAttribute('as_string')) {
|
||||
$compiler->raw('(string) ');
|
||||
}
|
||||
|
||||
if ($this->getAttribute('output')) {
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write("\$this->displayBlock(")
|
||||
->subcompile($this->getNode('name'))
|
||||
->raw(", \$context, \$blocks);\n")
|
||||
;
|
||||
if ($this->getAttribute('is_defined_test')) {
|
||||
$this->compileTemplateCall($compiler, 'hasBlock');
|
||||
} else {
|
||||
$compiler
|
||||
->raw("\$this->renderBlock(")
|
||||
->subcompile($this->getNode('name'))
|
||||
->raw(", \$context, \$blocks)")
|
||||
;
|
||||
if ($this->getAttribute('output')) {
|
||||
$compiler->addDebugInfo($this);
|
||||
|
||||
$this
|
||||
->compileTemplateCall($compiler, 'displayBlock')
|
||||
->raw(";\n");
|
||||
} else {
|
||||
$this->compileTemplateCall($compiler, 'renderBlock');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function compileTemplateCall(Twig_Compiler $compiler, $method)
|
||||
{
|
||||
if (!$this->hasNode('template')) {
|
||||
$compiler->write('$this');
|
||||
} else {
|
||||
$compiler
|
||||
->write('$this->loadTemplate(')
|
||||
->subcompile($this->getNode('template'))
|
||||
->raw(', ')
|
||||
->repr($this->getTemplateName())
|
||||
->raw(', ')
|
||||
->repr($this->getTemplateLine())
|
||||
->raw(')')
|
||||
;
|
||||
}
|
||||
|
||||
$compiler->raw(sprintf('->%s', $method));
|
||||
$this->compileBlockArguments($compiler);
|
||||
|
||||
return $compiler;
|
||||
}
|
||||
|
||||
private function compileBlockArguments(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->raw('(')
|
||||
->subcompile($this->getNode('name'))
|
||||
->raw(', $context');
|
||||
|
||||
if (!$this->hasNode('template')) {
|
||||
$compiler->raw(', $blocks');
|
||||
}
|
||||
|
||||
return $compiler->raw(')');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_BlockReference', 'Twig\Node\Expression\BlockReferenceExpression', false);
|
||||
|
@ -3,27 +3,36 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
||||
{
|
||||
private $reflector;
|
||||
|
||||
protected function compileCallable(Twig_Compiler $compiler)
|
||||
{
|
||||
$callable = $this->getAttribute('callable');
|
||||
|
||||
$closingParenthesis = false;
|
||||
if ($callable) {
|
||||
if (is_string($callable)) {
|
||||
if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) {
|
||||
if (is_string($callable) && false === strpos($callable, '::')) {
|
||||
$compiler->raw($callable);
|
||||
} elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) {
|
||||
$compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1]));
|
||||
} else {
|
||||
$type = ucfirst($this->getAttribute('type'));
|
||||
$compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name')));
|
||||
$closingParenthesis = true;
|
||||
list($r, $callable) = $this->reflectCallable($callable);
|
||||
if ($r instanceof ReflectionMethod && is_string($callable[0])) {
|
||||
if ($r->isStatic()) {
|
||||
$compiler->raw(sprintf('%s::%s', $callable[0], $callable[1]));
|
||||
} else {
|
||||
$compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1]));
|
||||
}
|
||||
} elseif ($r instanceof ReflectionMethod && $callable[0] instanceof Twig_ExtensionInterface) {
|
||||
$compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', get_class($callable[0]), $callable[1]));
|
||||
} else {
|
||||
$type = ucfirst($this->getAttribute('type'));
|
||||
$compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name')));
|
||||
$closingParenthesis = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$compiler->raw($this->getAttribute('thing')->compile());
|
||||
@ -73,7 +82,7 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
||||
$first = false;
|
||||
}
|
||||
|
||||
if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) {
|
||||
if ($this->hasNode('arguments')) {
|
||||
$callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null;
|
||||
|
||||
$arguments = $this->getArguments($callable, $this->getNode('arguments'));
|
||||
@ -92,6 +101,9 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
||||
|
||||
protected function getArguments($callable, $arguments)
|
||||
{
|
||||
$callType = $this->getAttribute('type');
|
||||
$callName = $this->getAttribute('name');
|
||||
|
||||
$parameters = array();
|
||||
$named = false;
|
||||
foreach ($arguments as $name => $node) {
|
||||
@ -99,73 +111,101 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
||||
$named = true;
|
||||
$name = $this->normalizeName($name);
|
||||
} elseif ($named) {
|
||||
throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName));
|
||||
}
|
||||
|
||||
$parameters[$name] = $node;
|
||||
}
|
||||
|
||||
if (!$named) {
|
||||
$isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic');
|
||||
if (!$named && !$isVariadic) {
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
if (!$callable) {
|
||||
throw new LogicException(sprintf('Named arguments are not supported for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
}
|
||||
|
||||
// manage named arguments
|
||||
if (is_array($callable)) {
|
||||
$r = new ReflectionMethod($callable[0], $callable[1]);
|
||||
} elseif (is_object($callable) && !$callable instanceof Closure) {
|
||||
$r = new ReflectionObject($callable);
|
||||
$r = $r->getMethod('__invoke');
|
||||
} else {
|
||||
$r = new ReflectionFunction($callable);
|
||||
}
|
||||
|
||||
$definition = $r->getParameters();
|
||||
if ($this->hasNode('node')) {
|
||||
array_shift($definition);
|
||||
}
|
||||
if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
|
||||
array_shift($definition);
|
||||
}
|
||||
if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
|
||||
array_shift($definition);
|
||||
}
|
||||
if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
|
||||
foreach ($this->getAttribute('arguments') as $argument) {
|
||||
array_shift($definition);
|
||||
if ($named) {
|
||||
$message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName);
|
||||
} else {
|
||||
$message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName);
|
||||
}
|
||||
|
||||
throw new LogicException($message);
|
||||
}
|
||||
|
||||
$callableParameters = $this->getCallableParameters($callable, $isVariadic);
|
||||
$arguments = array();
|
||||
$names = array();
|
||||
$missingArguments = array();
|
||||
$optionalArguments = array();
|
||||
$pos = 0;
|
||||
foreach ($definition as $param) {
|
||||
$name = $this->normalizeName($param->name);
|
||||
foreach ($callableParameters as $callableParameter) {
|
||||
$names[] = $name = $this->normalizeName($callableParameter->name);
|
||||
|
||||
if (array_key_exists($name, $parameters)) {
|
||||
if (array_key_exists($pos, $parameters)) {
|
||||
throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName));
|
||||
}
|
||||
|
||||
if (count($missingArguments)) {
|
||||
throw new Twig_Error_Syntax(sprintf(
|
||||
'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".',
|
||||
$name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments))
|
||||
);
|
||||
}
|
||||
|
||||
$arguments = array_merge($arguments, $optionalArguments);
|
||||
$arguments[] = $parameters[$name];
|
||||
unset($parameters[$name]);
|
||||
$optionalArguments = array();
|
||||
} elseif (array_key_exists($pos, $parameters)) {
|
||||
$arguments = array_merge($arguments, $optionalArguments);
|
||||
$arguments[] = $parameters[$pos];
|
||||
unset($parameters[$pos]);
|
||||
$optionalArguments = array();
|
||||
++$pos;
|
||||
} elseif ($param->isDefaultValueAvailable()) {
|
||||
$arguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1);
|
||||
} elseif ($param->isOptional()) {
|
||||
break;
|
||||
} elseif ($callableParameter->isDefaultValueAvailable()) {
|
||||
$optionalArguments[] = new Twig_Node_Expression_Constant($callableParameter->getDefaultValue(), -1);
|
||||
} elseif ($callableParameter->isOptional()) {
|
||||
if (empty($parameters)) {
|
||||
break;
|
||||
} else {
|
||||
$missingArguments[] = $name;
|
||||
}
|
||||
} else {
|
||||
throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName));
|
||||
}
|
||||
}
|
||||
|
||||
if ($isVariadic) {
|
||||
$arbitraryArguments = new Twig_Node_Expression_Array(array(), -1);
|
||||
foreach ($parameters as $key => $value) {
|
||||
if (is_int($key)) {
|
||||
$arbitraryArguments->addElement($value);
|
||||
} else {
|
||||
$arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1));
|
||||
}
|
||||
unset($parameters[$key]);
|
||||
}
|
||||
|
||||
if ($arbitraryArguments->count()) {
|
||||
$arguments = array_merge($arguments, $optionalArguments);
|
||||
$arguments[] = $arbitraryArguments;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($parameters)) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unknown argument%s "%s" for %s "%s".', count($parameters) > 1 ? 's' : '' , implode('", "', array_keys($parameters)), $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
$unknownParameter = null;
|
||||
foreach ($parameters as $parameter) {
|
||||
if ($parameter instanceof Twig_Node) {
|
||||
$unknownParameter = $parameter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Syntax(sprintf(
|
||||
'Unknown argument%s "%s" for %s "%s(%s)".',
|
||||
count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names)
|
||||
), $unknownParameter ? $unknownParameter->getTemplateLine() : -1);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
@ -175,4 +215,77 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
||||
{
|
||||
return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
|
||||
}
|
||||
|
||||
private function getCallableParameters($callable, $isVariadic)
|
||||
{
|
||||
list($r) = $this->reflectCallable($callable);
|
||||
if (null === $r) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$parameters = $r->getParameters();
|
||||
if ($this->hasNode('node')) {
|
||||
array_shift($parameters);
|
||||
}
|
||||
if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
|
||||
array_shift($parameters);
|
||||
}
|
||||
if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
|
||||
array_shift($parameters);
|
||||
}
|
||||
if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
|
||||
foreach ($this->getAttribute('arguments') as $argument) {
|
||||
array_shift($parameters);
|
||||
}
|
||||
}
|
||||
if ($isVariadic) {
|
||||
$argument = end($parameters);
|
||||
if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) {
|
||||
array_pop($parameters);
|
||||
} else {
|
||||
$callableName = $r->name;
|
||||
if ($r instanceof ReflectionMethod) {
|
||||
$callableName = $r->getDeclaringClass()->name.'::'.$callableName;
|
||||
}
|
||||
|
||||
throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = array()".', $callableName, $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
}
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
private function reflectCallable($callable)
|
||||
{
|
||||
if (null !== $this->reflector) {
|
||||
return $this->reflector;
|
||||
}
|
||||
|
||||
if (is_array($callable)) {
|
||||
if (!method_exists($callable[0], $callable[1])) {
|
||||
// __call()
|
||||
return array(null, array());
|
||||
}
|
||||
$r = new ReflectionMethod($callable[0], $callable[1]);
|
||||
} elseif (is_object($callable) && !$callable instanceof Closure) {
|
||||
$r = new ReflectionObject($callable);
|
||||
$r = $r->getMethod('__invoke');
|
||||
$callable = array($callable, '__invoke');
|
||||
} elseif (is_string($callable) && false !== $pos = strpos($callable, '::')) {
|
||||
$class = substr($callable, 0, $pos);
|
||||
$method = substr($callable, $pos + 2);
|
||||
if (!method_exists($class, $method)) {
|
||||
// __staticCall()
|
||||
return array(null, array());
|
||||
}
|
||||
$r = new ReflectionMethod($callable);
|
||||
$callable = array($class, $method);
|
||||
} else {
|
||||
$r = new ReflectionFunction($callable);
|
||||
}
|
||||
|
||||
return $this->reflector = array($r, $callable);
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Call', 'Twig\Node\Expression\CallExpression', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -29,3 +29,5 @@ class Twig_Node_Expression_Conditional extends Twig_Node_Expression
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Conditional', 'Twig\Node\Expression\ConditionalExpression', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -21,3 +21,5 @@ class Twig_Node_Expression_Constant extends Twig_Node_Expression
|
||||
$compiler->repr($this->getAttribute('value'));
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Constant', 'Twig\Node\Expression\ConstantExpression', false);
|
||||
|
@ -3,16 +3,20 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Node_Expression_ExtensionReference class is deprecated since version 1.23 and will be removed in 2.0.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents an extension call node.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.23 and will be removed in 2.0.
|
||||
*/
|
||||
class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
|
||||
{
|
||||
@ -21,11 +25,6 @@ class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
|
||||
parent::__construct(array(), array('name' => $name), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name')));
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -30,7 +30,12 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
|
||||
if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
|
||||
$this->setAttribute('callable', $filter->getCallable());
|
||||
}
|
||||
if ($filter instanceof Twig_SimpleFilter) {
|
||||
$this->setAttribute('is_variadic', $filter->isVariadic());
|
||||
}
|
||||
|
||||
$this->compileCallable($compiler);
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Filter', 'Twig\Node\Expression\FilterExpression', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2011 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -22,13 +22,13 @@ class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter
|
||||
{
|
||||
public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
||||
{
|
||||
$default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getLine()), $arguments, $node->getLine());
|
||||
$default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getTemplateLine()), $arguments, $node->getTemplateLine());
|
||||
|
||||
if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) {
|
||||
$test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getLine());
|
||||
$false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getLine());
|
||||
$test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getTemplateLine());
|
||||
$false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getTemplateLine());
|
||||
|
||||
$node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getLine());
|
||||
$node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getTemplateLine());
|
||||
} else {
|
||||
$node = $default;
|
||||
}
|
||||
@ -41,3 +41,5 @@ class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter
|
||||
$compiler->subcompile($this->getNode('node'));
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Filter_Default', 'Twig\Node\Expression\Filter\DefaultFilter', false);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -12,7 +12,7 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
|
||||
{
|
||||
public function __construct($name, Twig_NodeInterface $arguments, $lineno)
|
||||
{
|
||||
parent::__construct(array('arguments' => $arguments), array('name' => $name), $lineno);
|
||||
parent::__construct(array('arguments' => $arguments), array('name' => $name, 'is_defined_test' => false), $lineno);
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
@ -27,9 +27,19 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
|
||||
$this->setAttribute('needs_context', $function->needsContext());
|
||||
$this->setAttribute('arguments', $function->getArguments());
|
||||
if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
|
||||
$this->setAttribute('callable', $function->getCallable());
|
||||
$callable = $function->getCallable();
|
||||
if ('constant' === $name && $this->getAttribute('is_defined_test')) {
|
||||
$callable = 'twig_constant_is_defined';
|
||||
}
|
||||
|
||||
$this->setAttribute('callable', $callable);
|
||||
}
|
||||
if ($function instanceof Twig_SimpleFunction) {
|
||||
$this->setAttribute('is_variadic', $function->isVariadic());
|
||||
}
|
||||
|
||||
$this->compileCallable($compiler);
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Function', 'Twig\Node\Expression\FunctionExpression', false);
|
||||
|
@ -3,21 +3,30 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) 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_GetAttr extends Twig_Node_Expression
|
||||
{
|
||||
public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno)
|
||||
public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression $arguments = null, $type, $lineno)
|
||||
{
|
||||
parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno);
|
||||
$nodes = array('node' => $node, 'attribute' => $attribute);
|
||||
if (null !== $arguments) {
|
||||
$nodes['arguments'] = $arguments;
|
||||
}
|
||||
|
||||
parent::__construct($nodes, array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno);
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
if ($this->getAttribute('disable_c_ext')) {
|
||||
@trigger_error(sprintf('Using the "disable_c_ext" attribute on %s is deprecated since version 1.30 and will be removed in 2.0.', __CLASS__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) {
|
||||
$compiler->raw('twig_template_get_attributes($this, ');
|
||||
} else {
|
||||
@ -32,22 +41,34 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
|
||||
|
||||
$compiler->raw(', ')->subcompile($this->getNode('attribute'));
|
||||
|
||||
if (count($this->getNode('arguments')) || Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
|
||||
$compiler->raw(', ')->subcompile($this->getNode('arguments'));
|
||||
// only generate optional arguments when needed (to make generated code more readable)
|
||||
$needFourth = $this->getAttribute('ignore_strict_check');
|
||||
$needThird = $needFourth || $this->getAttribute('is_defined_test');
|
||||
$needSecond = $needThird || Twig_Template::ANY_CALL !== $this->getAttribute('type');
|
||||
$needFirst = $needSecond || $this->hasNode('arguments');
|
||||
|
||||
if (Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
|
||||
$compiler->raw(', ')->repr($this->getAttribute('type'));
|
||||
if ($needFirst) {
|
||||
if ($this->hasNode('arguments')) {
|
||||
$compiler->raw(', ')->subcompile($this->getNode('arguments'));
|
||||
} else {
|
||||
$compiler->raw(', array()');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
|
||||
$compiler->raw(', '.($this->getAttribute('is_defined_test') ? 'true' : 'false'));
|
||||
}
|
||||
if ($needSecond) {
|
||||
$compiler->raw(', ')->repr($this->getAttribute('type'));
|
||||
}
|
||||
|
||||
if ($this->getAttribute('ignore_strict_check')) {
|
||||
$compiler->raw(', '.($this->getAttribute('ignore_strict_check') ? 'true' : 'false'));
|
||||
}
|
||||
if ($needThird) {
|
||||
$compiler->raw(', ')->repr($this->getAttribute('is_defined_test'));
|
||||
}
|
||||
|
||||
if ($needFourth) {
|
||||
$compiler->raw(', ')->repr($this->getAttribute('ignore_strict_check'));
|
||||
}
|
||||
|
||||
$compiler->raw(')');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_GetAttr', 'Twig\Node\Expression\GetAttrExpression', false);
|
||||
|
@ -1,60 +0,0 @@
|
||||
<?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 macro call node.
|
||||
*
|
||||
* @author Martin Hasoň <martin.hason@gmail.com>
|
||||
*/
|
||||
class Twig_Node_Expression_MacroCall extends Twig_Node_Expression
|
||||
{
|
||||
public function __construct(Twig_Node_Expression $template, $name, Twig_Node_Expression_Array $arguments, $lineno)
|
||||
{
|
||||
parent::__construct(array('template' => $template, 'arguments' => $arguments), array('name' => $name), $lineno);
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$namedNames = array();
|
||||
$namedCount = 0;
|
||||
$positionalCount = 0;
|
||||
foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) {
|
||||
$name = $pair['key']->getAttribute('value');
|
||||
if (!is_int($name)) {
|
||||
$namedCount++;
|
||||
$namedNames[$name] = 1;
|
||||
} elseif ($namedCount > 0) {
|
||||
throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for macro "%s".', $this->getAttribute('name')), $this->lineno);
|
||||
} else {
|
||||
$positionalCount++;
|
||||
}
|
||||
}
|
||||
|
||||
$compiler
|
||||
->raw('$this->callMacro(')
|
||||
->subcompile($this->getNode('template'))
|
||||
->raw(', ')->repr($this->getAttribute('name'))
|
||||
->raw(', ')->subcompile($this->getNode('arguments'))
|
||||
;
|
||||
|
||||
if ($namedCount > 0) {
|
||||
$compiler
|
||||
->raw(', ')->repr($namedNames)
|
||||
->raw(', ')->repr($namedCount)
|
||||
->raw(', ')->repr($positionalCount)
|
||||
;
|
||||
}
|
||||
|
||||
$compiler
|
||||
->raw(')')
|
||||
;
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -39,3 +39,5 @@ class Twig_Node_Expression_MethodCall extends Twig_Node_Expression
|
||||
$compiler->raw(')');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_MethodCall', 'Twig\Node\Expression\MethodCallExpression', false);
|
||||
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -12,7 +12,7 @@
|
||||
class Twig_Node_Expression_Name extends Twig_Node_Expression
|
||||
{
|
||||
protected $specialVars = array(
|
||||
'_self' => '$this',
|
||||
'_self' => '$this',
|
||||
'_context' => '$context',
|
||||
'_charset' => '$this->env->getCharset()',
|
||||
);
|
||||
@ -26,6 +26,8 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
||||
{
|
||||
$name = $this->getAttribute('name');
|
||||
|
||||
$compiler->addDebugInfo($this);
|
||||
|
||||
if ($this->getAttribute('is_defined_test')) {
|
||||
if ($this->isSpecial()) {
|
||||
$compiler->repr(true);
|
||||
@ -41,10 +43,20 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
||||
->raw(']')
|
||||
;
|
||||
} else {
|
||||
// remove the non-PHP 5.4 version when PHP 5.3 support is dropped
|
||||
// as the non-optimized version is just a workaround for slow ternary operator
|
||||
// when the context has a lot of variables
|
||||
if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
|
||||
if (PHP_VERSION_ID >= 70000) {
|
||||
// use PHP 7 null coalescing operator
|
||||
$compiler
|
||||
->raw('($context[')
|
||||
->string($name)
|
||||
->raw('] ?? ')
|
||||
;
|
||||
|
||||
if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) {
|
||||
$compiler->raw('null)');
|
||||
} else {
|
||||
$compiler->raw('$this->getContext($context, ')->string($name)->raw('))');
|
||||
}
|
||||
} elseif (PHP_VERSION_ID >= 50400) {
|
||||
// PHP 5.4 ternary operator performance was optimized
|
||||
$compiler
|
||||
->raw('(isset($context[')
|
||||
@ -86,3 +98,5 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
||||
return !$this->isSpecial() && !$this->getAttribute('is_defined_test');
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Name', 'Twig\Node\Expression\NameExpression', false);
|
||||
|
48
inc/lib/Twig/Node/Expression/NullCoalesce.php
Normal file
48
inc/lib/Twig/Node/Expression/NullCoalesce.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 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_NullCoalesce extends Twig_Node_Expression_Conditional
|
||||
{
|
||||
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
|
||||
{
|
||||
$test = new Twig_Node_Expression_Binary_And(
|
||||
new Twig_Node_Expression_Test_Defined(clone $left, 'defined', new Twig_Node(), $left->getTemplateLine()),
|
||||
new Twig_Node_Expression_Unary_Not(new Twig_Node_Expression_Test_Null($left, 'null', new Twig_Node(), $left->getTemplateLine()), $left->getTemplateLine()),
|
||||
$left->getTemplateLine()
|
||||
);
|
||||
|
||||
parent::__construct($test, $left, $right, $lineno);
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
/*
|
||||
* This optimizes only one case. PHP 7 also supports more complex expressions
|
||||
* that can return null. So, for instance, if log is defined, log("foo") ?? "..." works,
|
||||
* but log($a["foo"]) ?? "..." does not if $a["foo"] is not defined. More advanced
|
||||
* cases might be implemented as an optimizer node visitor, but has not been done
|
||||
* as benefits are probably not worth the added complexity.
|
||||
*/
|
||||
if (PHP_VERSION_ID >= 70000 && $this->getNode('expr2') instanceof Twig_Node_Expression_Name) {
|
||||
$this->getNode('expr2')->setAttribute('always_defined', true);
|
||||
$compiler
|
||||
->raw('((')
|
||||
->subcompile($this->getNode('expr2'))
|
||||
->raw(') ?? (')
|
||||
->subcompile($this->getNode('expr3'))
|
||||
->raw('))')
|
||||
;
|
||||
} else {
|
||||
parent::compile($compiler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_NullCoalesce', 'Twig\Node\Expression\NullCoalesceExpression', false);
|
@ -3,8 +3,8 @@
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
* (c) Fabien Potencier
|
||||
* (c) Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@ -22,26 +22,23 @@ class Twig_Node_Expression_Parent extends Twig_Node_Expression
|
||||
parent::__construct(array(), array('output' => false, 'name' => $name), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
if ($this->getAttribute('output')) {
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write("\$this->displayParentBlock(")
|
||||
->write('$this->displayParentBlock(')
|
||||
->string($this->getAttribute('name'))
|
||||
->raw(", \$context, \$blocks);\n")
|
||||
;
|
||||
} else {
|
||||
$compiler
|
||||
->raw("\$this->renderParentBlock(")
|
||||
->raw('$this->renderParentBlock(')
|
||||
->string($this->getAttribute('name'))
|
||||
->raw(", \$context, \$blocks)")
|
||||
->raw(', $context, $blocks)')
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_alias('Twig_Node_Expression_Parent', 'Twig\Node\Expression\ParentExpression', false);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user